xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/ADT/STLExtras.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/BinaryFormat/MachO.h"
20 #include "llvm/Config/config.h"
21 #include "llvm/DebugInfo/DIContext.h"
22 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
23 #include "llvm/Demangle/Demangle.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCContext.h"
26 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCInstPrinter.h"
29 #include "llvm/MC/MCInstrDesc.h"
30 #include "llvm/MC/MCInstrInfo.h"
31 #include "llvm/MC/MCRegisterInfo.h"
32 #include "llvm/MC/MCSubtargetInfo.h"
33 #include "llvm/MC/MCTargetOptions.h"
34 #include "llvm/MC/TargetRegistry.h"
35 #include "llvm/Object/MachO.h"
36 #include "llvm/Object/MachOUniversal.h"
37 #include "llvm/Option/ArgList.h"
38 #include "llvm/Support/Casting.h"
39 #include "llvm/Support/Debug.h"
40 #include "llvm/Support/Endian.h"
41 #include "llvm/Support/Format.h"
42 #include "llvm/Support/FormattedStream.h"
43 #include "llvm/Support/LEB128.h"
44 #include "llvm/Support/MemoryBuffer.h"
45 #include "llvm/Support/WithColor.h"
46 #include "llvm/Support/raw_ostream.h"
47 #include "llvm/TargetParser/Triple.h"
48 #include <algorithm>
49 #include <cstring>
50 #include <system_error>
51 
52 using namespace llvm;
53 using namespace llvm::object;
54 using namespace llvm::objdump;
55 
56 bool objdump::FirstPrivateHeader;
57 bool objdump::ExportsTrie;
58 bool objdump::Rebase;
59 bool objdump::Rpaths;
60 bool objdump::Bind;
61 bool objdump::LazyBind;
62 bool objdump::WeakBind;
63 static bool UseDbg;
64 static std::string DSYMFile;
65 bool objdump::FullLeadingAddr;
66 bool objdump::LeadingHeaders;
67 bool objdump::UniversalHeaders;
68 static bool ArchiveMemberOffsets;
69 bool objdump::IndirectSymbols;
70 bool objdump::DataInCode;
71 FunctionStartsMode objdump::FunctionStartsType =
72     objdump::FunctionStartsMode::None;
73 bool objdump::LinkOptHints;
74 bool objdump::InfoPlist;
75 bool objdump::ChainedFixups;
76 bool objdump::DyldInfo;
77 bool objdump::DylibsUsed;
78 bool objdump::DylibId;
79 bool objdump::Verbose;
80 bool objdump::ObjcMetaData;
81 std::string objdump::DisSymName;
82 bool objdump::SymbolicOperands;
83 static std::vector<std::string> ArchFlags;
84 
85 static bool ArchAll = false;
86 static std::string ThumbTripleName;
87 
88 static StringRef ordinalName(const object::MachOObjectFile *, int);
89 
parseMachOOptions(const llvm::opt::InputArgList & InputArgs)90 void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) {
91   FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header);
92   ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie);
93   Rebase = InputArgs.hasArg(OBJDUMP_rebase);
94   Rpaths = InputArgs.hasArg(OBJDUMP_rpaths);
95   Bind = InputArgs.hasArg(OBJDUMP_bind);
96   LazyBind = InputArgs.hasArg(OBJDUMP_lazy_bind);
97   WeakBind = InputArgs.hasArg(OBJDUMP_weak_bind);
98   UseDbg = InputArgs.hasArg(OBJDUMP_g);
99   DSYMFile = InputArgs.getLastArgValue(OBJDUMP_dsym_EQ).str();
100   FullLeadingAddr = InputArgs.hasArg(OBJDUMP_full_leading_addr);
101   LeadingHeaders = !InputArgs.hasArg(OBJDUMP_no_leading_headers);
102   UniversalHeaders = InputArgs.hasArg(OBJDUMP_universal_headers);
103   ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets);
104   IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols);
105   DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code);
106   if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_function_starts_EQ)) {
107     FunctionStartsType = StringSwitch<FunctionStartsMode>(A->getValue())
108                              .Case("addrs", FunctionStartsMode::Addrs)
109                              .Case("names", FunctionStartsMode::Names)
110                              .Case("both", FunctionStartsMode::Both)
111                              .Default(FunctionStartsMode::None);
112     if (FunctionStartsType == FunctionStartsMode::None)
113       invalidArgValue(A);
114   }
115   LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints);
116   InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist);
117   ChainedFixups = InputArgs.hasArg(OBJDUMP_chained_fixups);
118   DyldInfo = InputArgs.hasArg(OBJDUMP_dyld_info);
119   DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used);
120   DylibId = InputArgs.hasArg(OBJDUMP_dylib_id);
121   Verbose = !InputArgs.hasArg(OBJDUMP_non_verbose);
122   ObjcMetaData = InputArgs.hasArg(OBJDUMP_objc_meta_data);
123   DisSymName = InputArgs.getLastArgValue(OBJDUMP_dis_symname).str();
124   SymbolicOperands = !InputArgs.hasArg(OBJDUMP_no_symbolic_operands);
125   ArchFlags = InputArgs.getAllArgValues(OBJDUMP_arch_EQ);
126 }
127 
GetTarget(const MachOObjectFile * MachOObj,const char ** McpuDefault,const Target ** ThumbTarget)128 static const Target *GetTarget(const MachOObjectFile *MachOObj,
129                                const char **McpuDefault,
130                                const Target **ThumbTarget) {
131   // Figure out the target triple.
132   Triple TT(TripleName);
133   if (TripleName.empty()) {
134     TT = MachOObj->getArchTriple(McpuDefault);
135     TripleName = TT.str();
136   }
137 
138   if (TT.getArch() == Triple::arm) {
139     // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
140     // that support ARM are also capable of Thumb mode.
141     Triple ThumbTriple = TT;
142     std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
143     ThumbTriple.setArchName(ThumbName);
144     ThumbTripleName = ThumbTriple.str();
145   }
146 
147   // Get the target specific parser.
148   std::string Error;
149   const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
150   if (TheTarget && ThumbTripleName.empty())
151     return TheTarget;
152 
153   *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
154   if (*ThumbTarget)
155     return TheTarget;
156 
157   WithColor::error(errs(), "llvm-objdump") << "unable to get target for '";
158   if (!TheTarget)
159     errs() << TripleName;
160   else
161     errs() << ThumbTripleName;
162   errs() << "', see --version and --triple.\n";
163   return nullptr;
164 }
165 
166 namespace {
167 struct SymbolSorter {
operator ()__anon061faff00111::SymbolSorter168   bool operator()(const SymbolRef &A, const SymbolRef &B) {
169     Expected<SymbolRef::Type> ATypeOrErr = A.getType();
170     if (!ATypeOrErr)
171       reportError(ATypeOrErr.takeError(), A.getObject()->getFileName());
172     SymbolRef::Type AType = *ATypeOrErr;
173     Expected<SymbolRef::Type> BTypeOrErr = B.getType();
174     if (!BTypeOrErr)
175       reportError(BTypeOrErr.takeError(), B.getObject()->getFileName());
176     SymbolRef::Type BType = *BTypeOrErr;
177     uint64_t AAddr =
178         (AType != SymbolRef::ST_Function) ? 0 : cantFail(A.getValue());
179     uint64_t BAddr =
180         (BType != SymbolRef::ST_Function) ? 0 : cantFail(B.getValue());
181     return AAddr < BAddr;
182   }
183 };
184 
185 class MachODumper : public Dumper {
186   const object::MachOObjectFile &Obj;
187 
188 public:
MachODumper(const object::MachOObjectFile & O)189   MachODumper(const object::MachOObjectFile &O) : Dumper(O), Obj(O) {}
190   void printPrivateHeaders() override;
191 };
192 } // namespace
193 
194 std::unique_ptr<Dumper>
createMachODumper(const object::MachOObjectFile & Obj)195 objdump::createMachODumper(const object::MachOObjectFile &Obj) {
196   return std::make_unique<MachODumper>(Obj);
197 }
198 
199 // Types for the storted data in code table that is built before disassembly
200 // and the predicate function to sort them.
201 typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
202 typedef std::vector<DiceTableEntry> DiceTable;
203 typedef DiceTable::iterator dice_table_iterator;
204 
205 // This is used to search for a data in code table entry for the PC being
206 // disassembled.  The j parameter has the PC in j.first.  A single data in code
207 // table entry can cover many bytes for each of its Kind's.  So if the offset,
208 // aka the i.first value, of the data in code table entry plus its Length
209 // covers the PC being searched for this will return true.  If not it will
210 // return false.
compareDiceTableEntries(const DiceTableEntry & i,const DiceTableEntry & j)211 static bool compareDiceTableEntries(const DiceTableEntry &i,
212                                     const DiceTableEntry &j) {
213   uint16_t Length;
214   i.second.getLength(Length);
215 
216   return j.first >= i.first && j.first < i.first + Length;
217 }
218 
DumpDataInCode(const uint8_t * bytes,uint64_t Length,unsigned short Kind)219 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
220                                unsigned short Kind) {
221   uint32_t Value, Size = 1;
222 
223   switch (Kind) {
224   default:
225   case MachO::DICE_KIND_DATA:
226     if (Length >= 4) {
227       if (ShowRawInsn)
228         dumpBytes(ArrayRef(bytes, 4), outs());
229       Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
230       outs() << "\t.long " << Value;
231       Size = 4;
232     } else if (Length >= 2) {
233       if (ShowRawInsn)
234         dumpBytes(ArrayRef(bytes, 2), outs());
235       Value = bytes[1] << 8 | bytes[0];
236       outs() << "\t.short " << Value;
237       Size = 2;
238     } else {
239       if (ShowRawInsn)
240         dumpBytes(ArrayRef(bytes, 2), outs());
241       Value = bytes[0];
242       outs() << "\t.byte " << Value;
243       Size = 1;
244     }
245     if (Kind == MachO::DICE_KIND_DATA)
246       outs() << "\t@ KIND_DATA\n";
247     else
248       outs() << "\t@ data in code kind = " << Kind << "\n";
249     break;
250   case MachO::DICE_KIND_JUMP_TABLE8:
251     if (ShowRawInsn)
252       dumpBytes(ArrayRef(bytes, 1), outs());
253     Value = bytes[0];
254     outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
255     Size = 1;
256     break;
257   case MachO::DICE_KIND_JUMP_TABLE16:
258     if (ShowRawInsn)
259       dumpBytes(ArrayRef(bytes, 2), outs());
260     Value = bytes[1] << 8 | bytes[0];
261     outs() << "\t.short " << format("%5u", Value & 0xffff)
262            << "\t@ KIND_JUMP_TABLE16\n";
263     Size = 2;
264     break;
265   case MachO::DICE_KIND_JUMP_TABLE32:
266   case MachO::DICE_KIND_ABS_JUMP_TABLE32:
267     if (ShowRawInsn)
268       dumpBytes(ArrayRef(bytes, 4), outs());
269     Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
270     outs() << "\t.long " << Value;
271     if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
272       outs() << "\t@ KIND_JUMP_TABLE32\n";
273     else
274       outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
275     Size = 4;
276     break;
277   }
278   return Size;
279 }
280 
getSectionsAndSymbols(MachOObjectFile * MachOObj,std::vector<SectionRef> & Sections,std::vector<SymbolRef> & Symbols,SmallVectorImpl<uint64_t> & FoundFns,uint64_t & BaseSegmentAddress)281 static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
282                                   std::vector<SectionRef> &Sections,
283                                   std::vector<SymbolRef> &Symbols,
284                                   SmallVectorImpl<uint64_t> &FoundFns,
285                                   uint64_t &BaseSegmentAddress) {
286   const StringRef FileName = MachOObj->getFileName();
287   for (const SymbolRef &Symbol : MachOObj->symbols()) {
288     StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
289     if (!SymName.starts_with("ltmp"))
290       Symbols.push_back(Symbol);
291   }
292 
293   append_range(Sections, MachOObj->sections());
294 
295   bool BaseSegmentAddressSet = false;
296   for (const auto &Command : MachOObj->load_commands()) {
297     if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
298       // We found a function starts segment, parse the addresses for later
299       // consumption.
300       MachO::linkedit_data_command LLC =
301           MachOObj->getLinkeditDataLoadCommand(Command);
302 
303       MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
304     } else if (Command.C.cmd == MachO::LC_SEGMENT) {
305       MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
306       StringRef SegName = SLC.segname;
307       if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
308         BaseSegmentAddressSet = true;
309         BaseSegmentAddress = SLC.vmaddr;
310       }
311     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
312       MachO::segment_command_64 SLC = MachOObj->getSegment64LoadCommand(Command);
313       StringRef SegName = SLC.segname;
314       if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
315         BaseSegmentAddressSet = true;
316         BaseSegmentAddress = SLC.vmaddr;
317       }
318     }
319   }
320 }
321 
DumpAndSkipDataInCode(uint64_t PC,const uint8_t * bytes,DiceTable & Dices,uint64_t & InstSize)322 static bool DumpAndSkipDataInCode(uint64_t PC, const uint8_t *bytes,
323                                  DiceTable &Dices, uint64_t &InstSize) {
324   // Check the data in code table here to see if this is data not an
325   // instruction to be disassembled.
326   DiceTable Dice;
327   Dice.push_back(std::make_pair(PC, DiceRef()));
328   dice_table_iterator DTI =
329       std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
330                   compareDiceTableEntries);
331   if (DTI != Dices.end()) {
332     uint16_t Length;
333     DTI->second.getLength(Length);
334     uint16_t Kind;
335     DTI->second.getKind(Kind);
336     InstSize = DumpDataInCode(bytes, Length, Kind);
337     if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
338         (PC == (DTI->first + Length - 1)) && (Length & 1))
339       InstSize++;
340     return true;
341   }
342   return false;
343 }
344 
printRelocationTargetName(const MachOObjectFile * O,const MachO::any_relocation_info & RE,raw_string_ostream & Fmt)345 static void printRelocationTargetName(const MachOObjectFile *O,
346                                       const MachO::any_relocation_info &RE,
347                                       raw_string_ostream &Fmt) {
348   // Target of a scattered relocation is an address.  In the interest of
349   // generating pretty output, scan through the symbol table looking for a
350   // symbol that aligns with that address.  If we find one, print it.
351   // Otherwise, we just print the hex address of the target.
352   const StringRef FileName = O->getFileName();
353   if (O->isRelocationScattered(RE)) {
354     uint32_t Val = O->getPlainRelocationSymbolNum(RE);
355 
356     for (const SymbolRef &Symbol : O->symbols()) {
357       uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
358       if (Addr != Val)
359         continue;
360       Fmt << unwrapOrError(Symbol.getName(), FileName);
361       return;
362     }
363 
364     // If we couldn't find a symbol that this relocation refers to, try
365     // to find a section beginning instead.
366     for (const SectionRef &Section : ToolSectionFilter(*O)) {
367       uint64_t Addr = Section.getAddress();
368       if (Addr != Val)
369         continue;
370       StringRef NameOrErr = unwrapOrError(Section.getName(), O->getFileName());
371       Fmt << NameOrErr;
372       return;
373     }
374 
375     Fmt << format("0x%x", Val);
376     return;
377   }
378 
379   StringRef S;
380   bool isExtern = O->getPlainRelocationExternal(RE);
381   uint64_t Val = O->getPlainRelocationSymbolNum(RE);
382 
383   if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND &&
384       (O->getArch() == Triple::aarch64 || O->getArch() == Triple::aarch64_be)) {
385     Fmt << format("0x%0" PRIx64, Val);
386     return;
387   }
388 
389   if (isExtern) {
390     symbol_iterator SI = O->symbol_begin();
391     std::advance(SI, Val);
392     S = unwrapOrError(SI->getName(), FileName);
393   } else {
394     section_iterator SI = O->section_begin();
395     // Adjust for the fact that sections are 1-indexed.
396     if (Val == 0) {
397       Fmt << "0 (?,?)";
398       return;
399     }
400     uint32_t I = Val - 1;
401     while (I != 0 && SI != O->section_end()) {
402       --I;
403       std::advance(SI, 1);
404     }
405     if (SI == O->section_end()) {
406       Fmt << Val << " (?,?)";
407     } else {
408       if (Expected<StringRef> NameOrErr = SI->getName())
409         S = *NameOrErr;
410       else
411         consumeError(NameOrErr.takeError());
412     }
413   }
414 
415   Fmt << S;
416 }
417 
getMachORelocationValueString(const MachOObjectFile * Obj,const RelocationRef & RelRef,SmallVectorImpl<char> & Result)418 Error objdump::getMachORelocationValueString(const MachOObjectFile *Obj,
419                                              const RelocationRef &RelRef,
420                                              SmallVectorImpl<char> &Result) {
421   DataRefImpl Rel = RelRef.getRawDataRefImpl();
422   MachO::any_relocation_info RE = Obj->getRelocation(Rel);
423 
424   unsigned Arch = Obj->getArch();
425 
426   std::string FmtBuf;
427   raw_string_ostream Fmt(FmtBuf);
428   unsigned Type = Obj->getAnyRelocationType(RE);
429   bool IsPCRel = Obj->getAnyRelocationPCRel(RE);
430 
431   // Determine any addends that should be displayed with the relocation.
432   // These require decoding the relocation type, which is triple-specific.
433 
434   // X86_64 has entirely custom relocation types.
435   if (Arch == Triple::x86_64) {
436     switch (Type) {
437     case MachO::X86_64_RELOC_GOT_LOAD:
438     case MachO::X86_64_RELOC_GOT: {
439       printRelocationTargetName(Obj, RE, Fmt);
440       Fmt << "@GOT";
441       if (IsPCRel)
442         Fmt << "PCREL";
443       break;
444     }
445     case MachO::X86_64_RELOC_SUBTRACTOR: {
446       DataRefImpl RelNext = Rel;
447       Obj->moveRelocationNext(RelNext);
448       MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
449 
450       // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
451       // X86_64_RELOC_UNSIGNED.
452       // NOTE: Scattered relocations don't exist on x86_64.
453       unsigned RType = Obj->getAnyRelocationType(RENext);
454       if (RType != MachO::X86_64_RELOC_UNSIGNED)
455         reportError(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after "
456                                         "X86_64_RELOC_SUBTRACTOR.");
457 
458       // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
459       // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
460       printRelocationTargetName(Obj, RENext, Fmt);
461       Fmt << "-";
462       printRelocationTargetName(Obj, RE, Fmt);
463       break;
464     }
465     case MachO::X86_64_RELOC_TLV:
466       printRelocationTargetName(Obj, RE, Fmt);
467       Fmt << "@TLV";
468       if (IsPCRel)
469         Fmt << "P";
470       break;
471     case MachO::X86_64_RELOC_SIGNED_1:
472       printRelocationTargetName(Obj, RE, Fmt);
473       Fmt << "-1";
474       break;
475     case MachO::X86_64_RELOC_SIGNED_2:
476       printRelocationTargetName(Obj, RE, Fmt);
477       Fmt << "-2";
478       break;
479     case MachO::X86_64_RELOC_SIGNED_4:
480       printRelocationTargetName(Obj, RE, Fmt);
481       Fmt << "-4";
482       break;
483     default:
484       printRelocationTargetName(Obj, RE, Fmt);
485       break;
486     }
487     // X86 and ARM share some relocation types in common.
488   } else if (Arch == Triple::x86 || Arch == Triple::arm ||
489              Arch == Triple::ppc) {
490     // Generic relocation types...
491     switch (Type) {
492     case MachO::GENERIC_RELOC_PAIR: // prints no info
493       return Error::success();
494     case MachO::GENERIC_RELOC_SECTDIFF: {
495       DataRefImpl RelNext = Rel;
496       Obj->moveRelocationNext(RelNext);
497       MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
498 
499       // X86 sect diff's must be followed by a relocation of type
500       // GENERIC_RELOC_PAIR.
501       unsigned RType = Obj->getAnyRelocationType(RENext);
502 
503       if (RType != MachO::GENERIC_RELOC_PAIR)
504         reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
505                                         "GENERIC_RELOC_SECTDIFF.");
506 
507       printRelocationTargetName(Obj, RE, Fmt);
508       Fmt << "-";
509       printRelocationTargetName(Obj, RENext, Fmt);
510       break;
511     }
512     }
513 
514     if (Arch == Triple::x86 || Arch == Triple::ppc) {
515       switch (Type) {
516       case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
517         DataRefImpl RelNext = Rel;
518         Obj->moveRelocationNext(RelNext);
519         MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
520 
521         // X86 sect diff's must be followed by a relocation of type
522         // GENERIC_RELOC_PAIR.
523         unsigned RType = Obj->getAnyRelocationType(RENext);
524         if (RType != MachO::GENERIC_RELOC_PAIR)
525           reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
526                                           "GENERIC_RELOC_LOCAL_SECTDIFF.");
527 
528         printRelocationTargetName(Obj, RE, Fmt);
529         Fmt << "-";
530         printRelocationTargetName(Obj, RENext, Fmt);
531         break;
532       }
533       case MachO::GENERIC_RELOC_TLV: {
534         printRelocationTargetName(Obj, RE, Fmt);
535         Fmt << "@TLV";
536         if (IsPCRel)
537           Fmt << "P";
538         break;
539       }
540       default:
541         printRelocationTargetName(Obj, RE, Fmt);
542       }
543     } else { // ARM-specific relocations
544       switch (Type) {
545       case MachO::ARM_RELOC_HALF:
546       case MachO::ARM_RELOC_HALF_SECTDIFF: {
547         // Half relocations steal a bit from the length field to encode
548         // whether this is an upper16 or a lower16 relocation.
549         bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1;
550 
551         if (isUpper)
552           Fmt << ":upper16:(";
553         else
554           Fmt << ":lower16:(";
555         printRelocationTargetName(Obj, RE, Fmt);
556 
557         DataRefImpl RelNext = Rel;
558         Obj->moveRelocationNext(RelNext);
559         MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
560 
561         // ARM half relocs must be followed by a relocation of type
562         // ARM_RELOC_PAIR.
563         unsigned RType = Obj->getAnyRelocationType(RENext);
564         if (RType != MachO::ARM_RELOC_PAIR)
565           reportError(Obj->getFileName(), "Expected ARM_RELOC_PAIR after "
566                                           "ARM_RELOC_HALF");
567 
568         // NOTE: The half of the target virtual address is stashed in the
569         // address field of the secondary relocation, but we can't reverse
570         // engineer the constant offset from it without decoding the movw/movt
571         // instruction to find the other half in its immediate field.
572 
573         // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
574         // symbol/section pointer of the follow-on relocation.
575         if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
576           Fmt << "-";
577           printRelocationTargetName(Obj, RENext, Fmt);
578         }
579 
580         Fmt << ")";
581         break;
582       }
583       default: {
584         printRelocationTargetName(Obj, RE, Fmt);
585       }
586       }
587     }
588   } else
589     printRelocationTargetName(Obj, RE, Fmt);
590 
591   Fmt.flush();
592   Result.append(FmtBuf.begin(), FmtBuf.end());
593   return Error::success();
594 }
595 
PrintIndirectSymbolTable(MachOObjectFile * O,bool verbose,uint32_t n,uint32_t count,uint32_t stride,uint64_t addr)596 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
597                                      uint32_t n, uint32_t count,
598                                      uint32_t stride, uint64_t addr) {
599   MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
600   uint32_t nindirectsyms = Dysymtab.nindirectsyms;
601   if (n > nindirectsyms)
602     outs() << " (entries start past the end of the indirect symbol "
603               "table) (reserved1 field greater than the table size)";
604   else if (n + count > nindirectsyms)
605     outs() << " (entries extends past the end of the indirect symbol "
606               "table)";
607   outs() << "\n";
608   uint32_t cputype = O->getHeader().cputype;
609   if (cputype & MachO::CPU_ARCH_ABI64)
610     outs() << "address            index";
611   else
612     outs() << "address    index";
613   if (verbose)
614     outs() << " name\n";
615   else
616     outs() << "\n";
617   for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
618     if (cputype & MachO::CPU_ARCH_ABI64)
619       outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
620     else
621       outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
622     MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
623     uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
624     if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
625       outs() << "LOCAL\n";
626       continue;
627     }
628     if (indirect_symbol ==
629         (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
630       outs() << "LOCAL ABSOLUTE\n";
631       continue;
632     }
633     if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
634       outs() << "ABSOLUTE\n";
635       continue;
636     }
637     outs() << format("%5u ", indirect_symbol);
638     if (verbose) {
639       MachO::symtab_command Symtab = O->getSymtabLoadCommand();
640       if (indirect_symbol < Symtab.nsyms) {
641         symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
642         SymbolRef Symbol = *Sym;
643         outs() << unwrapOrError(Symbol.getName(), O->getFileName());
644       } else {
645         outs() << "?";
646       }
647     }
648     outs() << "\n";
649   }
650 }
651 
PrintIndirectSymbols(MachOObjectFile * O,bool verbose)652 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
653   for (const auto &Load : O->load_commands()) {
654     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
655       MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
656       for (unsigned J = 0; J < Seg.nsects; ++J) {
657         MachO::section_64 Sec = O->getSection64(Load, J);
658         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
659         if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
660             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
661             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
662             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
663             section_type == MachO::S_SYMBOL_STUBS) {
664           uint32_t stride;
665           if (section_type == MachO::S_SYMBOL_STUBS)
666             stride = Sec.reserved2;
667           else
668             stride = 8;
669           if (stride == 0) {
670             outs() << "Can't print indirect symbols for (" << Sec.segname << ","
671                    << Sec.sectname << ") "
672                    << "(size of stubs in reserved2 field is zero)\n";
673             continue;
674           }
675           uint32_t count = Sec.size / stride;
676           outs() << "Indirect symbols for (" << Sec.segname << ","
677                  << Sec.sectname << ") " << count << " entries";
678           uint32_t n = Sec.reserved1;
679           PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
680         }
681       }
682     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
683       MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
684       for (unsigned J = 0; J < Seg.nsects; ++J) {
685         MachO::section Sec = O->getSection(Load, J);
686         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
687         if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
688             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
689             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
690             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
691             section_type == MachO::S_SYMBOL_STUBS) {
692           uint32_t stride;
693           if (section_type == MachO::S_SYMBOL_STUBS)
694             stride = Sec.reserved2;
695           else
696             stride = 4;
697           if (stride == 0) {
698             outs() << "Can't print indirect symbols for (" << Sec.segname << ","
699                    << Sec.sectname << ") "
700                    << "(size of stubs in reserved2 field is zero)\n";
701             continue;
702           }
703           uint32_t count = Sec.size / stride;
704           outs() << "Indirect symbols for (" << Sec.segname << ","
705                  << Sec.sectname << ") " << count << " entries";
706           uint32_t n = Sec.reserved1;
707           PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
708         }
709       }
710     }
711   }
712 }
713 
PrintRType(const uint64_t cputype,const unsigned r_type)714 static void PrintRType(const uint64_t cputype, const unsigned r_type) {
715   static char const *generic_r_types[] = {
716     "VANILLA ", "PAIR    ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV     ",
717     "  6 (?) ", "  7 (?) ", "  8 (?) ", "  9 (?) ", " 10 (?) ", " 11 (?) ",
718     " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
719   };
720   static char const *x86_64_r_types[] = {
721     "UNSIGND ", "SIGNED  ", "BRANCH  ", "GOT_LD  ", "GOT     ", "SUB     ",
722     "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV     ", " 10 (?) ", " 11 (?) ",
723     " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
724   };
725   static char const *arm_r_types[] = {
726     "VANILLA ", "PAIR    ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
727     "BR24    ", "T_BR22  ", "T_BR32  ", "HALF    ", "HALFDIF ",
728     " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
729   };
730   static char const *arm64_r_types[] = {
731     "UNSIGND ", "SUB     ", "BR26    ", "PAGE21  ", "PAGOF12 ",
732     "GOTLDP  ", "GOTLDPOF", "PTRTGOT ", "TLVLDP  ", "TLVLDPOF",
733     "ADDEND  ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
734   };
735 
736   if (r_type > 0xf){
737     outs() << format("%-7u", r_type) << " ";
738     return;
739   }
740   switch (cputype) {
741     case MachO::CPU_TYPE_I386:
742       outs() << generic_r_types[r_type];
743       break;
744     case MachO::CPU_TYPE_X86_64:
745       outs() << x86_64_r_types[r_type];
746       break;
747     case MachO::CPU_TYPE_ARM:
748       outs() << arm_r_types[r_type];
749       break;
750     case MachO::CPU_TYPE_ARM64:
751     case MachO::CPU_TYPE_ARM64_32:
752       outs() << arm64_r_types[r_type];
753       break;
754     default:
755       outs() << format("%-7u ", r_type);
756   }
757 }
758 
PrintRLength(const uint64_t cputype,const unsigned r_type,const unsigned r_length,const bool previous_arm_half)759 static void PrintRLength(const uint64_t cputype, const unsigned r_type,
760                          const unsigned r_length, const bool previous_arm_half){
761   if (cputype == MachO::CPU_TYPE_ARM &&
762       (r_type == MachO::ARM_RELOC_HALF ||
763        r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) {
764     if ((r_length & 0x1) == 0)
765       outs() << "lo/";
766     else
767       outs() << "hi/";
768     if ((r_length & 0x1) == 0)
769       outs() << "arm ";
770     else
771       outs() << "thm ";
772   } else {
773     switch (r_length) {
774       case 0:
775         outs() << "byte   ";
776         break;
777       case 1:
778         outs() << "word   ";
779         break;
780       case 2:
781         outs() << "long   ";
782         break;
783       case 3:
784         if (cputype == MachO::CPU_TYPE_X86_64)
785           outs() << "quad   ";
786         else
787           outs() << format("?(%2d)  ", r_length);
788         break;
789       default:
790         outs() << format("?(%2d)  ", r_length);
791     }
792   }
793 }
794 
PrintRelocationEntries(const MachOObjectFile * O,const relocation_iterator Begin,const relocation_iterator End,const uint64_t cputype,const bool verbose)795 static void PrintRelocationEntries(const MachOObjectFile *O,
796                                    const relocation_iterator Begin,
797                                    const relocation_iterator End,
798                                    const uint64_t cputype,
799                                    const bool verbose) {
800   const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
801   bool previous_arm_half = false;
802   bool previous_sectdiff = false;
803   uint32_t sectdiff_r_type = 0;
804 
805   for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
806     const DataRefImpl Rel = Reloc->getRawDataRefImpl();
807     const MachO::any_relocation_info RE = O->getRelocation(Rel);
808     const unsigned r_type = O->getAnyRelocationType(RE);
809     const bool r_scattered = O->isRelocationScattered(RE);
810     const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
811     const unsigned r_length = O->getAnyRelocationLength(RE);
812     const unsigned r_address = O->getAnyRelocationAddress(RE);
813     const bool r_extern = (r_scattered ? false :
814                            O->getPlainRelocationExternal(RE));
815     const uint32_t r_value = (r_scattered ?
816                               O->getScatteredRelocationValue(RE) : 0);
817     const unsigned r_symbolnum = (r_scattered ? 0 :
818                                   O->getPlainRelocationSymbolNum(RE));
819 
820     if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
821       if (verbose) {
822         // scattered: address
823         if ((cputype == MachO::CPU_TYPE_I386 &&
824              r_type == MachO::GENERIC_RELOC_PAIR) ||
825             (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR))
826           outs() << "         ";
827         else
828           outs() << format("%08x ", (unsigned int)r_address);
829 
830         // scattered: pcrel
831         if (r_pcrel)
832           outs() << "True  ";
833         else
834           outs() << "False ";
835 
836         // scattered: length
837         PrintRLength(cputype, r_type, r_length, previous_arm_half);
838 
839         // scattered: extern & type
840         outs() << "n/a    ";
841         PrintRType(cputype, r_type);
842 
843         // scattered: scattered & value
844         outs() << format("True      0x%08x", (unsigned int)r_value);
845         if (previous_sectdiff == false) {
846           if ((cputype == MachO::CPU_TYPE_ARM &&
847                r_type == MachO::ARM_RELOC_PAIR))
848             outs() << format(" half = 0x%04x ", (unsigned int)r_address);
849         } else if (cputype == MachO::CPU_TYPE_ARM &&
850                    sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF)
851           outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
852         if ((cputype == MachO::CPU_TYPE_I386 &&
853              (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
854               r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
855             (cputype == MachO::CPU_TYPE_ARM &&
856              (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF ||
857               sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
858               sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) {
859           previous_sectdiff = true;
860           sectdiff_r_type = r_type;
861         } else {
862           previous_sectdiff = false;
863           sectdiff_r_type = 0;
864         }
865         if (cputype == MachO::CPU_TYPE_ARM &&
866             (r_type == MachO::ARM_RELOC_HALF ||
867              r_type == MachO::ARM_RELOC_HALF_SECTDIFF))
868           previous_arm_half = true;
869         else
870           previous_arm_half = false;
871         outs() << "\n";
872       }
873       else {
874         // scattered: address pcrel length extern type scattered value
875         outs() << format("%08x %1d     %-2d     n/a    %-7d 1         0x%08x\n",
876                          (unsigned int)r_address, r_pcrel, r_length, r_type,
877                          (unsigned int)r_value);
878       }
879     }
880     else {
881       if (verbose) {
882         // plain: address
883         if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
884           outs() << "         ";
885         else
886           outs() << format("%08x ", (unsigned int)r_address);
887 
888         // plain: pcrel
889         if (r_pcrel)
890           outs() << "True  ";
891         else
892           outs() << "False ";
893 
894         // plain: length
895         PrintRLength(cputype, r_type, r_length, previous_arm_half);
896 
897         if (r_extern) {
898           // plain: extern & type & scattered
899           outs() << "True   ";
900           PrintRType(cputype, r_type);
901           outs() << "False     ";
902 
903           // plain: symbolnum/value
904           if (r_symbolnum > Symtab.nsyms)
905             outs() << format("?(%d)\n", r_symbolnum);
906           else {
907             SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
908             Expected<StringRef> SymNameNext = Symbol.getName();
909             const char *name = nullptr;
910             if (SymNameNext)
911               name = SymNameNext->data();
912             if (name == nullptr)
913               outs() << format("?(%d)\n", r_symbolnum);
914             else
915               outs() << name << "\n";
916           }
917         }
918         else {
919           // plain: extern & type & scattered
920           outs() << "False  ";
921           PrintRType(cputype, r_type);
922           outs() << "False     ";
923 
924           // plain: symbolnum/value
925           if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
926             outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
927           else if ((cputype == MachO::CPU_TYPE_ARM64 ||
928                     cputype == MachO::CPU_TYPE_ARM64_32) &&
929                    r_type == MachO::ARM64_RELOC_ADDEND)
930             outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
931           else {
932             outs() << format("%d ", r_symbolnum);
933             if (r_symbolnum == MachO::R_ABS)
934               outs() << "R_ABS\n";
935             else {
936               // in this case, r_symbolnum is actually a 1-based section number
937               uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
938               if (r_symbolnum > 0 && r_symbolnum <= nsects) {
939                 object::DataRefImpl DRI;
940                 DRI.d.a = r_symbolnum-1;
941                 StringRef SegName = O->getSectionFinalSegmentName(DRI);
942                 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
943                   outs() << "(" << SegName << "," << *NameOrErr << ")\n";
944                 else
945                   outs() << "(?,?)\n";
946               }
947               else {
948                 outs() << "(?,?)\n";
949               }
950             }
951           }
952         }
953         if (cputype == MachO::CPU_TYPE_ARM &&
954             (r_type == MachO::ARM_RELOC_HALF ||
955              r_type == MachO::ARM_RELOC_HALF_SECTDIFF))
956           previous_arm_half = true;
957         else
958           previous_arm_half = false;
959       }
960       else {
961         // plain: address pcrel length extern type scattered symbolnum/section
962         outs() << format("%08x %1d     %-2d     %1d      %-7d 0         %d\n",
963                          (unsigned int)r_address, r_pcrel, r_length, r_extern,
964                          r_type, r_symbolnum);
965       }
966     }
967   }
968 }
969 
PrintRelocations(const MachOObjectFile * O,const bool verbose)970 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
971   const uint64_t cputype = O->getHeader().cputype;
972   const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
973   if (Dysymtab.nextrel != 0) {
974     outs() << "External relocation information " << Dysymtab.nextrel
975            << " entries";
976     outs() << "\naddress  pcrel length extern type    scattered "
977               "symbolnum/value\n";
978     PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
979                            verbose);
980   }
981   if (Dysymtab.nlocrel != 0) {
982     outs() << format("Local relocation information %u entries",
983                      Dysymtab.nlocrel);
984     outs() << "\naddress  pcrel length extern type    scattered "
985               "symbolnum/value\n";
986     PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
987                            verbose);
988   }
989   for (const auto &Load : O->load_commands()) {
990     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
991       const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
992       for (unsigned J = 0; J < Seg.nsects; ++J) {
993         const MachO::section_64 Sec = O->getSection64(Load, J);
994         if (Sec.nreloc != 0) {
995           DataRefImpl DRI;
996           DRI.d.a = J;
997           const StringRef SegName = O->getSectionFinalSegmentName(DRI);
998           if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
999             outs() << "Relocation information (" << SegName << "," << *NameOrErr
1000                    << format(") %u entries", Sec.nreloc);
1001           else
1002             outs() << "Relocation information (" << SegName << ",?) "
1003                    << format("%u entries", Sec.nreloc);
1004           outs() << "\naddress  pcrel length extern type    scattered "
1005                     "symbolnum/value\n";
1006           PrintRelocationEntries(O, O->section_rel_begin(DRI),
1007                                  O->section_rel_end(DRI), cputype, verbose);
1008         }
1009       }
1010     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1011       const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
1012       for (unsigned J = 0; J < Seg.nsects; ++J) {
1013         const MachO::section Sec = O->getSection(Load, J);
1014         if (Sec.nreloc != 0) {
1015           DataRefImpl DRI;
1016           DRI.d.a = J;
1017           const StringRef SegName = O->getSectionFinalSegmentName(DRI);
1018           if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
1019             outs() << "Relocation information (" << SegName << "," << *NameOrErr
1020                    << format(") %u entries", Sec.nreloc);
1021           else
1022             outs() << "Relocation information (" << SegName << ",?) "
1023                    << format("%u entries", Sec.nreloc);
1024           outs() << "\naddress  pcrel length extern type    scattered "
1025                     "symbolnum/value\n";
1026           PrintRelocationEntries(O, O->section_rel_begin(DRI),
1027                                  O->section_rel_end(DRI), cputype, verbose);
1028         }
1029       }
1030     }
1031   }
1032 }
1033 
PrintFunctionStarts(MachOObjectFile * O)1034 static void PrintFunctionStarts(MachOObjectFile *O) {
1035   uint64_t BaseSegmentAddress = 0;
1036   for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
1037     if (Command.C.cmd == MachO::LC_SEGMENT) {
1038       MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
1039       if (StringRef(SLC.segname) == "__TEXT") {
1040         BaseSegmentAddress = SLC.vmaddr;
1041         break;
1042       }
1043     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1044       MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
1045       if (StringRef(SLC.segname) == "__TEXT") {
1046         BaseSegmentAddress = SLC.vmaddr;
1047         break;
1048       }
1049     }
1050   }
1051 
1052   SmallVector<uint64_t, 8> FunctionStarts;
1053   for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) {
1054     if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) {
1055       MachO::linkedit_data_command FunctionStartsLC =
1056           O->getLinkeditDataLoadCommand(LC);
1057       O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts);
1058       break;
1059     }
1060   }
1061 
1062   DenseMap<uint64_t, StringRef> SymbolNames;
1063   if (FunctionStartsType == FunctionStartsMode::Names ||
1064       FunctionStartsType == FunctionStartsMode::Both) {
1065     for (SymbolRef Sym : O->symbols()) {
1066       if (Expected<uint64_t> Addr = Sym.getAddress()) {
1067         if (Expected<StringRef> Name = Sym.getName()) {
1068           SymbolNames[*Addr] = *Name;
1069         }
1070       }
1071     }
1072   }
1073 
1074   for (uint64_t S : FunctionStarts) {
1075     uint64_t Addr = BaseSegmentAddress + S;
1076     if (FunctionStartsType == FunctionStartsMode::Names) {
1077       auto It = SymbolNames.find(Addr);
1078       if (It != SymbolNames.end())
1079         outs() << It->second << "\n";
1080     } else {
1081       if (O->is64Bit())
1082         outs() << format("%016" PRIx64, Addr);
1083       else
1084         outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr));
1085 
1086       if (FunctionStartsType == FunctionStartsMode::Both) {
1087         auto It = SymbolNames.find(Addr);
1088         if (It != SymbolNames.end())
1089           outs() << " " << It->second;
1090         else
1091           outs() << " ?";
1092       }
1093       outs() << "\n";
1094     }
1095   }
1096 }
1097 
PrintDataInCodeTable(MachOObjectFile * O,bool verbose)1098 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
1099   MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
1100   uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
1101   outs() << "Data in code table (" << nentries << " entries)\n";
1102   outs() << "offset     length kind\n";
1103   for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
1104        ++DI) {
1105     uint32_t Offset;
1106     DI->getOffset(Offset);
1107     outs() << format("0x%08" PRIx32, Offset) << " ";
1108     uint16_t Length;
1109     DI->getLength(Length);
1110     outs() << format("%6u", Length) << " ";
1111     uint16_t Kind;
1112     DI->getKind(Kind);
1113     if (verbose) {
1114       switch (Kind) {
1115       case MachO::DICE_KIND_DATA:
1116         outs() << "DATA";
1117         break;
1118       case MachO::DICE_KIND_JUMP_TABLE8:
1119         outs() << "JUMP_TABLE8";
1120         break;
1121       case MachO::DICE_KIND_JUMP_TABLE16:
1122         outs() << "JUMP_TABLE16";
1123         break;
1124       case MachO::DICE_KIND_JUMP_TABLE32:
1125         outs() << "JUMP_TABLE32";
1126         break;
1127       case MachO::DICE_KIND_ABS_JUMP_TABLE32:
1128         outs() << "ABS_JUMP_TABLE32";
1129         break;
1130       default:
1131         outs() << format("0x%04" PRIx32, Kind);
1132         break;
1133       }
1134     } else
1135       outs() << format("0x%04" PRIx32, Kind);
1136     outs() << "\n";
1137   }
1138 }
1139 
PrintLinkOptHints(MachOObjectFile * O)1140 static void PrintLinkOptHints(MachOObjectFile *O) {
1141   MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
1142   const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
1143   uint32_t nloh = LohLC.datasize;
1144   outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
1145   for (uint32_t i = 0; i < nloh;) {
1146     unsigned n;
1147     uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
1148     i += n;
1149     outs() << "    identifier " << identifier << " ";
1150     if (i >= nloh)
1151       return;
1152     switch (identifier) {
1153     case 1:
1154       outs() << "AdrpAdrp\n";
1155       break;
1156     case 2:
1157       outs() << "AdrpLdr\n";
1158       break;
1159     case 3:
1160       outs() << "AdrpAddLdr\n";
1161       break;
1162     case 4:
1163       outs() << "AdrpLdrGotLdr\n";
1164       break;
1165     case 5:
1166       outs() << "AdrpAddStr\n";
1167       break;
1168     case 6:
1169       outs() << "AdrpLdrGotStr\n";
1170       break;
1171     case 7:
1172       outs() << "AdrpAdd\n";
1173       break;
1174     case 8:
1175       outs() << "AdrpLdrGot\n";
1176       break;
1177     default:
1178       outs() << "Unknown identifier value\n";
1179       break;
1180     }
1181     uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
1182     i += n;
1183     outs() << "    narguments " << narguments << "\n";
1184     if (i >= nloh)
1185       return;
1186 
1187     for (uint32_t j = 0; j < narguments; j++) {
1188       uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
1189       i += n;
1190       outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
1191       if (i >= nloh)
1192         return;
1193     }
1194   }
1195 }
1196 
GetSegmentNames(object::MachOObjectFile * O)1197 static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) {
1198   SmallVector<std::string> Ret;
1199   for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
1200     if (Command.C.cmd == MachO::LC_SEGMENT) {
1201       MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
1202       Ret.push_back(SLC.segname);
1203     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1204       MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
1205       Ret.push_back(SLC.segname);
1206     }
1207   }
1208   return Ret;
1209 }
1210 
1211 static void
PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header & H)1212 PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) {
1213   outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n";
1214   outs() << "  fixups_version = " << H.fixups_version << '\n';
1215   outs() << "  starts_offset  = " << H.starts_offset << '\n';
1216   outs() << "  imports_offset = " << H.imports_offset << '\n';
1217   outs() << "  symbols_offset = " << H.symbols_offset << '\n';
1218   outs() << "  imports_count  = " << H.imports_count << '\n';
1219 
1220   outs() << "  imports_format = " << H.imports_format;
1221   switch (H.imports_format) {
1222   case llvm::MachO::DYLD_CHAINED_IMPORT:
1223     outs() << " (DYLD_CHAINED_IMPORT)";
1224     break;
1225   case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND:
1226     outs() << " (DYLD_CHAINED_IMPORT_ADDEND)";
1227     break;
1228   case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND64:
1229     outs() << " (DYLD_CHAINED_IMPORT_ADDEND64)";
1230     break;
1231   }
1232   outs() << '\n';
1233 
1234   outs() << "  symbols_format = " << H.symbols_format;
1235   if (H.symbols_format == llvm::MachO::DYLD_CHAINED_SYMBOL_ZLIB)
1236     outs() << " (zlib compressed)";
1237   outs() << '\n';
1238 }
1239 
1240 static constexpr std::array<StringRef, 13> PointerFormats{
1241     "DYLD_CHAINED_PTR_ARM64E",
1242     "DYLD_CHAINED_PTR_64",
1243     "DYLD_CHAINED_PTR_32",
1244     "DYLD_CHAINED_PTR_32_CACHE",
1245     "DYLD_CHAINED_PTR_32_FIRMWARE",
1246     "DYLD_CHAINED_PTR_64_OFFSET",
1247     "DYLD_CHAINED_PTR_ARM64E_KERNEL",
1248     "DYLD_CHAINED_PTR_64_KERNEL_CACHE",
1249     "DYLD_CHAINED_PTR_ARM64E_USERLAND",
1250     "DYLD_CHAINED_PTR_ARM64E_FIRMWARE",
1251     "DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE",
1252     "DYLD_CHAINED_PTR_ARM64E_USERLAND24",
1253 };
1254 
PrintChainedFixupsSegment(const ChainedFixupsSegment & Segment,StringRef SegName)1255 static void PrintChainedFixupsSegment(const ChainedFixupsSegment &Segment,
1256                                       StringRef SegName) {
1257   outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName
1258          << ")\n";
1259   outs() << "  size = " << Segment.Header.size << '\n';
1260   outs() << "  page_size = " << format("0x%0" PRIx16, Segment.Header.page_size)
1261          << '\n';
1262 
1263   outs() << "  pointer_format = " << Segment.Header.pointer_format;
1264   if ((Segment.Header.pointer_format - 1) <
1265       MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24)
1266     outs() << " (" << PointerFormats[Segment.Header.pointer_format - 1] << ")";
1267   outs() << '\n';
1268 
1269   outs() << "  segment_offset = "
1270          << format("0x%0" PRIx64, Segment.Header.segment_offset) << '\n';
1271   outs() << "  max_valid_pointer = " << Segment.Header.max_valid_pointer
1272          << '\n';
1273   outs() << "  page_count = " << Segment.Header.page_count << '\n';
1274   for (auto [Index, PageStart] : enumerate(Segment.PageStarts)) {
1275     outs() << "    page_start[" << Index << "] = " << PageStart;
1276     // FIXME: Support DYLD_CHAINED_PTR_START_MULTI (32-bit only)
1277     if (PageStart == MachO::DYLD_CHAINED_PTR_START_NONE)
1278       outs() << " (DYLD_CHAINED_PTR_START_NONE)";
1279     outs() << '\n';
1280   }
1281 }
1282 
PrintChainedFixupTarget(ChainedFixupTarget & Target,size_t Idx,int Format,MachOObjectFile * O)1283 static void PrintChainedFixupTarget(ChainedFixupTarget &Target, size_t Idx,
1284                                     int Format, MachOObjectFile *O) {
1285   if (Format == MachO::DYLD_CHAINED_IMPORT)
1286     outs() << "dyld chained import";
1287   else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND)
1288     outs() << "dyld chained import addend";
1289   else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)
1290     outs() << "dyld chained import addend64";
1291   // FIXME: otool prints the encoded value as well.
1292   outs() << '[' << Idx << "]\n";
1293 
1294   outs() << "  lib_ordinal = " << Target.libOrdinal() << " ("
1295          << ordinalName(O, Target.libOrdinal()) << ")\n";
1296   outs() << "  weak_import = " << Target.weakImport() << '\n';
1297   outs() << "  name_offset = " << Target.nameOffset() << " ("
1298          << Target.symbolName() << ")\n";
1299   if (Format != MachO::DYLD_CHAINED_IMPORT)
1300     outs() << "  addend      = " << (int64_t)Target.addend() << '\n';
1301 }
1302 
PrintChainedFixups(MachOObjectFile * O)1303 static void PrintChainedFixups(MachOObjectFile *O) {
1304   // MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS.
1305   // FIXME: Support chained fixups in __TEXT,__chain_starts section too.
1306   auto ChainedFixupHeader =
1307       unwrapOrError(O->getChainedFixupsHeader(), O->getFileName());
1308   if (!ChainedFixupHeader)
1309     return;
1310 
1311   PrintChainedFixupsHeader(*ChainedFixupHeader);
1312 
1313   auto [SegCount, Segments] =
1314       unwrapOrError(O->getChainedFixupsSegments(), O->getFileName());
1315 
1316   auto SegNames = GetSegmentNames(O);
1317 
1318   size_t StartsIdx = 0;
1319   outs() << "chained starts in image\n";
1320   outs() << "  seg_count = " << SegCount << '\n';
1321   for (size_t I = 0; I < SegCount; ++I) {
1322     uint64_t SegOffset = 0;
1323     if (StartsIdx < Segments.size() && I == Segments[StartsIdx].SegIdx) {
1324       SegOffset = Segments[StartsIdx].Offset;
1325       ++StartsIdx;
1326     }
1327 
1328     outs() << "    seg_offset[" << I << "] = " << SegOffset << " ("
1329            << SegNames[I] << ")\n";
1330   }
1331 
1332   for (const ChainedFixupsSegment &S : Segments)
1333     PrintChainedFixupsSegment(S, SegNames[S.SegIdx]);
1334 
1335   auto FixupTargets =
1336       unwrapOrError(O->getDyldChainedFixupTargets(), O->getFileName());
1337 
1338   uint32_t ImportsFormat = ChainedFixupHeader->imports_format;
1339   for (auto [Idx, Target] : enumerate(FixupTargets))
1340     PrintChainedFixupTarget(Target, Idx, ImportsFormat, O);
1341 }
1342 
PrintDyldInfo(MachOObjectFile * O)1343 static void PrintDyldInfo(MachOObjectFile *O) {
1344   Error Err = Error::success();
1345 
1346   size_t SegmentWidth = strlen("segment");
1347   size_t SectionWidth = strlen("section");
1348   size_t AddressWidth = strlen("address");
1349   size_t AddendWidth = strlen("addend");
1350   size_t DylibWidth = strlen("dylib");
1351   const size_t PointerWidth = 2 + O->getBytesInAddress() * 2;
1352 
1353   auto HexLength = [](uint64_t Num) {
1354     return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1;
1355   };
1356   for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
1357     SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size());
1358     SectionWidth = std::max(SectionWidth, Entry.sectionName().size());
1359     AddressWidth = std::max(AddressWidth, HexLength(Entry.address()) + 2);
1360     if (Entry.isBind()) {
1361       AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2);
1362       DylibWidth = std::max(DylibWidth, Entry.symbolName().size());
1363     }
1364   }
1365   // Errors will be handled when printing the table.
1366   if (Err)
1367     consumeError(std::move(Err));
1368 
1369   outs() << "dyld information:\n";
1370   outs() << left_justify("segment", SegmentWidth) << ' '
1371          << left_justify("section", SectionWidth) << ' '
1372          << left_justify("address", AddressWidth) << ' '
1373          << left_justify("pointer", PointerWidth) << " type   "
1374          << left_justify("addend", AddendWidth) << ' '
1375          << left_justify("dylib", DylibWidth) << " symbol/vm address\n";
1376   for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
1377     outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' '
1378            << left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x"
1379            << left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' '
1380            << format_hex(Entry.rawValue(), PointerWidth, true) << ' ';
1381     if (Entry.isBind()) {
1382       outs() << "bind   "
1383              << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2)
1384              << ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth)
1385              << ' ' << Entry.symbolName();
1386       if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
1387         outs() << " (weak import)";
1388       outs() << '\n';
1389     } else {
1390       assert(Entry.isRebase());
1391       outs() << "rebase";
1392       outs().indent(AddendWidth + DylibWidth + 2);
1393       outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n';
1394     }
1395   }
1396   if (Err)
1397     reportError(std::move(Err), O->getFileName());
1398 
1399   // TODO: Print opcode-based fixups if the object uses those.
1400 }
1401 
PrintDylibs(MachOObjectFile * O,bool JustId)1402 static void PrintDylibs(MachOObjectFile *O, bool JustId) {
1403   unsigned Index = 0;
1404   for (const auto &Load : O->load_commands()) {
1405     if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
1406         (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
1407                      Load.C.cmd == MachO::LC_LOAD_DYLIB ||
1408                      Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
1409                      Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
1410                      Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
1411                      Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
1412       MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
1413       if (dl.dylib.name < dl.cmdsize) {
1414         const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
1415         if (JustId)
1416           outs() << p << "\n";
1417         else {
1418           outs() << "\t" << p;
1419           outs() << " (compatibility version "
1420                  << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
1421                  << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
1422                  << (dl.dylib.compatibility_version & 0xff) << ",";
1423           outs() << " current version "
1424                  << ((dl.dylib.current_version >> 16) & 0xffff) << "."
1425                  << ((dl.dylib.current_version >> 8) & 0xff) << "."
1426                  << (dl.dylib.current_version & 0xff);
1427           if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
1428             outs() << ", weak";
1429           if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
1430             outs() << ", reexport";
1431           if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
1432             outs() << ", upward";
1433           if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
1434             outs() << ", lazy";
1435           outs() << ")\n";
1436         }
1437       } else {
1438         outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
1439         if (Load.C.cmd == MachO::LC_ID_DYLIB)
1440           outs() << "LC_ID_DYLIB ";
1441         else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
1442           outs() << "LC_LOAD_DYLIB ";
1443         else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
1444           outs() << "LC_LOAD_WEAK_DYLIB ";
1445         else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
1446           outs() << "LC_LAZY_LOAD_DYLIB ";
1447         else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
1448           outs() << "LC_REEXPORT_DYLIB ";
1449         else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
1450           outs() << "LC_LOAD_UPWARD_DYLIB ";
1451         else
1452           outs() << "LC_??? ";
1453         outs() << "command " << Index++ << "\n";
1454       }
1455     }
1456   }
1457 }
1458 
printRpaths(MachOObjectFile * O)1459 static void printRpaths(MachOObjectFile *O) {
1460   for (const auto &Command : O->load_commands()) {
1461     if (Command.C.cmd == MachO::LC_RPATH) {
1462       auto Rpath = O->getRpathCommand(Command);
1463       const char *P = (const char *)(Command.Ptr) + Rpath.path;
1464       outs() << P << "\n";
1465     }
1466   }
1467 }
1468 
1469 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
1470 
CreateSymbolAddressMap(MachOObjectFile * O,SymbolAddressMap * AddrMap)1471 static void CreateSymbolAddressMap(MachOObjectFile *O,
1472                                    SymbolAddressMap *AddrMap) {
1473   // Create a map of symbol addresses to symbol names.
1474   const StringRef FileName = O->getFileName();
1475   for (const SymbolRef &Symbol : O->symbols()) {
1476     SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName);
1477     if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
1478         ST == SymbolRef::ST_Other) {
1479       uint64_t Address = cantFail(Symbol.getValue());
1480       StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
1481       if (!SymName.starts_with(".objc"))
1482         (*AddrMap)[Address] = SymName;
1483     }
1484   }
1485 }
1486 
1487 // GuessSymbolName is passed the address of what might be a symbol and a
1488 // pointer to the SymbolAddressMap.  It returns the name of a symbol
1489 // with that address or nullptr if no symbol is found with that address.
GuessSymbolName(uint64_t value,SymbolAddressMap * AddrMap)1490 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
1491   const char *SymbolName = nullptr;
1492   // A DenseMap can't lookup up some values.
1493   if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
1494     StringRef name = AddrMap->lookup(value);
1495     if (!name.empty())
1496       SymbolName = name.data();
1497   }
1498   return SymbolName;
1499 }
1500 
DumpCstringChar(const char c)1501 static void DumpCstringChar(const char c) {
1502   char p[2];
1503   p[0] = c;
1504   p[1] = '\0';
1505   outs().write_escaped(p);
1506 }
1507 
DumpCstringSection(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1508 static void DumpCstringSection(MachOObjectFile *O, const char *sect,
1509                                uint32_t sect_size, uint64_t sect_addr,
1510                                bool print_addresses) {
1511   for (uint32_t i = 0; i < sect_size; i++) {
1512     if (print_addresses) {
1513       if (O->is64Bit())
1514         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1515       else
1516         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1517     }
1518     for (; i < sect_size && sect[i] != '\0'; i++)
1519       DumpCstringChar(sect[i]);
1520     if (i < sect_size && sect[i] == '\0')
1521       outs() << "\n";
1522   }
1523 }
1524 
DumpLiteral4(uint32_t l,float f)1525 static void DumpLiteral4(uint32_t l, float f) {
1526   outs() << format("0x%08" PRIx32, l);
1527   if ((l & 0x7f800000) != 0x7f800000)
1528     outs() << format(" (%.16e)\n", f);
1529   else {
1530     if (l == 0x7f800000)
1531       outs() << " (+Infinity)\n";
1532     else if (l == 0xff800000)
1533       outs() << " (-Infinity)\n";
1534     else if ((l & 0x00400000) == 0x00400000)
1535       outs() << " (non-signaling Not-a-Number)\n";
1536     else
1537       outs() << " (signaling Not-a-Number)\n";
1538   }
1539 }
1540 
DumpLiteral4Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1541 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
1542                                 uint32_t sect_size, uint64_t sect_addr,
1543                                 bool print_addresses) {
1544   for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
1545     if (print_addresses) {
1546       if (O->is64Bit())
1547         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1548       else
1549         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1550     }
1551     float f;
1552     memcpy(&f, sect + i, sizeof(float));
1553     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1554       sys::swapByteOrder(f);
1555     uint32_t l;
1556     memcpy(&l, sect + i, sizeof(uint32_t));
1557     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1558       sys::swapByteOrder(l);
1559     DumpLiteral4(l, f);
1560   }
1561 }
1562 
DumpLiteral8(MachOObjectFile * O,uint32_t l0,uint32_t l1,double d)1563 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
1564                          double d) {
1565   outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
1566   uint32_t Hi, Lo;
1567   Hi = (O->isLittleEndian()) ? l1 : l0;
1568   Lo = (O->isLittleEndian()) ? l0 : l1;
1569 
1570   // Hi is the high word, so this is equivalent to if(isfinite(d))
1571   if ((Hi & 0x7ff00000) != 0x7ff00000)
1572     outs() << format(" (%.16e)\n", d);
1573   else {
1574     if (Hi == 0x7ff00000 && Lo == 0)
1575       outs() << " (+Infinity)\n";
1576     else if (Hi == 0xfff00000 && Lo == 0)
1577       outs() << " (-Infinity)\n";
1578     else if ((Hi & 0x00080000) == 0x00080000)
1579       outs() << " (non-signaling Not-a-Number)\n";
1580     else
1581       outs() << " (signaling Not-a-Number)\n";
1582   }
1583 }
1584 
DumpLiteral8Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1585 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
1586                                 uint32_t sect_size, uint64_t sect_addr,
1587                                 bool print_addresses) {
1588   for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
1589     if (print_addresses) {
1590       if (O->is64Bit())
1591         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1592       else
1593         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1594     }
1595     double d;
1596     memcpy(&d, sect + i, sizeof(double));
1597     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1598       sys::swapByteOrder(d);
1599     uint32_t l0, l1;
1600     memcpy(&l0, sect + i, sizeof(uint32_t));
1601     memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1602     if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1603       sys::swapByteOrder(l0);
1604       sys::swapByteOrder(l1);
1605     }
1606     DumpLiteral8(O, l0, l1, d);
1607   }
1608 }
1609 
DumpLiteral16(uint32_t l0,uint32_t l1,uint32_t l2,uint32_t l3)1610 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
1611   outs() << format("0x%08" PRIx32, l0) << " ";
1612   outs() << format("0x%08" PRIx32, l1) << " ";
1613   outs() << format("0x%08" PRIx32, l2) << " ";
1614   outs() << format("0x%08" PRIx32, l3) << "\n";
1615 }
1616 
DumpLiteral16Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1617 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
1618                                  uint32_t sect_size, uint64_t sect_addr,
1619                                  bool print_addresses) {
1620   for (uint32_t i = 0; i < sect_size; i += 16) {
1621     if (print_addresses) {
1622       if (O->is64Bit())
1623         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1624       else
1625         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1626     }
1627     uint32_t l0, l1, l2, l3;
1628     memcpy(&l0, sect + i, sizeof(uint32_t));
1629     memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1630     memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
1631     memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
1632     if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1633       sys::swapByteOrder(l0);
1634       sys::swapByteOrder(l1);
1635       sys::swapByteOrder(l2);
1636       sys::swapByteOrder(l3);
1637     }
1638     DumpLiteral16(l0, l1, l2, l3);
1639   }
1640 }
1641 
DumpLiteralPointerSection(MachOObjectFile * O,const SectionRef & Section,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1642 static void DumpLiteralPointerSection(MachOObjectFile *O,
1643                                       const SectionRef &Section,
1644                                       const char *sect, uint32_t sect_size,
1645                                       uint64_t sect_addr,
1646                                       bool print_addresses) {
1647   // Collect the literal sections in this Mach-O file.
1648   std::vector<SectionRef> LiteralSections;
1649   for (const SectionRef &Section : O->sections()) {
1650     DataRefImpl Ref = Section.getRawDataRefImpl();
1651     uint32_t section_type;
1652     if (O->is64Bit()) {
1653       const MachO::section_64 Sec = O->getSection64(Ref);
1654       section_type = Sec.flags & MachO::SECTION_TYPE;
1655     } else {
1656       const MachO::section Sec = O->getSection(Ref);
1657       section_type = Sec.flags & MachO::SECTION_TYPE;
1658     }
1659     if (section_type == MachO::S_CSTRING_LITERALS ||
1660         section_type == MachO::S_4BYTE_LITERALS ||
1661         section_type == MachO::S_8BYTE_LITERALS ||
1662         section_type == MachO::S_16BYTE_LITERALS)
1663       LiteralSections.push_back(Section);
1664   }
1665 
1666   // Set the size of the literal pointer.
1667   uint32_t lp_size = O->is64Bit() ? 8 : 4;
1668 
1669   // Collect the external relocation symbols for the literal pointers.
1670   std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1671   for (const RelocationRef &Reloc : Section.relocations()) {
1672     DataRefImpl Rel;
1673     MachO::any_relocation_info RE;
1674     bool isExtern = false;
1675     Rel = Reloc.getRawDataRefImpl();
1676     RE = O->getRelocation(Rel);
1677     isExtern = O->getPlainRelocationExternal(RE);
1678     if (isExtern) {
1679       uint64_t RelocOffset = Reloc.getOffset();
1680       symbol_iterator RelocSym = Reloc.getSymbol();
1681       Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1682     }
1683   }
1684   array_pod_sort(Relocs.begin(), Relocs.end());
1685 
1686   // Dump each literal pointer.
1687   for (uint32_t i = 0; i < sect_size; i += lp_size) {
1688     if (print_addresses) {
1689       if (O->is64Bit())
1690         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1691       else
1692         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1693     }
1694     uint64_t lp;
1695     if (O->is64Bit()) {
1696       memcpy(&lp, sect + i, sizeof(uint64_t));
1697       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1698         sys::swapByteOrder(lp);
1699     } else {
1700       uint32_t li;
1701       memcpy(&li, sect + i, sizeof(uint32_t));
1702       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1703         sys::swapByteOrder(li);
1704       lp = li;
1705     }
1706 
1707     // First look for an external relocation entry for this literal pointer.
1708     auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1709       return P.first == i;
1710     });
1711     if (Reloc != Relocs.end()) {
1712       symbol_iterator RelocSym = Reloc->second;
1713       StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName());
1714       outs() << "external relocation entry for symbol:" << SymName << "\n";
1715       continue;
1716     }
1717 
1718     // For local references see what the section the literal pointer points to.
1719     auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
1720       return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
1721     });
1722     if (Sect == LiteralSections.end()) {
1723       outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
1724       continue;
1725     }
1726 
1727     uint64_t SectAddress = Sect->getAddress();
1728     uint64_t SectSize = Sect->getSize();
1729 
1730     StringRef SectName;
1731     Expected<StringRef> SectNameOrErr = Sect->getName();
1732     if (SectNameOrErr)
1733       SectName = *SectNameOrErr;
1734     else
1735       consumeError(SectNameOrErr.takeError());
1736 
1737     DataRefImpl Ref = Sect->getRawDataRefImpl();
1738     StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
1739     outs() << SegmentName << ":" << SectName << ":";
1740 
1741     uint32_t section_type;
1742     if (O->is64Bit()) {
1743       const MachO::section_64 Sec = O->getSection64(Ref);
1744       section_type = Sec.flags & MachO::SECTION_TYPE;
1745     } else {
1746       const MachO::section Sec = O->getSection(Ref);
1747       section_type = Sec.flags & MachO::SECTION_TYPE;
1748     }
1749 
1750     StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName());
1751 
1752     const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
1753 
1754     switch (section_type) {
1755     case MachO::S_CSTRING_LITERALS:
1756       for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
1757            i++) {
1758         DumpCstringChar(Contents[i]);
1759       }
1760       outs() << "\n";
1761       break;
1762     case MachO::S_4BYTE_LITERALS:
1763       float f;
1764       memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
1765       uint32_t l;
1766       memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
1767       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1768         sys::swapByteOrder(f);
1769         sys::swapByteOrder(l);
1770       }
1771       DumpLiteral4(l, f);
1772       break;
1773     case MachO::S_8BYTE_LITERALS: {
1774       double d;
1775       memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
1776       uint32_t l0, l1;
1777       memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1778       memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1779              sizeof(uint32_t));
1780       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1781         sys::swapByteOrder(f);
1782         sys::swapByteOrder(l0);
1783         sys::swapByteOrder(l1);
1784       }
1785       DumpLiteral8(O, l0, l1, d);
1786       break;
1787     }
1788     case MachO::S_16BYTE_LITERALS: {
1789       uint32_t l0, l1, l2, l3;
1790       memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1791       memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1792              sizeof(uint32_t));
1793       memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
1794              sizeof(uint32_t));
1795       memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
1796              sizeof(uint32_t));
1797       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1798         sys::swapByteOrder(l0);
1799         sys::swapByteOrder(l1);
1800         sys::swapByteOrder(l2);
1801         sys::swapByteOrder(l3);
1802       }
1803       DumpLiteral16(l0, l1, l2, l3);
1804       break;
1805     }
1806     }
1807   }
1808 }
1809 
DumpInitTermPointerSection(MachOObjectFile * O,const SectionRef & Section,const char * sect,uint32_t sect_size,uint64_t sect_addr,SymbolAddressMap * AddrMap,bool verbose)1810 static void DumpInitTermPointerSection(MachOObjectFile *O,
1811                                        const SectionRef &Section,
1812                                        const char *sect,
1813                                        uint32_t sect_size, uint64_t sect_addr,
1814                                        SymbolAddressMap *AddrMap,
1815                                        bool verbose) {
1816   uint32_t stride;
1817   stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
1818 
1819   // Collect the external relocation symbols for the pointers.
1820   std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1821   for (const RelocationRef &Reloc : Section.relocations()) {
1822     DataRefImpl Rel;
1823     MachO::any_relocation_info RE;
1824     bool isExtern = false;
1825     Rel = Reloc.getRawDataRefImpl();
1826     RE = O->getRelocation(Rel);
1827     isExtern = O->getPlainRelocationExternal(RE);
1828     if (isExtern) {
1829       uint64_t RelocOffset = Reloc.getOffset();
1830       symbol_iterator RelocSym = Reloc.getSymbol();
1831       Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1832     }
1833   }
1834   array_pod_sort(Relocs.begin(), Relocs.end());
1835 
1836   for (uint32_t i = 0; i < sect_size; i += stride) {
1837     const char *SymbolName = nullptr;
1838     uint64_t p;
1839     if (O->is64Bit()) {
1840       outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
1841       uint64_t pointer_value;
1842       memcpy(&pointer_value, sect + i, stride);
1843       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1844         sys::swapByteOrder(pointer_value);
1845       outs() << format("0x%016" PRIx64, pointer_value);
1846       p = pointer_value;
1847     } else {
1848       outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
1849       uint32_t pointer_value;
1850       memcpy(&pointer_value, sect + i, stride);
1851       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1852         sys::swapByteOrder(pointer_value);
1853       outs() << format("0x%08" PRIx32, pointer_value);
1854       p = pointer_value;
1855     }
1856     if (verbose) {
1857       // First look for an external relocation entry for this pointer.
1858       auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1859         return P.first == i;
1860       });
1861       if (Reloc != Relocs.end()) {
1862         symbol_iterator RelocSym = Reloc->second;
1863         outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName());
1864       } else {
1865         SymbolName = GuessSymbolName(p, AddrMap);
1866         if (SymbolName)
1867           outs() << " " << SymbolName;
1868       }
1869     }
1870     outs() << "\n";
1871   }
1872 }
1873 
DumpRawSectionContents(MachOObjectFile * O,const char * sect,uint32_t size,uint64_t addr)1874 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1875                                    uint32_t size, uint64_t addr) {
1876   uint32_t cputype = O->getHeader().cputype;
1877   if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1878     uint32_t j;
1879     for (uint32_t i = 0; i < size; i += j, addr += j) {
1880       if (O->is64Bit())
1881         outs() << format("%016" PRIx64, addr) << "\t";
1882       else
1883         outs() << format("%08" PRIx64, addr) << "\t";
1884       for (j = 0; j < 16 && i + j < size; j++) {
1885         uint8_t byte_word = *(sect + i + j);
1886         outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1887       }
1888       outs() << "\n";
1889     }
1890   } else {
1891     uint32_t j;
1892     for (uint32_t i = 0; i < size; i += j, addr += j) {
1893       if (O->is64Bit())
1894         outs() << format("%016" PRIx64, addr) << "\t";
1895       else
1896         outs() << format("%08" PRIx64, addr) << "\t";
1897       for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1898            j += sizeof(int32_t)) {
1899         if (i + j + sizeof(int32_t) <= size) {
1900           uint32_t long_word;
1901           memcpy(&long_word, sect + i + j, sizeof(int32_t));
1902           if (O->isLittleEndian() != sys::IsLittleEndianHost)
1903             sys::swapByteOrder(long_word);
1904           outs() << format("%08" PRIx32, long_word) << " ";
1905         } else {
1906           for (uint32_t k = 0; i + j + k < size; k++) {
1907             uint8_t byte_word = *(sect + i + j + k);
1908             outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1909           }
1910         }
1911       }
1912       outs() << "\n";
1913     }
1914   }
1915 }
1916 
1917 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1918                              StringRef DisSegName, StringRef DisSectName);
1919 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1920                                 uint32_t size, uint32_t addr);
DumpSectionContents(StringRef Filename,MachOObjectFile * O,bool verbose)1921 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1922                                 bool verbose) {
1923   SymbolAddressMap AddrMap;
1924   if (verbose)
1925     CreateSymbolAddressMap(O, &AddrMap);
1926 
1927   for (unsigned i = 0; i < FilterSections.size(); ++i) {
1928     StringRef DumpSection = FilterSections[i];
1929     std::pair<StringRef, StringRef> DumpSegSectName;
1930     DumpSegSectName = DumpSection.split(',');
1931     StringRef DumpSegName, DumpSectName;
1932     if (!DumpSegSectName.second.empty()) {
1933       DumpSegName = DumpSegSectName.first;
1934       DumpSectName = DumpSegSectName.second;
1935     } else {
1936       DumpSegName = "";
1937       DumpSectName = DumpSegSectName.first;
1938     }
1939     for (const SectionRef &Section : O->sections()) {
1940       StringRef SectName;
1941       Expected<StringRef> SecNameOrErr = Section.getName();
1942       if (SecNameOrErr)
1943         SectName = *SecNameOrErr;
1944       else
1945         consumeError(SecNameOrErr.takeError());
1946 
1947       if (!DumpSection.empty())
1948         FoundSectionSet.insert(DumpSection);
1949 
1950       DataRefImpl Ref = Section.getRawDataRefImpl();
1951       StringRef SegName = O->getSectionFinalSegmentName(Ref);
1952       if ((DumpSegName.empty() || SegName == DumpSegName) &&
1953           (SectName == DumpSectName)) {
1954 
1955         uint32_t section_flags;
1956         if (O->is64Bit()) {
1957           const MachO::section_64 Sec = O->getSection64(Ref);
1958           section_flags = Sec.flags;
1959 
1960         } else {
1961           const MachO::section Sec = O->getSection(Ref);
1962           section_flags = Sec.flags;
1963         }
1964         uint32_t section_type = section_flags & MachO::SECTION_TYPE;
1965 
1966         StringRef BytesStr =
1967             unwrapOrError(Section.getContents(), O->getFileName());
1968         const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1969         uint32_t sect_size = BytesStr.size();
1970         uint64_t sect_addr = Section.getAddress();
1971 
1972         if (LeadingHeaders)
1973           outs() << "Contents of (" << SegName << "," << SectName
1974                  << ") section\n";
1975 
1976         if (verbose) {
1977           if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
1978               (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
1979             DisassembleMachO(Filename, O, SegName, SectName);
1980             continue;
1981           }
1982           if (SegName == "__TEXT" && SectName == "__info_plist") {
1983             outs() << sect;
1984             continue;
1985           }
1986           if (SegName == "__OBJC" && SectName == "__protocol") {
1987             DumpProtocolSection(O, sect, sect_size, sect_addr);
1988             continue;
1989           }
1990           switch (section_type) {
1991           case MachO::S_REGULAR:
1992             DumpRawSectionContents(O, sect, sect_size, sect_addr);
1993             break;
1994           case MachO::S_ZEROFILL:
1995             outs() << "zerofill section and has no contents in the file\n";
1996             break;
1997           case MachO::S_CSTRING_LITERALS:
1998             DumpCstringSection(O, sect, sect_size, sect_addr, LeadingAddr);
1999             break;
2000           case MachO::S_4BYTE_LITERALS:
2001             DumpLiteral4Section(O, sect, sect_size, sect_addr, LeadingAddr);
2002             break;
2003           case MachO::S_8BYTE_LITERALS:
2004             DumpLiteral8Section(O, sect, sect_size, sect_addr, LeadingAddr);
2005             break;
2006           case MachO::S_16BYTE_LITERALS:
2007             DumpLiteral16Section(O, sect, sect_size, sect_addr, LeadingAddr);
2008             break;
2009           case MachO::S_LITERAL_POINTERS:
2010             DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
2011                                       LeadingAddr);
2012             break;
2013           case MachO::S_MOD_INIT_FUNC_POINTERS:
2014           case MachO::S_MOD_TERM_FUNC_POINTERS:
2015             DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
2016                                        &AddrMap, verbose);
2017             break;
2018           default:
2019             outs() << "Unknown section type ("
2020                    << format("0x%08" PRIx32, section_type) << ")\n";
2021             DumpRawSectionContents(O, sect, sect_size, sect_addr);
2022             break;
2023           }
2024         } else {
2025           if (section_type == MachO::S_ZEROFILL)
2026             outs() << "zerofill section and has no contents in the file\n";
2027           else
2028             DumpRawSectionContents(O, sect, sect_size, sect_addr);
2029         }
2030       }
2031     }
2032   }
2033 }
2034 
DumpInfoPlistSectionContents(StringRef Filename,MachOObjectFile * O)2035 static void DumpInfoPlistSectionContents(StringRef Filename,
2036                                          MachOObjectFile *O) {
2037   for (const SectionRef &Section : O->sections()) {
2038     StringRef SectName;
2039     Expected<StringRef> SecNameOrErr = Section.getName();
2040     if (SecNameOrErr)
2041       SectName = *SecNameOrErr;
2042     else
2043       consumeError(SecNameOrErr.takeError());
2044 
2045     DataRefImpl Ref = Section.getRawDataRefImpl();
2046     StringRef SegName = O->getSectionFinalSegmentName(Ref);
2047     if (SegName == "__TEXT" && SectName == "__info_plist") {
2048       if (LeadingHeaders)
2049         outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
2050       StringRef BytesStr =
2051           unwrapOrError(Section.getContents(), O->getFileName());
2052       const char *sect = reinterpret_cast<const char *>(BytesStr.data());
2053       outs() << format("%.*s", BytesStr.size(), sect) << "\n";
2054       return;
2055     }
2056   }
2057 }
2058 
2059 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
2060 // and if it is and there is a list of architecture flags is specified then
2061 // check to make sure this Mach-O file is one of those architectures or all
2062 // architectures were specified.  If not then an error is generated and this
2063 // routine returns false.  Else it returns true.
checkMachOAndArchFlags(ObjectFile * O,StringRef Filename)2064 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
2065   auto *MachO = dyn_cast<MachOObjectFile>(O);
2066 
2067   if (!MachO || ArchAll || ArchFlags.empty())
2068     return true;
2069 
2070   MachO::mach_header H;
2071   MachO::mach_header_64 H_64;
2072   Triple T;
2073   const char *McpuDefault, *ArchFlag;
2074   if (MachO->is64Bit()) {
2075     H_64 = MachO->MachOObjectFile::getHeader64();
2076     T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
2077                                        &McpuDefault, &ArchFlag);
2078   } else {
2079     H = MachO->MachOObjectFile::getHeader();
2080     T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
2081                                        &McpuDefault, &ArchFlag);
2082   }
2083   const std::string ArchFlagName(ArchFlag);
2084   if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
2085     WithColor::error(errs(), "llvm-objdump")
2086         << Filename << ": no architecture specified.\n";
2087     return false;
2088   }
2089   return true;
2090 }
2091 
2092 static void printObjcMetaData(MachOObjectFile *O, bool verbose);
2093 
2094 // ProcessMachO() is passed a single opened Mach-O file, which may be an
2095 // archive member and or in a slice of a universal file.  It prints the
2096 // the file name and header info and then processes it according to the
2097 // command line options.
ProcessMachO(StringRef Name,MachOObjectFile * MachOOF,StringRef ArchiveMemberName=StringRef (),StringRef ArchitectureName=StringRef ())2098 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
2099                          StringRef ArchiveMemberName = StringRef(),
2100                          StringRef ArchitectureName = StringRef()) {
2101   std::unique_ptr<Dumper> D = createMachODumper(*MachOOF);
2102 
2103   // If we are doing some processing here on the Mach-O file print the header
2104   // info.  And don't print it otherwise like in the case of printing the
2105   // UniversalHeaders or ArchiveHeaders.
2106   if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
2107       Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
2108       DataInCode || FunctionStartsType != FunctionStartsMode::None ||
2109       LinkOptHints || ChainedFixups || DyldInfo || DylibsUsed || DylibId ||
2110       Rpaths || ObjcMetaData || (!FilterSections.empty())) {
2111     if (LeadingHeaders) {
2112       outs() << Name;
2113       if (!ArchiveMemberName.empty())
2114         outs() << '(' << ArchiveMemberName << ')';
2115       if (!ArchitectureName.empty())
2116         outs() << " (architecture " << ArchitectureName << ")";
2117       outs() << ":\n";
2118     }
2119   }
2120   // To use the report_error() form with an ArchiveName and FileName set
2121   // these up based on what is passed for Name and ArchiveMemberName.
2122   StringRef ArchiveName;
2123   StringRef FileName;
2124   if (!ArchiveMemberName.empty()) {
2125     ArchiveName = Name;
2126     FileName = ArchiveMemberName;
2127   } else {
2128     ArchiveName = StringRef();
2129     FileName = Name;
2130   }
2131 
2132   // If we need the symbol table to do the operation then check it here to
2133   // produce a good error message as to where the Mach-O file comes from in
2134   // the error message.
2135   if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo)
2136     if (Error Err = MachOOF->checkSymbolTable())
2137       reportError(std::move(Err), FileName, ArchiveName, ArchitectureName);
2138 
2139   if (DisassembleAll) {
2140     for (const SectionRef &Section : MachOOF->sections()) {
2141       StringRef SectName;
2142       if (Expected<StringRef> NameOrErr = Section.getName())
2143         SectName = *NameOrErr;
2144       else
2145         consumeError(NameOrErr.takeError());
2146 
2147       if (SectName == "__text") {
2148         DataRefImpl Ref = Section.getRawDataRefImpl();
2149         StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref);
2150         DisassembleMachO(FileName, MachOOF, SegName, SectName);
2151       }
2152     }
2153   }
2154   else if (Disassemble) {
2155     if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE &&
2156         MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64)
2157       DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text");
2158     else
2159       DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
2160   }
2161   if (IndirectSymbols)
2162     PrintIndirectSymbols(MachOOF, Verbose);
2163   if (DataInCode)
2164     PrintDataInCodeTable(MachOOF, Verbose);
2165   if (FunctionStartsType != FunctionStartsMode::None)
2166     PrintFunctionStarts(MachOOF);
2167   if (LinkOptHints)
2168     PrintLinkOptHints(MachOOF);
2169   if (Relocations)
2170     PrintRelocations(MachOOF, Verbose);
2171   if (SectionHeaders)
2172     printSectionHeaders(*MachOOF);
2173   if (SectionContents)
2174     printSectionContents(MachOOF);
2175   if (!FilterSections.empty())
2176     DumpSectionContents(FileName, MachOOF, Verbose);
2177   if (InfoPlist)
2178     DumpInfoPlistSectionContents(FileName, MachOOF);
2179   if (DyldInfo)
2180     PrintDyldInfo(MachOOF);
2181   if (ChainedFixups)
2182     PrintChainedFixups(MachOOF);
2183   if (DylibsUsed)
2184     PrintDylibs(MachOOF, false);
2185   if (DylibId)
2186     PrintDylibs(MachOOF, true);
2187   if (SymbolTable)
2188     D->printSymbolTable(ArchiveName, ArchitectureName);
2189   if (UnwindInfo)
2190     printMachOUnwindInfo(MachOOF);
2191   if (PrivateHeaders) {
2192     printMachOFileHeader(MachOOF);
2193     printMachOLoadCommands(MachOOF);
2194   }
2195   if (FirstPrivateHeader)
2196     printMachOFileHeader(MachOOF);
2197   if (ObjcMetaData)
2198     printObjcMetaData(MachOOF, Verbose);
2199   if (ExportsTrie)
2200     printExportsTrie(MachOOF);
2201   if (Rebase)
2202     printRebaseTable(MachOOF);
2203   if (Rpaths)
2204     printRpaths(MachOOF);
2205   if (Bind)
2206     printBindTable(MachOOF);
2207   if (LazyBind)
2208     printLazyBindTable(MachOOF);
2209   if (WeakBind)
2210     printWeakBindTable(MachOOF);
2211 
2212   if (DwarfDumpType != DIDT_Null) {
2213     std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
2214     // Dump the complete DWARF structure.
2215     DIDumpOptions DumpOpts;
2216     DumpOpts.DumpType = DwarfDumpType;
2217     DICtx->dump(outs(), DumpOpts);
2218   }
2219 }
2220 
2221 // printUnknownCPUType() helps print_fat_headers for unknown CPU's.
printUnknownCPUType(uint32_t cputype,uint32_t cpusubtype)2222 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
2223   outs() << "    cputype (" << cputype << ")\n";
2224   outs() << "    cpusubtype (" << cpusubtype << ")\n";
2225 }
2226 
2227 // printCPUType() helps print_fat_headers by printing the cputype and
2228 // pusubtype (symbolically for the one's it knows about).
printCPUType(uint32_t cputype,uint32_t cpusubtype)2229 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
2230   switch (cputype) {
2231   case MachO::CPU_TYPE_I386:
2232     switch (cpusubtype) {
2233     case MachO::CPU_SUBTYPE_I386_ALL:
2234       outs() << "    cputype CPU_TYPE_I386\n";
2235       outs() << "    cpusubtype CPU_SUBTYPE_I386_ALL\n";
2236       break;
2237     default:
2238       printUnknownCPUType(cputype, cpusubtype);
2239       break;
2240     }
2241     break;
2242   case MachO::CPU_TYPE_X86_64:
2243     switch (cpusubtype) {
2244     case MachO::CPU_SUBTYPE_X86_64_ALL:
2245       outs() << "    cputype CPU_TYPE_X86_64\n";
2246       outs() << "    cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
2247       break;
2248     case MachO::CPU_SUBTYPE_X86_64_H:
2249       outs() << "    cputype CPU_TYPE_X86_64\n";
2250       outs() << "    cpusubtype CPU_SUBTYPE_X86_64_H\n";
2251       break;
2252     default:
2253       printUnknownCPUType(cputype, cpusubtype);
2254       break;
2255     }
2256     break;
2257   case MachO::CPU_TYPE_ARM:
2258     switch (cpusubtype) {
2259     case MachO::CPU_SUBTYPE_ARM_ALL:
2260       outs() << "    cputype CPU_TYPE_ARM\n";
2261       outs() << "    cpusubtype CPU_SUBTYPE_ARM_ALL\n";
2262       break;
2263     case MachO::CPU_SUBTYPE_ARM_V4T:
2264       outs() << "    cputype CPU_TYPE_ARM\n";
2265       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V4T\n";
2266       break;
2267     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2268       outs() << "    cputype CPU_TYPE_ARM\n";
2269       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
2270       break;
2271     case MachO::CPU_SUBTYPE_ARM_XSCALE:
2272       outs() << "    cputype CPU_TYPE_ARM\n";
2273       outs() << "    cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
2274       break;
2275     case MachO::CPU_SUBTYPE_ARM_V6:
2276       outs() << "    cputype CPU_TYPE_ARM\n";
2277       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6\n";
2278       break;
2279     case MachO::CPU_SUBTYPE_ARM_V6M:
2280       outs() << "    cputype CPU_TYPE_ARM\n";
2281       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6M\n";
2282       break;
2283     case MachO::CPU_SUBTYPE_ARM_V7:
2284       outs() << "    cputype CPU_TYPE_ARM\n";
2285       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7\n";
2286       break;
2287     case MachO::CPU_SUBTYPE_ARM_V7EM:
2288       outs() << "    cputype CPU_TYPE_ARM\n";
2289       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
2290       break;
2291     case MachO::CPU_SUBTYPE_ARM_V7K:
2292       outs() << "    cputype CPU_TYPE_ARM\n";
2293       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7K\n";
2294       break;
2295     case MachO::CPU_SUBTYPE_ARM_V7M:
2296       outs() << "    cputype CPU_TYPE_ARM\n";
2297       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7M\n";
2298       break;
2299     case MachO::CPU_SUBTYPE_ARM_V7S:
2300       outs() << "    cputype CPU_TYPE_ARM\n";
2301       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7S\n";
2302       break;
2303     default:
2304       printUnknownCPUType(cputype, cpusubtype);
2305       break;
2306     }
2307     break;
2308   case MachO::CPU_TYPE_ARM64:
2309     switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
2310     case MachO::CPU_SUBTYPE_ARM64_ALL:
2311       outs() << "    cputype CPU_TYPE_ARM64\n";
2312       outs() << "    cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
2313       break;
2314     case MachO::CPU_SUBTYPE_ARM64_V8:
2315       outs() << "    cputype CPU_TYPE_ARM64\n";
2316       outs() << "    cpusubtype CPU_SUBTYPE_ARM64_V8\n";
2317       break;
2318     case MachO::CPU_SUBTYPE_ARM64E:
2319       outs() << "    cputype CPU_TYPE_ARM64\n";
2320       outs() << "    cpusubtype CPU_SUBTYPE_ARM64E\n";
2321       break;
2322     default:
2323       printUnknownCPUType(cputype, cpusubtype);
2324       break;
2325     }
2326     break;
2327   case MachO::CPU_TYPE_ARM64_32:
2328     switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
2329     case MachO::CPU_SUBTYPE_ARM64_32_V8:
2330       outs() << "    cputype CPU_TYPE_ARM64_32\n";
2331       outs() << "    cpusubtype CPU_SUBTYPE_ARM64_32_V8\n";
2332       break;
2333     default:
2334       printUnknownCPUType(cputype, cpusubtype);
2335       break;
2336     }
2337     break;
2338   default:
2339     printUnknownCPUType(cputype, cpusubtype);
2340     break;
2341   }
2342 }
2343 
printMachOUniversalHeaders(const object::MachOUniversalBinary * UB,bool verbose)2344 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
2345                                        bool verbose) {
2346   outs() << "Fat headers\n";
2347   if (verbose) {
2348     if (UB->getMagic() == MachO::FAT_MAGIC)
2349       outs() << "fat_magic FAT_MAGIC\n";
2350     else // UB->getMagic() == MachO::FAT_MAGIC_64
2351       outs() << "fat_magic FAT_MAGIC_64\n";
2352   } else
2353     outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
2354 
2355   uint32_t nfat_arch = UB->getNumberOfObjects();
2356   StringRef Buf = UB->getData();
2357   uint64_t size = Buf.size();
2358   uint64_t big_size = sizeof(struct MachO::fat_header) +
2359                       nfat_arch * sizeof(struct MachO::fat_arch);
2360   outs() << "nfat_arch " << UB->getNumberOfObjects();
2361   if (nfat_arch == 0)
2362     outs() << " (malformed, contains zero architecture types)\n";
2363   else if (big_size > size)
2364     outs() << " (malformed, architectures past end of file)\n";
2365   else
2366     outs() << "\n";
2367 
2368   for (uint32_t i = 0; i < nfat_arch; ++i) {
2369     MachOUniversalBinary::ObjectForArch OFA(UB, i);
2370     uint32_t cputype = OFA.getCPUType();
2371     uint32_t cpusubtype = OFA.getCPUSubType();
2372     outs() << "architecture ";
2373     for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
2374       MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
2375       uint32_t other_cputype = other_OFA.getCPUType();
2376       uint32_t other_cpusubtype = other_OFA.getCPUSubType();
2377       if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
2378           (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
2379               (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
2380         outs() << "(illegal duplicate architecture) ";
2381         break;
2382       }
2383     }
2384     if (verbose) {
2385       outs() << OFA.getArchFlagName() << "\n";
2386       printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
2387     } else {
2388       outs() << i << "\n";
2389       outs() << "    cputype " << cputype << "\n";
2390       outs() << "    cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
2391              << "\n";
2392     }
2393     if (verbose && cputype == MachO::CPU_TYPE_ARM64 &&
2394         MachO::CPU_SUBTYPE_ARM64E_IS_VERSIONED_PTRAUTH_ABI(cpusubtype)) {
2395       outs() << "    capabilities CPU_SUBTYPE_ARM64E_";
2396       if (MachO::CPU_SUBTYPE_ARM64E_IS_KERNEL_PTRAUTH_ABI(cpusubtype))
2397         outs() << "KERNEL_";
2398       outs() << format("PTRAUTH_VERSION %d",
2399                        MachO::CPU_SUBTYPE_ARM64E_PTRAUTH_VERSION(cpusubtype))
2400              << "\n";
2401     } else if (verbose && (cpusubtype & MachO::CPU_SUBTYPE_MASK) ==
2402                               MachO::CPU_SUBTYPE_LIB64)
2403       outs() << "    capabilities CPU_SUBTYPE_LIB64\n";
2404     else
2405       outs() << "    capabilities "
2406              << format("0x%" PRIx32,
2407                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
2408     outs() << "    offset " << OFA.getOffset();
2409     if (OFA.getOffset() > size)
2410       outs() << " (past end of file)";
2411     if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0)
2412       outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
2413     outs() << "\n";
2414     outs() << "    size " << OFA.getSize();
2415     big_size = OFA.getOffset() + OFA.getSize();
2416     if (big_size > size)
2417       outs() << " (past end of file)";
2418     outs() << "\n";
2419     outs() << "    align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
2420            << ")\n";
2421   }
2422 }
2423 
printArchiveChild(StringRef Filename,const Archive::Child & C,size_t ChildIndex,bool verbose,bool print_offset,StringRef ArchitectureName=StringRef ())2424 static void printArchiveChild(StringRef Filename, const Archive::Child &C,
2425                               size_t ChildIndex, bool verbose,
2426                               bool print_offset,
2427                               StringRef ArchitectureName = StringRef()) {
2428   if (print_offset)
2429     outs() << C.getChildOffset() << "\t";
2430   sys::fs::perms Mode =
2431       unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex),
2432                     Filename, ArchitectureName);
2433   if (verbose) {
2434     // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
2435     // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
2436     outs() << "-";
2437     outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
2438     outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
2439     outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
2440     outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
2441     outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
2442     outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
2443     outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
2444     outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
2445     outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
2446   } else {
2447     outs() << format("0%o ", Mode);
2448   }
2449 
2450   outs() << format("%3d/%-3d %5" PRId64 " ",
2451                    unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex),
2452                                  Filename, ArchitectureName),
2453                    unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex),
2454                                  Filename, ArchitectureName),
2455                    unwrapOrError(C.getRawSize(),
2456                                  getFileNameForError(C, ChildIndex), Filename,
2457                                  ArchitectureName));
2458 
2459   StringRef RawLastModified = C.getRawLastModified();
2460   if (verbose) {
2461     unsigned Seconds;
2462     if (RawLastModified.getAsInteger(10, Seconds))
2463       outs() << "(date: \"" << RawLastModified
2464              << "\" contains non-decimal chars) ";
2465     else {
2466       // Since cime(3) returns a 26 character string of the form:
2467       // "Sun Sep 16 01:03:52 1973\n\0"
2468       // just print 24 characters.
2469       time_t t = Seconds;
2470       outs() << format("%.24s ", ctime(&t));
2471     }
2472   } else {
2473     outs() << RawLastModified << " ";
2474   }
2475 
2476   if (verbose) {
2477     Expected<StringRef> NameOrErr = C.getName();
2478     if (!NameOrErr) {
2479       consumeError(NameOrErr.takeError());
2480       outs() << unwrapOrError(C.getRawName(),
2481                               getFileNameForError(C, ChildIndex), Filename,
2482                               ArchitectureName)
2483              << "\n";
2484     } else {
2485       StringRef Name = NameOrErr.get();
2486       outs() << Name << "\n";
2487     }
2488   } else {
2489     outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex),
2490                             Filename, ArchitectureName)
2491            << "\n";
2492   }
2493 }
2494 
printArchiveHeaders(StringRef Filename,Archive * A,bool verbose,bool print_offset,StringRef ArchitectureName=StringRef ())2495 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
2496                                 bool print_offset,
2497                                 StringRef ArchitectureName = StringRef()) {
2498   Error Err = Error::success();
2499   size_t I = 0;
2500   for (const auto &C : A->children(Err, false))
2501     printArchiveChild(Filename, C, I++, verbose, print_offset,
2502                       ArchitectureName);
2503 
2504   if (Err)
2505     reportError(std::move(Err), Filename, "", ArchitectureName);
2506 }
2507 
ValidateArchFlags()2508 static bool ValidateArchFlags() {
2509   // Check for -arch all and verifiy the -arch flags are valid.
2510   for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2511     if (ArchFlags[i] == "all") {
2512       ArchAll = true;
2513     } else {
2514       if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
2515         WithColor::error(errs(), "llvm-objdump")
2516             << "unknown architecture named '" + ArchFlags[i] +
2517                    "'for the -arch option\n";
2518         return false;
2519       }
2520     }
2521   }
2522   return true;
2523 }
2524 
2525 // ParseInputMachO() parses the named Mach-O file in Filename and handles the
2526 // -arch flags selecting just those slices as specified by them and also parses
2527 // archive files.  Then for each individual Mach-O file ProcessMachO() is
2528 // called to process the file based on the command line options.
parseInputMachO(StringRef Filename)2529 void objdump::parseInputMachO(StringRef Filename) {
2530   if (!ValidateArchFlags())
2531     return;
2532 
2533   // Attempt to open the binary.
2534   Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
2535   if (!BinaryOrErr) {
2536     if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
2537       reportError(std::move(E), Filename);
2538     else
2539       outs() << Filename << ": is not an object file\n";
2540     return;
2541   }
2542   Binary &Bin = *BinaryOrErr.get().getBinary();
2543 
2544   if (Archive *A = dyn_cast<Archive>(&Bin)) {
2545     outs() << "Archive : " << Filename << "\n";
2546     if (ArchiveHeaders)
2547       printArchiveHeaders(Filename, A, Verbose, ArchiveMemberOffsets);
2548 
2549     Error Err = Error::success();
2550     unsigned I = -1;
2551     for (auto &C : A->children(Err)) {
2552       ++I;
2553       Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2554       if (!ChildOrErr) {
2555         if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2556           reportError(std::move(E), getFileNameForError(C, I), Filename);
2557         continue;
2558       }
2559       if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2560         if (!checkMachOAndArchFlags(O, Filename))
2561           return;
2562         ProcessMachO(Filename, O, O->getFileName());
2563       }
2564     }
2565     if (Err)
2566       reportError(std::move(Err), Filename);
2567     return;
2568   }
2569   if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
2570     parseInputMachO(UB);
2571     return;
2572   }
2573   if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
2574     if (!checkMachOAndArchFlags(O, Filename))
2575       return;
2576     if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O))
2577       ProcessMachO(Filename, MachOOF);
2578     else
2579       WithColor::error(errs(), "llvm-objdump")
2580           << Filename << "': "
2581           << "object is not a Mach-O file type.\n";
2582     return;
2583   }
2584   llvm_unreachable("Input object can't be invalid at this point");
2585 }
2586 
parseInputMachO(MachOUniversalBinary * UB)2587 void objdump::parseInputMachO(MachOUniversalBinary *UB) {
2588   if (!ValidateArchFlags())
2589     return;
2590 
2591   auto Filename = UB->getFileName();
2592 
2593   if (UniversalHeaders)
2594     printMachOUniversalHeaders(UB, Verbose);
2595 
2596   // If we have a list of architecture flags specified dump only those.
2597   if (!ArchAll && !ArchFlags.empty()) {
2598     // Look for a slice in the universal binary that matches each ArchFlag.
2599     bool ArchFound;
2600     for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2601       ArchFound = false;
2602       for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2603                                                   E = UB->end_objects();
2604             I != E; ++I) {
2605         if (ArchFlags[i] == I->getArchFlagName()) {
2606           ArchFound = true;
2607           Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
2608               I->getAsObjectFile();
2609           std::string ArchitectureName;
2610           if (ArchFlags.size() > 1)
2611             ArchitectureName = I->getArchFlagName();
2612           if (ObjOrErr) {
2613             ObjectFile &O = *ObjOrErr.get();
2614             if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2615               ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2616           } else if (Error E = isNotObjectErrorInvalidFileType(
2617                          ObjOrErr.takeError())) {
2618             reportError(std::move(E), "", Filename, ArchitectureName);
2619             continue;
2620           } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2621                          I->getAsArchive()) {
2622             std::unique_ptr<Archive> &A = *AOrErr;
2623             outs() << "Archive : " << Filename;
2624             if (!ArchitectureName.empty())
2625               outs() << " (architecture " << ArchitectureName << ")";
2626             outs() << "\n";
2627             if (ArchiveHeaders)
2628               printArchiveHeaders(Filename, A.get(), Verbose,
2629                                   ArchiveMemberOffsets, ArchitectureName);
2630             Error Err = Error::success();
2631             unsigned I = -1;
2632             for (auto &C : A->children(Err)) {
2633               ++I;
2634               Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2635               if (!ChildOrErr) {
2636                 if (Error E =
2637                         isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2638                   reportError(std::move(E), getFileNameForError(C, I), Filename,
2639                               ArchitectureName);
2640                 continue;
2641               }
2642               if (MachOObjectFile *O =
2643                       dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2644                 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
2645             }
2646             if (Err)
2647               reportError(std::move(Err), Filename);
2648           } else {
2649             consumeError(AOrErr.takeError());
2650             reportError(Filename,
2651                         "Mach-O universal file for architecture " +
2652                             StringRef(I->getArchFlagName()) +
2653                             " is not a Mach-O file or an archive file");
2654           }
2655         }
2656       }
2657       if (!ArchFound) {
2658         WithColor::error(errs(), "llvm-objdump")
2659             << "file: " + Filename + " does not contain "
2660             << "architecture: " + ArchFlags[i] + "\n";
2661         return;
2662       }
2663     }
2664     return;
2665   }
2666   // No architecture flags were specified so if this contains a slice that
2667   // matches the host architecture dump only that.
2668   if (!ArchAll) {
2669     for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2670                                                 E = UB->end_objects();
2671           I != E; ++I) {
2672       if (MachOObjectFile::getHostArch().getArchName() ==
2673           I->getArchFlagName()) {
2674         Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2675         std::string ArchiveName;
2676         ArchiveName.clear();
2677         if (ObjOrErr) {
2678           ObjectFile &O = *ObjOrErr.get();
2679           if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2680             ProcessMachO(Filename, MachOOF);
2681         } else if (Error E =
2682                        isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2683           reportError(std::move(E), Filename);
2684         } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2685                        I->getAsArchive()) {
2686           std::unique_ptr<Archive> &A = *AOrErr;
2687           outs() << "Archive : " << Filename << "\n";
2688           if (ArchiveHeaders)
2689             printArchiveHeaders(Filename, A.get(), Verbose,
2690                                 ArchiveMemberOffsets);
2691           Error Err = Error::success();
2692           unsigned I = -1;
2693           for (auto &C : A->children(Err)) {
2694             ++I;
2695             Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2696             if (!ChildOrErr) {
2697               if (Error E =
2698                       isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2699                 reportError(std::move(E), getFileNameForError(C, I), Filename);
2700               continue;
2701             }
2702             if (MachOObjectFile *O =
2703                     dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2704               ProcessMachO(Filename, O, O->getFileName());
2705           }
2706           if (Err)
2707             reportError(std::move(Err), Filename);
2708         } else {
2709           consumeError(AOrErr.takeError());
2710           reportError(Filename, "Mach-O universal file for architecture " +
2711                                     StringRef(I->getArchFlagName()) +
2712                                     " is not a Mach-O file or an archive file");
2713         }
2714         return;
2715       }
2716     }
2717   }
2718   // Either all architectures have been specified or none have been specified
2719   // and this does not contain the host architecture so dump all the slices.
2720   bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2721   for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2722                                               E = UB->end_objects();
2723         I != E; ++I) {
2724     Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2725     std::string ArchitectureName;
2726     if (moreThanOneArch)
2727       ArchitectureName = I->getArchFlagName();
2728     if (ObjOrErr) {
2729       ObjectFile &Obj = *ObjOrErr.get();
2730       if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
2731         ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2732     } else if (Error E =
2733                    isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2734       reportError(std::move(E), Filename, "", ArchitectureName);
2735     } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2736       std::unique_ptr<Archive> &A = *AOrErr;
2737       outs() << "Archive : " << Filename;
2738       if (!ArchitectureName.empty())
2739         outs() << " (architecture " << ArchitectureName << ")";
2740       outs() << "\n";
2741       if (ArchiveHeaders)
2742         printArchiveHeaders(Filename, A.get(), Verbose, ArchiveMemberOffsets,
2743                             ArchitectureName);
2744       Error Err = Error::success();
2745       unsigned I = -1;
2746       for (auto &C : A->children(Err)) {
2747         ++I;
2748         Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2749         if (!ChildOrErr) {
2750           if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2751             reportError(std::move(E), getFileNameForError(C, I), Filename,
2752                         ArchitectureName);
2753           continue;
2754         }
2755         if (MachOObjectFile *O =
2756                 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2757           if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
2758             ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
2759                           ArchitectureName);
2760         }
2761       }
2762       if (Err)
2763         reportError(std::move(Err), Filename);
2764     } else {
2765       consumeError(AOrErr.takeError());
2766       reportError(Filename, "Mach-O universal file for architecture " +
2767                                 StringRef(I->getArchFlagName()) +
2768                                 " is not a Mach-O file or an archive file");
2769     }
2770   }
2771 }
2772 
2773 namespace {
2774 // The block of info used by the Symbolizer call backs.
2775 struct DisassembleInfo {
DisassembleInfo__anon061faff00611::DisassembleInfo2776   DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
2777                   std::vector<SectionRef> *Sections, bool verbose)
2778     : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
2779   bool verbose;
2780   MachOObjectFile *O;
2781   SectionRef S;
2782   SymbolAddressMap *AddrMap;
2783   std::vector<SectionRef> *Sections;
2784   const char *class_name = nullptr;
2785   const char *selector_name = nullptr;
2786   std::unique_ptr<char[]> method = nullptr;
2787   char *demangled_name = nullptr;
2788   uint64_t adrp_addr = 0;
2789   uint32_t adrp_inst = 0;
2790   std::unique_ptr<SymbolAddressMap> bindtable;
2791   uint32_t depth = 0;
2792 };
2793 } // namespace
2794 
2795 // SymbolizerGetOpInfo() is the operand information call back function.
2796 // This is called to get the symbolic information for operand(s) of an
2797 // instruction when it is being done.  This routine does this from
2798 // the relocation information, symbol table, etc. That block of information
2799 // is a pointer to the struct DisassembleInfo that was passed when the
2800 // disassembler context was created and passed to back to here when
2801 // called back by the disassembler for instruction operands that could have
2802 // relocation information. The address of the instruction containing operand is
2803 // at the Pc parameter.  The immediate value the operand has is passed in
2804 // op_info->Value and is at Offset past the start of the instruction and has a
2805 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
2806 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
2807 // names and addends of the symbolic expression to add for the operand.  The
2808 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
2809 // 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)2810 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
2811                                uint64_t OpSize, uint64_t InstSize, int TagType,
2812                                void *TagBuf) {
2813   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
2814   struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
2815   uint64_t value = op_info->Value;
2816 
2817   // Make sure all fields returned are zero if we don't set them.
2818   memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
2819   op_info->Value = value;
2820 
2821   // If the TagType is not the value 1 which it code knows about or if no
2822   // verbose symbolic information is wanted then just return 0, indicating no
2823   // information is being returned.
2824   if (TagType != 1 || !info->verbose)
2825     return 0;
2826 
2827   unsigned int Arch = info->O->getArch();
2828   if (Arch == Triple::x86) {
2829     if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0)
2830       return 0;
2831     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2832       // TODO:
2833       // Search the external relocation entries of a fully linked image
2834       // (if any) for an entry that matches this segment offset.
2835       // uint32_t seg_offset = (Pc + Offset);
2836       return 0;
2837     }
2838     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2839     // for an entry for this section offset.
2840     uint32_t sect_addr = info->S.getAddress();
2841     uint32_t sect_offset = (Pc + Offset) - sect_addr;
2842     bool reloc_found = false;
2843     DataRefImpl Rel;
2844     MachO::any_relocation_info RE;
2845     bool isExtern = false;
2846     SymbolRef Symbol;
2847     bool r_scattered = false;
2848     uint32_t r_value, pair_r_value, r_type;
2849     for (const RelocationRef &Reloc : info->S.relocations()) {
2850       uint64_t RelocOffset = Reloc.getOffset();
2851       if (RelocOffset == sect_offset) {
2852         Rel = Reloc.getRawDataRefImpl();
2853         RE = info->O->getRelocation(Rel);
2854         r_type = info->O->getAnyRelocationType(RE);
2855         r_scattered = info->O->isRelocationScattered(RE);
2856         if (r_scattered) {
2857           r_value = info->O->getScatteredRelocationValue(RE);
2858           if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2859               r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
2860             DataRefImpl RelNext = Rel;
2861             info->O->moveRelocationNext(RelNext);
2862             MachO::any_relocation_info RENext;
2863             RENext = info->O->getRelocation(RelNext);
2864             if (info->O->isRelocationScattered(RENext))
2865               pair_r_value = info->O->getScatteredRelocationValue(RENext);
2866             else
2867               return 0;
2868           }
2869         } else {
2870           isExtern = info->O->getPlainRelocationExternal(RE);
2871           if (isExtern) {
2872             symbol_iterator RelocSym = Reloc.getSymbol();
2873             Symbol = *RelocSym;
2874           }
2875         }
2876         reloc_found = true;
2877         break;
2878       }
2879     }
2880     if (reloc_found && isExtern) {
2881       op_info->AddSymbol.Present = 1;
2882       op_info->AddSymbol.Name =
2883           unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2884       // For i386 extern relocation entries the value in the instruction is
2885       // the offset from the symbol, and value is already set in op_info->Value.
2886       return 1;
2887     }
2888     if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2889                         r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
2890       const char *add = GuessSymbolName(r_value, info->AddrMap);
2891       const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2892       uint32_t offset = value - (r_value - pair_r_value);
2893       op_info->AddSymbol.Present = 1;
2894       if (add != nullptr)
2895         op_info->AddSymbol.Name = add;
2896       else
2897         op_info->AddSymbol.Value = r_value;
2898       op_info->SubtractSymbol.Present = 1;
2899       if (sub != nullptr)
2900         op_info->SubtractSymbol.Name = sub;
2901       else
2902         op_info->SubtractSymbol.Value = pair_r_value;
2903       op_info->Value = offset;
2904       return 1;
2905     }
2906     return 0;
2907   }
2908   if (Arch == Triple::x86_64) {
2909     if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0)
2910       return 0;
2911     // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external
2912     // relocation entries of a linked image (if any) for an entry that matches
2913     // this segment offset.
2914     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2915       uint64_t seg_offset = Pc + Offset;
2916       bool reloc_found = false;
2917       DataRefImpl Rel;
2918       MachO::any_relocation_info RE;
2919       bool isExtern = false;
2920       SymbolRef Symbol;
2921       for (const RelocationRef &Reloc : info->O->external_relocations()) {
2922         uint64_t RelocOffset = Reloc.getOffset();
2923         if (RelocOffset == seg_offset) {
2924           Rel = Reloc.getRawDataRefImpl();
2925           RE = info->O->getRelocation(Rel);
2926           // external relocation entries should always be external.
2927           isExtern = info->O->getPlainRelocationExternal(RE);
2928           if (isExtern) {
2929             symbol_iterator RelocSym = Reloc.getSymbol();
2930             Symbol = *RelocSym;
2931           }
2932           reloc_found = true;
2933           break;
2934         }
2935       }
2936       if (reloc_found && isExtern) {
2937         // The Value passed in will be adjusted by the Pc if the instruction
2938         // adds the Pc.  But for x86_64 external relocation entries the Value
2939         // is the offset from the external symbol.
2940         if (info->O->getAnyRelocationPCRel(RE))
2941           op_info->Value -= Pc + InstSize;
2942         const char *name =
2943             unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2944         op_info->AddSymbol.Present = 1;
2945         op_info->AddSymbol.Name = name;
2946         return 1;
2947       }
2948       return 0;
2949     }
2950     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2951     // for an entry for this section offset.
2952     uint64_t sect_addr = info->S.getAddress();
2953     uint64_t sect_offset = (Pc + Offset) - sect_addr;
2954     bool reloc_found = false;
2955     DataRefImpl Rel;
2956     MachO::any_relocation_info RE;
2957     bool isExtern = false;
2958     SymbolRef Symbol;
2959     for (const RelocationRef &Reloc : info->S.relocations()) {
2960       uint64_t RelocOffset = Reloc.getOffset();
2961       if (RelocOffset == sect_offset) {
2962         Rel = Reloc.getRawDataRefImpl();
2963         RE = info->O->getRelocation(Rel);
2964         // NOTE: Scattered relocations don't exist on x86_64.
2965         isExtern = info->O->getPlainRelocationExternal(RE);
2966         if (isExtern) {
2967           symbol_iterator RelocSym = Reloc.getSymbol();
2968           Symbol = *RelocSym;
2969         }
2970         reloc_found = true;
2971         break;
2972       }
2973     }
2974     if (reloc_found && isExtern) {
2975       // The Value passed in will be adjusted by the Pc if the instruction
2976       // adds the Pc.  But for x86_64 external relocation entries the Value
2977       // is the offset from the external symbol.
2978       if (info->O->getAnyRelocationPCRel(RE))
2979         op_info->Value -= Pc + InstSize;
2980       const char *name =
2981           unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2982       unsigned Type = info->O->getAnyRelocationType(RE);
2983       if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
2984         DataRefImpl RelNext = Rel;
2985         info->O->moveRelocationNext(RelNext);
2986         MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2987         unsigned TypeNext = info->O->getAnyRelocationType(RENext);
2988         bool isExternNext = info->O->getPlainRelocationExternal(RENext);
2989         unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
2990         if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
2991           op_info->SubtractSymbol.Present = 1;
2992           op_info->SubtractSymbol.Name = name;
2993           symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
2994           Symbol = *RelocSymNext;
2995           name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2996         }
2997       }
2998       // TODO: add the VariantKinds to op_info->VariantKind for relocation types
2999       // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
3000       op_info->AddSymbol.Present = 1;
3001       op_info->AddSymbol.Name = name;
3002       return 1;
3003     }
3004     return 0;
3005   }
3006   if (Arch == Triple::arm) {
3007     if (Offset != 0 || (InstSize != 4 && InstSize != 2))
3008       return 0;
3009     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
3010       // TODO:
3011       // Search the external relocation entries of a fully linked image
3012       // (if any) for an entry that matches this segment offset.
3013       // uint32_t seg_offset = (Pc + Offset);
3014       return 0;
3015     }
3016     // In MH_OBJECT filetypes search the section's relocation entries (if any)
3017     // for an entry for this section offset.
3018     uint32_t sect_addr = info->S.getAddress();
3019     uint32_t sect_offset = (Pc + Offset) - sect_addr;
3020     DataRefImpl Rel;
3021     MachO::any_relocation_info RE;
3022     bool isExtern = false;
3023     SymbolRef Symbol;
3024     bool r_scattered = false;
3025     uint32_t r_value, pair_r_value, r_type, r_length, other_half;
3026     auto Reloc =
3027         find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
3028           uint64_t RelocOffset = Reloc.getOffset();
3029           return RelocOffset == sect_offset;
3030         });
3031 
3032     if (Reloc == info->S.relocations().end())
3033       return 0;
3034 
3035     Rel = Reloc->getRawDataRefImpl();
3036     RE = info->O->getRelocation(Rel);
3037     r_length = info->O->getAnyRelocationLength(RE);
3038     r_scattered = info->O->isRelocationScattered(RE);
3039     if (r_scattered) {
3040       r_value = info->O->getScatteredRelocationValue(RE);
3041       r_type = info->O->getScatteredRelocationType(RE);
3042     } else {
3043       r_type = info->O->getAnyRelocationType(RE);
3044       isExtern = info->O->getPlainRelocationExternal(RE);
3045       if (isExtern) {
3046         symbol_iterator RelocSym = Reloc->getSymbol();
3047         Symbol = *RelocSym;
3048       }
3049     }
3050     if (r_type == MachO::ARM_RELOC_HALF ||
3051         r_type == MachO::ARM_RELOC_SECTDIFF ||
3052         r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
3053         r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3054       DataRefImpl RelNext = Rel;
3055       info->O->moveRelocationNext(RelNext);
3056       MachO::any_relocation_info RENext;
3057       RENext = info->O->getRelocation(RelNext);
3058       other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
3059       if (info->O->isRelocationScattered(RENext))
3060         pair_r_value = info->O->getScatteredRelocationValue(RENext);
3061     }
3062 
3063     if (isExtern) {
3064       const char *name =
3065           unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
3066       op_info->AddSymbol.Present = 1;
3067       op_info->AddSymbol.Name = name;
3068       switch (r_type) {
3069       case MachO::ARM_RELOC_HALF:
3070         if ((r_length & 0x1) == 1) {
3071           op_info->Value = value << 16 | other_half;
3072           op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3073         } else {
3074           op_info->Value = other_half << 16 | value;
3075           op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3076         }
3077         break;
3078       default:
3079         break;
3080       }
3081       return 1;
3082     }
3083     // If we have a branch that is not an external relocation entry then
3084     // return 0 so the code in tryAddingSymbolicOperand() can use the
3085     // SymbolLookUp call back with the branch target address to look up the
3086     // symbol and possibility add an annotation for a symbol stub.
3087     if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
3088                           r_type == MachO::ARM_THUMB_RELOC_BR22))
3089       return 0;
3090 
3091     uint32_t offset = 0;
3092     if (r_type == MachO::ARM_RELOC_HALF ||
3093         r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3094       if ((r_length & 0x1) == 1)
3095         value = value << 16 | other_half;
3096       else
3097         value = other_half << 16 | value;
3098     }
3099     if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
3100                         r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
3101       offset = value - r_value;
3102       value = r_value;
3103     }
3104 
3105     if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3106       if ((r_length & 0x1) == 1)
3107         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3108       else
3109         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3110       const char *add = GuessSymbolName(r_value, info->AddrMap);
3111       const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
3112       int32_t offset = value - (r_value - pair_r_value);
3113       op_info->AddSymbol.Present = 1;
3114       if (add != nullptr)
3115         op_info->AddSymbol.Name = add;
3116       else
3117         op_info->AddSymbol.Value = r_value;
3118       op_info->SubtractSymbol.Present = 1;
3119       if (sub != nullptr)
3120         op_info->SubtractSymbol.Name = sub;
3121       else
3122         op_info->SubtractSymbol.Value = pair_r_value;
3123       op_info->Value = offset;
3124       return 1;
3125     }
3126 
3127     op_info->AddSymbol.Present = 1;
3128     op_info->Value = offset;
3129     if (r_type == MachO::ARM_RELOC_HALF) {
3130       if ((r_length & 0x1) == 1)
3131         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3132       else
3133         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3134     }
3135     const char *add = GuessSymbolName(value, info->AddrMap);
3136     if (add != nullptr) {
3137       op_info->AddSymbol.Name = add;
3138       return 1;
3139     }
3140     op_info->AddSymbol.Value = value;
3141     return 1;
3142   }
3143   if (Arch == Triple::aarch64) {
3144     if (Offset != 0 || InstSize != 4)
3145       return 0;
3146     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
3147       // TODO:
3148       // Search the external relocation entries of a fully linked image
3149       // (if any) for an entry that matches this segment offset.
3150       // uint64_t seg_offset = (Pc + Offset);
3151       return 0;
3152     }
3153     // In MH_OBJECT filetypes search the section's relocation entries (if any)
3154     // for an entry for this section offset.
3155     uint64_t sect_addr = info->S.getAddress();
3156     uint64_t sect_offset = (Pc + Offset) - sect_addr;
3157     auto Reloc =
3158         find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
3159           uint64_t RelocOffset = Reloc.getOffset();
3160           return RelocOffset == sect_offset;
3161         });
3162 
3163     if (Reloc == info->S.relocations().end())
3164       return 0;
3165 
3166     DataRefImpl Rel = Reloc->getRawDataRefImpl();
3167     MachO::any_relocation_info RE = info->O->getRelocation(Rel);
3168     uint32_t r_type = info->O->getAnyRelocationType(RE);
3169     if (r_type == MachO::ARM64_RELOC_ADDEND) {
3170       DataRefImpl RelNext = Rel;
3171       info->O->moveRelocationNext(RelNext);
3172       MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
3173       if (value == 0) {
3174         value = info->O->getPlainRelocationSymbolNum(RENext);
3175         op_info->Value = value;
3176       }
3177     }
3178     // NOTE: Scattered relocations don't exist on arm64.
3179     if (!info->O->getPlainRelocationExternal(RE))
3180       return 0;
3181     const char *name =
3182         unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName())
3183             .data();
3184     op_info->AddSymbol.Present = 1;
3185     op_info->AddSymbol.Name = name;
3186 
3187     switch (r_type) {
3188     case MachO::ARM64_RELOC_PAGE21:
3189       /* @page */
3190       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
3191       break;
3192     case MachO::ARM64_RELOC_PAGEOFF12:
3193       /* @pageoff */
3194       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
3195       break;
3196     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
3197       /* @gotpage */
3198       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
3199       break;
3200     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
3201       /* @gotpageoff */
3202       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
3203       break;
3204     case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
3205       /* @tvlppage is not implemented in llvm-mc */
3206       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
3207       break;
3208     case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
3209       /* @tvlppageoff is not implemented in llvm-mc */
3210       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
3211       break;
3212     default:
3213     case MachO::ARM64_RELOC_BRANCH26:
3214       op_info->VariantKind = LLVMDisassembler_VariantKind_None;
3215       break;
3216     }
3217     return 1;
3218   }
3219   return 0;
3220 }
3221 
3222 // GuessCstringPointer is passed the address of what might be a pointer to a
3223 // literal string in a cstring section.  If that address is in a cstring section
3224 // it returns a pointer to that string.  Else it returns nullptr.
GuessCstringPointer(uint64_t ReferenceValue,struct DisassembleInfo * info)3225 static const char *GuessCstringPointer(uint64_t ReferenceValue,
3226                                        struct DisassembleInfo *info) {
3227   for (const auto &Load : info->O->load_commands()) {
3228     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3229       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3230       for (unsigned J = 0; J < Seg.nsects; ++J) {
3231         MachO::section_64 Sec = info->O->getSection64(Load, J);
3232         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3233         if (section_type == MachO::S_CSTRING_LITERALS &&
3234             ReferenceValue >= Sec.addr &&
3235             ReferenceValue < Sec.addr + Sec.size) {
3236           uint64_t sect_offset = ReferenceValue - Sec.addr;
3237           uint64_t object_offset = Sec.offset + sect_offset;
3238           StringRef MachOContents = info->O->getData();
3239           uint64_t object_size = MachOContents.size();
3240           const char *object_addr = (const char *)MachOContents.data();
3241           if (object_offset < object_size) {
3242             const char *name = object_addr + object_offset;
3243             return name;
3244           } else {
3245             return nullptr;
3246           }
3247         }
3248       }
3249     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
3250       MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
3251       for (unsigned J = 0; J < Seg.nsects; ++J) {
3252         MachO::section Sec = info->O->getSection(Load, J);
3253         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3254         if (section_type == MachO::S_CSTRING_LITERALS &&
3255             ReferenceValue >= Sec.addr &&
3256             ReferenceValue < Sec.addr + Sec.size) {
3257           uint64_t sect_offset = ReferenceValue - Sec.addr;
3258           uint64_t object_offset = Sec.offset + sect_offset;
3259           StringRef MachOContents = info->O->getData();
3260           uint64_t object_size = MachOContents.size();
3261           const char *object_addr = (const char *)MachOContents.data();
3262           if (object_offset < object_size) {
3263             const char *name = object_addr + object_offset;
3264             return name;
3265           } else {
3266             return nullptr;
3267           }
3268         }
3269       }
3270     }
3271   }
3272   return nullptr;
3273 }
3274 
3275 // GuessIndirectSymbol returns the name of the indirect symbol for the
3276 // ReferenceValue passed in or nullptr.  This is used when ReferenceValue maybe
3277 // an address of a symbol stub or a lazy or non-lazy pointer to associate the
3278 // symbol name being referenced by the stub or pointer.
GuessIndirectSymbol(uint64_t ReferenceValue,struct DisassembleInfo * info)3279 static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
3280                                        struct DisassembleInfo *info) {
3281   MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
3282   MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
3283   for (const auto &Load : info->O->load_commands()) {
3284     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3285       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3286       for (unsigned J = 0; J < Seg.nsects; ++J) {
3287         MachO::section_64 Sec = info->O->getSection64(Load, J);
3288         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3289         if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
3290              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
3291              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
3292              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
3293              section_type == MachO::S_SYMBOL_STUBS) &&
3294             ReferenceValue >= Sec.addr &&
3295             ReferenceValue < Sec.addr + Sec.size) {
3296           uint32_t stride;
3297           if (section_type == MachO::S_SYMBOL_STUBS)
3298             stride = Sec.reserved2;
3299           else
3300             stride = 8;
3301           if (stride == 0)
3302             return nullptr;
3303           uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
3304           if (index < Dysymtab.nindirectsyms) {
3305             uint32_t indirect_symbol =
3306                 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
3307             if (indirect_symbol < Symtab.nsyms) {
3308               symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
3309               return unwrapOrError(Sym->getName(), info->O->getFileName())
3310                   .data();
3311             }
3312           }
3313         }
3314       }
3315     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
3316       MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
3317       for (unsigned J = 0; J < Seg.nsects; ++J) {
3318         MachO::section Sec = info->O->getSection(Load, J);
3319         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3320         if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
3321              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
3322              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
3323              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
3324              section_type == MachO::S_SYMBOL_STUBS) &&
3325             ReferenceValue >= Sec.addr &&
3326             ReferenceValue < Sec.addr + Sec.size) {
3327           uint32_t stride;
3328           if (section_type == MachO::S_SYMBOL_STUBS)
3329             stride = Sec.reserved2;
3330           else
3331             stride = 4;
3332           if (stride == 0)
3333             return nullptr;
3334           uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
3335           if (index < Dysymtab.nindirectsyms) {
3336             uint32_t indirect_symbol =
3337                 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
3338             if (indirect_symbol < Symtab.nsyms) {
3339               symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
3340               return unwrapOrError(Sym->getName(), info->O->getFileName())
3341                   .data();
3342             }
3343           }
3344         }
3345       }
3346     }
3347   }
3348   return nullptr;
3349 }
3350 
3351 // method_reference() is called passing it the ReferenceName that might be
3352 // a reference it to an Objective-C method call.  If so then it allocates and
3353 // assembles a method call string with the values last seen and saved in
3354 // the DisassembleInfo's class_name and selector_name fields.  This is saved
3355 // into the method field of the info and any previous string is free'ed.
3356 // Then the class_name field in the info is set to nullptr.  The method call
3357 // string is set into ReferenceName and ReferenceType is set to
3358 // LLVMDisassembler_ReferenceType_Out_Objc_Message.  If this not a method call
3359 // then both ReferenceType and ReferenceName are left unchanged.
method_reference(struct DisassembleInfo * info,uint64_t * ReferenceType,const char ** ReferenceName)3360 static void method_reference(struct DisassembleInfo *info,
3361                              uint64_t *ReferenceType,
3362                              const char **ReferenceName) {
3363   unsigned int Arch = info->O->getArch();
3364   if (*ReferenceName != nullptr) {
3365     if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
3366       if (info->selector_name != nullptr) {
3367         if (info->class_name != nullptr) {
3368           info->method = std::make_unique<char[]>(
3369               5 + strlen(info->class_name) + strlen(info->selector_name));
3370           char *method = info->method.get();
3371           if (method != nullptr) {
3372             strcpy(method, "+[");
3373             strcat(method, info->class_name);
3374             strcat(method, " ");
3375             strcat(method, info->selector_name);
3376             strcat(method, "]");
3377             *ReferenceName = method;
3378             *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3379           }
3380         } else {
3381           info->method =
3382               std::make_unique<char[]>(9 + strlen(info->selector_name));
3383           char *method = info->method.get();
3384           if (method != nullptr) {
3385             if (Arch == Triple::x86_64)
3386               strcpy(method, "-[%rdi ");
3387             else if (Arch == Triple::aarch64)
3388               strcpy(method, "-[x0 ");
3389             else
3390               strcpy(method, "-[r? ");
3391             strcat(method, info->selector_name);
3392             strcat(method, "]");
3393             *ReferenceName = method;
3394             *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3395           }
3396         }
3397         info->class_name = nullptr;
3398       }
3399     } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
3400       if (info->selector_name != nullptr) {
3401         info->method =
3402             std::make_unique<char[]>(17 + strlen(info->selector_name));
3403         char *method = info->method.get();
3404         if (method != nullptr) {
3405           if (Arch == Triple::x86_64)
3406             strcpy(method, "-[[%rdi super] ");
3407           else if (Arch == Triple::aarch64)
3408             strcpy(method, "-[[x0 super] ");
3409           else
3410             strcpy(method, "-[[r? super] ");
3411           strcat(method, info->selector_name);
3412           strcat(method, "]");
3413           *ReferenceName = method;
3414           *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3415         }
3416         info->class_name = nullptr;
3417       }
3418     }
3419   }
3420 }
3421 
3422 // GuessPointerPointer() is passed the address of what might be a pointer to
3423 // a reference to an Objective-C class, selector, message ref or cfstring.
3424 // If so the value of the pointer is returned and one of the booleans are set
3425 // 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)3426 static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
3427                                     struct DisassembleInfo *info,
3428                                     bool &classref, bool &selref, bool &msgref,
3429                                     bool &cfstring) {
3430   classref = false;
3431   selref = false;
3432   msgref = false;
3433   cfstring = false;
3434   for (const auto &Load : info->O->load_commands()) {
3435     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3436       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3437       for (unsigned J = 0; J < Seg.nsects; ++J) {
3438         MachO::section_64 Sec = info->O->getSection64(Load, J);
3439         if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
3440              strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
3441              strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
3442              strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
3443              strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
3444             ReferenceValue >= Sec.addr &&
3445             ReferenceValue < Sec.addr + Sec.size) {
3446           uint64_t sect_offset = ReferenceValue - Sec.addr;
3447           uint64_t object_offset = Sec.offset + sect_offset;
3448           StringRef MachOContents = info->O->getData();
3449           uint64_t object_size = MachOContents.size();
3450           const char *object_addr = (const char *)MachOContents.data();
3451           if (object_offset < object_size) {
3452             uint64_t pointer_value;
3453             memcpy(&pointer_value, object_addr + object_offset,
3454                    sizeof(uint64_t));
3455             if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3456               sys::swapByteOrder(pointer_value);
3457             if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
3458               selref = true;
3459             else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
3460                      strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
3461               classref = true;
3462             else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
3463                      ReferenceValue + 8 < Sec.addr + Sec.size) {
3464               msgref = true;
3465               memcpy(&pointer_value, object_addr + object_offset + 8,
3466                      sizeof(uint64_t));
3467               if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3468                 sys::swapByteOrder(pointer_value);
3469             } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
3470               cfstring = true;
3471             return pointer_value;
3472           } else {
3473             return 0;
3474           }
3475         }
3476       }
3477     }
3478     // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
3479   }
3480   return 0;
3481 }
3482 
3483 // get_pointer_64 returns a pointer to the bytes in the object file at the
3484 // Address from a section in the Mach-O file.  And indirectly returns the
3485 // offset into the section, number of bytes left in the section past the offset
3486 // and which section is was being referenced.  If the Address is not in a
3487 // section nullptr is returned.
get_pointer_64(uint64_t Address,uint32_t & offset,uint32_t & left,SectionRef & S,DisassembleInfo * info,bool objc_only=false)3488 static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
3489                                   uint32_t &left, SectionRef &S,
3490                                   DisassembleInfo *info,
3491                                   bool objc_only = false) {
3492   offset = 0;
3493   left = 0;
3494   S = SectionRef();
3495   for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
3496     uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
3497     uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
3498     if (SectSize == 0)
3499       continue;
3500     if (objc_only) {
3501       StringRef SectName;
3502       Expected<StringRef> SecNameOrErr =
3503           ((*(info->Sections))[SectIdx]).getName();
3504       if (SecNameOrErr)
3505         SectName = *SecNameOrErr;
3506       else
3507         consumeError(SecNameOrErr.takeError());
3508 
3509       DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
3510       StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
3511       if (SegName != "__OBJC" && SectName != "__cstring")
3512         continue;
3513     }
3514     if (Address >= SectAddress && Address < SectAddress + SectSize) {
3515       S = (*(info->Sections))[SectIdx];
3516       offset = Address - SectAddress;
3517       left = SectSize - offset;
3518       StringRef SectContents = unwrapOrError(
3519           ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName());
3520       return SectContents.data() + offset;
3521     }
3522   }
3523   return nullptr;
3524 }
3525 
get_pointer_32(uint32_t Address,uint32_t & offset,uint32_t & left,SectionRef & S,DisassembleInfo * info,bool objc_only=false)3526 static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
3527                                   uint32_t &left, SectionRef &S,
3528                                   DisassembleInfo *info,
3529                                   bool objc_only = false) {
3530   return get_pointer_64(Address, offset, left, S, info, objc_only);
3531 }
3532 
3533 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of
3534 // the symbol indirectly through n_value. Based on the relocation information
3535 // for the specified section offset in the specified section reference.
3536 // If no relocation information is found and a non-zero ReferenceValue for the
3537 // 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)3538 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
3539                                  DisassembleInfo *info, uint64_t &n_value,
3540                                  uint64_t ReferenceValue = 0) {
3541   n_value = 0;
3542   if (!info->verbose)
3543     return nullptr;
3544 
3545   // See if there is an external relocation entry at the sect_offset.
3546   bool reloc_found = false;
3547   DataRefImpl Rel;
3548   MachO::any_relocation_info RE;
3549   bool isExtern = false;
3550   SymbolRef Symbol;
3551   for (const RelocationRef &Reloc : S.relocations()) {
3552     uint64_t RelocOffset = Reloc.getOffset();
3553     if (RelocOffset == sect_offset) {
3554       Rel = Reloc.getRawDataRefImpl();
3555       RE = info->O->getRelocation(Rel);
3556       if (info->O->isRelocationScattered(RE))
3557         continue;
3558       isExtern = info->O->getPlainRelocationExternal(RE);
3559       if (isExtern) {
3560         symbol_iterator RelocSym = Reloc.getSymbol();
3561         Symbol = *RelocSym;
3562       }
3563       reloc_found = true;
3564       break;
3565     }
3566   }
3567   // If there is an external relocation entry for a symbol in this section
3568   // at this section_offset then use that symbol's value for the n_value
3569   // and return its name.
3570   const char *SymbolName = nullptr;
3571   if (reloc_found && isExtern) {
3572     n_value = cantFail(Symbol.getValue());
3573     StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName());
3574     if (!Name.empty()) {
3575       SymbolName = Name.data();
3576       return SymbolName;
3577     }
3578   }
3579 
3580   // TODO: For fully linked images, look through the external relocation
3581   // entries off the dynamic symtab command. For these the r_offset is from the
3582   // start of the first writeable segment in the Mach-O file.  So the offset
3583   // to this section from that segment is passed to this routine by the caller,
3584   // as the database_offset. Which is the difference of the section's starting
3585   // address and the first writable segment.
3586   //
3587   // NOTE: need add passing the database_offset to this routine.
3588 
3589   // We did not find an external relocation entry so look up the ReferenceValue
3590   // as an address of a symbol and if found return that symbol's name.
3591   SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
3592 
3593   return SymbolName;
3594 }
3595 
get_symbol_32(uint32_t sect_offset,SectionRef S,DisassembleInfo * info,uint32_t ReferenceValue)3596 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
3597                                  DisassembleInfo *info,
3598                                  uint32_t ReferenceValue) {
3599   uint64_t n_value64;
3600   return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
3601 }
3602 
3603 namespace {
3604 
3605 // These are structs in the Objective-C meta data and read to produce the
3606 // comments for disassembly.  While these are part of the ABI they are no
3607 // public defintions.  So the are here not in include/llvm/BinaryFormat/MachO.h
3608 // .
3609 
3610 // The cfstring object in a 64-bit Mach-O file.
3611 struct cfstring64_t {
3612   uint64_t isa;        // class64_t * (64-bit pointer)
3613   uint64_t flags;      // flag bits
3614   uint64_t characters; // char * (64-bit pointer)
3615   uint64_t length;     // number of non-NULL characters in above
3616 };
3617 
3618 // The class object in a 64-bit Mach-O file.
3619 struct class64_t {
3620   uint64_t isa;        // class64_t * (64-bit pointer)
3621   uint64_t superclass; // class64_t * (64-bit pointer)
3622   uint64_t cache;      // Cache (64-bit pointer)
3623   uint64_t vtable;     // IMP * (64-bit pointer)
3624   uint64_t data;       // class_ro64_t * (64-bit pointer)
3625 };
3626 
3627 struct class32_t {
3628   uint32_t isa;        /* class32_t * (32-bit pointer) */
3629   uint32_t superclass; /* class32_t * (32-bit pointer) */
3630   uint32_t cache;      /* Cache (32-bit pointer) */
3631   uint32_t vtable;     /* IMP * (32-bit pointer) */
3632   uint32_t data;       /* class_ro32_t * (32-bit pointer) */
3633 };
3634 
3635 struct class_ro64_t {
3636   uint32_t flags;
3637   uint32_t instanceStart;
3638   uint32_t instanceSize;
3639   uint32_t reserved;
3640   uint64_t ivarLayout;     // const uint8_t * (64-bit pointer)
3641   uint64_t name;           // const char * (64-bit pointer)
3642   uint64_t baseMethods;    // const method_list_t * (64-bit pointer)
3643   uint64_t baseProtocols;  // const protocol_list_t * (64-bit pointer)
3644   uint64_t ivars;          // const ivar_list_t * (64-bit pointer)
3645   uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
3646   uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
3647 };
3648 
3649 struct class_ro32_t {
3650   uint32_t flags;
3651   uint32_t instanceStart;
3652   uint32_t instanceSize;
3653   uint32_t ivarLayout;     /* const uint8_t * (32-bit pointer) */
3654   uint32_t name;           /* const char * (32-bit pointer) */
3655   uint32_t baseMethods;    /* const method_list_t * (32-bit pointer) */
3656   uint32_t baseProtocols;  /* const protocol_list_t * (32-bit pointer) */
3657   uint32_t ivars;          /* const ivar_list_t * (32-bit pointer) */
3658   uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
3659   uint32_t baseProperties; /* const struct objc_property_list *
3660                                                    (32-bit pointer) */
3661 };
3662 
3663 /* Values for class_ro{64,32}_t->flags */
3664 #define RO_META (1 << 0)
3665 #define RO_ROOT (1 << 1)
3666 #define RO_HAS_CXX_STRUCTORS (1 << 2)
3667 
3668 /* Values for method_list{64,32}_t->entsize */
3669 #define ML_HAS_RELATIVE_PTRS (1 << 31)
3670 #define ML_ENTSIZE_MASK 0xFFFF
3671 
3672 struct method_list64_t {
3673   uint32_t entsize;
3674   uint32_t count;
3675   /* struct method64_t first;  These structures follow inline */
3676 };
3677 
3678 struct method_list32_t {
3679   uint32_t entsize;
3680   uint32_t count;
3681   /* struct method32_t first;  These structures follow inline */
3682 };
3683 
3684 struct method64_t {
3685   uint64_t name;  /* SEL (64-bit pointer) */
3686   uint64_t types; /* const char * (64-bit pointer) */
3687   uint64_t imp;   /* IMP (64-bit pointer) */
3688 };
3689 
3690 struct method32_t {
3691   uint32_t name;  /* SEL (32-bit pointer) */
3692   uint32_t types; /* const char * (32-bit pointer) */
3693   uint32_t imp;   /* IMP (32-bit pointer) */
3694 };
3695 
3696 struct method_relative_t {
3697   int32_t name;  /* SEL (32-bit relative) */
3698   int32_t types; /* const char * (32-bit relative) */
3699   int32_t imp;   /* IMP (32-bit relative) */
3700 };
3701 
3702 struct protocol_list64_t {
3703   uint64_t count; /* uintptr_t (a 64-bit value) */
3704   /* struct protocol64_t * list[0];  These pointers follow inline */
3705 };
3706 
3707 struct protocol_list32_t {
3708   uint32_t count; /* uintptr_t (a 32-bit value) */
3709   /* struct protocol32_t * list[0];  These pointers follow inline */
3710 };
3711 
3712 struct protocol64_t {
3713   uint64_t isa;                     /* id * (64-bit pointer) */
3714   uint64_t name;                    /* const char * (64-bit pointer) */
3715   uint64_t protocols;               /* struct protocol_list64_t *
3716                                                     (64-bit pointer) */
3717   uint64_t instanceMethods;         /* method_list_t * (64-bit pointer) */
3718   uint64_t classMethods;            /* method_list_t * (64-bit pointer) */
3719   uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3720   uint64_t optionalClassMethods;    /* method_list_t * (64-bit pointer) */
3721   uint64_t instanceProperties;      /* struct objc_property_list *
3722                                                        (64-bit pointer) */
3723 };
3724 
3725 struct protocol32_t {
3726   uint32_t isa;                     /* id * (32-bit pointer) */
3727   uint32_t name;                    /* const char * (32-bit pointer) */
3728   uint32_t protocols;               /* struct protocol_list_t *
3729                                                     (32-bit pointer) */
3730   uint32_t instanceMethods;         /* method_list_t * (32-bit pointer) */
3731   uint32_t classMethods;            /* method_list_t * (32-bit pointer) */
3732   uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3733   uint32_t optionalClassMethods;    /* method_list_t * (32-bit pointer) */
3734   uint32_t instanceProperties;      /* struct objc_property_list *
3735                                                        (32-bit pointer) */
3736 };
3737 
3738 struct ivar_list64_t {
3739   uint32_t entsize;
3740   uint32_t count;
3741   /* struct ivar64_t first;  These structures follow inline */
3742 };
3743 
3744 struct ivar_list32_t {
3745   uint32_t entsize;
3746   uint32_t count;
3747   /* struct ivar32_t first;  These structures follow inline */
3748 };
3749 
3750 struct ivar64_t {
3751   uint64_t offset; /* uintptr_t * (64-bit pointer) */
3752   uint64_t name;   /* const char * (64-bit pointer) */
3753   uint64_t type;   /* const char * (64-bit pointer) */
3754   uint32_t alignment;
3755   uint32_t size;
3756 };
3757 
3758 struct ivar32_t {
3759   uint32_t offset; /* uintptr_t * (32-bit pointer) */
3760   uint32_t name;   /* const char * (32-bit pointer) */
3761   uint32_t type;   /* const char * (32-bit pointer) */
3762   uint32_t alignment;
3763   uint32_t size;
3764 };
3765 
3766 struct objc_property_list64 {
3767   uint32_t entsize;
3768   uint32_t count;
3769   /* struct objc_property64 first;  These structures follow inline */
3770 };
3771 
3772 struct objc_property_list32 {
3773   uint32_t entsize;
3774   uint32_t count;
3775   /* struct objc_property32 first;  These structures follow inline */
3776 };
3777 
3778 struct objc_property64 {
3779   uint64_t name;       /* const char * (64-bit pointer) */
3780   uint64_t attributes; /* const char * (64-bit pointer) */
3781 };
3782 
3783 struct objc_property32 {
3784   uint32_t name;       /* const char * (32-bit pointer) */
3785   uint32_t attributes; /* const char * (32-bit pointer) */
3786 };
3787 
3788 struct category64_t {
3789   uint64_t name;               /* const char * (64-bit pointer) */
3790   uint64_t cls;                /* struct class_t * (64-bit pointer) */
3791   uint64_t instanceMethods;    /* struct method_list_t * (64-bit pointer) */
3792   uint64_t classMethods;       /* struct method_list_t * (64-bit pointer) */
3793   uint64_t protocols;          /* struct protocol_list_t * (64-bit pointer) */
3794   uint64_t instanceProperties; /* struct objc_property_list *
3795                                   (64-bit pointer) */
3796 };
3797 
3798 struct category32_t {
3799   uint32_t name;               /* const char * (32-bit pointer) */
3800   uint32_t cls;                /* struct class_t * (32-bit pointer) */
3801   uint32_t instanceMethods;    /* struct method_list_t * (32-bit pointer) */
3802   uint32_t classMethods;       /* struct method_list_t * (32-bit pointer) */
3803   uint32_t protocols;          /* struct protocol_list_t * (32-bit pointer) */
3804   uint32_t instanceProperties; /* struct objc_property_list *
3805                                   (32-bit pointer) */
3806 };
3807 
3808 struct objc_image_info64 {
3809   uint32_t version;
3810   uint32_t flags;
3811 };
3812 struct objc_image_info32 {
3813   uint32_t version;
3814   uint32_t flags;
3815 };
3816 struct imageInfo_t {
3817   uint32_t version;
3818   uint32_t flags;
3819 };
3820 /* masks for objc_image_info.flags */
3821 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
3822 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
3823 #define OBJC_IMAGE_IS_SIMULATED (1 << 5)
3824 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
3825 
3826 struct message_ref64 {
3827   uint64_t imp; /* IMP (64-bit pointer) */
3828   uint64_t sel; /* SEL (64-bit pointer) */
3829 };
3830 
3831 struct message_ref32 {
3832   uint32_t imp; /* IMP (32-bit pointer) */
3833   uint32_t sel; /* SEL (32-bit pointer) */
3834 };
3835 
3836 // Objective-C 1 (32-bit only) meta data structs.
3837 
3838 struct objc_module_t {
3839   uint32_t version;
3840   uint32_t size;
3841   uint32_t name;   /* char * (32-bit pointer) */
3842   uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3843 };
3844 
3845 struct objc_symtab_t {
3846   uint32_t sel_ref_cnt;
3847   uint32_t refs; /* SEL * (32-bit pointer) */
3848   uint16_t cls_def_cnt;
3849   uint16_t cat_def_cnt;
3850   // uint32_t defs[1];        /* void * (32-bit pointer) variable size */
3851 };
3852 
3853 struct objc_class_t {
3854   uint32_t isa;         /* struct objc_class * (32-bit pointer) */
3855   uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3856   uint32_t name;        /* const char * (32-bit pointer) */
3857   int32_t version;
3858   int32_t info;
3859   int32_t instance_size;
3860   uint32_t ivars;       /* struct objc_ivar_list * (32-bit pointer) */
3861   uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3862   uint32_t cache;       /* struct objc_cache * (32-bit pointer) */
3863   uint32_t protocols;   /* struct objc_protocol_list * (32-bit pointer) */
3864 };
3865 
3866 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
3867 // class is not a metaclass
3868 #define CLS_CLASS 0x1
3869 // class is a metaclass
3870 #define CLS_META 0x2
3871 
3872 struct objc_category_t {
3873   uint32_t category_name;    /* char * (32-bit pointer) */
3874   uint32_t class_name;       /* char * (32-bit pointer) */
3875   uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3876   uint32_t class_methods;    /* struct objc_method_list * (32-bit pointer) */
3877   uint32_t protocols;        /* struct objc_protocol_list * (32-bit ptr) */
3878 };
3879 
3880 struct objc_ivar_t {
3881   uint32_t ivar_name; /* char * (32-bit pointer) */
3882   uint32_t ivar_type; /* char * (32-bit pointer) */
3883   int32_t ivar_offset;
3884 };
3885 
3886 struct objc_ivar_list_t {
3887   int32_t ivar_count;
3888   // struct objc_ivar_t ivar_list[1];          /* variable length structure */
3889 };
3890 
3891 struct objc_method_list_t {
3892   uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3893   int32_t method_count;
3894   // struct objc_method_t method_list[1];      /* variable length structure */
3895 };
3896 
3897 struct objc_method_t {
3898   uint32_t method_name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3899   uint32_t method_types; /* char * (32-bit pointer) */
3900   uint32_t method_imp;   /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3901                             (32-bit pointer) */
3902 };
3903 
3904 struct objc_protocol_list_t {
3905   uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3906   int32_t count;
3907   // uint32_t list[1];   /* Protocol *, aka struct objc_protocol_t *
3908   //                        (32-bit pointer) */
3909 };
3910 
3911 struct objc_protocol_t {
3912   uint32_t isa;              /* struct objc_class * (32-bit pointer) */
3913   uint32_t protocol_name;    /* char * (32-bit pointer) */
3914   uint32_t protocol_list;    /* struct objc_protocol_list * (32-bit pointer) */
3915   uint32_t instance_methods; /* struct objc_method_description_list *
3916                                 (32-bit pointer) */
3917   uint32_t class_methods;    /* struct objc_method_description_list *
3918                                 (32-bit pointer) */
3919 };
3920 
3921 struct objc_method_description_list_t {
3922   int32_t count;
3923   // struct objc_method_description_t list[1];
3924 };
3925 
3926 struct objc_method_description_t {
3927   uint32_t name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3928   uint32_t types; /* char * (32-bit pointer) */
3929 };
3930 
swapStruct(struct cfstring64_t & cfs)3931 inline void swapStruct(struct cfstring64_t &cfs) {
3932   sys::swapByteOrder(cfs.isa);
3933   sys::swapByteOrder(cfs.flags);
3934   sys::swapByteOrder(cfs.characters);
3935   sys::swapByteOrder(cfs.length);
3936 }
3937 
swapStruct(struct class64_t & c)3938 inline void swapStruct(struct class64_t &c) {
3939   sys::swapByteOrder(c.isa);
3940   sys::swapByteOrder(c.superclass);
3941   sys::swapByteOrder(c.cache);
3942   sys::swapByteOrder(c.vtable);
3943   sys::swapByteOrder(c.data);
3944 }
3945 
swapStruct(struct class32_t & c)3946 inline void swapStruct(struct class32_t &c) {
3947   sys::swapByteOrder(c.isa);
3948   sys::swapByteOrder(c.superclass);
3949   sys::swapByteOrder(c.cache);
3950   sys::swapByteOrder(c.vtable);
3951   sys::swapByteOrder(c.data);
3952 }
3953 
swapStruct(struct class_ro64_t & cro)3954 inline void swapStruct(struct class_ro64_t &cro) {
3955   sys::swapByteOrder(cro.flags);
3956   sys::swapByteOrder(cro.instanceStart);
3957   sys::swapByteOrder(cro.instanceSize);
3958   sys::swapByteOrder(cro.reserved);
3959   sys::swapByteOrder(cro.ivarLayout);
3960   sys::swapByteOrder(cro.name);
3961   sys::swapByteOrder(cro.baseMethods);
3962   sys::swapByteOrder(cro.baseProtocols);
3963   sys::swapByteOrder(cro.ivars);
3964   sys::swapByteOrder(cro.weakIvarLayout);
3965   sys::swapByteOrder(cro.baseProperties);
3966 }
3967 
swapStruct(struct class_ro32_t & cro)3968 inline void swapStruct(struct class_ro32_t &cro) {
3969   sys::swapByteOrder(cro.flags);
3970   sys::swapByteOrder(cro.instanceStart);
3971   sys::swapByteOrder(cro.instanceSize);
3972   sys::swapByteOrder(cro.ivarLayout);
3973   sys::swapByteOrder(cro.name);
3974   sys::swapByteOrder(cro.baseMethods);
3975   sys::swapByteOrder(cro.baseProtocols);
3976   sys::swapByteOrder(cro.ivars);
3977   sys::swapByteOrder(cro.weakIvarLayout);
3978   sys::swapByteOrder(cro.baseProperties);
3979 }
3980 
swapStruct(struct method_list64_t & ml)3981 inline void swapStruct(struct method_list64_t &ml) {
3982   sys::swapByteOrder(ml.entsize);
3983   sys::swapByteOrder(ml.count);
3984 }
3985 
swapStruct(struct method_list32_t & ml)3986 inline void swapStruct(struct method_list32_t &ml) {
3987   sys::swapByteOrder(ml.entsize);
3988   sys::swapByteOrder(ml.count);
3989 }
3990 
swapStruct(struct method64_t & m)3991 inline void swapStruct(struct method64_t &m) {
3992   sys::swapByteOrder(m.name);
3993   sys::swapByteOrder(m.types);
3994   sys::swapByteOrder(m.imp);
3995 }
3996 
swapStruct(struct method32_t & m)3997 inline void swapStruct(struct method32_t &m) {
3998   sys::swapByteOrder(m.name);
3999   sys::swapByteOrder(m.types);
4000   sys::swapByteOrder(m.imp);
4001 }
4002 
swapStruct(struct method_relative_t & m)4003 inline void swapStruct(struct method_relative_t &m) {
4004   sys::swapByteOrder(m.name);
4005   sys::swapByteOrder(m.types);
4006   sys::swapByteOrder(m.imp);
4007 }
4008 
swapStruct(struct protocol_list64_t & pl)4009 inline void swapStruct(struct protocol_list64_t &pl) {
4010   sys::swapByteOrder(pl.count);
4011 }
4012 
swapStruct(struct protocol_list32_t & pl)4013 inline void swapStruct(struct protocol_list32_t &pl) {
4014   sys::swapByteOrder(pl.count);
4015 }
4016 
swapStruct(struct protocol64_t & p)4017 inline void swapStruct(struct protocol64_t &p) {
4018   sys::swapByteOrder(p.isa);
4019   sys::swapByteOrder(p.name);
4020   sys::swapByteOrder(p.protocols);
4021   sys::swapByteOrder(p.instanceMethods);
4022   sys::swapByteOrder(p.classMethods);
4023   sys::swapByteOrder(p.optionalInstanceMethods);
4024   sys::swapByteOrder(p.optionalClassMethods);
4025   sys::swapByteOrder(p.instanceProperties);
4026 }
4027 
swapStruct(struct protocol32_t & p)4028 inline void swapStruct(struct protocol32_t &p) {
4029   sys::swapByteOrder(p.isa);
4030   sys::swapByteOrder(p.name);
4031   sys::swapByteOrder(p.protocols);
4032   sys::swapByteOrder(p.instanceMethods);
4033   sys::swapByteOrder(p.classMethods);
4034   sys::swapByteOrder(p.optionalInstanceMethods);
4035   sys::swapByteOrder(p.optionalClassMethods);
4036   sys::swapByteOrder(p.instanceProperties);
4037 }
4038 
swapStruct(struct ivar_list64_t & il)4039 inline void swapStruct(struct ivar_list64_t &il) {
4040   sys::swapByteOrder(il.entsize);
4041   sys::swapByteOrder(il.count);
4042 }
4043 
swapStruct(struct ivar_list32_t & il)4044 inline void swapStruct(struct ivar_list32_t &il) {
4045   sys::swapByteOrder(il.entsize);
4046   sys::swapByteOrder(il.count);
4047 }
4048 
swapStruct(struct ivar64_t & i)4049 inline void swapStruct(struct ivar64_t &i) {
4050   sys::swapByteOrder(i.offset);
4051   sys::swapByteOrder(i.name);
4052   sys::swapByteOrder(i.type);
4053   sys::swapByteOrder(i.alignment);
4054   sys::swapByteOrder(i.size);
4055 }
4056 
swapStruct(struct ivar32_t & i)4057 inline void swapStruct(struct ivar32_t &i) {
4058   sys::swapByteOrder(i.offset);
4059   sys::swapByteOrder(i.name);
4060   sys::swapByteOrder(i.type);
4061   sys::swapByteOrder(i.alignment);
4062   sys::swapByteOrder(i.size);
4063 }
4064 
swapStruct(struct objc_property_list64 & pl)4065 inline void swapStruct(struct objc_property_list64 &pl) {
4066   sys::swapByteOrder(pl.entsize);
4067   sys::swapByteOrder(pl.count);
4068 }
4069 
swapStruct(struct objc_property_list32 & pl)4070 inline void swapStruct(struct objc_property_list32 &pl) {
4071   sys::swapByteOrder(pl.entsize);
4072   sys::swapByteOrder(pl.count);
4073 }
4074 
swapStruct(struct objc_property64 & op)4075 inline void swapStruct(struct objc_property64 &op) {
4076   sys::swapByteOrder(op.name);
4077   sys::swapByteOrder(op.attributes);
4078 }
4079 
swapStruct(struct objc_property32 & op)4080 inline void swapStruct(struct objc_property32 &op) {
4081   sys::swapByteOrder(op.name);
4082   sys::swapByteOrder(op.attributes);
4083 }
4084 
swapStruct(struct category64_t & c)4085 inline void swapStruct(struct category64_t &c) {
4086   sys::swapByteOrder(c.name);
4087   sys::swapByteOrder(c.cls);
4088   sys::swapByteOrder(c.instanceMethods);
4089   sys::swapByteOrder(c.classMethods);
4090   sys::swapByteOrder(c.protocols);
4091   sys::swapByteOrder(c.instanceProperties);
4092 }
4093 
swapStruct(struct category32_t & c)4094 inline void swapStruct(struct category32_t &c) {
4095   sys::swapByteOrder(c.name);
4096   sys::swapByteOrder(c.cls);
4097   sys::swapByteOrder(c.instanceMethods);
4098   sys::swapByteOrder(c.classMethods);
4099   sys::swapByteOrder(c.protocols);
4100   sys::swapByteOrder(c.instanceProperties);
4101 }
4102 
swapStruct(struct objc_image_info64 & o)4103 inline void swapStruct(struct objc_image_info64 &o) {
4104   sys::swapByteOrder(o.version);
4105   sys::swapByteOrder(o.flags);
4106 }
4107 
swapStruct(struct objc_image_info32 & o)4108 inline void swapStruct(struct objc_image_info32 &o) {
4109   sys::swapByteOrder(o.version);
4110   sys::swapByteOrder(o.flags);
4111 }
4112 
swapStruct(struct imageInfo_t & o)4113 inline void swapStruct(struct imageInfo_t &o) {
4114   sys::swapByteOrder(o.version);
4115   sys::swapByteOrder(o.flags);
4116 }
4117 
swapStruct(struct message_ref64 & mr)4118 inline void swapStruct(struct message_ref64 &mr) {
4119   sys::swapByteOrder(mr.imp);
4120   sys::swapByteOrder(mr.sel);
4121 }
4122 
swapStruct(struct message_ref32 & mr)4123 inline void swapStruct(struct message_ref32 &mr) {
4124   sys::swapByteOrder(mr.imp);
4125   sys::swapByteOrder(mr.sel);
4126 }
4127 
swapStruct(struct objc_module_t & module)4128 inline void swapStruct(struct objc_module_t &module) {
4129   sys::swapByteOrder(module.version);
4130   sys::swapByteOrder(module.size);
4131   sys::swapByteOrder(module.name);
4132   sys::swapByteOrder(module.symtab);
4133 }
4134 
swapStruct(struct objc_symtab_t & symtab)4135 inline void swapStruct(struct objc_symtab_t &symtab) {
4136   sys::swapByteOrder(symtab.sel_ref_cnt);
4137   sys::swapByteOrder(symtab.refs);
4138   sys::swapByteOrder(symtab.cls_def_cnt);
4139   sys::swapByteOrder(symtab.cat_def_cnt);
4140 }
4141 
swapStruct(struct objc_class_t & objc_class)4142 inline void swapStruct(struct objc_class_t &objc_class) {
4143   sys::swapByteOrder(objc_class.isa);
4144   sys::swapByteOrder(objc_class.super_class);
4145   sys::swapByteOrder(objc_class.name);
4146   sys::swapByteOrder(objc_class.version);
4147   sys::swapByteOrder(objc_class.info);
4148   sys::swapByteOrder(objc_class.instance_size);
4149   sys::swapByteOrder(objc_class.ivars);
4150   sys::swapByteOrder(objc_class.methodLists);
4151   sys::swapByteOrder(objc_class.cache);
4152   sys::swapByteOrder(objc_class.protocols);
4153 }
4154 
swapStruct(struct objc_category_t & objc_category)4155 inline void swapStruct(struct objc_category_t &objc_category) {
4156   sys::swapByteOrder(objc_category.category_name);
4157   sys::swapByteOrder(objc_category.class_name);
4158   sys::swapByteOrder(objc_category.instance_methods);
4159   sys::swapByteOrder(objc_category.class_methods);
4160   sys::swapByteOrder(objc_category.protocols);
4161 }
4162 
swapStruct(struct objc_ivar_list_t & objc_ivar_list)4163 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
4164   sys::swapByteOrder(objc_ivar_list.ivar_count);
4165 }
4166 
swapStruct(struct objc_ivar_t & objc_ivar)4167 inline void swapStruct(struct objc_ivar_t &objc_ivar) {
4168   sys::swapByteOrder(objc_ivar.ivar_name);
4169   sys::swapByteOrder(objc_ivar.ivar_type);
4170   sys::swapByteOrder(objc_ivar.ivar_offset);
4171 }
4172 
swapStruct(struct objc_method_list_t & method_list)4173 inline void swapStruct(struct objc_method_list_t &method_list) {
4174   sys::swapByteOrder(method_list.obsolete);
4175   sys::swapByteOrder(method_list.method_count);
4176 }
4177 
swapStruct(struct objc_method_t & method)4178 inline void swapStruct(struct objc_method_t &method) {
4179   sys::swapByteOrder(method.method_name);
4180   sys::swapByteOrder(method.method_types);
4181   sys::swapByteOrder(method.method_imp);
4182 }
4183 
swapStruct(struct objc_protocol_list_t & protocol_list)4184 inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
4185   sys::swapByteOrder(protocol_list.next);
4186   sys::swapByteOrder(protocol_list.count);
4187 }
4188 
swapStruct(struct objc_protocol_t & protocol)4189 inline void swapStruct(struct objc_protocol_t &protocol) {
4190   sys::swapByteOrder(protocol.isa);
4191   sys::swapByteOrder(protocol.protocol_name);
4192   sys::swapByteOrder(protocol.protocol_list);
4193   sys::swapByteOrder(protocol.instance_methods);
4194   sys::swapByteOrder(protocol.class_methods);
4195 }
4196 
swapStruct(struct objc_method_description_list_t & mdl)4197 inline void swapStruct(struct objc_method_description_list_t &mdl) {
4198   sys::swapByteOrder(mdl.count);
4199 }
4200 
swapStruct(struct objc_method_description_t & md)4201 inline void swapStruct(struct objc_method_description_t &md) {
4202   sys::swapByteOrder(md.name);
4203   sys::swapByteOrder(md.types);
4204 }
4205 
4206 } // namespace
4207 
4208 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
4209                                                  struct DisassembleInfo *info);
4210 
4211 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
4212 // to an Objective-C class and returns the class name.  It is also passed the
4213 // address of the pointer, so when the pointer is zero as it can be in an .o
4214 // file, that is used to look for an external relocation entry with a symbol
4215 // name.
get_objc2_64bit_class_name(uint64_t pointer_value,uint64_t ReferenceValue,struct DisassembleInfo * info)4216 static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
4217                                               uint64_t ReferenceValue,
4218                                               struct DisassembleInfo *info) {
4219   const char *r;
4220   uint32_t offset, left;
4221   SectionRef S;
4222 
4223   // The pointer_value can be 0 in an object file and have a relocation
4224   // entry for the class symbol at the ReferenceValue (the address of the
4225   // pointer).
4226   if (pointer_value == 0) {
4227     r = get_pointer_64(ReferenceValue, offset, left, S, info);
4228     if (r == nullptr || left < sizeof(uint64_t))
4229       return nullptr;
4230     uint64_t n_value;
4231     const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4232     if (symbol_name == nullptr)
4233       return nullptr;
4234     const char *class_name = strrchr(symbol_name, '$');
4235     if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
4236       return class_name + 2;
4237     else
4238       return nullptr;
4239   }
4240 
4241   // The case were the pointer_value is non-zero and points to a class defined
4242   // in this Mach-O file.
4243   r = get_pointer_64(pointer_value, offset, left, S, info);
4244   if (r == nullptr || left < sizeof(struct class64_t))
4245     return nullptr;
4246   struct class64_t c;
4247   memcpy(&c, r, sizeof(struct class64_t));
4248   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4249     swapStruct(c);
4250   if (c.data == 0)
4251     return nullptr;
4252   r = get_pointer_64(c.data, offset, left, S, info);
4253   if (r == nullptr || left < sizeof(struct class_ro64_t))
4254     return nullptr;
4255   struct class_ro64_t cro;
4256   memcpy(&cro, r, sizeof(struct class_ro64_t));
4257   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4258     swapStruct(cro);
4259   if (cro.name == 0)
4260     return nullptr;
4261   const char *name = get_pointer_64(cro.name, offset, left, S, info);
4262   return name;
4263 }
4264 
4265 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
4266 // pointer to a cfstring and returns its name or nullptr.
get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,struct DisassembleInfo * info)4267 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
4268                                                  struct DisassembleInfo *info) {
4269   const char *r, *name;
4270   uint32_t offset, left;
4271   SectionRef S;
4272   struct cfstring64_t cfs;
4273   uint64_t cfs_characters;
4274 
4275   r = get_pointer_64(ReferenceValue, offset, left, S, info);
4276   if (r == nullptr || left < sizeof(struct cfstring64_t))
4277     return nullptr;
4278   memcpy(&cfs, r, sizeof(struct cfstring64_t));
4279   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4280     swapStruct(cfs);
4281   if (cfs.characters == 0) {
4282     uint64_t n_value;
4283     const char *symbol_name = get_symbol_64(
4284         offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
4285     if (symbol_name == nullptr)
4286       return nullptr;
4287     cfs_characters = n_value;
4288   } else
4289     cfs_characters = cfs.characters;
4290   name = get_pointer_64(cfs_characters, offset, left, S, info);
4291 
4292   return name;
4293 }
4294 
4295 // get_objc2_64bit_selref() is used for disassembly and is passed a the address
4296 // of a pointer to an Objective-C selector reference when the pointer value is
4297 // zero as in a .o file and is likely to have a external relocation entry with
4298 // who's symbol's n_value is the real pointer to the selector name.  If that is
4299 // the case the real pointer to the selector name is returned else 0 is
4300 // returned
get_objc2_64bit_selref(uint64_t ReferenceValue,struct DisassembleInfo * info)4301 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
4302                                        struct DisassembleInfo *info) {
4303   uint32_t offset, left;
4304   SectionRef S;
4305 
4306   const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
4307   if (r == nullptr || left < sizeof(uint64_t))
4308     return 0;
4309   uint64_t n_value;
4310   const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4311   if (symbol_name == nullptr)
4312     return 0;
4313   return n_value;
4314 }
4315 
get_section(MachOObjectFile * O,const char * segname,const char * sectname)4316 static const SectionRef get_section(MachOObjectFile *O, const char *segname,
4317                                     const char *sectname) {
4318   for (const SectionRef &Section : O->sections()) {
4319     StringRef SectName;
4320     Expected<StringRef> SecNameOrErr = Section.getName();
4321     if (SecNameOrErr)
4322       SectName = *SecNameOrErr;
4323     else
4324       consumeError(SecNameOrErr.takeError());
4325 
4326     DataRefImpl Ref = Section.getRawDataRefImpl();
4327     StringRef SegName = O->getSectionFinalSegmentName(Ref);
4328     if (SegName == segname && SectName == sectname)
4329       return Section;
4330   }
4331   return SectionRef();
4332 }
4333 
4334 static void
walk_pointer_list_64(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint64_t,struct DisassembleInfo * info))4335 walk_pointer_list_64(const char *listname, const SectionRef S,
4336                      MachOObjectFile *O, struct DisassembleInfo *info,
4337                      void (*func)(uint64_t, struct DisassembleInfo *info)) {
4338   if (S == SectionRef())
4339     return;
4340 
4341   StringRef SectName;
4342   Expected<StringRef> SecNameOrErr = S.getName();
4343   if (SecNameOrErr)
4344     SectName = *SecNameOrErr;
4345   else
4346     consumeError(SecNameOrErr.takeError());
4347 
4348   DataRefImpl Ref = S.getRawDataRefImpl();
4349   StringRef SegName = O->getSectionFinalSegmentName(Ref);
4350   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4351 
4352   StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4353   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4354 
4355   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
4356     uint32_t left = S.getSize() - i;
4357     uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
4358     uint64_t p = 0;
4359     memcpy(&p, Contents + i, size);
4360     if (i + sizeof(uint64_t) > S.getSize())
4361       outs() << listname << " list pointer extends past end of (" << SegName
4362              << "," << SectName << ") section\n";
4363     outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
4364 
4365     if (O->isLittleEndian() != sys::IsLittleEndianHost)
4366       sys::swapByteOrder(p);
4367 
4368     uint64_t n_value = 0;
4369     const char *name = get_symbol_64(i, S, info, n_value, p);
4370     if (name == nullptr)
4371       name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
4372 
4373     if (n_value != 0) {
4374       outs() << format("0x%" PRIx64, n_value);
4375       if (p != 0)
4376         outs() << " + " << format("0x%" PRIx64, p);
4377     } else
4378       outs() << format("0x%" PRIx64, p);
4379     if (name != nullptr)
4380       outs() << " " << name;
4381     outs() << "\n";
4382 
4383     p += n_value;
4384     if (func)
4385       func(p, info);
4386   }
4387 }
4388 
4389 static void
walk_pointer_list_32(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint32_t,struct DisassembleInfo * info))4390 walk_pointer_list_32(const char *listname, const SectionRef S,
4391                      MachOObjectFile *O, struct DisassembleInfo *info,
4392                      void (*func)(uint32_t, struct DisassembleInfo *info)) {
4393   if (S == SectionRef())
4394     return;
4395 
4396   StringRef SectName = unwrapOrError(S.getName(), O->getFileName());
4397   DataRefImpl Ref = S.getRawDataRefImpl();
4398   StringRef SegName = O->getSectionFinalSegmentName(Ref);
4399   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4400 
4401   StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4402   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4403 
4404   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
4405     uint32_t left = S.getSize() - i;
4406     uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
4407     uint32_t p = 0;
4408     memcpy(&p, Contents + i, size);
4409     if (i + sizeof(uint32_t) > S.getSize())
4410       outs() << listname << " list pointer extends past end of (" << SegName
4411              << "," << SectName << ") section\n";
4412     uint32_t Address = S.getAddress() + i;
4413     outs() << format("%08" PRIx32, Address) << " ";
4414 
4415     if (O->isLittleEndian() != sys::IsLittleEndianHost)
4416       sys::swapByteOrder(p);
4417     outs() << format("0x%" PRIx32, p);
4418 
4419     const char *name = get_symbol_32(i, S, info, p);
4420     if (name != nullptr)
4421       outs() << " " << name;
4422     outs() << "\n";
4423 
4424     if (func)
4425       func(p, info);
4426   }
4427 }
4428 
print_layout_map(const char * layout_map,uint32_t left)4429 static void print_layout_map(const char *layout_map, uint32_t left) {
4430   if (layout_map == nullptr)
4431     return;
4432   outs() << "                layout map: ";
4433   do {
4434     outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
4435     left--;
4436     layout_map++;
4437   } while (*layout_map != '\0' && left != 0);
4438   outs() << "\n";
4439 }
4440 
print_layout_map64(uint64_t p,struct DisassembleInfo * info)4441 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
4442   uint32_t offset, left;
4443   SectionRef S;
4444   const char *layout_map;
4445 
4446   if (p == 0)
4447     return;
4448   layout_map = get_pointer_64(p, offset, left, S, info);
4449   print_layout_map(layout_map, left);
4450 }
4451 
print_layout_map32(uint32_t p,struct DisassembleInfo * info)4452 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
4453   uint32_t offset, left;
4454   SectionRef S;
4455   const char *layout_map;
4456 
4457   if (p == 0)
4458     return;
4459   layout_map = get_pointer_32(p, offset, left, S, info);
4460   print_layout_map(layout_map, left);
4461 }
4462 
print_relative_method_list(uint32_t structSizeAndFlags,uint32_t structCount,uint64_t p,struct DisassembleInfo * info,const char * indent,uint32_t pointerBits)4463 static void print_relative_method_list(uint32_t structSizeAndFlags,
4464                                        uint32_t structCount, uint64_t p,
4465                                        struct DisassembleInfo *info,
4466                                        const char *indent,
4467                                        uint32_t pointerBits) {
4468   struct method_relative_t m;
4469   const char *r, *name;
4470   uint32_t offset, xoffset, left, i;
4471   SectionRef S, xS;
4472 
4473   assert(((structSizeAndFlags & ML_HAS_RELATIVE_PTRS) != 0) &&
4474          "expected structSizeAndFlags to have ML_HAS_RELATIVE_PTRS flag");
4475 
4476   outs() << indent << "\t\t   entsize "
4477          << (structSizeAndFlags & ML_ENTSIZE_MASK) << " (relative) \n";
4478   outs() << indent << "\t\t     count " << structCount << "\n";
4479 
4480   for (i = 0; i < structCount; i++) {
4481     r = get_pointer_64(p, offset, left, S, info);
4482     memset(&m, '\0', sizeof(struct method_relative_t));
4483     if (left < sizeof(struct method_relative_t)) {
4484       memcpy(&m, r, left);
4485       outs() << indent << "   (method_t extends past the end of the section)\n";
4486     } else
4487       memcpy(&m, r, sizeof(struct method_relative_t));
4488     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4489       swapStruct(m);
4490 
4491     outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
4492     uint64_t relNameRefVA = p + offsetof(struct method_relative_t, name);
4493     uint64_t absNameRefVA = relNameRefVA + m.name;
4494     outs() << " (" << format("0x%" PRIx32, absNameRefVA) << ")";
4495 
4496     // since this is a relative list, absNameRefVA is the address of the
4497     // __objc_selrefs entry, so a pointer, not the actual name
4498     const char *nameRefPtr =
4499         get_pointer_64(absNameRefVA, xoffset, left, xS, info);
4500     if (nameRefPtr) {
4501       uint32_t pointerSize = pointerBits / CHAR_BIT;
4502       if (left < pointerSize)
4503         outs() << indent << " (nameRefPtr extends past the end of the section)";
4504       else {
4505         if (pointerSize == 64) {
4506           uint64_t nameOff_64 = *reinterpret_cast<const uint64_t *>(nameRefPtr);
4507           if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4508             sys::swapByteOrder(nameOff_64);
4509           name = get_pointer_64(nameOff_64, xoffset, left, xS, info);
4510         } else {
4511           uint32_t nameOff_32 = *reinterpret_cast<const uint32_t *>(nameRefPtr);
4512           if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4513             sys::swapByteOrder(nameOff_32);
4514           name = get_pointer_32(nameOff_32, xoffset, left, xS, info);
4515         }
4516         if (name != nullptr)
4517           outs() << format(" %.*s", left, name);
4518       }
4519     }
4520     outs() << "\n";
4521 
4522     outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
4523     uint64_t relTypesVA = p + offsetof(struct method_relative_t, types);
4524     uint64_t absTypesVA = relTypesVA + m.types;
4525     outs() << " (" << format("0x%" PRIx32, absTypesVA) << ")";
4526     name = get_pointer_32(absTypesVA, xoffset, left, xS, info);
4527     if (name != nullptr)
4528       outs() << format(" %.*s", left, name);
4529     outs() << "\n";
4530 
4531     outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4532     uint64_t relImpVA = p + offsetof(struct method_relative_t, imp);
4533     uint64_t absImpVA = relImpVA + m.imp;
4534     outs() << " (" << format("0x%" PRIx32, absImpVA) << ")";
4535     name = GuessSymbolName(absImpVA, info->AddrMap);
4536     if (name != nullptr)
4537       outs() << " " << name;
4538     outs() << "\n";
4539 
4540     p += sizeof(struct method_relative_t);
4541     offset += sizeof(struct method_relative_t);
4542   }
4543 }
4544 
print_method_list64_t(uint64_t p,struct DisassembleInfo * info,const char * indent)4545 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
4546                                   const char *indent) {
4547   struct method_list64_t ml;
4548   struct method64_t m;
4549   const char *r;
4550   uint32_t offset, xoffset, left, i;
4551   SectionRef S, xS;
4552   const char *name, *sym_name;
4553   uint64_t n_value;
4554 
4555   r = get_pointer_64(p, offset, left, S, info);
4556   if (r == nullptr)
4557     return;
4558   memset(&ml, '\0', sizeof(struct method_list64_t));
4559   if (left < sizeof(struct method_list64_t)) {
4560     memcpy(&ml, r, left);
4561     outs() << "   (method_list_t entends past the end of the section)\n";
4562   } else
4563     memcpy(&ml, r, sizeof(struct method_list64_t));
4564   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4565     swapStruct(ml);
4566   p += sizeof(struct method_list64_t);
4567 
4568   if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) {
4569     print_relative_method_list(ml.entsize, ml.count, p, info, indent,
4570                                /*pointerBits=*/64);
4571     return;
4572   }
4573 
4574   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4575   outs() << indent << "\t\t     count " << ml.count << "\n";
4576 
4577   offset += sizeof(struct method_list64_t);
4578   for (i = 0; i < ml.count; i++) {
4579     r = get_pointer_64(p, offset, left, S, info);
4580     if (r == nullptr)
4581       return;
4582     memset(&m, '\0', sizeof(struct method64_t));
4583     if (left < sizeof(struct method64_t)) {
4584       memcpy(&m, r, left);
4585       outs() << indent << "   (method_t extends past the end of the section)\n";
4586     } else
4587       memcpy(&m, r, sizeof(struct method64_t));
4588     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4589       swapStruct(m);
4590 
4591     outs() << indent << "\t\t      name ";
4592     sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
4593                              info, n_value, m.name);
4594     if (n_value != 0) {
4595       if (info->verbose && sym_name != nullptr)
4596         outs() << sym_name;
4597       else
4598         outs() << format("0x%" PRIx64, n_value);
4599       if (m.name != 0)
4600         outs() << " + " << format("0x%" PRIx64, m.name);
4601     } else
4602       outs() << format("0x%" PRIx64, m.name);
4603     name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
4604     if (name != nullptr)
4605       outs() << format(" %.*s", left, name);
4606     outs() << "\n";
4607 
4608     outs() << indent << "\t\t     types ";
4609     sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
4610                              info, n_value, m.types);
4611     if (n_value != 0) {
4612       if (info->verbose && sym_name != nullptr)
4613         outs() << sym_name;
4614       else
4615         outs() << format("0x%" PRIx64, n_value);
4616       if (m.types != 0)
4617         outs() << " + " << format("0x%" PRIx64, m.types);
4618     } else
4619       outs() << format("0x%" PRIx64, m.types);
4620     name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
4621     if (name != nullptr)
4622       outs() << format(" %.*s", left, name);
4623     outs() << "\n";
4624 
4625     outs() << indent << "\t\t       imp ";
4626     name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
4627                          n_value, m.imp);
4628     if (info->verbose && name == nullptr) {
4629       if (n_value != 0) {
4630         outs() << format("0x%" PRIx64, n_value) << " ";
4631         if (m.imp != 0)
4632           outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
4633       } else
4634         outs() << format("0x%" PRIx64, m.imp) << " ";
4635     }
4636     if (name != nullptr)
4637       outs() << name;
4638     outs() << "\n";
4639 
4640     p += sizeof(struct method64_t);
4641     offset += sizeof(struct method64_t);
4642   }
4643 }
4644 
print_method_list32_t(uint64_t p,struct DisassembleInfo * info,const char * indent)4645 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
4646                                   const char *indent) {
4647   struct method_list32_t ml;
4648   struct method32_t m;
4649   const char *r, *name;
4650   uint32_t offset, xoffset, left, i;
4651   SectionRef S, xS;
4652 
4653   r = get_pointer_32(p, offset, left, S, info);
4654   if (r == nullptr)
4655     return;
4656   memset(&ml, '\0', sizeof(struct method_list32_t));
4657   if (left < sizeof(struct method_list32_t)) {
4658     memcpy(&ml, r, left);
4659     outs() << "   (method_list_t entends past the end of the section)\n";
4660   } else
4661     memcpy(&ml, r, sizeof(struct method_list32_t));
4662   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4663     swapStruct(ml);
4664   p += sizeof(struct method_list32_t);
4665 
4666   if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) {
4667     print_relative_method_list(ml.entsize, ml.count, p, info, indent,
4668                                /*pointerBits=*/32);
4669     return;
4670   }
4671 
4672   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4673   outs() << indent << "\t\t     count " << ml.count << "\n";
4674 
4675   offset += sizeof(struct method_list32_t);
4676   for (i = 0; i < ml.count; i++) {
4677     r = get_pointer_32(p, offset, left, S, info);
4678     if (r == nullptr)
4679       return;
4680     memset(&m, '\0', sizeof(struct method32_t));
4681     if (left < sizeof(struct method32_t)) {
4682       memcpy(&ml, r, left);
4683       outs() << indent << "   (method_t entends past the end of the section)\n";
4684     } else
4685       memcpy(&m, r, sizeof(struct method32_t));
4686     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4687       swapStruct(m);
4688 
4689     outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
4690     name = get_pointer_32(m.name, xoffset, left, xS, info);
4691     if (name != nullptr)
4692       outs() << format(" %.*s", left, name);
4693     outs() << "\n";
4694 
4695     outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
4696     name = get_pointer_32(m.types, xoffset, left, xS, info);
4697     if (name != nullptr)
4698       outs() << format(" %.*s", left, name);
4699     outs() << "\n";
4700 
4701     outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4702     name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
4703                          m.imp);
4704     if (name != nullptr)
4705       outs() << " " << name;
4706     outs() << "\n";
4707 
4708     p += sizeof(struct method32_t);
4709     offset += sizeof(struct method32_t);
4710   }
4711 }
4712 
print_method_list(uint32_t p,struct DisassembleInfo * info)4713 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
4714   uint32_t offset, left, xleft;
4715   SectionRef S;
4716   struct objc_method_list_t method_list;
4717   struct objc_method_t method;
4718   const char *r, *methods, *name, *SymbolName;
4719   int32_t i;
4720 
4721   r = get_pointer_32(p, offset, left, S, info, true);
4722   if (r == nullptr)
4723     return true;
4724 
4725   outs() << "\n";
4726   if (left > sizeof(struct objc_method_list_t)) {
4727     memcpy(&method_list, r, sizeof(struct objc_method_list_t));
4728   } else {
4729     outs() << "\t\t objc_method_list extends past end of the section\n";
4730     memset(&method_list, '\0', sizeof(struct objc_method_list_t));
4731     memcpy(&method_list, r, left);
4732   }
4733   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4734     swapStruct(method_list);
4735 
4736   outs() << "\t\t         obsolete "
4737          << format("0x%08" PRIx32, method_list.obsolete) << "\n";
4738   outs() << "\t\t     method_count " << method_list.method_count << "\n";
4739 
4740   methods = r + sizeof(struct objc_method_list_t);
4741   for (i = 0; i < method_list.method_count; i++) {
4742     if ((i + 1) * sizeof(struct objc_method_t) > left) {
4743       outs() << "\t\t remaining method's extend past the of the section\n";
4744       break;
4745     }
4746     memcpy(&method, methods + i * sizeof(struct objc_method_t),
4747            sizeof(struct objc_method_t));
4748     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4749       swapStruct(method);
4750 
4751     outs() << "\t\t      method_name "
4752            << format("0x%08" PRIx32, method.method_name);
4753     if (info->verbose) {
4754       name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4755       if (name != nullptr)
4756         outs() << format(" %.*s", xleft, name);
4757       else
4758         outs() << " (not in an __OBJC section)";
4759     }
4760     outs() << "\n";
4761 
4762     outs() << "\t\t     method_types "
4763            << format("0x%08" PRIx32, method.method_types);
4764     if (info->verbose) {
4765       name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4766       if (name != nullptr)
4767         outs() << format(" %.*s", xleft, name);
4768       else
4769         outs() << " (not in an __OBJC section)";
4770     }
4771     outs() << "\n";
4772 
4773     outs() << "\t\t       method_imp "
4774            << format("0x%08" PRIx32, method.method_imp) << " ";
4775     if (info->verbose) {
4776       SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4777       if (SymbolName != nullptr)
4778         outs() << SymbolName;
4779     }
4780     outs() << "\n";
4781   }
4782   return false;
4783 }
4784 
print_protocol_list64_t(uint64_t p,struct DisassembleInfo * info)4785 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4786   struct protocol_list64_t pl;
4787   uint64_t q, n_value;
4788   struct protocol64_t pc;
4789   const char *r;
4790   uint32_t offset, xoffset, left, i;
4791   SectionRef S, xS;
4792   const char *name, *sym_name;
4793 
4794   r = get_pointer_64(p, offset, left, S, info);
4795   if (r == nullptr)
4796     return;
4797   memset(&pl, '\0', sizeof(struct protocol_list64_t));
4798   if (left < sizeof(struct protocol_list64_t)) {
4799     memcpy(&pl, r, left);
4800     outs() << "   (protocol_list_t entends past the end of the section)\n";
4801   } else
4802     memcpy(&pl, r, sizeof(struct protocol_list64_t));
4803   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4804     swapStruct(pl);
4805   outs() << "                      count " << pl.count << "\n";
4806 
4807   p += sizeof(struct protocol_list64_t);
4808   offset += sizeof(struct protocol_list64_t);
4809   for (i = 0; i < pl.count; i++) {
4810     r = get_pointer_64(p, offset, left, S, info);
4811     if (r == nullptr)
4812       return;
4813     q = 0;
4814     if (left < sizeof(uint64_t)) {
4815       memcpy(&q, r, left);
4816       outs() << "   (protocol_t * entends past the end of the section)\n";
4817     } else
4818       memcpy(&q, r, sizeof(uint64_t));
4819     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4820       sys::swapByteOrder(q);
4821 
4822     outs() << "\t\t      list[" << i << "] ";
4823     sym_name = get_symbol_64(offset, S, info, n_value, q);
4824     if (n_value != 0) {
4825       if (info->verbose && sym_name != nullptr)
4826         outs() << sym_name;
4827       else
4828         outs() << format("0x%" PRIx64, n_value);
4829       if (q != 0)
4830         outs() << " + " << format("0x%" PRIx64, q);
4831     } else
4832       outs() << format("0x%" PRIx64, q);
4833     outs() << " (struct protocol_t *)\n";
4834 
4835     r = get_pointer_64(q + n_value, offset, left, S, info);
4836     if (r == nullptr)
4837       return;
4838     memset(&pc, '\0', sizeof(struct protocol64_t));
4839     if (left < sizeof(struct protocol64_t)) {
4840       memcpy(&pc, r, left);
4841       outs() << "   (protocol_t entends past the end of the section)\n";
4842     } else
4843       memcpy(&pc, r, sizeof(struct protocol64_t));
4844     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4845       swapStruct(pc);
4846 
4847     outs() << "\t\t\t      isa " << format("0x%" PRIx64, pc.isa) << "\n";
4848 
4849     outs() << "\t\t\t     name ";
4850     sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
4851                              info, n_value, pc.name);
4852     if (n_value != 0) {
4853       if (info->verbose && sym_name != nullptr)
4854         outs() << sym_name;
4855       else
4856         outs() << format("0x%" PRIx64, n_value);
4857       if (pc.name != 0)
4858         outs() << " + " << format("0x%" PRIx64, pc.name);
4859     } else
4860       outs() << format("0x%" PRIx64, pc.name);
4861     name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4862     if (name != nullptr)
4863       outs() << format(" %.*s", left, name);
4864     outs() << "\n";
4865 
4866     outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
4867 
4868     outs() << "\t\t  instanceMethods ";
4869     sym_name =
4870         get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
4871                       S, info, n_value, pc.instanceMethods);
4872     if (n_value != 0) {
4873       if (info->verbose && sym_name != nullptr)
4874         outs() << sym_name;
4875       else
4876         outs() << format("0x%" PRIx64, n_value);
4877       if (pc.instanceMethods != 0)
4878         outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
4879     } else
4880       outs() << format("0x%" PRIx64, pc.instanceMethods);
4881     outs() << " (struct method_list_t *)\n";
4882     if (pc.instanceMethods + n_value != 0)
4883       print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4884 
4885     outs() << "\t\t     classMethods ";
4886     sym_name =
4887         get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
4888                       info, n_value, pc.classMethods);
4889     if (n_value != 0) {
4890       if (info->verbose && sym_name != nullptr)
4891         outs() << sym_name;
4892       else
4893         outs() << format("0x%" PRIx64, n_value);
4894       if (pc.classMethods != 0)
4895         outs() << " + " << format("0x%" PRIx64, pc.classMethods);
4896     } else
4897       outs() << format("0x%" PRIx64, pc.classMethods);
4898     outs() << " (struct method_list_t *)\n";
4899     if (pc.classMethods + n_value != 0)
4900       print_method_list64_t(pc.classMethods + n_value, info, "\t");
4901 
4902     outs() << "\t  optionalInstanceMethods "
4903            << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
4904     outs() << "\t     optionalClassMethods "
4905            << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
4906     outs() << "\t       instanceProperties "
4907            << format("0x%" PRIx64, pc.instanceProperties) << "\n";
4908 
4909     p += sizeof(uint64_t);
4910     offset += sizeof(uint64_t);
4911   }
4912 }
4913 
print_protocol_list32_t(uint32_t p,struct DisassembleInfo * info)4914 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4915   struct protocol_list32_t pl;
4916   uint32_t q;
4917   struct protocol32_t pc;
4918   const char *r;
4919   uint32_t offset, xoffset, left, i;
4920   SectionRef S, xS;
4921   const char *name;
4922 
4923   r = get_pointer_32(p, offset, left, S, info);
4924   if (r == nullptr)
4925     return;
4926   memset(&pl, '\0', sizeof(struct protocol_list32_t));
4927   if (left < sizeof(struct protocol_list32_t)) {
4928     memcpy(&pl, r, left);
4929     outs() << "   (protocol_list_t entends past the end of the section)\n";
4930   } else
4931     memcpy(&pl, r, sizeof(struct protocol_list32_t));
4932   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4933     swapStruct(pl);
4934   outs() << "                      count " << pl.count << "\n";
4935 
4936   p += sizeof(struct protocol_list32_t);
4937   offset += sizeof(struct protocol_list32_t);
4938   for (i = 0; i < pl.count; i++) {
4939     r = get_pointer_32(p, offset, left, S, info);
4940     if (r == nullptr)
4941       return;
4942     q = 0;
4943     if (left < sizeof(uint32_t)) {
4944       memcpy(&q, r, left);
4945       outs() << "   (protocol_t * entends past the end of the section)\n";
4946     } else
4947       memcpy(&q, r, sizeof(uint32_t));
4948     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4949       sys::swapByteOrder(q);
4950     outs() << "\t\t      list[" << i << "] " << format("0x%" PRIx32, q)
4951            << " (struct protocol_t *)\n";
4952     r = get_pointer_32(q, offset, left, S, info);
4953     if (r == nullptr)
4954       return;
4955     memset(&pc, '\0', sizeof(struct protocol32_t));
4956     if (left < sizeof(struct protocol32_t)) {
4957       memcpy(&pc, r, left);
4958       outs() << "   (protocol_t entends past the end of the section)\n";
4959     } else
4960       memcpy(&pc, r, sizeof(struct protocol32_t));
4961     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4962       swapStruct(pc);
4963     outs() << "\t\t\t      isa " << format("0x%" PRIx32, pc.isa) << "\n";
4964     outs() << "\t\t\t     name " << format("0x%" PRIx32, pc.name);
4965     name = get_pointer_32(pc.name, xoffset, left, xS, info);
4966     if (name != nullptr)
4967       outs() << format(" %.*s", left, name);
4968     outs() << "\n";
4969     outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
4970     outs() << "\t\t  instanceMethods "
4971            << format("0x%" PRIx32, pc.instanceMethods)
4972            << " (struct method_list_t *)\n";
4973     if (pc.instanceMethods != 0)
4974       print_method_list32_t(pc.instanceMethods, info, "\t");
4975     outs() << "\t\t     classMethods " << format("0x%" PRIx32, pc.classMethods)
4976            << " (struct method_list_t *)\n";
4977     if (pc.classMethods != 0)
4978       print_method_list32_t(pc.classMethods, info, "\t");
4979     outs() << "\t  optionalInstanceMethods "
4980            << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
4981     outs() << "\t     optionalClassMethods "
4982            << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
4983     outs() << "\t       instanceProperties "
4984            << format("0x%" PRIx32, pc.instanceProperties) << "\n";
4985     p += sizeof(uint32_t);
4986     offset += sizeof(uint32_t);
4987   }
4988 }
4989 
print_indent(uint32_t indent)4990 static void print_indent(uint32_t indent) {
4991   for (uint32_t i = 0; i < indent;) {
4992     if (indent - i >= 8) {
4993       outs() << "\t";
4994       i += 8;
4995     } else {
4996       for (uint32_t j = i; j < indent; j++)
4997         outs() << " ";
4998       return;
4999     }
5000   }
5001 }
5002 
print_method_description_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)5003 static bool print_method_description_list(uint32_t p, uint32_t indent,
5004                                           struct DisassembleInfo *info) {
5005   uint32_t offset, left, xleft;
5006   SectionRef S;
5007   struct objc_method_description_list_t mdl;
5008   struct objc_method_description_t md;
5009   const char *r, *list, *name;
5010   int32_t i;
5011 
5012   r = get_pointer_32(p, offset, left, S, info, true);
5013   if (r == nullptr)
5014     return true;
5015 
5016   outs() << "\n";
5017   if (left > sizeof(struct objc_method_description_list_t)) {
5018     memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
5019   } else {
5020     print_indent(indent);
5021     outs() << " objc_method_description_list extends past end of the section\n";
5022     memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
5023     memcpy(&mdl, r, left);
5024   }
5025   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5026     swapStruct(mdl);
5027 
5028   print_indent(indent);
5029   outs() << "        count " << mdl.count << "\n";
5030 
5031   list = r + sizeof(struct objc_method_description_list_t);
5032   for (i = 0; i < mdl.count; i++) {
5033     if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
5034       print_indent(indent);
5035       outs() << " remaining list entries extend past the of the section\n";
5036       break;
5037     }
5038     print_indent(indent);
5039     outs() << "        list[" << i << "]\n";
5040     memcpy(&md, list + i * sizeof(struct objc_method_description_t),
5041            sizeof(struct objc_method_description_t));
5042     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5043       swapStruct(md);
5044 
5045     print_indent(indent);
5046     outs() << "             name " << format("0x%08" PRIx32, md.name);
5047     if (info->verbose) {
5048       name = get_pointer_32(md.name, offset, xleft, S, info, true);
5049       if (name != nullptr)
5050         outs() << format(" %.*s", xleft, name);
5051       else
5052         outs() << " (not in an __OBJC section)";
5053     }
5054     outs() << "\n";
5055 
5056     print_indent(indent);
5057     outs() << "            types " << format("0x%08" PRIx32, md.types);
5058     if (info->verbose) {
5059       name = get_pointer_32(md.types, offset, xleft, S, info, true);
5060       if (name != nullptr)
5061         outs() << format(" %.*s", xleft, name);
5062       else
5063         outs() << " (not in an __OBJC section)";
5064     }
5065     outs() << "\n";
5066   }
5067   return false;
5068 }
5069 
5070 static bool print_protocol_list(uint32_t p, uint32_t indent,
5071                                 struct DisassembleInfo *info);
5072 
print_protocol(uint32_t p,uint32_t indent,struct DisassembleInfo * info)5073 static bool print_protocol(uint32_t p, uint32_t indent,
5074                            struct DisassembleInfo *info) {
5075   uint32_t offset, left;
5076   SectionRef S;
5077   struct objc_protocol_t protocol;
5078   const char *r, *name;
5079 
5080   r = get_pointer_32(p, offset, left, S, info, true);
5081   if (r == nullptr)
5082     return true;
5083 
5084   outs() << "\n";
5085   if (left >= sizeof(struct objc_protocol_t)) {
5086     memcpy(&protocol, r, sizeof(struct objc_protocol_t));
5087   } else {
5088     print_indent(indent);
5089     outs() << "            Protocol extends past end of the section\n";
5090     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
5091     memcpy(&protocol, r, left);
5092   }
5093   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5094     swapStruct(protocol);
5095 
5096   print_indent(indent);
5097   outs() << "              isa " << format("0x%08" PRIx32, protocol.isa)
5098          << "\n";
5099 
5100   print_indent(indent);
5101   outs() << "    protocol_name "
5102          << format("0x%08" PRIx32, protocol.protocol_name);
5103   if (info->verbose) {
5104     name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
5105     if (name != nullptr)
5106       outs() << format(" %.*s", left, name);
5107     else
5108       outs() << " (not in an __OBJC section)";
5109   }
5110   outs() << "\n";
5111 
5112   print_indent(indent);
5113   outs() << "    protocol_list "
5114          << format("0x%08" PRIx32, protocol.protocol_list);
5115   if (print_protocol_list(protocol.protocol_list, indent + 4, info))
5116     outs() << " (not in an __OBJC section)\n";
5117 
5118   print_indent(indent);
5119   outs() << " instance_methods "
5120          << format("0x%08" PRIx32, protocol.instance_methods);
5121   if (print_method_description_list(protocol.instance_methods, indent, info))
5122     outs() << " (not in an __OBJC section)\n";
5123 
5124   print_indent(indent);
5125   outs() << "    class_methods "
5126          << format("0x%08" PRIx32, protocol.class_methods);
5127   if (print_method_description_list(protocol.class_methods, indent, info))
5128     outs() << " (not in an __OBJC section)\n";
5129 
5130   return false;
5131 }
5132 
print_protocol_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)5133 static bool print_protocol_list(uint32_t p, uint32_t indent,
5134                                 struct DisassembleInfo *info) {
5135   uint32_t offset, left, l;
5136   SectionRef S;
5137   struct objc_protocol_list_t protocol_list;
5138   const char *r, *list;
5139   int32_t i;
5140 
5141   r = get_pointer_32(p, offset, left, S, info, true);
5142   if (r == nullptr)
5143     return true;
5144 
5145   outs() << "\n";
5146   if (left > sizeof(struct objc_protocol_list_t)) {
5147     memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
5148   } else {
5149     outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
5150     memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
5151     memcpy(&protocol_list, r, left);
5152   }
5153   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5154     swapStruct(protocol_list);
5155 
5156   print_indent(indent);
5157   outs() << "         next " << format("0x%08" PRIx32, protocol_list.next)
5158          << "\n";
5159   print_indent(indent);
5160   outs() << "        count " << protocol_list.count << "\n";
5161 
5162   list = r + sizeof(struct objc_protocol_list_t);
5163   for (i = 0; i < protocol_list.count; i++) {
5164     if ((i + 1) * sizeof(uint32_t) > left) {
5165       outs() << "\t\t remaining list entries extend past the of the section\n";
5166       break;
5167     }
5168     memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
5169     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5170       sys::swapByteOrder(l);
5171 
5172     print_indent(indent);
5173     outs() << "      list[" << i << "] " << format("0x%08" PRIx32, l);
5174     if (print_protocol(l, indent, info))
5175       outs() << "(not in an __OBJC section)\n";
5176   }
5177   return false;
5178 }
5179 
print_ivar_list64_t(uint64_t p,struct DisassembleInfo * info)5180 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
5181   struct ivar_list64_t il;
5182   struct ivar64_t i;
5183   const char *r;
5184   uint32_t offset, xoffset, left, j;
5185   SectionRef S, xS;
5186   const char *name, *sym_name, *ivar_offset_p;
5187   uint64_t ivar_offset, n_value;
5188 
5189   r = get_pointer_64(p, offset, left, S, info);
5190   if (r == nullptr)
5191     return;
5192   memset(&il, '\0', sizeof(struct ivar_list64_t));
5193   if (left < sizeof(struct ivar_list64_t)) {
5194     memcpy(&il, r, left);
5195     outs() << "   (ivar_list_t entends past the end of the section)\n";
5196   } else
5197     memcpy(&il, r, sizeof(struct ivar_list64_t));
5198   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5199     swapStruct(il);
5200   outs() << "                    entsize " << il.entsize << "\n";
5201   outs() << "                      count " << il.count << "\n";
5202 
5203   p += sizeof(struct ivar_list64_t);
5204   offset += sizeof(struct ivar_list64_t);
5205   for (j = 0; j < il.count; j++) {
5206     r = get_pointer_64(p, offset, left, S, info);
5207     if (r == nullptr)
5208       return;
5209     memset(&i, '\0', sizeof(struct ivar64_t));
5210     if (left < sizeof(struct ivar64_t)) {
5211       memcpy(&i, r, left);
5212       outs() << "   (ivar_t entends past the end of the section)\n";
5213     } else
5214       memcpy(&i, r, sizeof(struct ivar64_t));
5215     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5216       swapStruct(i);
5217 
5218     outs() << "\t\t\t   offset ";
5219     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
5220                              info, n_value, i.offset);
5221     if (n_value != 0) {
5222       if (info->verbose && sym_name != nullptr)
5223         outs() << sym_name;
5224       else
5225         outs() << format("0x%" PRIx64, n_value);
5226       if (i.offset != 0)
5227         outs() << " + " << format("0x%" PRIx64, i.offset);
5228     } else
5229       outs() << format("0x%" PRIx64, i.offset);
5230     ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
5231     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5232       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5233       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5234         sys::swapByteOrder(ivar_offset);
5235       outs() << " " << ivar_offset << "\n";
5236     } else
5237       outs() << "\n";
5238 
5239     outs() << "\t\t\t     name ";
5240     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
5241                              n_value, i.name);
5242     if (n_value != 0) {
5243       if (info->verbose && sym_name != nullptr)
5244         outs() << sym_name;
5245       else
5246         outs() << format("0x%" PRIx64, n_value);
5247       if (i.name != 0)
5248         outs() << " + " << format("0x%" PRIx64, i.name);
5249     } else
5250       outs() << format("0x%" PRIx64, i.name);
5251     name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
5252     if (name != nullptr)
5253       outs() << format(" %.*s", left, name);
5254     outs() << "\n";
5255 
5256     outs() << "\t\t\t     type ";
5257     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
5258                              n_value, i.name);
5259     name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
5260     if (n_value != 0) {
5261       if (info->verbose && sym_name != nullptr)
5262         outs() << sym_name;
5263       else
5264         outs() << format("0x%" PRIx64, n_value);
5265       if (i.type != 0)
5266         outs() << " + " << format("0x%" PRIx64, i.type);
5267     } else
5268       outs() << format("0x%" PRIx64, i.type);
5269     if (name != nullptr)
5270       outs() << format(" %.*s", left, name);
5271     outs() << "\n";
5272 
5273     outs() << "\t\t\talignment " << i.alignment << "\n";
5274     outs() << "\t\t\t     size " << i.size << "\n";
5275 
5276     p += sizeof(struct ivar64_t);
5277     offset += sizeof(struct ivar64_t);
5278   }
5279 }
5280 
print_ivar_list32_t(uint32_t p,struct DisassembleInfo * info)5281 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
5282   struct ivar_list32_t il;
5283   struct ivar32_t i;
5284   const char *r;
5285   uint32_t offset, xoffset, left, j;
5286   SectionRef S, xS;
5287   const char *name, *ivar_offset_p;
5288   uint32_t ivar_offset;
5289 
5290   r = get_pointer_32(p, offset, left, S, info);
5291   if (r == nullptr)
5292     return;
5293   memset(&il, '\0', sizeof(struct ivar_list32_t));
5294   if (left < sizeof(struct ivar_list32_t)) {
5295     memcpy(&il, r, left);
5296     outs() << "   (ivar_list_t entends past the end of the section)\n";
5297   } else
5298     memcpy(&il, r, sizeof(struct ivar_list32_t));
5299   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5300     swapStruct(il);
5301   outs() << "                    entsize " << il.entsize << "\n";
5302   outs() << "                      count " << il.count << "\n";
5303 
5304   p += sizeof(struct ivar_list32_t);
5305   offset += sizeof(struct ivar_list32_t);
5306   for (j = 0; j < il.count; j++) {
5307     r = get_pointer_32(p, offset, left, S, info);
5308     if (r == nullptr)
5309       return;
5310     memset(&i, '\0', sizeof(struct ivar32_t));
5311     if (left < sizeof(struct ivar32_t)) {
5312       memcpy(&i, r, left);
5313       outs() << "   (ivar_t entends past the end of the section)\n";
5314     } else
5315       memcpy(&i, r, sizeof(struct ivar32_t));
5316     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5317       swapStruct(i);
5318 
5319     outs() << "\t\t\t   offset " << format("0x%" PRIx32, i.offset);
5320     ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
5321     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5322       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5323       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5324         sys::swapByteOrder(ivar_offset);
5325       outs() << " " << ivar_offset << "\n";
5326     } else
5327       outs() << "\n";
5328 
5329     outs() << "\t\t\t     name " << format("0x%" PRIx32, i.name);
5330     name = get_pointer_32(i.name, xoffset, left, xS, info);
5331     if (name != nullptr)
5332       outs() << format(" %.*s", left, name);
5333     outs() << "\n";
5334 
5335     outs() << "\t\t\t     type " << format("0x%" PRIx32, i.type);
5336     name = get_pointer_32(i.type, xoffset, left, xS, info);
5337     if (name != nullptr)
5338       outs() << format(" %.*s", left, name);
5339     outs() << "\n";
5340 
5341     outs() << "\t\t\talignment " << i.alignment << "\n";
5342     outs() << "\t\t\t     size " << i.size << "\n";
5343 
5344     p += sizeof(struct ivar32_t);
5345     offset += sizeof(struct ivar32_t);
5346   }
5347 }
5348 
print_objc_property_list64(uint64_t p,struct DisassembleInfo * info)5349 static void print_objc_property_list64(uint64_t p,
5350                                        struct DisassembleInfo *info) {
5351   struct objc_property_list64 opl;
5352   struct objc_property64 op;
5353   const char *r;
5354   uint32_t offset, xoffset, left, j;
5355   SectionRef S, xS;
5356   const char *name, *sym_name;
5357   uint64_t n_value;
5358 
5359   r = get_pointer_64(p, offset, left, S, info);
5360   if (r == nullptr)
5361     return;
5362   memset(&opl, '\0', sizeof(struct objc_property_list64));
5363   if (left < sizeof(struct objc_property_list64)) {
5364     memcpy(&opl, r, left);
5365     outs() << "   (objc_property_list entends past the end of the section)\n";
5366   } else
5367     memcpy(&opl, r, sizeof(struct objc_property_list64));
5368   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5369     swapStruct(opl);
5370   outs() << "                    entsize " << opl.entsize << "\n";
5371   outs() << "                      count " << opl.count << "\n";
5372 
5373   p += sizeof(struct objc_property_list64);
5374   offset += sizeof(struct objc_property_list64);
5375   for (j = 0; j < opl.count; j++) {
5376     r = get_pointer_64(p, offset, left, S, info);
5377     if (r == nullptr)
5378       return;
5379     memset(&op, '\0', sizeof(struct objc_property64));
5380     if (left < sizeof(struct objc_property64)) {
5381       memcpy(&op, r, left);
5382       outs() << "   (objc_property entends past the end of the section)\n";
5383     } else
5384       memcpy(&op, r, sizeof(struct objc_property64));
5385     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5386       swapStruct(op);
5387 
5388     outs() << "\t\t\t     name ";
5389     sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
5390                              info, n_value, op.name);
5391     if (n_value != 0) {
5392       if (info->verbose && sym_name != nullptr)
5393         outs() << sym_name;
5394       else
5395         outs() << format("0x%" PRIx64, n_value);
5396       if (op.name != 0)
5397         outs() << " + " << format("0x%" PRIx64, op.name);
5398     } else
5399       outs() << format("0x%" PRIx64, op.name);
5400     name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
5401     if (name != nullptr)
5402       outs() << format(" %.*s", left, name);
5403     outs() << "\n";
5404 
5405     outs() << "\t\t\tattributes ";
5406     sym_name =
5407         get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
5408                       info, n_value, op.attributes);
5409     if (n_value != 0) {
5410       if (info->verbose && sym_name != nullptr)
5411         outs() << sym_name;
5412       else
5413         outs() << format("0x%" PRIx64, n_value);
5414       if (op.attributes != 0)
5415         outs() << " + " << format("0x%" PRIx64, op.attributes);
5416     } else
5417       outs() << format("0x%" PRIx64, op.attributes);
5418     name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
5419     if (name != nullptr)
5420       outs() << format(" %.*s", left, name);
5421     outs() << "\n";
5422 
5423     p += sizeof(struct objc_property64);
5424     offset += sizeof(struct objc_property64);
5425   }
5426 }
5427 
print_objc_property_list32(uint32_t p,struct DisassembleInfo * info)5428 static void print_objc_property_list32(uint32_t p,
5429                                        struct DisassembleInfo *info) {
5430   struct objc_property_list32 opl;
5431   struct objc_property32 op;
5432   const char *r;
5433   uint32_t offset, xoffset, left, j;
5434   SectionRef S, xS;
5435   const char *name;
5436 
5437   r = get_pointer_32(p, offset, left, S, info);
5438   if (r == nullptr)
5439     return;
5440   memset(&opl, '\0', sizeof(struct objc_property_list32));
5441   if (left < sizeof(struct objc_property_list32)) {
5442     memcpy(&opl, r, left);
5443     outs() << "   (objc_property_list entends past the end of the section)\n";
5444   } else
5445     memcpy(&opl, r, sizeof(struct objc_property_list32));
5446   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5447     swapStruct(opl);
5448   outs() << "                    entsize " << opl.entsize << "\n";
5449   outs() << "                      count " << opl.count << "\n";
5450 
5451   p += sizeof(struct objc_property_list32);
5452   offset += sizeof(struct objc_property_list32);
5453   for (j = 0; j < opl.count; j++) {
5454     r = get_pointer_32(p, offset, left, S, info);
5455     if (r == nullptr)
5456       return;
5457     memset(&op, '\0', sizeof(struct objc_property32));
5458     if (left < sizeof(struct objc_property32)) {
5459       memcpy(&op, r, left);
5460       outs() << "   (objc_property entends past the end of the section)\n";
5461     } else
5462       memcpy(&op, r, sizeof(struct objc_property32));
5463     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5464       swapStruct(op);
5465 
5466     outs() << "\t\t\t     name " << format("0x%" PRIx32, op.name);
5467     name = get_pointer_32(op.name, xoffset, left, xS, info);
5468     if (name != nullptr)
5469       outs() << format(" %.*s", left, name);
5470     outs() << "\n";
5471 
5472     outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
5473     name = get_pointer_32(op.attributes, xoffset, left, xS, info);
5474     if (name != nullptr)
5475       outs() << format(" %.*s", left, name);
5476     outs() << "\n";
5477 
5478     p += sizeof(struct objc_property32);
5479     offset += sizeof(struct objc_property32);
5480   }
5481 }
5482 
print_class_ro64_t(uint64_t p,struct DisassembleInfo * info,bool & is_meta_class)5483 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
5484                                bool &is_meta_class) {
5485   struct class_ro64_t cro;
5486   const char *r;
5487   uint32_t offset, xoffset, left;
5488   SectionRef S, xS;
5489   const char *name, *sym_name;
5490   uint64_t n_value;
5491 
5492   r = get_pointer_64(p, offset, left, S, info);
5493   if (r == nullptr || left < sizeof(struct class_ro64_t))
5494     return false;
5495   memcpy(&cro, r, sizeof(struct class_ro64_t));
5496   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5497     swapStruct(cro);
5498   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5499   if (cro.flags & RO_META)
5500     outs() << " RO_META";
5501   if (cro.flags & RO_ROOT)
5502     outs() << " RO_ROOT";
5503   if (cro.flags & RO_HAS_CXX_STRUCTORS)
5504     outs() << " RO_HAS_CXX_STRUCTORS";
5505   outs() << "\n";
5506   outs() << "            instanceStart " << cro.instanceStart << "\n";
5507   outs() << "             instanceSize " << cro.instanceSize << "\n";
5508   outs() << "                 reserved " << format("0x%" PRIx32, cro.reserved)
5509          << "\n";
5510   outs() << "               ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
5511          << "\n";
5512   print_layout_map64(cro.ivarLayout, info);
5513 
5514   outs() << "                     name ";
5515   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
5516                            info, n_value, cro.name);
5517   if (n_value != 0) {
5518     if (info->verbose && sym_name != nullptr)
5519       outs() << sym_name;
5520     else
5521       outs() << format("0x%" PRIx64, n_value);
5522     if (cro.name != 0)
5523       outs() << " + " << format("0x%" PRIx64, cro.name);
5524   } else
5525     outs() << format("0x%" PRIx64, cro.name);
5526   name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
5527   if (name != nullptr)
5528     outs() << format(" %.*s", left, name);
5529   outs() << "\n";
5530 
5531   outs() << "              baseMethods ";
5532   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
5533                            S, info, n_value, cro.baseMethods);
5534   if (n_value != 0) {
5535     if (info->verbose && sym_name != nullptr)
5536       outs() << sym_name;
5537     else
5538       outs() << format("0x%" PRIx64, n_value);
5539     if (cro.baseMethods != 0)
5540       outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
5541   } else
5542     outs() << format("0x%" PRIx64, cro.baseMethods);
5543   outs() << " (struct method_list_t *)\n";
5544   if (cro.baseMethods + n_value != 0)
5545     print_method_list64_t(cro.baseMethods + n_value, info, "");
5546 
5547   outs() << "            baseProtocols ";
5548   sym_name =
5549       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
5550                     info, n_value, cro.baseProtocols);
5551   if (n_value != 0) {
5552     if (info->verbose && sym_name != nullptr)
5553       outs() << sym_name;
5554     else
5555       outs() << format("0x%" PRIx64, n_value);
5556     if (cro.baseProtocols != 0)
5557       outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
5558   } else
5559     outs() << format("0x%" PRIx64, cro.baseProtocols);
5560   outs() << "\n";
5561   if (cro.baseProtocols + n_value != 0)
5562     print_protocol_list64_t(cro.baseProtocols + n_value, info);
5563 
5564   outs() << "                    ivars ";
5565   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
5566                            info, n_value, cro.ivars);
5567   if (n_value != 0) {
5568     if (info->verbose && sym_name != nullptr)
5569       outs() << sym_name;
5570     else
5571       outs() << format("0x%" PRIx64, n_value);
5572     if (cro.ivars != 0)
5573       outs() << " + " << format("0x%" PRIx64, cro.ivars);
5574   } else
5575     outs() << format("0x%" PRIx64, cro.ivars);
5576   outs() << "\n";
5577   if (cro.ivars + n_value != 0)
5578     print_ivar_list64_t(cro.ivars + n_value, info);
5579 
5580   outs() << "           weakIvarLayout ";
5581   sym_name =
5582       get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
5583                     info, n_value, cro.weakIvarLayout);
5584   if (n_value != 0) {
5585     if (info->verbose && sym_name != nullptr)
5586       outs() << sym_name;
5587     else
5588       outs() << format("0x%" PRIx64, n_value);
5589     if (cro.weakIvarLayout != 0)
5590       outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
5591   } else
5592     outs() << format("0x%" PRIx64, cro.weakIvarLayout);
5593   outs() << "\n";
5594   print_layout_map64(cro.weakIvarLayout + n_value, info);
5595 
5596   outs() << "           baseProperties ";
5597   sym_name =
5598       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
5599                     info, n_value, cro.baseProperties);
5600   if (n_value != 0) {
5601     if (info->verbose && sym_name != nullptr)
5602       outs() << sym_name;
5603     else
5604       outs() << format("0x%" PRIx64, n_value);
5605     if (cro.baseProperties != 0)
5606       outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
5607   } else
5608     outs() << format("0x%" PRIx64, cro.baseProperties);
5609   outs() << "\n";
5610   if (cro.baseProperties + n_value != 0)
5611     print_objc_property_list64(cro.baseProperties + n_value, info);
5612 
5613   is_meta_class = (cro.flags & RO_META) != 0;
5614   return true;
5615 }
5616 
print_class_ro32_t(uint32_t p,struct DisassembleInfo * info,bool & is_meta_class)5617 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
5618                                bool &is_meta_class) {
5619   struct class_ro32_t cro;
5620   const char *r;
5621   uint32_t offset, xoffset, left;
5622   SectionRef S, xS;
5623   const char *name;
5624 
5625   r = get_pointer_32(p, offset, left, S, info);
5626   if (r == nullptr)
5627     return false;
5628   memset(&cro, '\0', sizeof(struct class_ro32_t));
5629   if (left < sizeof(struct class_ro32_t)) {
5630     memcpy(&cro, r, left);
5631     outs() << "   (class_ro_t entends past the end of the section)\n";
5632   } else
5633     memcpy(&cro, r, sizeof(struct class_ro32_t));
5634   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5635     swapStruct(cro);
5636   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5637   if (cro.flags & RO_META)
5638     outs() << " RO_META";
5639   if (cro.flags & RO_ROOT)
5640     outs() << " RO_ROOT";
5641   if (cro.flags & RO_HAS_CXX_STRUCTORS)
5642     outs() << " RO_HAS_CXX_STRUCTORS";
5643   outs() << "\n";
5644   outs() << "            instanceStart " << cro.instanceStart << "\n";
5645   outs() << "             instanceSize " << cro.instanceSize << "\n";
5646   outs() << "               ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
5647          << "\n";
5648   print_layout_map32(cro.ivarLayout, info);
5649 
5650   outs() << "                     name " << format("0x%" PRIx32, cro.name);
5651   name = get_pointer_32(cro.name, xoffset, left, xS, info);
5652   if (name != nullptr)
5653     outs() << format(" %.*s", left, name);
5654   outs() << "\n";
5655 
5656   outs() << "              baseMethods "
5657          << format("0x%" PRIx32, cro.baseMethods)
5658          << " (struct method_list_t *)\n";
5659   if (cro.baseMethods != 0)
5660     print_method_list32_t(cro.baseMethods, info, "");
5661 
5662   outs() << "            baseProtocols "
5663          << format("0x%" PRIx32, cro.baseProtocols) << "\n";
5664   if (cro.baseProtocols != 0)
5665     print_protocol_list32_t(cro.baseProtocols, info);
5666   outs() << "                    ivars " << format("0x%" PRIx32, cro.ivars)
5667          << "\n";
5668   if (cro.ivars != 0)
5669     print_ivar_list32_t(cro.ivars, info);
5670   outs() << "           weakIvarLayout "
5671          << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
5672   print_layout_map32(cro.weakIvarLayout, info);
5673   outs() << "           baseProperties "
5674          << format("0x%" PRIx32, cro.baseProperties) << "\n";
5675   if (cro.baseProperties != 0)
5676     print_objc_property_list32(cro.baseProperties, info);
5677   is_meta_class = (cro.flags & RO_META) != 0;
5678   return true;
5679 }
5680 
print_class64_t(uint64_t p,struct DisassembleInfo * info)5681 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
5682   struct class64_t c;
5683   const char *r;
5684   uint32_t offset, left;
5685   SectionRef S;
5686   const char *name;
5687   uint64_t isa_n_value, n_value;
5688 
5689   r = get_pointer_64(p, offset, left, S, info);
5690   if (r == nullptr || left < sizeof(struct class64_t))
5691     return;
5692   memcpy(&c, r, sizeof(struct class64_t));
5693   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5694     swapStruct(c);
5695 
5696   outs() << "           isa " << format("0x%" PRIx64, c.isa);
5697   name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
5698                        isa_n_value, c.isa);
5699   if (name != nullptr)
5700     outs() << " " << name;
5701   outs() << "\n";
5702 
5703   outs() << "    superclass " << format("0x%" PRIx64, c.superclass);
5704   name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
5705                        n_value, c.superclass);
5706   if (name != nullptr)
5707     outs() << " " << name;
5708   else {
5709     name = get_dyld_bind_info_symbolname(S.getAddress() +
5710              offset + offsetof(struct class64_t, superclass), info);
5711     if (name != nullptr)
5712       outs() << " " << name;
5713   }
5714   outs() << "\n";
5715 
5716   outs() << "         cache " << format("0x%" PRIx64, c.cache);
5717   name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
5718                        n_value, c.cache);
5719   if (name != nullptr)
5720     outs() << " " << name;
5721   outs() << "\n";
5722 
5723   outs() << "        vtable " << format("0x%" PRIx64, c.vtable);
5724   name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
5725                        n_value, c.vtable);
5726   if (name != nullptr)
5727     outs() << " " << name;
5728   outs() << "\n";
5729 
5730   name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
5731                        n_value, c.data);
5732   outs() << "          data ";
5733   if (n_value != 0) {
5734     if (info->verbose && name != nullptr)
5735       outs() << name;
5736     else
5737       outs() << format("0x%" PRIx64, n_value);
5738     if (c.data != 0)
5739       outs() << " + " << format("0x%" PRIx64, c.data);
5740   } else
5741     outs() << format("0x%" PRIx64, c.data);
5742   outs() << " (struct class_ro_t *)";
5743 
5744   // This is a Swift class if some of the low bits of the pointer are set.
5745   if ((c.data + n_value) & 0x7)
5746     outs() << " Swift class";
5747   outs() << "\n";
5748   bool is_meta_class;
5749   if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5750     return;
5751 
5752   if (!is_meta_class &&
5753       c.isa + isa_n_value != p &&
5754       c.isa + isa_n_value != 0 &&
5755       info->depth < 100) {
5756       info->depth++;
5757       outs() << "Meta Class\n";
5758       print_class64_t(c.isa + isa_n_value, info);
5759   }
5760 }
5761 
print_class32_t(uint32_t p,struct DisassembleInfo * info)5762 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5763   struct class32_t c;
5764   const char *r;
5765   uint32_t offset, left;
5766   SectionRef S;
5767   const char *name;
5768 
5769   r = get_pointer_32(p, offset, left, S, info);
5770   if (r == nullptr)
5771     return;
5772   memset(&c, '\0', sizeof(struct class32_t));
5773   if (left < sizeof(struct class32_t)) {
5774     memcpy(&c, r, left);
5775     outs() << "   (class_t entends past the end of the section)\n";
5776   } else
5777     memcpy(&c, r, sizeof(struct class32_t));
5778   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5779     swapStruct(c);
5780 
5781   outs() << "           isa " << format("0x%" PRIx32, c.isa);
5782   name =
5783       get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
5784   if (name != nullptr)
5785     outs() << " " << name;
5786   outs() << "\n";
5787 
5788   outs() << "    superclass " << format("0x%" PRIx32, c.superclass);
5789   name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
5790                        c.superclass);
5791   if (name != nullptr)
5792     outs() << " " << name;
5793   outs() << "\n";
5794 
5795   outs() << "         cache " << format("0x%" PRIx32, c.cache);
5796   name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
5797                        c.cache);
5798   if (name != nullptr)
5799     outs() << " " << name;
5800   outs() << "\n";
5801 
5802   outs() << "        vtable " << format("0x%" PRIx32, c.vtable);
5803   name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
5804                        c.vtable);
5805   if (name != nullptr)
5806     outs() << " " << name;
5807   outs() << "\n";
5808 
5809   name =
5810       get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
5811   outs() << "          data " << format("0x%" PRIx32, c.data)
5812          << " (struct class_ro_t *)";
5813 
5814   // This is a Swift class if some of the low bits of the pointer are set.
5815   if (c.data & 0x3)
5816     outs() << " Swift class";
5817   outs() << "\n";
5818   bool is_meta_class;
5819   if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5820     return;
5821 
5822   if (!is_meta_class) {
5823     outs() << "Meta Class\n";
5824     print_class32_t(c.isa, info);
5825   }
5826 }
5827 
print_objc_class_t(struct objc_class_t * objc_class,struct DisassembleInfo * info)5828 static void print_objc_class_t(struct objc_class_t *objc_class,
5829                                struct DisassembleInfo *info) {
5830   uint32_t offset, left, xleft;
5831   const char *name, *p, *ivar_list;
5832   SectionRef S;
5833   int32_t i;
5834   struct objc_ivar_list_t objc_ivar_list;
5835   struct objc_ivar_t ivar;
5836 
5837   outs() << "\t\t      isa " << format("0x%08" PRIx32, objc_class->isa);
5838   if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
5839     name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5840     if (name != nullptr)
5841       outs() << format(" %.*s", left, name);
5842     else
5843       outs() << " (not in an __OBJC section)";
5844   }
5845   outs() << "\n";
5846 
5847   outs() << "\t      super_class "
5848          << format("0x%08" PRIx32, objc_class->super_class);
5849   if (info->verbose) {
5850     name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5851     if (name != nullptr)
5852       outs() << format(" %.*s", left, name);
5853     else
5854       outs() << " (not in an __OBJC section)";
5855   }
5856   outs() << "\n";
5857 
5858   outs() << "\t\t     name " << format("0x%08" PRIx32, objc_class->name);
5859   if (info->verbose) {
5860     name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5861     if (name != nullptr)
5862       outs() << format(" %.*s", left, name);
5863     else
5864       outs() << " (not in an __OBJC section)";
5865   }
5866   outs() << "\n";
5867 
5868   outs() << "\t\t  version " << format("0x%08" PRIx32, objc_class->version)
5869          << "\n";
5870 
5871   outs() << "\t\t     info " << format("0x%08" PRIx32, objc_class->info);
5872   if (info->verbose) {
5873     if (CLS_GETINFO(objc_class, CLS_CLASS))
5874       outs() << " CLS_CLASS";
5875     else if (CLS_GETINFO(objc_class, CLS_META))
5876       outs() << " CLS_META";
5877   }
5878   outs() << "\n";
5879 
5880   outs() << "\t    instance_size "
5881          << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
5882 
5883   p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5884   outs() << "\t\t    ivars " << format("0x%08" PRIx32, objc_class->ivars);
5885   if (p != nullptr) {
5886     if (left > sizeof(struct objc_ivar_list_t)) {
5887       outs() << "\n";
5888       memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5889     } else {
5890       outs() << " (entends past the end of the section)\n";
5891       memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5892       memcpy(&objc_ivar_list, p, left);
5893     }
5894     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5895       swapStruct(objc_ivar_list);
5896     outs() << "\t\t       ivar_count " << objc_ivar_list.ivar_count << "\n";
5897     ivar_list = p + sizeof(struct objc_ivar_list_t);
5898     for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5899       if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5900         outs() << "\t\t remaining ivar's extend past the of the section\n";
5901         break;
5902       }
5903       memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5904              sizeof(struct objc_ivar_t));
5905       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5906         swapStruct(ivar);
5907 
5908       outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
5909       if (info->verbose) {
5910         name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5911         if (name != nullptr)
5912           outs() << format(" %.*s", xleft, name);
5913         else
5914           outs() << " (not in an __OBJC section)";
5915       }
5916       outs() << "\n";
5917 
5918       outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
5919       if (info->verbose) {
5920         name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5921         if (name != nullptr)
5922           outs() << format(" %.*s", xleft, name);
5923         else
5924           outs() << " (not in an __OBJC section)";
5925       }
5926       outs() << "\n";
5927 
5928       outs() << "\t\t      ivar_offset "
5929              << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
5930     }
5931   } else {
5932     outs() << " (not in an __OBJC section)\n";
5933   }
5934 
5935   outs() << "\t\t  methods " << format("0x%08" PRIx32, objc_class->methodLists);
5936   if (print_method_list(objc_class->methodLists, info))
5937     outs() << " (not in an __OBJC section)\n";
5938 
5939   outs() << "\t\t    cache " << format("0x%08" PRIx32, objc_class->cache)
5940          << "\n";
5941 
5942   outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
5943   if (print_protocol_list(objc_class->protocols, 16, info))
5944     outs() << " (not in an __OBJC section)\n";
5945 }
5946 
print_objc_objc_category_t(struct objc_category_t * objc_category,struct DisassembleInfo * info)5947 static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5948                                        struct DisassembleInfo *info) {
5949   uint32_t offset, left;
5950   const char *name;
5951   SectionRef S;
5952 
5953   outs() << "\t       category name "
5954          << format("0x%08" PRIx32, objc_category->category_name);
5955   if (info->verbose) {
5956     name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5957                           true);
5958     if (name != nullptr)
5959       outs() << format(" %.*s", left, name);
5960     else
5961       outs() << " (not in an __OBJC section)";
5962   }
5963   outs() << "\n";
5964 
5965   outs() << "\t\t  class name "
5966          << format("0x%08" PRIx32, objc_category->class_name);
5967   if (info->verbose) {
5968     name =
5969         get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5970     if (name != nullptr)
5971       outs() << format(" %.*s", left, name);
5972     else
5973       outs() << " (not in an __OBJC section)";
5974   }
5975   outs() << "\n";
5976 
5977   outs() << "\t    instance methods "
5978          << format("0x%08" PRIx32, objc_category->instance_methods);
5979   if (print_method_list(objc_category->instance_methods, info))
5980     outs() << " (not in an __OBJC section)\n";
5981 
5982   outs() << "\t       class methods "
5983          << format("0x%08" PRIx32, objc_category->class_methods);
5984   if (print_method_list(objc_category->class_methods, info))
5985     outs() << " (not in an __OBJC section)\n";
5986 }
5987 
print_category64_t(uint64_t p,struct DisassembleInfo * info)5988 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5989   struct category64_t c;
5990   const char *r;
5991   uint32_t offset, xoffset, left;
5992   SectionRef S, xS;
5993   const char *name, *sym_name;
5994   uint64_t n_value;
5995 
5996   r = get_pointer_64(p, offset, left, S, info);
5997   if (r == nullptr)
5998     return;
5999   memset(&c, '\0', sizeof(struct category64_t));
6000   if (left < sizeof(struct category64_t)) {
6001     memcpy(&c, r, left);
6002     outs() << "   (category_t entends past the end of the section)\n";
6003   } else
6004     memcpy(&c, r, sizeof(struct category64_t));
6005   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6006     swapStruct(c);
6007 
6008   outs() << "              name ";
6009   sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
6010                            info, n_value, c.name);
6011   if (n_value != 0) {
6012     if (info->verbose && sym_name != nullptr)
6013       outs() << sym_name;
6014     else
6015       outs() << format("0x%" PRIx64, n_value);
6016     if (c.name != 0)
6017       outs() << " + " << format("0x%" PRIx64, c.name);
6018   } else
6019     outs() << format("0x%" PRIx64, c.name);
6020   name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
6021   if (name != nullptr)
6022     outs() << format(" %.*s", left, name);
6023   outs() << "\n";
6024 
6025   outs() << "               cls ";
6026   sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
6027                            n_value, c.cls);
6028   if (n_value != 0) {
6029     if (info->verbose && sym_name != nullptr)
6030       outs() << sym_name;
6031     else
6032       outs() << format("0x%" PRIx64, n_value);
6033     if (c.cls != 0)
6034       outs() << " + " << format("0x%" PRIx64, c.cls);
6035   } else
6036     outs() << format("0x%" PRIx64, c.cls);
6037   outs() << "\n";
6038   if (c.cls + n_value != 0)
6039     print_class64_t(c.cls + n_value, info);
6040 
6041   outs() << "   instanceMethods ";
6042   sym_name =
6043       get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
6044                     info, n_value, c.instanceMethods);
6045   if (n_value != 0) {
6046     if (info->verbose && sym_name != nullptr)
6047       outs() << sym_name;
6048     else
6049       outs() << format("0x%" PRIx64, n_value);
6050     if (c.instanceMethods != 0)
6051       outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
6052   } else
6053     outs() << format("0x%" PRIx64, c.instanceMethods);
6054   outs() << "\n";
6055   if (c.instanceMethods + n_value != 0)
6056     print_method_list64_t(c.instanceMethods + n_value, info, "");
6057 
6058   outs() << "      classMethods ";
6059   sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
6060                            S, info, n_value, c.classMethods);
6061   if (n_value != 0) {
6062     if (info->verbose && sym_name != nullptr)
6063       outs() << sym_name;
6064     else
6065       outs() << format("0x%" PRIx64, n_value);
6066     if (c.classMethods != 0)
6067       outs() << " + " << format("0x%" PRIx64, c.classMethods);
6068   } else
6069     outs() << format("0x%" PRIx64, c.classMethods);
6070   outs() << "\n";
6071   if (c.classMethods + n_value != 0)
6072     print_method_list64_t(c.classMethods + n_value, info, "");
6073 
6074   outs() << "         protocols ";
6075   sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
6076                            info, n_value, c.protocols);
6077   if (n_value != 0) {
6078     if (info->verbose && sym_name != nullptr)
6079       outs() << sym_name;
6080     else
6081       outs() << format("0x%" PRIx64, n_value);
6082     if (c.protocols != 0)
6083       outs() << " + " << format("0x%" PRIx64, c.protocols);
6084   } else
6085     outs() << format("0x%" PRIx64, c.protocols);
6086   outs() << "\n";
6087   if (c.protocols + n_value != 0)
6088     print_protocol_list64_t(c.protocols + n_value, info);
6089 
6090   outs() << "instanceProperties ";
6091   sym_name =
6092       get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
6093                     S, info, n_value, c.instanceProperties);
6094   if (n_value != 0) {
6095     if (info->verbose && sym_name != nullptr)
6096       outs() << sym_name;
6097     else
6098       outs() << format("0x%" PRIx64, n_value);
6099     if (c.instanceProperties != 0)
6100       outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
6101   } else
6102     outs() << format("0x%" PRIx64, c.instanceProperties);
6103   outs() << "\n";
6104   if (c.instanceProperties + n_value != 0)
6105     print_objc_property_list64(c.instanceProperties + n_value, info);
6106 }
6107 
print_category32_t(uint32_t p,struct DisassembleInfo * info)6108 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
6109   struct category32_t c;
6110   const char *r;
6111   uint32_t offset, left;
6112   SectionRef S, xS;
6113   const char *name;
6114 
6115   r = get_pointer_32(p, offset, left, S, info);
6116   if (r == nullptr)
6117     return;
6118   memset(&c, '\0', sizeof(struct category32_t));
6119   if (left < sizeof(struct category32_t)) {
6120     memcpy(&c, r, left);
6121     outs() << "   (category_t entends past the end of the section)\n";
6122   } else
6123     memcpy(&c, r, sizeof(struct category32_t));
6124   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6125     swapStruct(c);
6126 
6127   outs() << "              name " << format("0x%" PRIx32, c.name);
6128   name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
6129                        c.name);
6130   if (name)
6131     outs() << " " << name;
6132   outs() << "\n";
6133 
6134   outs() << "               cls " << format("0x%" PRIx32, c.cls) << "\n";
6135   if (c.cls != 0)
6136     print_class32_t(c.cls, info);
6137   outs() << "   instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
6138          << "\n";
6139   if (c.instanceMethods != 0)
6140     print_method_list32_t(c.instanceMethods, info, "");
6141   outs() << "      classMethods " << format("0x%" PRIx32, c.classMethods)
6142          << "\n";
6143   if (c.classMethods != 0)
6144     print_method_list32_t(c.classMethods, info, "");
6145   outs() << "         protocols " << format("0x%" PRIx32, c.protocols) << "\n";
6146   if (c.protocols != 0)
6147     print_protocol_list32_t(c.protocols, info);
6148   outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
6149          << "\n";
6150   if (c.instanceProperties != 0)
6151     print_objc_property_list32(c.instanceProperties, info);
6152 }
6153 
print_message_refs64(SectionRef S,struct DisassembleInfo * info)6154 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
6155   uint32_t i, left, offset, xoffset;
6156   uint64_t p, n_value;
6157   struct message_ref64 mr;
6158   const char *name, *sym_name;
6159   const char *r;
6160   SectionRef xS;
6161 
6162   if (S == SectionRef())
6163     return;
6164 
6165   StringRef SectName;
6166   Expected<StringRef> SecNameOrErr = S.getName();
6167   if (SecNameOrErr)
6168     SectName = *SecNameOrErr;
6169   else
6170     consumeError(SecNameOrErr.takeError());
6171 
6172   DataRefImpl Ref = S.getRawDataRefImpl();
6173   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6174   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6175   offset = 0;
6176   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6177     p = S.getAddress() + i;
6178     r = get_pointer_64(p, offset, left, S, info);
6179     if (r == nullptr)
6180       return;
6181     memset(&mr, '\0', sizeof(struct message_ref64));
6182     if (left < sizeof(struct message_ref64)) {
6183       memcpy(&mr, r, left);
6184       outs() << "   (message_ref entends past the end of the section)\n";
6185     } else
6186       memcpy(&mr, r, sizeof(struct message_ref64));
6187     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6188       swapStruct(mr);
6189 
6190     outs() << "  imp ";
6191     name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
6192                          n_value, mr.imp);
6193     if (n_value != 0) {
6194       outs() << format("0x%" PRIx64, n_value) << " ";
6195       if (mr.imp != 0)
6196         outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
6197     } else
6198       outs() << format("0x%" PRIx64, mr.imp) << " ";
6199     if (name != nullptr)
6200       outs() << " " << name;
6201     outs() << "\n";
6202 
6203     outs() << "  sel ";
6204     sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
6205                              info, n_value, mr.sel);
6206     if (n_value != 0) {
6207       if (info->verbose && sym_name != nullptr)
6208         outs() << sym_name;
6209       else
6210         outs() << format("0x%" PRIx64, n_value);
6211       if (mr.sel != 0)
6212         outs() << " + " << format("0x%" PRIx64, mr.sel);
6213     } else
6214       outs() << format("0x%" PRIx64, mr.sel);
6215     name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
6216     if (name != nullptr)
6217       outs() << format(" %.*s", left, name);
6218     outs() << "\n";
6219 
6220     offset += sizeof(struct message_ref64);
6221   }
6222 }
6223 
print_message_refs32(SectionRef S,struct DisassembleInfo * info)6224 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
6225   uint32_t i, left, offset, xoffset, p;
6226   struct message_ref32 mr;
6227   const char *name, *r;
6228   SectionRef xS;
6229 
6230   if (S == SectionRef())
6231     return;
6232 
6233   StringRef SectName;
6234   Expected<StringRef> SecNameOrErr = S.getName();
6235   if (SecNameOrErr)
6236     SectName = *SecNameOrErr;
6237   else
6238     consumeError(SecNameOrErr.takeError());
6239 
6240   DataRefImpl Ref = S.getRawDataRefImpl();
6241   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6242   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6243   offset = 0;
6244   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6245     p = S.getAddress() + i;
6246     r = get_pointer_32(p, offset, left, S, info);
6247     if (r == nullptr)
6248       return;
6249     memset(&mr, '\0', sizeof(struct message_ref32));
6250     if (left < sizeof(struct message_ref32)) {
6251       memcpy(&mr, r, left);
6252       outs() << "   (message_ref entends past the end of the section)\n";
6253     } else
6254       memcpy(&mr, r, sizeof(struct message_ref32));
6255     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6256       swapStruct(mr);
6257 
6258     outs() << "  imp " << format("0x%" PRIx32, mr.imp);
6259     name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
6260                          mr.imp);
6261     if (name != nullptr)
6262       outs() << " " << name;
6263     outs() << "\n";
6264 
6265     outs() << "  sel " << format("0x%" PRIx32, mr.sel);
6266     name = get_pointer_32(mr.sel, xoffset, left, xS, info);
6267     if (name != nullptr)
6268       outs() << " " << name;
6269     outs() << "\n";
6270 
6271     offset += sizeof(struct message_ref32);
6272   }
6273 }
6274 
print_image_info64(SectionRef S,struct DisassembleInfo * info)6275 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
6276   uint32_t left, offset, swift_version;
6277   uint64_t p;
6278   struct objc_image_info64 o;
6279   const char *r;
6280 
6281   if (S == SectionRef())
6282     return;
6283 
6284   StringRef SectName;
6285   Expected<StringRef> SecNameOrErr = S.getName();
6286   if (SecNameOrErr)
6287     SectName = *SecNameOrErr;
6288   else
6289     consumeError(SecNameOrErr.takeError());
6290 
6291   DataRefImpl Ref = S.getRawDataRefImpl();
6292   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6293   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6294   p = S.getAddress();
6295   r = get_pointer_64(p, offset, left, S, info);
6296   if (r == nullptr)
6297     return;
6298   memset(&o, '\0', sizeof(struct objc_image_info64));
6299   if (left < sizeof(struct objc_image_info64)) {
6300     memcpy(&o, r, left);
6301     outs() << "   (objc_image_info entends past the end of the section)\n";
6302   } else
6303     memcpy(&o, r, sizeof(struct objc_image_info64));
6304   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6305     swapStruct(o);
6306   outs() << "  version " << o.version << "\n";
6307   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6308   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6309     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6310   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6311     outs() << " OBJC_IMAGE_SUPPORTS_GC";
6312   if (o.flags & OBJC_IMAGE_IS_SIMULATED)
6313     outs() << " OBJC_IMAGE_IS_SIMULATED";
6314   if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
6315     outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
6316   swift_version = (o.flags >> 8) & 0xff;
6317   if (swift_version != 0) {
6318     if (swift_version == 1)
6319       outs() << " Swift 1.0";
6320     else if (swift_version == 2)
6321       outs() << " Swift 1.1";
6322     else if(swift_version == 3)
6323       outs() << " Swift 2.0";
6324     else if(swift_version == 4)
6325       outs() << " Swift 3.0";
6326     else if(swift_version == 5)
6327       outs() << " Swift 4.0";
6328     else if(swift_version == 6)
6329       outs() << " Swift 4.1/Swift 4.2";
6330     else if(swift_version == 7)
6331       outs() << " Swift 5 or later";
6332     else
6333       outs() << " unknown future Swift version (" << swift_version << ")";
6334   }
6335   outs() << "\n";
6336 }
6337 
print_image_info32(SectionRef S,struct DisassembleInfo * info)6338 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
6339   uint32_t left, offset, swift_version, p;
6340   struct objc_image_info32 o;
6341   const char *r;
6342 
6343   if (S == SectionRef())
6344     return;
6345 
6346   StringRef SectName;
6347   Expected<StringRef> SecNameOrErr = S.getName();
6348   if (SecNameOrErr)
6349     SectName = *SecNameOrErr;
6350   else
6351     consumeError(SecNameOrErr.takeError());
6352 
6353   DataRefImpl Ref = S.getRawDataRefImpl();
6354   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6355   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6356   p = S.getAddress();
6357   r = get_pointer_32(p, offset, left, S, info);
6358   if (r == nullptr)
6359     return;
6360   memset(&o, '\0', sizeof(struct objc_image_info32));
6361   if (left < sizeof(struct objc_image_info32)) {
6362     memcpy(&o, r, left);
6363     outs() << "   (objc_image_info entends past the end of the section)\n";
6364   } else
6365     memcpy(&o, r, sizeof(struct objc_image_info32));
6366   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6367     swapStruct(o);
6368   outs() << "  version " << o.version << "\n";
6369   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6370   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6371     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6372   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6373     outs() << " OBJC_IMAGE_SUPPORTS_GC";
6374   swift_version = (o.flags >> 8) & 0xff;
6375   if (swift_version != 0) {
6376     if (swift_version == 1)
6377       outs() << " Swift 1.0";
6378     else if (swift_version == 2)
6379       outs() << " Swift 1.1";
6380     else if(swift_version == 3)
6381       outs() << " Swift 2.0";
6382     else if(swift_version == 4)
6383       outs() << " Swift 3.0";
6384     else if(swift_version == 5)
6385       outs() << " Swift 4.0";
6386     else if(swift_version == 6)
6387       outs() << " Swift 4.1/Swift 4.2";
6388     else if(swift_version == 7)
6389       outs() << " Swift 5 or later";
6390     else
6391       outs() << " unknown future Swift version (" << swift_version << ")";
6392   }
6393   outs() << "\n";
6394 }
6395 
print_image_info(SectionRef S,struct DisassembleInfo * info)6396 static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
6397   uint32_t left, offset, p;
6398   struct imageInfo_t o;
6399   const char *r;
6400 
6401   StringRef SectName;
6402   Expected<StringRef> SecNameOrErr = S.getName();
6403   if (SecNameOrErr)
6404     SectName = *SecNameOrErr;
6405   else
6406     consumeError(SecNameOrErr.takeError());
6407 
6408   DataRefImpl Ref = S.getRawDataRefImpl();
6409   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6410   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6411   p = S.getAddress();
6412   r = get_pointer_32(p, offset, left, S, info);
6413   if (r == nullptr)
6414     return;
6415   memset(&o, '\0', sizeof(struct imageInfo_t));
6416   if (left < sizeof(struct imageInfo_t)) {
6417     memcpy(&o, r, left);
6418     outs() << " (imageInfo entends past the end of the section)\n";
6419   } else
6420     memcpy(&o, r, sizeof(struct imageInfo_t));
6421   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6422     swapStruct(o);
6423   outs() << "  version " << o.version << "\n";
6424   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6425   if (o.flags & 0x1)
6426     outs() << "  F&C";
6427   if (o.flags & 0x2)
6428     outs() << " GC";
6429   if (o.flags & 0x4)
6430     outs() << " GC-only";
6431   else
6432     outs() << " RR";
6433   outs() << "\n";
6434 }
6435 
printObjc2_64bit_MetaData(MachOObjectFile * O,bool verbose)6436 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
6437   SymbolAddressMap AddrMap;
6438   if (verbose)
6439     CreateSymbolAddressMap(O, &AddrMap);
6440 
6441   std::vector<SectionRef> Sections;
6442   append_range(Sections, O->sections());
6443 
6444   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6445 
6446   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6447   if (CL == SectionRef())
6448     CL = get_section(O, "__DATA", "__objc_classlist");
6449   if (CL == SectionRef())
6450     CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6451   if (CL == SectionRef())
6452     CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6453   info.S = CL;
6454   walk_pointer_list_64("class", CL, O, &info, print_class64_t);
6455 
6456   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6457   if (CR == SectionRef())
6458     CR = get_section(O, "__DATA", "__objc_classrefs");
6459   if (CR == SectionRef())
6460     CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6461   if (CR == SectionRef())
6462     CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6463   info.S = CR;
6464   walk_pointer_list_64("class refs", CR, O, &info, nullptr);
6465 
6466   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6467   if (SR == SectionRef())
6468     SR = get_section(O, "__DATA", "__objc_superrefs");
6469   if (SR == SectionRef())
6470     SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6471   if (SR == SectionRef())
6472     SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6473   info.S = SR;
6474   walk_pointer_list_64("super refs", SR, O, &info, nullptr);
6475 
6476   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6477   if (CA == SectionRef())
6478     CA = get_section(O, "__DATA", "__objc_catlist");
6479   if (CA == SectionRef())
6480     CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6481   if (CA == SectionRef())
6482     CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6483   info.S = CA;
6484   walk_pointer_list_64("category", CA, O, &info, print_category64_t);
6485 
6486   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6487   if (PL == SectionRef())
6488     PL = get_section(O, "__DATA", "__objc_protolist");
6489   if (PL == SectionRef())
6490     PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6491   if (PL == SectionRef())
6492     PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6493   info.S = PL;
6494   walk_pointer_list_64("protocol", PL, O, &info, nullptr);
6495 
6496   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6497   if (MR == SectionRef())
6498     MR = get_section(O, "__DATA", "__objc_msgrefs");
6499   if (MR == SectionRef())
6500     MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6501   if (MR == SectionRef())
6502     MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6503   info.S = MR;
6504   print_message_refs64(MR, &info);
6505 
6506   SectionRef II = get_section(O, "__OBJC2", "__image_info");
6507   if (II == SectionRef())
6508     II = get_section(O, "__DATA", "__objc_imageinfo");
6509   if (II == SectionRef())
6510     II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6511   if (II == SectionRef())
6512     II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6513   info.S = II;
6514   print_image_info64(II, &info);
6515 }
6516 
printObjc2_32bit_MetaData(MachOObjectFile * O,bool verbose)6517 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6518   SymbolAddressMap AddrMap;
6519   if (verbose)
6520     CreateSymbolAddressMap(O, &AddrMap);
6521 
6522   std::vector<SectionRef> Sections;
6523   append_range(Sections, O->sections());
6524 
6525   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6526 
6527   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6528   if (CL == SectionRef())
6529     CL = get_section(O, "__DATA", "__objc_classlist");
6530   if (CL == SectionRef())
6531     CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6532   if (CL == SectionRef())
6533     CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6534   info.S = CL;
6535   walk_pointer_list_32("class", CL, O, &info, print_class32_t);
6536 
6537   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6538   if (CR == SectionRef())
6539     CR = get_section(O, "__DATA", "__objc_classrefs");
6540   if (CR == SectionRef())
6541     CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6542   if (CR == SectionRef())
6543     CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6544   info.S = CR;
6545   walk_pointer_list_32("class refs", CR, O, &info, nullptr);
6546 
6547   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6548   if (SR == SectionRef())
6549     SR = get_section(O, "__DATA", "__objc_superrefs");
6550   if (SR == SectionRef())
6551     SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6552   if (SR == SectionRef())
6553     SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6554   info.S = SR;
6555   walk_pointer_list_32("super refs", SR, O, &info, nullptr);
6556 
6557   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6558   if (CA == SectionRef())
6559     CA = get_section(O, "__DATA", "__objc_catlist");
6560   if (CA == SectionRef())
6561     CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6562   if (CA == SectionRef())
6563     CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6564   info.S = CA;
6565   walk_pointer_list_32("category", CA, O, &info, print_category32_t);
6566 
6567   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6568   if (PL == SectionRef())
6569     PL = get_section(O, "__DATA", "__objc_protolist");
6570   if (PL == SectionRef())
6571     PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6572   if (PL == SectionRef())
6573     PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6574   info.S = PL;
6575   walk_pointer_list_32("protocol", PL, O, &info, nullptr);
6576 
6577   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6578   if (MR == SectionRef())
6579     MR = get_section(O, "__DATA", "__objc_msgrefs");
6580   if (MR == SectionRef())
6581     MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6582   if (MR == SectionRef())
6583     MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6584   info.S = MR;
6585   print_message_refs32(MR, &info);
6586 
6587   SectionRef II = get_section(O, "__OBJC2", "__image_info");
6588   if (II == SectionRef())
6589     II = get_section(O, "__DATA", "__objc_imageinfo");
6590   if (II == SectionRef())
6591     II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6592   if (II == SectionRef())
6593     II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6594   info.S = II;
6595   print_image_info32(II, &info);
6596 }
6597 
printObjc1_32bit_MetaData(MachOObjectFile * O,bool verbose)6598 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6599   uint32_t i, j, p, offset, xoffset, left, defs_left, def;
6600   const char *r, *name, *defs;
6601   struct objc_module_t module;
6602   SectionRef S, xS;
6603   struct objc_symtab_t symtab;
6604   struct objc_class_t objc_class;
6605   struct objc_category_t objc_category;
6606 
6607   outs() << "Objective-C segment\n";
6608   S = get_section(O, "__OBJC", "__module_info");
6609   if (S == SectionRef())
6610     return false;
6611 
6612   SymbolAddressMap AddrMap;
6613   if (verbose)
6614     CreateSymbolAddressMap(O, &AddrMap);
6615 
6616   std::vector<SectionRef> Sections;
6617   append_range(Sections, O->sections());
6618 
6619   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6620 
6621   for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
6622     p = S.getAddress() + i;
6623     r = get_pointer_32(p, offset, left, S, &info, true);
6624     if (r == nullptr)
6625       return true;
6626     memset(&module, '\0', sizeof(struct objc_module_t));
6627     if (left < sizeof(struct objc_module_t)) {
6628       memcpy(&module, r, left);
6629       outs() << "   (module extends past end of __module_info section)\n";
6630     } else
6631       memcpy(&module, r, sizeof(struct objc_module_t));
6632     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6633       swapStruct(module);
6634 
6635     outs() << "Module " << format("0x%" PRIx32, p) << "\n";
6636     outs() << "    version " << module.version << "\n";
6637     outs() << "       size " << module.size << "\n";
6638     outs() << "       name ";
6639     name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
6640     if (name != nullptr)
6641       outs() << format("%.*s", left, name);
6642     else
6643       outs() << format("0x%08" PRIx32, module.name)
6644              << "(not in an __OBJC section)";
6645     outs() << "\n";
6646 
6647     r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
6648     if (module.symtab == 0 || r == nullptr) {
6649       outs() << "     symtab " << format("0x%08" PRIx32, module.symtab)
6650              << " (not in an __OBJC section)\n";
6651       continue;
6652     }
6653     outs() << "     symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
6654     memset(&symtab, '\0', sizeof(struct objc_symtab_t));
6655     defs_left = 0;
6656     defs = nullptr;
6657     if (left < sizeof(struct objc_symtab_t)) {
6658       memcpy(&symtab, r, left);
6659       outs() << "\tsymtab extends past end of an __OBJC section)\n";
6660     } else {
6661       memcpy(&symtab, r, sizeof(struct objc_symtab_t));
6662       if (left > sizeof(struct objc_symtab_t)) {
6663         defs_left = left - sizeof(struct objc_symtab_t);
6664         defs = r + sizeof(struct objc_symtab_t);
6665       }
6666     }
6667     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6668       swapStruct(symtab);
6669 
6670     outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
6671     r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
6672     outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
6673     if (r == nullptr)
6674       outs() << " (not in an __OBJC section)";
6675     outs() << "\n";
6676     outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
6677     outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
6678     if (symtab.cls_def_cnt > 0)
6679       outs() << "\tClass Definitions\n";
6680     for (j = 0; j < symtab.cls_def_cnt; j++) {
6681       if ((j + 1) * sizeof(uint32_t) > defs_left) {
6682         outs() << "\t(remaining class defs entries entends past the end of the "
6683                << "section)\n";
6684         break;
6685       }
6686       memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
6687       if (O->isLittleEndian() != sys::IsLittleEndianHost)
6688         sys::swapByteOrder(def);
6689 
6690       r = get_pointer_32(def, xoffset, left, xS, &info, true);
6691       outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
6692       if (r != nullptr) {
6693         if (left > sizeof(struct objc_class_t)) {
6694           outs() << "\n";
6695           memcpy(&objc_class, r, sizeof(struct objc_class_t));
6696         } else {
6697           outs() << " (entends past the end of the section)\n";
6698           memset(&objc_class, '\0', sizeof(struct objc_class_t));
6699           memcpy(&objc_class, r, left);
6700         }
6701         if (O->isLittleEndian() != sys::IsLittleEndianHost)
6702           swapStruct(objc_class);
6703         print_objc_class_t(&objc_class, &info);
6704       } else {
6705         outs() << "(not in an __OBJC section)\n";
6706       }
6707 
6708       if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
6709         outs() << "\tMeta Class";
6710         r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
6711         if (r != nullptr) {
6712           if (left > sizeof(struct objc_class_t)) {
6713             outs() << "\n";
6714             memcpy(&objc_class, r, sizeof(struct objc_class_t));
6715           } else {
6716             outs() << " (entends past the end of the section)\n";
6717             memset(&objc_class, '\0', sizeof(struct objc_class_t));
6718             memcpy(&objc_class, r, left);
6719           }
6720           if (O->isLittleEndian() != sys::IsLittleEndianHost)
6721             swapStruct(objc_class);
6722           print_objc_class_t(&objc_class, &info);
6723         } else {
6724           outs() << "(not in an __OBJC section)\n";
6725         }
6726       }
6727     }
6728     if (symtab.cat_def_cnt > 0)
6729       outs() << "\tCategory Definitions\n";
6730     for (j = 0; j < symtab.cat_def_cnt; j++) {
6731       if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
6732         outs() << "\t(remaining category defs entries entends past the end of "
6733                << "the section)\n";
6734         break;
6735       }
6736       memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6737              sizeof(uint32_t));
6738       if (O->isLittleEndian() != sys::IsLittleEndianHost)
6739         sys::swapByteOrder(def);
6740 
6741       r = get_pointer_32(def, xoffset, left, xS, &info, true);
6742       outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6743              << format("0x%08" PRIx32, def);
6744       if (r != nullptr) {
6745         if (left > sizeof(struct objc_category_t)) {
6746           outs() << "\n";
6747           memcpy(&objc_category, r, sizeof(struct objc_category_t));
6748         } else {
6749           outs() << " (entends past the end of the section)\n";
6750           memset(&objc_category, '\0', sizeof(struct objc_category_t));
6751           memcpy(&objc_category, r, left);
6752         }
6753         if (O->isLittleEndian() != sys::IsLittleEndianHost)
6754           swapStruct(objc_category);
6755         print_objc_objc_category_t(&objc_category, &info);
6756       } else {
6757         outs() << "(not in an __OBJC section)\n";
6758       }
6759     }
6760   }
6761   const SectionRef II = get_section(O, "__OBJC", "__image_info");
6762   if (II != SectionRef())
6763     print_image_info(II, &info);
6764 
6765   return true;
6766 }
6767 
DumpProtocolSection(MachOObjectFile * O,const char * sect,uint32_t size,uint32_t addr)6768 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6769                                 uint32_t size, uint32_t addr) {
6770   SymbolAddressMap AddrMap;
6771   CreateSymbolAddressMap(O, &AddrMap);
6772 
6773   std::vector<SectionRef> Sections;
6774   append_range(Sections, O->sections());
6775 
6776   struct DisassembleInfo info(O, &AddrMap, &Sections, true);
6777 
6778   const char *p;
6779   struct objc_protocol_t protocol;
6780   uint32_t left, paddr;
6781   for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6782     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6783     left = size - (p - sect);
6784     if (left < sizeof(struct objc_protocol_t)) {
6785       outs() << "Protocol extends past end of __protocol section\n";
6786       memcpy(&protocol, p, left);
6787     } else
6788       memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6789     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6790       swapStruct(protocol);
6791     paddr = addr + (p - sect);
6792     outs() << "Protocol " << format("0x%" PRIx32, paddr);
6793     if (print_protocol(paddr, 0, &info))
6794       outs() << "(not in an __OBJC section)\n";
6795   }
6796 }
6797 
printObjcMetaData(MachOObjectFile * O,bool verbose)6798 static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6799   if (O->is64Bit())
6800     printObjc2_64bit_MetaData(O, verbose);
6801   else {
6802     MachO::mach_header H;
6803     H = O->getHeader();
6804     if (H.cputype == MachO::CPU_TYPE_ARM)
6805       printObjc2_32bit_MetaData(O, verbose);
6806     else {
6807       // This is the 32-bit non-arm cputype case.  Which is normally
6808       // the first Objective-C ABI.  But it may be the case of a
6809       // binary for the iOS simulator which is the second Objective-C
6810       // ABI.  In that case printObjc1_32bit_MetaData() will determine that
6811       // and return false.
6812       if (!printObjc1_32bit_MetaData(O, verbose))
6813         printObjc2_32bit_MetaData(O, verbose);
6814     }
6815   }
6816 }
6817 
6818 // GuessLiteralPointer returns a string which for the item in the Mach-O file
6819 // for the address passed in as ReferenceValue for printing as a comment with
6820 // the instruction and also returns the corresponding type of that item
6821 // indirectly through ReferenceType.
6822 //
6823 // If ReferenceValue is an address of literal cstring then a pointer to the
6824 // cstring is returned and ReferenceType is set to
6825 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6826 //
6827 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6828 // Class ref that name is returned and the ReferenceType is set accordingly.
6829 //
6830 // Lastly, literals which are Symbol address in a literal pool are looked for
6831 // and if found the symbol name is returned and ReferenceType is set to
6832 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6833 //
6834 // If there is no item in the Mach-O file for the address passed in as
6835 // ReferenceValue nullptr is returned and ReferenceType is unchanged.
GuessLiteralPointer(uint64_t ReferenceValue,uint64_t ReferencePC,uint64_t * ReferenceType,struct DisassembleInfo * info)6836 static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6837                                        uint64_t ReferencePC,
6838                                        uint64_t *ReferenceType,
6839                                        struct DisassembleInfo *info) {
6840   // First see if there is an external relocation entry at the ReferencePC.
6841   if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6842     uint64_t sect_addr = info->S.getAddress();
6843     uint64_t sect_offset = ReferencePC - sect_addr;
6844     bool reloc_found = false;
6845     DataRefImpl Rel;
6846     MachO::any_relocation_info RE;
6847     bool isExtern = false;
6848     SymbolRef Symbol;
6849     for (const RelocationRef &Reloc : info->S.relocations()) {
6850       uint64_t RelocOffset = Reloc.getOffset();
6851       if (RelocOffset == sect_offset) {
6852         Rel = Reloc.getRawDataRefImpl();
6853         RE = info->O->getRelocation(Rel);
6854         if (info->O->isRelocationScattered(RE))
6855           continue;
6856         isExtern = info->O->getPlainRelocationExternal(RE);
6857         if (isExtern) {
6858           symbol_iterator RelocSym = Reloc.getSymbol();
6859           Symbol = *RelocSym;
6860         }
6861         reloc_found = true;
6862         break;
6863       }
6864     }
6865     // If there is an external relocation entry for a symbol in a section
6866     // then used that symbol's value for the value of the reference.
6867     if (reloc_found && isExtern) {
6868       if (info->O->getAnyRelocationPCRel(RE)) {
6869         unsigned Type = info->O->getAnyRelocationType(RE);
6870         if (Type == MachO::X86_64_RELOC_SIGNED) {
6871           ReferenceValue = cantFail(Symbol.getValue());
6872         }
6873       }
6874     }
6875   }
6876 
6877   // Look for literals such as Objective-C CFStrings refs, Selector refs,
6878   // Message refs and Class refs.
6879   bool classref, selref, msgref, cfstring;
6880   uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6881                                                selref, msgref, cfstring);
6882   if (classref && pointer_value == 0) {
6883     // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6884     // And the pointer_value in that section is typically zero as it will be
6885     // set by dyld as part of the "bind information".
6886     const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6887     if (name != nullptr) {
6888       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6889       const char *class_name = strrchr(name, '$');
6890       if (class_name != nullptr && class_name[1] == '_' &&
6891           class_name[2] != '\0') {
6892         info->class_name = class_name + 2;
6893         return name;
6894       }
6895     }
6896   }
6897 
6898   if (classref) {
6899     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6900     const char *name =
6901         get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6902     if (name != nullptr)
6903       info->class_name = name;
6904     else
6905       name = "bad class ref";
6906     return name;
6907   }
6908 
6909   if (cfstring) {
6910     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
6911     const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6912     return name;
6913   }
6914 
6915   if (selref && pointer_value == 0)
6916     pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6917 
6918   if (pointer_value != 0)
6919     ReferenceValue = pointer_value;
6920 
6921   const char *name = GuessCstringPointer(ReferenceValue, info);
6922   if (name) {
6923     if (pointer_value != 0 && selref) {
6924       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
6925       info->selector_name = name;
6926     } else if (pointer_value != 0 && msgref) {
6927       info->class_name = nullptr;
6928       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
6929       info->selector_name = name;
6930     } else
6931       *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
6932     return name;
6933   }
6934 
6935   // Lastly look for an indirect symbol with this ReferenceValue which is in
6936   // a literal pool.  If found return that symbol name.
6937   name = GuessIndirectSymbol(ReferenceValue, info);
6938   if (name) {
6939     *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
6940     return name;
6941   }
6942 
6943   return nullptr;
6944 }
6945 
6946 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6947 // the Symbolizer.  It looks up the ReferenceValue using the info passed via the
6948 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6949 // is created and returns the symbol name that matches the ReferenceValue or
6950 // nullptr if none.  The ReferenceType is passed in for the IN type of
6951 // reference the instruction is making from the values in defined in the header
6952 // "llvm-c/Disassembler.h".  On return the ReferenceType can set to a specific
6953 // Out type and the ReferenceName will also be set which is added as a comment
6954 // to the disassembled instruction.
6955 //
6956 // If the symbol name is a C++ mangled name then the demangled name is
6957 // returned through ReferenceName and ReferenceType is set to
6958 // LLVMDisassembler_ReferenceType_DeMangled_Name .
6959 //
6960 // When this is called to get a symbol name for a branch target then the
6961 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6962 // SymbolValue will be looked for in the indirect symbol table to determine if
6963 // it is an address for a symbol stub.  If so then the symbol name for that
6964 // stub is returned indirectly through ReferenceName and then ReferenceType is
6965 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6966 //
6967 // When this is called with an value loaded via a PC relative load then
6968 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6969 // SymbolValue is checked to be an address of literal pointer, symbol pointer,
6970 // or an Objective-C meta data reference.  If so the output ReferenceType is
6971 // 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)6972 static const char *SymbolizerSymbolLookUp(void *DisInfo,
6973                                           uint64_t ReferenceValue,
6974                                           uint64_t *ReferenceType,
6975                                           uint64_t ReferencePC,
6976                                           const char **ReferenceName) {
6977   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6978   // If no verbose symbolic information is wanted then just return nullptr.
6979   if (!info->verbose) {
6980     *ReferenceName = nullptr;
6981     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6982     return nullptr;
6983   }
6984 
6985   const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6986 
6987   if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
6988     *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6989     if (*ReferenceName != nullptr) {
6990       method_reference(info, ReferenceType, ReferenceName);
6991       if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
6992         *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
6993     } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6994       if (info->demangled_name != nullptr)
6995         free(info->demangled_name);
6996       info->demangled_name = itaniumDemangle(SymbolName + 1);
6997       if (info->demangled_name != nullptr) {
6998         *ReferenceName = info->demangled_name;
6999         *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
7000       } else
7001         *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7002     } else
7003       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7004   } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
7005     *ReferenceName =
7006         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7007     if (*ReferenceName)
7008       method_reference(info, ReferenceType, ReferenceName);
7009     else
7010       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7011     // If this is arm64 and the reference is an adrp instruction save the
7012     // instruction, passed in ReferenceValue and the address of the instruction
7013     // for use later if we see and add immediate instruction.
7014   } else if (info->O->getArch() == Triple::aarch64 &&
7015              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
7016     info->adrp_inst = ReferenceValue;
7017     info->adrp_addr = ReferencePC;
7018     SymbolName = nullptr;
7019     *ReferenceName = nullptr;
7020     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7021     // If this is arm64 and reference is an add immediate instruction and we
7022     // have
7023     // seen an adrp instruction just before it and the adrp's Xd register
7024     // matches
7025     // this add's Xn register reconstruct the value being referenced and look to
7026     // see if it is a literal pointer.  Note the add immediate instruction is
7027     // passed in ReferenceValue.
7028   } else if (info->O->getArch() == Triple::aarch64 &&
7029              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
7030              ReferencePC - 4 == info->adrp_addr &&
7031              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
7032              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
7033     uint32_t addxri_inst;
7034     uint64_t adrp_imm, addxri_imm;
7035 
7036     adrp_imm =
7037         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
7038     if (info->adrp_inst & 0x0200000)
7039       adrp_imm |= 0xfffffffffc000000LL;
7040 
7041     addxri_inst = ReferenceValue;
7042     addxri_imm = (addxri_inst >> 10) & 0xfff;
7043     if (((addxri_inst >> 22) & 0x3) == 1)
7044       addxri_imm <<= 12;
7045 
7046     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
7047                      (adrp_imm << 12) + addxri_imm;
7048 
7049     *ReferenceName =
7050         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7051     if (*ReferenceName == nullptr)
7052       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7053     // If this is arm64 and the reference is a load register instruction and we
7054     // have seen an adrp instruction just before it and the adrp's Xd register
7055     // matches this add's Xn register reconstruct the value being referenced and
7056     // look to see if it is a literal pointer.  Note the load register
7057     // instruction is passed in ReferenceValue.
7058   } else if (info->O->getArch() == Triple::aarch64 &&
7059              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
7060              ReferencePC - 4 == info->adrp_addr &&
7061              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
7062              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
7063     uint32_t ldrxui_inst;
7064     uint64_t adrp_imm, ldrxui_imm;
7065 
7066     adrp_imm =
7067         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
7068     if (info->adrp_inst & 0x0200000)
7069       adrp_imm |= 0xfffffffffc000000LL;
7070 
7071     ldrxui_inst = ReferenceValue;
7072     ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
7073 
7074     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
7075                      (adrp_imm << 12) + (ldrxui_imm << 3);
7076 
7077     *ReferenceName =
7078         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7079     if (*ReferenceName == nullptr)
7080       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7081   }
7082   // If this arm64 and is an load register (PC-relative) instruction the
7083   // ReferenceValue is the PC plus the immediate value.
7084   else if (info->O->getArch() == Triple::aarch64 &&
7085            (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
7086             *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
7087     *ReferenceName =
7088         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7089     if (*ReferenceName == nullptr)
7090       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7091   } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
7092     if (info->demangled_name != nullptr)
7093       free(info->demangled_name);
7094     info->demangled_name = itaniumDemangle(SymbolName + 1);
7095     if (info->demangled_name != nullptr) {
7096       *ReferenceName = info->demangled_name;
7097       *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
7098     }
7099   }
7100   else {
7101     *ReferenceName = nullptr;
7102     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7103   }
7104 
7105   return SymbolName;
7106 }
7107 
7108 /// Emits the comments that are stored in the CommentStream.
7109 /// 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)7110 static void emitComments(raw_svector_ostream &CommentStream,
7111                          SmallString<128> &CommentsToEmit,
7112                          formatted_raw_ostream &FormattedOS,
7113                          const MCAsmInfo &MAI) {
7114   // Flush the stream before taking its content.
7115   StringRef Comments = CommentsToEmit.str();
7116   // Get the default information for printing a comment.
7117   StringRef CommentBegin = MAI.getCommentString();
7118   unsigned CommentColumn = MAI.getCommentColumn();
7119   ListSeparator LS("\n");
7120   while (!Comments.empty()) {
7121     FormattedOS << LS;
7122     // Emit a line of comments.
7123     FormattedOS.PadToColumn(CommentColumn);
7124     size_t Position = Comments.find('\n');
7125     FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
7126     // Move after the newline character.
7127     Comments = Comments.substr(Position + 1);
7128   }
7129   FormattedOS.flush();
7130 
7131   // Tell the comment stream that the vector changed underneath it.
7132   CommentsToEmit.clear();
7133 }
7134 
7135 const MachOObjectFile *
getMachODSymObject(const MachOObjectFile * MachOOF,StringRef Filename,std::unique_ptr<Binary> & DSYMBinary,std::unique_ptr<MemoryBuffer> & DSYMBuf)7136 objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename,
7137                             std::unique_ptr<Binary> &DSYMBinary,
7138                             std::unique_ptr<MemoryBuffer> &DSYMBuf) {
7139   const MachOObjectFile *DbgObj = MachOOF;
7140   std::string DSYMPath;
7141 
7142   // Auto-detect w/o --dsym.
7143   if (DSYMFile.empty()) {
7144     sys::fs::file_status DSYMStatus;
7145     Twine FilenameDSYM = Filename + ".dSYM";
7146     if (!status(FilenameDSYM, DSYMStatus)) {
7147       if (sys::fs::is_directory(DSYMStatus)) {
7148         SmallString<1024> Path;
7149         FilenameDSYM.toVector(Path);
7150         sys::path::append(Path, "Contents", "Resources", "DWARF",
7151                           sys::path::filename(Filename));
7152         DSYMPath = std::string(Path);
7153       } else if (sys::fs::is_regular_file(DSYMStatus)) {
7154         DSYMPath = FilenameDSYM.str();
7155       }
7156     }
7157   }
7158 
7159   if (DSYMPath.empty() && !DSYMFile.empty()) {
7160     // If DSYMPath is a .dSYM directory, append the Mach-O file.
7161     if (sys::fs::is_directory(DSYMFile) &&
7162         sys::path::extension(DSYMFile) == ".dSYM") {
7163       SmallString<128> ShortName(sys::path::filename(DSYMFile));
7164       sys::path::replace_extension(ShortName, "");
7165       SmallString<1024> FullPath(DSYMFile);
7166       sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName);
7167       DSYMPath = FullPath.str();
7168     } else {
7169       DSYMPath = DSYMFile;
7170     }
7171   }
7172 
7173   if (!DSYMPath.empty()) {
7174     // Load the file.
7175     ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
7176         MemoryBuffer::getFileOrSTDIN(DSYMPath);
7177     if (std::error_code EC = BufOrErr.getError()) {
7178       reportError(errorCodeToError(EC), DSYMPath);
7179       return nullptr;
7180     }
7181 
7182     // We need to keep the file alive, because we're replacing DbgObj with it.
7183     DSYMBuf = std::move(BufOrErr.get());
7184 
7185     Expected<std::unique_ptr<Binary>> BinaryOrErr =
7186         createBinary(DSYMBuf->getMemBufferRef());
7187     if (!BinaryOrErr) {
7188       reportError(BinaryOrErr.takeError(), DSYMPath);
7189       return nullptr;
7190     }
7191 
7192     // We need to keep the Binary alive with the buffer
7193     DSYMBinary = std::move(BinaryOrErr.get());
7194     if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) {
7195       // this is a Mach-O object file, use it
7196       if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) {
7197         DbgObj = MachDSYM;
7198       } else {
7199         WithColor::error(errs(), "llvm-objdump")
7200             << DSYMPath << " is not a Mach-O file type.\n";
7201         return nullptr;
7202       }
7203     } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) {
7204       // this is a Universal Binary, find a Mach-O for this architecture
7205       uint32_t CPUType, CPUSubType;
7206       const char *ArchFlag;
7207       if (MachOOF->is64Bit()) {
7208         const MachO::mach_header_64 H_64 = MachOOF->getHeader64();
7209         CPUType = H_64.cputype;
7210         CPUSubType = H_64.cpusubtype;
7211       } else {
7212         const MachO::mach_header H = MachOOF->getHeader();
7213         CPUType = H.cputype;
7214         CPUSubType = H.cpusubtype;
7215       }
7216       Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr,
7217                                                 &ArchFlag);
7218       Expected<std::unique_ptr<MachOObjectFile>> MachDSYM =
7219           UB->getMachOObjectForArch(ArchFlag);
7220       if (!MachDSYM) {
7221         reportError(MachDSYM.takeError(), DSYMPath);
7222         return nullptr;
7223       }
7224 
7225       // We need to keep the Binary alive with the buffer
7226       DbgObj = &*MachDSYM.get();
7227       DSYMBinary = std::move(*MachDSYM);
7228     } else {
7229       WithColor::error(errs(), "llvm-objdump")
7230           << DSYMPath << " is not a Mach-O or Universal file type.\n";
7231       return nullptr;
7232     }
7233   }
7234   return DbgObj;
7235 }
7236 
DisassembleMachO(StringRef Filename,MachOObjectFile * MachOOF,StringRef DisSegName,StringRef DisSectName)7237 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
7238                              StringRef DisSegName, StringRef DisSectName) {
7239   const char *McpuDefault = nullptr;
7240   const Target *ThumbTarget = nullptr;
7241   const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
7242   if (!TheTarget) {
7243     // GetTarget prints out stuff.
7244     return;
7245   }
7246   std::string MachOMCPU;
7247   if (MCPU.empty() && McpuDefault)
7248     MachOMCPU = McpuDefault;
7249   else
7250     MachOMCPU = MCPU;
7251 
7252 #define CHECK_TARGET_INFO_CREATION(NAME)                                       \
7253   do {                                                                         \
7254     if (!NAME) {                                                               \
7255       WithColor::error(errs(), "llvm-objdump")                                 \
7256           << "couldn't initialize disassembler for target " << TripleName      \
7257           << '\n';                                                             \
7258       return;                                                                  \
7259     }                                                                          \
7260   } while (false)
7261 #define CHECK_THUMB_TARGET_INFO_CREATION(NAME)                                 \
7262   do {                                                                         \
7263     if (!NAME) {                                                               \
7264       WithColor::error(errs(), "llvm-objdump")                                 \
7265           << "couldn't initialize disassembler for target " << ThumbTripleName \
7266           << '\n';                                                             \
7267       return;                                                                  \
7268     }                                                                          \
7269   } while (false)
7270 
7271   std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
7272   CHECK_TARGET_INFO_CREATION(InstrInfo);
7273   std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
7274   if (ThumbTarget) {
7275     ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
7276     CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo);
7277   }
7278 
7279   // Package up features to be passed to target/subtarget
7280   std::string FeaturesStr;
7281   if (!MAttrs.empty()) {
7282     SubtargetFeatures Features;
7283     for (unsigned i = 0; i != MAttrs.size(); ++i)
7284       Features.AddFeature(MAttrs[i]);
7285     FeaturesStr = Features.getString();
7286   }
7287 
7288   MCTargetOptions MCOptions;
7289   // Set up disassembler.
7290   std::unique_ptr<const MCRegisterInfo> MRI(
7291       TheTarget->createMCRegInfo(TripleName));
7292   CHECK_TARGET_INFO_CREATION(MRI);
7293   std::unique_ptr<const MCAsmInfo> AsmInfo(
7294       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
7295   CHECK_TARGET_INFO_CREATION(AsmInfo);
7296   std::unique_ptr<const MCSubtargetInfo> STI(
7297       TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
7298   CHECK_TARGET_INFO_CREATION(STI);
7299   MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
7300   std::unique_ptr<MCDisassembler> DisAsm(
7301       TheTarget->createMCDisassembler(*STI, Ctx));
7302   CHECK_TARGET_INFO_CREATION(DisAsm);
7303   std::unique_ptr<MCSymbolizer> Symbolizer;
7304   struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
7305   std::unique_ptr<MCRelocationInfo> RelInfo(
7306       TheTarget->createMCRelocationInfo(TripleName, Ctx));
7307   if (RelInfo) {
7308     Symbolizer.reset(TheTarget->createMCSymbolizer(
7309         TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7310         &SymbolizerInfo, &Ctx, std::move(RelInfo)));
7311     DisAsm->setSymbolizer(std::move(Symbolizer));
7312   }
7313   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
7314   std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
7315       Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
7316   CHECK_TARGET_INFO_CREATION(IP);
7317   // Set the display preference for hex vs. decimal immediates.
7318   IP->setPrintImmHex(PrintImmHex);
7319   // Comment stream and backing vector.
7320   SmallString<128> CommentsToEmit;
7321   raw_svector_ostream CommentStream(CommentsToEmit);
7322   // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
7323   // if it is done then arm64 comments for string literals don't get printed
7324   // and some constant get printed instead and not setting it causes intel
7325   // (32-bit and 64-bit) comments printed with different spacing before the
7326   // comment causing different diffs with the 'C' disassembler library API.
7327   // IP->setCommentStream(CommentStream);
7328 
7329   for (StringRef Opt : DisassemblerOptions)
7330     if (!IP->applyTargetSpecificCLOption(Opt))
7331       reportError(Filename, "unrecognized disassembler option: " + Opt);
7332 
7333   // Set up separate thumb disassembler if needed.
7334   std::unique_ptr<const MCRegisterInfo> ThumbMRI;
7335   std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
7336   std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
7337   std::unique_ptr<MCDisassembler> ThumbDisAsm;
7338   std::unique_ptr<MCInstPrinter> ThumbIP;
7339   std::unique_ptr<MCContext> ThumbCtx;
7340   std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
7341   struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
7342   std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
7343   if (ThumbTarget) {
7344     ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
7345     CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI);
7346     ThumbAsmInfo.reset(
7347         ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions));
7348     CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo);
7349     ThumbSTI.reset(
7350         ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
7351                                            FeaturesStr));
7352     CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI);
7353     ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(),
7354                                  ThumbMRI.get(), ThumbSTI.get()));
7355     ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
7356     CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm);
7357     MCContext *PtrThumbCtx = ThumbCtx.get();
7358     ThumbRelInfo.reset(
7359         ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
7360     if (ThumbRelInfo) {
7361       ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
7362           ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7363           &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
7364       ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
7365     }
7366     int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
7367     ThumbIP.reset(ThumbTarget->createMCInstPrinter(
7368         Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
7369         *ThumbInstrInfo, *ThumbMRI));
7370     CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP);
7371     // Set the display preference for hex vs. decimal immediates.
7372     ThumbIP->setPrintImmHex(PrintImmHex);
7373   }
7374 
7375 #undef CHECK_TARGET_INFO_CREATION
7376 #undef CHECK_THUMB_TARGET_INFO_CREATION
7377 
7378   MachO::mach_header Header = MachOOF->getHeader();
7379 
7380   // FIXME: Using the -cfg command line option, this code used to be able to
7381   // annotate relocations with the referenced symbol's name, and if this was
7382   // inside a __[cf]string section, the data it points to. This is now replaced
7383   // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
7384   std::vector<SectionRef> Sections;
7385   std::vector<SymbolRef> Symbols;
7386   SmallVector<uint64_t, 8> FoundFns;
7387   uint64_t BaseSegmentAddress = 0;
7388 
7389   getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
7390                         BaseSegmentAddress);
7391 
7392   // Sort the symbols by address, just in case they didn't come in that way.
7393   llvm::stable_sort(Symbols, SymbolSorter());
7394 
7395   // Build a data in code table that is sorted on by the address of each entry.
7396   uint64_t BaseAddress = 0;
7397   if (Header.filetype == MachO::MH_OBJECT)
7398     BaseAddress = Sections[0].getAddress();
7399   else
7400     BaseAddress = BaseSegmentAddress;
7401   DiceTable Dices;
7402   for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
7403        DI != DE; ++DI) {
7404     uint32_t Offset;
7405     DI->getOffset(Offset);
7406     Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
7407   }
7408   array_pod_sort(Dices.begin(), Dices.end());
7409 
7410   // Try to find debug info and set up the DIContext for it.
7411   std::unique_ptr<DIContext> diContext;
7412   std::unique_ptr<Binary> DSYMBinary;
7413   std::unique_ptr<MemoryBuffer> DSYMBuf;
7414   if (UseDbg) {
7415     // If separate DSym file path was specified, parse it as a macho file,
7416     // get the sections and supply it to the section name parsing machinery.
7417     if (const ObjectFile *DbgObj =
7418             getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) {
7419       // Setup the DIContext
7420       diContext = DWARFContext::create(*DbgObj);
7421     } else {
7422       return;
7423     }
7424   }
7425 
7426   if (FilterSections.empty())
7427     outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
7428 
7429   for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
7430     Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName();
7431     if (!SecNameOrErr) {
7432       consumeError(SecNameOrErr.takeError());
7433       continue;
7434     }
7435     if (*SecNameOrErr != DisSectName)
7436       continue;
7437 
7438     DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
7439 
7440     StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
7441     if (SegmentName != DisSegName)
7442       continue;
7443 
7444     StringRef BytesStr =
7445         unwrapOrError(Sections[SectIdx].getContents(), Filename);
7446     ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr);
7447     uint64_t SectAddress = Sections[SectIdx].getAddress();
7448 
7449     bool symbolTableWorked = false;
7450 
7451     // Create a map of symbol addresses to symbol names for use by
7452     // the SymbolizerSymbolLookUp() routine.
7453     SymbolAddressMap AddrMap;
7454     bool DisSymNameFound = false;
7455     for (const SymbolRef &Symbol : MachOOF->symbols()) {
7456       SymbolRef::Type ST =
7457           unwrapOrError(Symbol.getType(), MachOOF->getFileName());
7458       if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
7459           ST == SymbolRef::ST_Other) {
7460         uint64_t Address = cantFail(Symbol.getValue());
7461         StringRef SymName =
7462             unwrapOrError(Symbol.getName(), MachOOF->getFileName());
7463         AddrMap[Address] = SymName;
7464         if (!DisSymName.empty() && DisSymName == SymName)
7465           DisSymNameFound = true;
7466       }
7467     }
7468     if (!DisSymName.empty() && !DisSymNameFound) {
7469       outs() << "Can't find -dis-symname: " << DisSymName << "\n";
7470       return;
7471     }
7472     // Set up the block of info used by the Symbolizer call backs.
7473     SymbolizerInfo.verbose = SymbolicOperands;
7474     SymbolizerInfo.O = MachOOF;
7475     SymbolizerInfo.S = Sections[SectIdx];
7476     SymbolizerInfo.AddrMap = &AddrMap;
7477     SymbolizerInfo.Sections = &Sections;
7478     // Same for the ThumbSymbolizer
7479     ThumbSymbolizerInfo.verbose = SymbolicOperands;
7480     ThumbSymbolizerInfo.O = MachOOF;
7481     ThumbSymbolizerInfo.S = Sections[SectIdx];
7482     ThumbSymbolizerInfo.AddrMap = &AddrMap;
7483     ThumbSymbolizerInfo.Sections = &Sections;
7484 
7485     unsigned int Arch = MachOOF->getArch();
7486 
7487     // Skip all symbols if this is a stubs file.
7488     if (Bytes.empty())
7489       return;
7490 
7491     // If the section has symbols but no symbol at the start of the section
7492     // these are used to make sure the bytes before the first symbol are
7493     // disassembled.
7494     bool FirstSymbol = true;
7495     bool FirstSymbolAtSectionStart = true;
7496 
7497     // Disassemble symbol by symbol.
7498     for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7499       StringRef SymName =
7500           unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName());
7501       SymbolRef::Type ST =
7502           unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName());
7503       if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7504         continue;
7505 
7506       // Make sure the symbol is defined in this section.
7507       bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7508       if (!containsSym) {
7509         if (!DisSymName.empty() && DisSymName == SymName) {
7510           outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7511           return;
7512         }
7513         continue;
7514       }
7515       // The __mh_execute_header is special and we need to deal with that fact
7516       // this symbol is before the start of the (__TEXT,__text) section and at the
7517       // address of the start of the __TEXT segment.  This is because this symbol
7518       // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7519       // start of the section in a standard MH_EXECUTE filetype.
7520       if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7521         outs() << "-dis-symname: __mh_execute_header not in any section\n";
7522         return;
7523       }
7524       // When this code is trying to disassemble a symbol at a time and in the
7525       // case there is only the __mh_execute_header symbol left as in a stripped
7526       // executable, we need to deal with this by ignoring this symbol so the
7527       // whole section is disassembled and this symbol is then not displayed.
7528       if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7529           SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7530           SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7531         continue;
7532 
7533       // If we are only disassembling one symbol see if this is that symbol.
7534       if (!DisSymName.empty() && DisSymName != SymName)
7535         continue;
7536 
7537       // Start at the address of the symbol relative to the section's address.
7538       uint64_t SectSize = Sections[SectIdx].getSize();
7539       uint64_t Start = cantFail(Symbols[SymIdx].getValue());
7540       uint64_t SectionAddress = Sections[SectIdx].getAddress();
7541       Start -= SectionAddress;
7542 
7543       if (Start > SectSize) {
7544         outs() << "section data ends, " << SymName
7545                << " lies outside valid range\n";
7546         return;
7547       }
7548 
7549       // Stop disassembling either at the beginning of the next symbol or at
7550       // the end of the section.
7551       bool containsNextSym = false;
7552       uint64_t NextSym = 0;
7553       uint64_t NextSymIdx = SymIdx + 1;
7554       while (Symbols.size() > NextSymIdx) {
7555         SymbolRef::Type NextSymType = unwrapOrError(
7556             Symbols[NextSymIdx].getType(), MachOOF->getFileName());
7557         if (NextSymType == SymbolRef::ST_Function) {
7558           containsNextSym =
7559               Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7560           NextSym = cantFail(Symbols[NextSymIdx].getValue());
7561           NextSym -= SectionAddress;
7562           break;
7563         }
7564         ++NextSymIdx;
7565       }
7566 
7567       uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7568       uint64_t Size;
7569 
7570       symbolTableWorked = true;
7571 
7572       DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7573       uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb));
7574       bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb;
7575 
7576       // We only need the dedicated Thumb target if there's a real choice
7577       // (i.e. we're not targeting M-class) and the function is Thumb.
7578       bool UseThumbTarget = IsThumb && ThumbTarget;
7579 
7580       // If we are not specifying a symbol to start disassembly with and this
7581       // is the first symbol in the section but not at the start of the section
7582       // then move the disassembly index to the start of the section and
7583       // don't print the symbol name just yet.  This is so the bytes before the
7584       // first symbol are disassembled.
7585       uint64_t SymbolStart = Start;
7586       if (DisSymName.empty() && FirstSymbol && Start != 0) {
7587         FirstSymbolAtSectionStart = false;
7588         Start = 0;
7589       }
7590       else
7591         outs() << SymName << ":\n";
7592 
7593       DILineInfo lastLine;
7594       for (uint64_t Index = Start; Index < End; Index += Size) {
7595         MCInst Inst;
7596 
7597         // If this is the first symbol in the section and it was not at the
7598         // start of the section, see if we are at its Index now and if so print
7599         // the symbol name.
7600         if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7601           outs() << SymName << ":\n";
7602 
7603         uint64_t PC = SectAddress + Index;
7604         if (LeadingAddr) {
7605           if (FullLeadingAddr) {
7606             if (MachOOF->is64Bit())
7607               outs() << format("%016" PRIx64, PC);
7608             else
7609               outs() << format("%08" PRIx64, PC);
7610           } else {
7611             outs() << format("%8" PRIx64 ":", PC);
7612           }
7613         }
7614         if (ShowRawInsn || Arch == Triple::arm)
7615           outs() << "\t";
7616 
7617         if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size))
7618           continue;
7619 
7620         SmallVector<char, 64> AnnotationsBytes;
7621         raw_svector_ostream Annotations(AnnotationsBytes);
7622 
7623         bool gotInst;
7624         if (UseThumbTarget)
7625           gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7626                                                 PC, Annotations);
7627         else
7628           gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7629                                            Annotations);
7630         if (gotInst) {
7631           if (ShowRawInsn || Arch == Triple::arm) {
7632             dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs());
7633           }
7634           formatted_raw_ostream FormattedOS(outs());
7635           StringRef AnnotationsStr = Annotations.str();
7636           if (UseThumbTarget)
7637             ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI,
7638                                FormattedOS);
7639           else
7640             IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS);
7641           emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7642 
7643           // Print debug info.
7644           if (diContext) {
7645             DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx})
7646                                  .value_or(DILineInfo());
7647             // Print valid line info if it changed.
7648             if (dli != lastLine && dli.Line != 0)
7649               outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7650                      << dli.Column;
7651             lastLine = dli;
7652           }
7653           outs() << "\n";
7654         } else {
7655           if (MachOOF->getArchTriple().isX86()) {
7656             outs() << format("\t.byte 0x%02x #bad opcode\n",
7657                              *(Bytes.data() + Index) & 0xff);
7658             Size = 1; // skip exactly one illegible byte and move on.
7659           } else if (Arch == Triple::aarch64 ||
7660                      (Arch == Triple::arm && !IsThumb)) {
7661             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7662                               (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7663                               (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7664                               (*(Bytes.data() + Index + 3) & 0xff) << 24;
7665             outs() << format("\t.long\t0x%08x\n", opcode);
7666             Size = 4;
7667           } else if (Arch == Triple::arm) {
7668             assert(IsThumb && "ARM mode should have been dealt with above");
7669             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7670                               (*(Bytes.data() + Index + 1) & 0xff) << 8;
7671             outs() << format("\t.short\t0x%04x\n", opcode);
7672             Size = 2;
7673           } else{
7674             WithColor::warning(errs(), "llvm-objdump")
7675                 << "invalid instruction encoding\n";
7676             if (Size == 0)
7677               Size = 1; // skip illegible bytes
7678           }
7679         }
7680       }
7681       // Now that we are done disassembled the first symbol set the bool that
7682       // were doing this to false.
7683       FirstSymbol = false;
7684     }
7685     if (!symbolTableWorked) {
7686       // Reading the symbol table didn't work, disassemble the whole section.
7687       uint64_t SectAddress = Sections[SectIdx].getAddress();
7688       uint64_t SectSize = Sections[SectIdx].getSize();
7689       uint64_t InstSize;
7690       for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7691         MCInst Inst;
7692 
7693         uint64_t PC = SectAddress + Index;
7694 
7695         if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize))
7696           continue;
7697 
7698         SmallVector<char, 64> AnnotationsBytes;
7699         raw_svector_ostream Annotations(AnnotationsBytes);
7700         if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7701                                    Annotations)) {
7702           if (LeadingAddr) {
7703             if (FullLeadingAddr) {
7704               if (MachOOF->is64Bit())
7705                 outs() << format("%016" PRIx64, PC);
7706               else
7707                 outs() << format("%08" PRIx64, PC);
7708             } else {
7709               outs() << format("%8" PRIx64 ":", PC);
7710             }
7711           }
7712           if (ShowRawInsn || Arch == Triple::arm) {
7713             outs() << "\t";
7714             dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs());
7715           }
7716           StringRef AnnotationsStr = Annotations.str();
7717           IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs());
7718           outs() << "\n";
7719         } else {
7720           if (MachOOF->getArchTriple().isX86()) {
7721             outs() << format("\t.byte 0x%02x #bad opcode\n",
7722                              *(Bytes.data() + Index) & 0xff);
7723             InstSize = 1; // skip exactly one illegible byte and move on.
7724           } else {
7725             WithColor::warning(errs(), "llvm-objdump")
7726                 << "invalid instruction encoding\n";
7727             if (InstSize == 0)
7728               InstSize = 1; // skip illegible bytes
7729           }
7730         }
7731       }
7732     }
7733     // The TripleName's need to be reset if we are called again for a different
7734     // architecture.
7735     TripleName = "";
7736     ThumbTripleName = "";
7737 
7738     if (SymbolizerInfo.demangled_name != nullptr)
7739       free(SymbolizerInfo.demangled_name);
7740     if (ThumbSymbolizerInfo.demangled_name != nullptr)
7741       free(ThumbSymbolizerInfo.demangled_name);
7742   }
7743 }
7744 
7745 //===----------------------------------------------------------------------===//
7746 // __compact_unwind section dumping
7747 //===----------------------------------------------------------------------===//
7748 
7749 namespace {
7750 
7751 template <typename T>
read(StringRef Contents,ptrdiff_t Offset)7752 static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
7753   if (Offset + sizeof(T) > Contents.size()) {
7754     outs() << "warning: attempt to read past end of buffer\n";
7755     return T();
7756   }
7757 
7758   uint64_t Val = support::endian::read<T, llvm::endianness::little>(
7759       Contents.data() + Offset);
7760   return Val;
7761 }
7762 
7763 template <typename T>
readNext(StringRef Contents,ptrdiff_t & Offset)7764 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
7765   T Val = read<T>(Contents, Offset);
7766   Offset += sizeof(T);
7767   return Val;
7768 }
7769 
7770 struct CompactUnwindEntry {
7771   uint32_t OffsetInSection;
7772 
7773   uint64_t FunctionAddr;
7774   uint32_t Length;
7775   uint32_t CompactEncoding;
7776   uint64_t PersonalityAddr;
7777   uint64_t LSDAAddr;
7778 
7779   RelocationRef FunctionReloc;
7780   RelocationRef PersonalityReloc;
7781   RelocationRef LSDAReloc;
7782 
CompactUnwindEntry__anon061faff00a11::CompactUnwindEntry7783   CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
7784       : OffsetInSection(Offset) {
7785     if (Is64)
7786       read<uint64_t>(Contents, Offset);
7787     else
7788       read<uint32_t>(Contents, Offset);
7789   }
7790 
7791 private:
read__anon061faff00a11::CompactUnwindEntry7792   template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
7793     FunctionAddr = readNext<UIntPtr>(Contents, Offset);
7794     Length = readNext<uint32_t>(Contents, Offset);
7795     CompactEncoding = readNext<uint32_t>(Contents, Offset);
7796     PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
7797     LSDAAddr = readNext<UIntPtr>(Contents, Offset);
7798   }
7799 };
7800 }
7801 
7802 /// Given a relocation from __compact_unwind, consisting of the RelocationRef
7803 /// and data being relocated, determine the best base Name and Addend to use for
7804 /// display purposes.
7805 ///
7806 /// 1. An Extern relocation will directly reference a symbol (and the data is
7807 ///    then already an addend), so use that.
7808 /// 2. Otherwise the data is an offset in the object file's layout; try to find
7809 //     a symbol before it in the same section, and use the offset from there.
7810 /// 3. Finally, if all that fails, fall back to an offset from the start of the
7811 ///    referenced section.
findUnwindRelocNameAddend(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr,StringRef & Name,uint64_t & Addend)7812 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
7813                                       std::map<uint64_t, SymbolRef> &Symbols,
7814                                       const RelocationRef &Reloc, uint64_t Addr,
7815                                       StringRef &Name, uint64_t &Addend) {
7816   if (Reloc.getSymbol() != Obj->symbol_end()) {
7817     Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName());
7818     Addend = Addr;
7819     return;
7820   }
7821 
7822   auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
7823   SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
7824 
7825   uint64_t SectionAddr = RelocSection.getAddress();
7826 
7827   auto Sym = Symbols.upper_bound(Addr);
7828   if (Sym == Symbols.begin()) {
7829     // The first symbol in the object is after this reference, the best we can
7830     // do is section-relative notation.
7831     if (Expected<StringRef> NameOrErr = RelocSection.getName())
7832       Name = *NameOrErr;
7833     else
7834       consumeError(NameOrErr.takeError());
7835 
7836     Addend = Addr - SectionAddr;
7837     return;
7838   }
7839 
7840   // Go back one so that SymbolAddress <= Addr.
7841   --Sym;
7842 
7843   section_iterator SymSection =
7844       unwrapOrError(Sym->second.getSection(), Obj->getFileName());
7845   if (RelocSection == *SymSection) {
7846     // There's a valid symbol in the same section before this reference.
7847     Name = unwrapOrError(Sym->second.getName(), Obj->getFileName());
7848     Addend = Addr - Sym->first;
7849     return;
7850   }
7851 
7852   // There is a symbol before this reference, but it's in a different
7853   // section. Probably not helpful to mention it, so use the section name.
7854   if (Expected<StringRef> NameOrErr = RelocSection.getName())
7855     Name = *NameOrErr;
7856   else
7857     consumeError(NameOrErr.takeError());
7858 
7859   Addend = Addr - SectionAddr;
7860 }
7861 
printUnwindRelocDest(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr)7862 static void printUnwindRelocDest(const MachOObjectFile *Obj,
7863                                  std::map<uint64_t, SymbolRef> &Symbols,
7864                                  const RelocationRef &Reloc, uint64_t Addr) {
7865   StringRef Name;
7866   uint64_t Addend;
7867 
7868   if (!Reloc.getObject())
7869     return;
7870 
7871   findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7872 
7873   outs() << Name;
7874   if (Addend)
7875     outs() << " + " << format("0x%" PRIx64, Addend);
7876 }
7877 
7878 static void
printMachOCompactUnwindSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & CompactUnwind)7879 printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7880                                std::map<uint64_t, SymbolRef> &Symbols,
7881                                const SectionRef &CompactUnwind) {
7882 
7883   if (!Obj->isLittleEndian()) {
7884     outs() << "Skipping big-endian __compact_unwind section\n";
7885     return;
7886   }
7887 
7888   bool Is64 = Obj->is64Bit();
7889   uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7890   uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7891 
7892   StringRef Contents =
7893       unwrapOrError(CompactUnwind.getContents(), Obj->getFileName());
7894   SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7895 
7896   // First populate the initial raw offsets, encodings and so on from the entry.
7897   for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7898     CompactUnwindEntry Entry(Contents, Offset, Is64);
7899     CompactUnwinds.push_back(Entry);
7900   }
7901 
7902   // Next we need to look at the relocations to find out what objects are
7903   // actually being referred to.
7904   for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7905     uint64_t RelocAddress = Reloc.getOffset();
7906 
7907     uint32_t EntryIdx = RelocAddress / EntrySize;
7908     uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7909     CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7910 
7911     if (OffsetInEntry == 0)
7912       Entry.FunctionReloc = Reloc;
7913     else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7914       Entry.PersonalityReloc = Reloc;
7915     else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7916       Entry.LSDAReloc = Reloc;
7917     else {
7918       outs() << "Invalid relocation in __compact_unwind section\n";
7919       return;
7920     }
7921   }
7922 
7923   // Finally, we're ready to print the data we've gathered.
7924   outs() << "Contents of __compact_unwind section:\n";
7925   for (auto &Entry : CompactUnwinds) {
7926     outs() << "  Entry at offset "
7927            << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
7928 
7929     // 1. Start of the region this entry applies to.
7930     outs() << "    start:                " << format("0x%" PRIx64,
7931                                                      Entry.FunctionAddr) << ' ';
7932     printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
7933     outs() << '\n';
7934 
7935     // 2. Length of the region this entry applies to.
7936     outs() << "    length:               " << format("0x%" PRIx32, Entry.Length)
7937            << '\n';
7938     // 3. The 32-bit compact encoding.
7939     outs() << "    compact encoding:     "
7940            << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
7941 
7942     // 4. The personality function, if present.
7943     if (Entry.PersonalityReloc.getObject()) {
7944       outs() << "    personality function: "
7945              << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
7946       printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
7947                            Entry.PersonalityAddr);
7948       outs() << '\n';
7949     }
7950 
7951     // 5. This entry's language-specific data area.
7952     if (Entry.LSDAReloc.getObject()) {
7953       outs() << "    LSDA:                 " << format("0x%" PRIx64,
7954                                                        Entry.LSDAAddr) << ' ';
7955       printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
7956       outs() << '\n';
7957     }
7958   }
7959 }
7960 
7961 //===----------------------------------------------------------------------===//
7962 // __unwind_info section dumping
7963 //===----------------------------------------------------------------------===//
7964 
printRegularSecondLevelUnwindPage(StringRef PageData)7965 static void printRegularSecondLevelUnwindPage(StringRef PageData) {
7966   ptrdiff_t Pos = 0;
7967   uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7968   (void)Kind;
7969   assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
7970 
7971   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7972   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7973 
7974   Pos = EntriesStart;
7975   for (unsigned i = 0; i < NumEntries; ++i) {
7976     uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
7977     uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7978 
7979     outs() << "      [" << i << "]: "
7980            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7981            << ", "
7982            << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
7983   }
7984 }
7985 
printCompressedSecondLevelUnwindPage(StringRef PageData,uint32_t FunctionBase,const SmallVectorImpl<uint32_t> & CommonEncodings)7986 static void printCompressedSecondLevelUnwindPage(
7987     StringRef PageData, uint32_t FunctionBase,
7988     const SmallVectorImpl<uint32_t> &CommonEncodings) {
7989   ptrdiff_t Pos = 0;
7990   uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7991   (void)Kind;
7992   assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
7993 
7994   uint32_t NumCommonEncodings = CommonEncodings.size();
7995   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7996   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7997 
7998   uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos);
7999   uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos);
8000   SmallVector<uint32_t, 64> PageEncodings;
8001   if (NumPageEncodings) {
8002     outs() << "      Page encodings: (count = " << NumPageEncodings << ")\n";
8003     Pos = PageEncodingsStart;
8004     for (unsigned i = 0; i < NumPageEncodings; ++i) {
8005       uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
8006       PageEncodings.push_back(Encoding);
8007       outs() << "        encoding[" << (i + NumCommonEncodings)
8008              << "]: " << format("0x%08" PRIx32, Encoding) << '\n';
8009     }
8010   }
8011 
8012   Pos = EntriesStart;
8013   for (unsigned i = 0; i < NumEntries; ++i) {
8014     uint32_t Entry = readNext<uint32_t>(PageData, Pos);
8015     uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
8016     uint32_t EncodingIdx = Entry >> 24;
8017 
8018     uint32_t Encoding;
8019     if (EncodingIdx < NumCommonEncodings)
8020       Encoding = CommonEncodings[EncodingIdx];
8021     else
8022       Encoding = PageEncodings[EncodingIdx - NumCommonEncodings];
8023 
8024     outs() << "      [" << i << "]: "
8025            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8026            << ", "
8027            << "encoding[" << EncodingIdx
8028            << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
8029   }
8030 }
8031 
printMachOUnwindInfoSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & UnwindInfo)8032 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
8033                                         std::map<uint64_t, SymbolRef> &Symbols,
8034                                         const SectionRef &UnwindInfo) {
8035 
8036   if (!Obj->isLittleEndian()) {
8037     outs() << "Skipping big-endian __unwind_info section\n";
8038     return;
8039   }
8040 
8041   outs() << "Contents of __unwind_info section:\n";
8042 
8043   StringRef Contents =
8044       unwrapOrError(UnwindInfo.getContents(), Obj->getFileName());
8045   ptrdiff_t Pos = 0;
8046 
8047   //===----------------------------------
8048   // Section header
8049   //===----------------------------------
8050 
8051   uint32_t Version = readNext<uint32_t>(Contents, Pos);
8052   outs() << "  Version:                                   "
8053          << format("0x%" PRIx32, Version) << '\n';
8054   if (Version != 1) {
8055     outs() << "    Skipping section with unknown version\n";
8056     return;
8057   }
8058 
8059   uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
8060   outs() << "  Common encodings array section offset:     "
8061          << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
8062   uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
8063   outs() << "  Number of common encodings in array:       "
8064          << format("0x%" PRIx32, NumCommonEncodings) << '\n';
8065 
8066   uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
8067   outs() << "  Personality function array section offset: "
8068          << format("0x%" PRIx32, PersonalitiesStart) << '\n';
8069   uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
8070   outs() << "  Number of personality functions in array:  "
8071          << format("0x%" PRIx32, NumPersonalities) << '\n';
8072 
8073   uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
8074   outs() << "  Index array section offset:                "
8075          << format("0x%" PRIx32, IndicesStart) << '\n';
8076   uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
8077   outs() << "  Number of indices in array:                "
8078          << format("0x%" PRIx32, NumIndices) << '\n';
8079 
8080   //===----------------------------------
8081   // A shared list of common encodings
8082   //===----------------------------------
8083 
8084   // These occupy indices in the range [0, N] whenever an encoding is referenced
8085   // from a compressed 2nd level index table. In practice the linker only
8086   // creates ~128 of these, so that indices are available to embed encodings in
8087   // the 2nd level index.
8088 
8089   SmallVector<uint32_t, 64> CommonEncodings;
8090   outs() << "  Common encodings: (count = " << NumCommonEncodings << ")\n";
8091   Pos = CommonEncodingsStart;
8092   for (unsigned i = 0; i < NumCommonEncodings; ++i) {
8093     uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
8094     CommonEncodings.push_back(Encoding);
8095 
8096     outs() << "    encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
8097            << '\n';
8098   }
8099 
8100   //===----------------------------------
8101   // Personality functions used in this executable
8102   //===----------------------------------
8103 
8104   // There should be only a handful of these (one per source language,
8105   // roughly). Particularly since they only get 2 bits in the compact encoding.
8106 
8107   outs() << "  Personality functions: (count = " << NumPersonalities << ")\n";
8108   Pos = PersonalitiesStart;
8109   for (unsigned i = 0; i < NumPersonalities; ++i) {
8110     uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
8111     outs() << "    personality[" << i + 1
8112            << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
8113   }
8114 
8115   //===----------------------------------
8116   // The level 1 index entries
8117   //===----------------------------------
8118 
8119   // These specify an approximate place to start searching for the more detailed
8120   // information, sorted by PC.
8121 
8122   struct IndexEntry {
8123     uint32_t FunctionOffset;
8124     uint32_t SecondLevelPageStart;
8125     uint32_t LSDAStart;
8126   };
8127 
8128   SmallVector<IndexEntry, 4> IndexEntries;
8129 
8130   outs() << "  Top level indices: (count = " << NumIndices << ")\n";
8131   Pos = IndicesStart;
8132   for (unsigned i = 0; i < NumIndices; ++i) {
8133     IndexEntry Entry;
8134 
8135     Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
8136     Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
8137     Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
8138     IndexEntries.push_back(Entry);
8139 
8140     outs() << "    [" << i << "]: "
8141            << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
8142            << ", "
8143            << "2nd level page offset="
8144            << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
8145            << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
8146   }
8147 
8148   //===----------------------------------
8149   // Next come the LSDA tables
8150   //===----------------------------------
8151 
8152   // The LSDA layout is rather implicit: it's a contiguous array of entries from
8153   // the first top-level index's LSDAOffset to the last (sentinel).
8154 
8155   outs() << "  LSDA descriptors:\n";
8156   Pos = IndexEntries[0].LSDAStart;
8157   const uint32_t LSDASize = 2 * sizeof(uint32_t);
8158   int NumLSDAs =
8159       (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
8160 
8161   for (int i = 0; i < NumLSDAs; ++i) {
8162     uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
8163     uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
8164     outs() << "    [" << i << "]: "
8165            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8166            << ", "
8167            << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
8168   }
8169 
8170   //===----------------------------------
8171   // Finally, the 2nd level indices
8172   //===----------------------------------
8173 
8174   // Generally these are 4K in size, and have 2 possible forms:
8175   //   + Regular stores up to 511 entries with disparate encodings
8176   //   + Compressed stores up to 1021 entries if few enough compact encoding
8177   //     values are used.
8178   outs() << "  Second level indices:\n";
8179   for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
8180     // The final sentinel top-level index has no associated 2nd level page
8181     if (IndexEntries[i].SecondLevelPageStart == 0)
8182       break;
8183 
8184     outs() << "    Second level index[" << i << "]: "
8185            << "offset in section="
8186            << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
8187            << ", "
8188            << "base function offset="
8189            << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
8190 
8191     Pos = IndexEntries[i].SecondLevelPageStart;
8192     if (Pos + sizeof(uint32_t) > Contents.size()) {
8193       outs() << "warning: invalid offset for second level page: " << Pos << '\n';
8194       continue;
8195     }
8196 
8197     uint32_t Kind =
8198         *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
8199     if (Kind == 2)
8200       printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
8201     else if (Kind == 3)
8202       printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
8203                                            IndexEntries[i].FunctionOffset,
8204                                            CommonEncodings);
8205     else
8206       outs() << "    Skipping 2nd level page with unknown kind " << Kind
8207              << '\n';
8208   }
8209 }
8210 
printMachOUnwindInfo(const MachOObjectFile * Obj)8211 void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) {
8212   std::map<uint64_t, SymbolRef> Symbols;
8213   for (const SymbolRef &SymRef : Obj->symbols()) {
8214     // Discard any undefined or absolute symbols. They're not going to take part
8215     // in the convenience lookup for unwind info and just take up resources.
8216     auto SectOrErr = SymRef.getSection();
8217     if (!SectOrErr) {
8218       // TODO: Actually report errors helpfully.
8219       consumeError(SectOrErr.takeError());
8220       continue;
8221     }
8222     section_iterator Section = *SectOrErr;
8223     if (Section == Obj->section_end())
8224       continue;
8225 
8226     uint64_t Addr = cantFail(SymRef.getValue());
8227     Symbols.insert(std::make_pair(Addr, SymRef));
8228   }
8229 
8230   for (const SectionRef &Section : Obj->sections()) {
8231     StringRef SectName;
8232     if (Expected<StringRef> NameOrErr = Section.getName())
8233       SectName = *NameOrErr;
8234     else
8235       consumeError(NameOrErr.takeError());
8236 
8237     if (SectName == "__compact_unwind")
8238       printMachOCompactUnwindSection(Obj, Symbols, Section);
8239     else if (SectName == "__unwind_info")
8240       printMachOUnwindInfoSection(Obj, Symbols, Section);
8241   }
8242 }
8243 
PrintMachHeader(uint32_t magic,uint32_t cputype,uint32_t cpusubtype,uint32_t filetype,uint32_t ncmds,uint32_t sizeofcmds,uint32_t flags,bool verbose)8244 static void PrintMachHeader(uint32_t magic, uint32_t cputype,
8245                             uint32_t cpusubtype, uint32_t filetype,
8246                             uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
8247                             bool verbose) {
8248   outs() << "Mach header\n";
8249   outs() << "      magic cputype cpusubtype  caps    filetype ncmds "
8250             "sizeofcmds      flags\n";
8251   if (verbose) {
8252     if (magic == MachO::MH_MAGIC)
8253       outs() << "   MH_MAGIC";
8254     else if (magic == MachO::MH_MAGIC_64)
8255       outs() << "MH_MAGIC_64";
8256     else
8257       outs() << format(" 0x%08" PRIx32, magic);
8258     switch (cputype) {
8259     case MachO::CPU_TYPE_I386:
8260       outs() << "    I386";
8261       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8262       case MachO::CPU_SUBTYPE_I386_ALL:
8263         outs() << "        ALL";
8264         break;
8265       default:
8266         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8267         break;
8268       }
8269       break;
8270     case MachO::CPU_TYPE_X86_64:
8271       outs() << "  X86_64";
8272       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8273       case MachO::CPU_SUBTYPE_X86_64_ALL:
8274         outs() << "        ALL";
8275         break;
8276       case MachO::CPU_SUBTYPE_X86_64_H:
8277         outs() << "    Haswell";
8278         break;
8279       default:
8280         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8281         break;
8282       }
8283       break;
8284     case MachO::CPU_TYPE_ARM:
8285       outs() << "     ARM";
8286       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8287       case MachO::CPU_SUBTYPE_ARM_ALL:
8288         outs() << "        ALL";
8289         break;
8290       case MachO::CPU_SUBTYPE_ARM_V4T:
8291         outs() << "        V4T";
8292         break;
8293       case MachO::CPU_SUBTYPE_ARM_V5TEJ:
8294         outs() << "      V5TEJ";
8295         break;
8296       case MachO::CPU_SUBTYPE_ARM_XSCALE:
8297         outs() << "     XSCALE";
8298         break;
8299       case MachO::CPU_SUBTYPE_ARM_V6:
8300         outs() << "         V6";
8301         break;
8302       case MachO::CPU_SUBTYPE_ARM_V6M:
8303         outs() << "        V6M";
8304         break;
8305       case MachO::CPU_SUBTYPE_ARM_V7:
8306         outs() << "         V7";
8307         break;
8308       case MachO::CPU_SUBTYPE_ARM_V7EM:
8309         outs() << "       V7EM";
8310         break;
8311       case MachO::CPU_SUBTYPE_ARM_V7K:
8312         outs() << "        V7K";
8313         break;
8314       case MachO::CPU_SUBTYPE_ARM_V7M:
8315         outs() << "        V7M";
8316         break;
8317       case MachO::CPU_SUBTYPE_ARM_V7S:
8318         outs() << "        V7S";
8319         break;
8320       default:
8321         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8322         break;
8323       }
8324       break;
8325     case MachO::CPU_TYPE_ARM64:
8326       outs() << "   ARM64";
8327       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8328       case MachO::CPU_SUBTYPE_ARM64_ALL:
8329         outs() << "        ALL";
8330         break;
8331       case MachO::CPU_SUBTYPE_ARM64_V8:
8332         outs() << "         V8";
8333         break;
8334       case MachO::CPU_SUBTYPE_ARM64E:
8335         outs() << "          E";
8336         break;
8337       default:
8338         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8339         break;
8340       }
8341       break;
8342     case MachO::CPU_TYPE_ARM64_32:
8343       outs() << " ARM64_32";
8344       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8345       case MachO::CPU_SUBTYPE_ARM64_32_V8:
8346         outs() << "        V8";
8347         break;
8348       default:
8349         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8350         break;
8351       }
8352       break;
8353     case MachO::CPU_TYPE_POWERPC:
8354       outs() << "     PPC";
8355       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8356       case MachO::CPU_SUBTYPE_POWERPC_ALL:
8357         outs() << "        ALL";
8358         break;
8359       default:
8360         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8361         break;
8362       }
8363       break;
8364     case MachO::CPU_TYPE_POWERPC64:
8365       outs() << "   PPC64";
8366       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8367       case MachO::CPU_SUBTYPE_POWERPC_ALL:
8368         outs() << "        ALL";
8369         break;
8370       default:
8371         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8372         break;
8373       }
8374       break;
8375     default:
8376       outs() << format(" %7d", cputype);
8377       outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8378       break;
8379     }
8380 
8381     if (cputype == MachO::CPU_TYPE_ARM64 &&
8382         MachO::CPU_SUBTYPE_ARM64E_IS_VERSIONED_PTRAUTH_ABI(cpusubtype)) {
8383       const char *Format =
8384           MachO::CPU_SUBTYPE_ARM64E_IS_KERNEL_PTRAUTH_ABI(cpusubtype)
8385               ? " PAK%02d"
8386               : " PAC%02d";
8387       outs() << format(Format,
8388                        MachO::CPU_SUBTYPE_ARM64E_PTRAUTH_VERSION(cpusubtype));
8389     } else if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) ==
8390                MachO::CPU_SUBTYPE_LIB64) {
8391       outs() << " LIB64";
8392     } else {
8393       outs() << format("  0x%02" PRIx32,
8394                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8395     }
8396     switch (filetype) {
8397     case MachO::MH_OBJECT:
8398       outs() << "      OBJECT";
8399       break;
8400     case MachO::MH_EXECUTE:
8401       outs() << "     EXECUTE";
8402       break;
8403     case MachO::MH_FVMLIB:
8404       outs() << "      FVMLIB";
8405       break;
8406     case MachO::MH_CORE:
8407       outs() << "        CORE";
8408       break;
8409     case MachO::MH_PRELOAD:
8410       outs() << "     PRELOAD";
8411       break;
8412     case MachO::MH_DYLIB:
8413       outs() << "       DYLIB";
8414       break;
8415     case MachO::MH_DYLIB_STUB:
8416       outs() << "  DYLIB_STUB";
8417       break;
8418     case MachO::MH_DYLINKER:
8419       outs() << "    DYLINKER";
8420       break;
8421     case MachO::MH_BUNDLE:
8422       outs() << "      BUNDLE";
8423       break;
8424     case MachO::MH_DSYM:
8425       outs() << "        DSYM";
8426       break;
8427     case MachO::MH_KEXT_BUNDLE:
8428       outs() << "  KEXTBUNDLE";
8429       break;
8430     case MachO::MH_FILESET:
8431       outs() << "     FILESET";
8432       break;
8433     default:
8434       outs() << format("  %10u", filetype);
8435       break;
8436     }
8437     outs() << format(" %5u", ncmds);
8438     outs() << format(" %10u", sizeofcmds);
8439     uint32_t f = flags;
8440     if (f & MachO::MH_NOUNDEFS) {
8441       outs() << "   NOUNDEFS";
8442       f &= ~MachO::MH_NOUNDEFS;
8443     }
8444     if (f & MachO::MH_INCRLINK) {
8445       outs() << " INCRLINK";
8446       f &= ~MachO::MH_INCRLINK;
8447     }
8448     if (f & MachO::MH_DYLDLINK) {
8449       outs() << " DYLDLINK";
8450       f &= ~MachO::MH_DYLDLINK;
8451     }
8452     if (f & MachO::MH_BINDATLOAD) {
8453       outs() << " BINDATLOAD";
8454       f &= ~MachO::MH_BINDATLOAD;
8455     }
8456     if (f & MachO::MH_PREBOUND) {
8457       outs() << " PREBOUND";
8458       f &= ~MachO::MH_PREBOUND;
8459     }
8460     if (f & MachO::MH_SPLIT_SEGS) {
8461       outs() << " SPLIT_SEGS";
8462       f &= ~MachO::MH_SPLIT_SEGS;
8463     }
8464     if (f & MachO::MH_LAZY_INIT) {
8465       outs() << " LAZY_INIT";
8466       f &= ~MachO::MH_LAZY_INIT;
8467     }
8468     if (f & MachO::MH_TWOLEVEL) {
8469       outs() << " TWOLEVEL";
8470       f &= ~MachO::MH_TWOLEVEL;
8471     }
8472     if (f & MachO::MH_FORCE_FLAT) {
8473       outs() << " FORCE_FLAT";
8474       f &= ~MachO::MH_FORCE_FLAT;
8475     }
8476     if (f & MachO::MH_NOMULTIDEFS) {
8477       outs() << " NOMULTIDEFS";
8478       f &= ~MachO::MH_NOMULTIDEFS;
8479     }
8480     if (f & MachO::MH_NOFIXPREBINDING) {
8481       outs() << " NOFIXPREBINDING";
8482       f &= ~MachO::MH_NOFIXPREBINDING;
8483     }
8484     if (f & MachO::MH_PREBINDABLE) {
8485       outs() << " PREBINDABLE";
8486       f &= ~MachO::MH_PREBINDABLE;
8487     }
8488     if (f & MachO::MH_ALLMODSBOUND) {
8489       outs() << " ALLMODSBOUND";
8490       f &= ~MachO::MH_ALLMODSBOUND;
8491     }
8492     if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
8493       outs() << " SUBSECTIONS_VIA_SYMBOLS";
8494       f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
8495     }
8496     if (f & MachO::MH_CANONICAL) {
8497       outs() << " CANONICAL";
8498       f &= ~MachO::MH_CANONICAL;
8499     }
8500     if (f & MachO::MH_WEAK_DEFINES) {
8501       outs() << " WEAK_DEFINES";
8502       f &= ~MachO::MH_WEAK_DEFINES;
8503     }
8504     if (f & MachO::MH_BINDS_TO_WEAK) {
8505       outs() << " BINDS_TO_WEAK";
8506       f &= ~MachO::MH_BINDS_TO_WEAK;
8507     }
8508     if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
8509       outs() << " ALLOW_STACK_EXECUTION";
8510       f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
8511     }
8512     if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
8513       outs() << " DEAD_STRIPPABLE_DYLIB";
8514       f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
8515     }
8516     if (f & MachO::MH_PIE) {
8517       outs() << " PIE";
8518       f &= ~MachO::MH_PIE;
8519     }
8520     if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
8521       outs() << " NO_REEXPORTED_DYLIBS";
8522       f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
8523     }
8524     if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
8525       outs() << " MH_HAS_TLV_DESCRIPTORS";
8526       f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
8527     }
8528     if (f & MachO::MH_NO_HEAP_EXECUTION) {
8529       outs() << " MH_NO_HEAP_EXECUTION";
8530       f &= ~MachO::MH_NO_HEAP_EXECUTION;
8531     }
8532     if (f & MachO::MH_APP_EXTENSION_SAFE) {
8533       outs() << " APP_EXTENSION_SAFE";
8534       f &= ~MachO::MH_APP_EXTENSION_SAFE;
8535     }
8536     if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
8537       outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
8538       f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
8539     }
8540     if (f != 0 || flags == 0)
8541       outs() << format(" 0x%08" PRIx32, f);
8542   } else {
8543     outs() << format(" 0x%08" PRIx32, magic);
8544     outs() << format(" %7d", cputype);
8545     outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8546     outs() << format("  0x%02" PRIx32,
8547                      (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8548     outs() << format("  %10u", filetype);
8549     outs() << format(" %5u", ncmds);
8550     outs() << format(" %10u", sizeofcmds);
8551     outs() << format(" 0x%08" PRIx32, flags);
8552   }
8553   outs() << "\n";
8554 }
8555 
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)8556 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
8557                                 StringRef SegName, uint64_t vmaddr,
8558                                 uint64_t vmsize, uint64_t fileoff,
8559                                 uint64_t filesize, uint32_t maxprot,
8560                                 uint32_t initprot, uint32_t nsects,
8561                                 uint32_t flags, uint32_t object_size,
8562                                 bool verbose) {
8563   uint64_t expected_cmdsize;
8564   if (cmd == MachO::LC_SEGMENT) {
8565     outs() << "      cmd LC_SEGMENT\n";
8566     expected_cmdsize = nsects;
8567     expected_cmdsize *= sizeof(struct MachO::section);
8568     expected_cmdsize += sizeof(struct MachO::segment_command);
8569   } else {
8570     outs() << "      cmd LC_SEGMENT_64\n";
8571     expected_cmdsize = nsects;
8572     expected_cmdsize *= sizeof(struct MachO::section_64);
8573     expected_cmdsize += sizeof(struct MachO::segment_command_64);
8574   }
8575   outs() << "  cmdsize " << cmdsize;
8576   if (cmdsize != expected_cmdsize)
8577     outs() << " Inconsistent size\n";
8578   else
8579     outs() << "\n";
8580   outs() << "  segname " << SegName << "\n";
8581   if (cmd == MachO::LC_SEGMENT_64) {
8582     outs() << "   vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
8583     outs() << "   vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
8584   } else {
8585     outs() << "   vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
8586     outs() << "   vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
8587   }
8588   outs() << "  fileoff " << fileoff;
8589   if (fileoff > object_size)
8590     outs() << " (past end of file)\n";
8591   else
8592     outs() << "\n";
8593   outs() << " filesize " << filesize;
8594   if (fileoff + filesize > object_size)
8595     outs() << " (past end of file)\n";
8596   else
8597     outs() << "\n";
8598   if (verbose) {
8599     if ((maxprot &
8600          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8601            MachO::VM_PROT_EXECUTE)) != 0)
8602       outs() << "  maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
8603     else {
8604       outs() << "  maxprot ";
8605       outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
8606       outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8607       outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8608     }
8609     if ((initprot &
8610          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8611            MachO::VM_PROT_EXECUTE)) != 0)
8612       outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
8613     else {
8614       outs() << " initprot ";
8615       outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
8616       outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8617       outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8618     }
8619   } else {
8620     outs() << "  maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
8621     outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
8622   }
8623   outs() << "   nsects " << nsects << "\n";
8624   if (verbose) {
8625     outs() << "    flags";
8626     if (flags == 0)
8627       outs() << " (none)\n";
8628     else {
8629       if (flags & MachO::SG_HIGHVM) {
8630         outs() << " HIGHVM";
8631         flags &= ~MachO::SG_HIGHVM;
8632       }
8633       if (flags & MachO::SG_FVMLIB) {
8634         outs() << " FVMLIB";
8635         flags &= ~MachO::SG_FVMLIB;
8636       }
8637       if (flags & MachO::SG_NORELOC) {
8638         outs() << " NORELOC";
8639         flags &= ~MachO::SG_NORELOC;
8640       }
8641       if (flags & MachO::SG_PROTECTED_VERSION_1) {
8642         outs() << " PROTECTED_VERSION_1";
8643         flags &= ~MachO::SG_PROTECTED_VERSION_1;
8644       }
8645       if (flags & MachO::SG_READ_ONLY) {
8646         // Apple's otool prints the SG_ prefix for this flag, but not for the
8647         // others.
8648         outs() << " SG_READ_ONLY";
8649         flags &= ~MachO::SG_READ_ONLY;
8650       }
8651       if (flags)
8652         outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
8653       else
8654         outs() << "\n";
8655     }
8656   } else {
8657     outs() << "    flags " << format("0x%" PRIx32, flags) << "\n";
8658   }
8659 }
8660 
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)8661 static void PrintSection(const char *sectname, const char *segname,
8662                          uint64_t addr, uint64_t size, uint32_t offset,
8663                          uint32_t align, uint32_t reloff, uint32_t nreloc,
8664                          uint32_t flags, uint32_t reserved1, uint32_t reserved2,
8665                          uint32_t cmd, const char *sg_segname,
8666                          uint32_t filetype, uint32_t object_size,
8667                          bool verbose) {
8668   outs() << "Section\n";
8669   outs() << "  sectname " << format("%.16s\n", sectname);
8670   outs() << "   segname " << format("%.16s", segname);
8671   if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
8672     outs() << " (does not match segment)\n";
8673   else
8674     outs() << "\n";
8675   if (cmd == MachO::LC_SEGMENT_64) {
8676     outs() << "      addr " << format("0x%016" PRIx64, addr) << "\n";
8677     outs() << "      size " << format("0x%016" PRIx64, size);
8678   } else {
8679     outs() << "      addr " << format("0x%08" PRIx64, addr) << "\n";
8680     outs() << "      size " << format("0x%08" PRIx64, size);
8681   }
8682   if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
8683     outs() << " (past end of file)\n";
8684   else
8685     outs() << "\n";
8686   outs() << "    offset " << offset;
8687   if (offset > object_size)
8688     outs() << " (past end of file)\n";
8689   else
8690     outs() << "\n";
8691   uint32_t align_shifted = 1 << align;
8692   outs() << "     align 2^" << align << " (" << align_shifted << ")\n";
8693   outs() << "    reloff " << reloff;
8694   if (reloff > object_size)
8695     outs() << " (past end of file)\n";
8696   else
8697     outs() << "\n";
8698   outs() << "    nreloc " << nreloc;
8699   if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
8700     outs() << " (past end of file)\n";
8701   else
8702     outs() << "\n";
8703   uint32_t section_type = flags & MachO::SECTION_TYPE;
8704   if (verbose) {
8705     outs() << "      type";
8706     if (section_type == MachO::S_REGULAR)
8707       outs() << " S_REGULAR\n";
8708     else if (section_type == MachO::S_ZEROFILL)
8709       outs() << " S_ZEROFILL\n";
8710     else if (section_type == MachO::S_CSTRING_LITERALS)
8711       outs() << " S_CSTRING_LITERALS\n";
8712     else if (section_type == MachO::S_4BYTE_LITERALS)
8713       outs() << " S_4BYTE_LITERALS\n";
8714     else if (section_type == MachO::S_8BYTE_LITERALS)
8715       outs() << " S_8BYTE_LITERALS\n";
8716     else if (section_type == MachO::S_16BYTE_LITERALS)
8717       outs() << " S_16BYTE_LITERALS\n";
8718     else if (section_type == MachO::S_LITERAL_POINTERS)
8719       outs() << " S_LITERAL_POINTERS\n";
8720     else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
8721       outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
8722     else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
8723       outs() << " S_LAZY_SYMBOL_POINTERS\n";
8724     else if (section_type == MachO::S_SYMBOL_STUBS)
8725       outs() << " S_SYMBOL_STUBS\n";
8726     else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
8727       outs() << " S_MOD_INIT_FUNC_POINTERS\n";
8728     else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
8729       outs() << " S_MOD_TERM_FUNC_POINTERS\n";
8730     else if (section_type == MachO::S_COALESCED)
8731       outs() << " S_COALESCED\n";
8732     else if (section_type == MachO::S_INTERPOSING)
8733       outs() << " S_INTERPOSING\n";
8734     else if (section_type == MachO::S_DTRACE_DOF)
8735       outs() << " S_DTRACE_DOF\n";
8736     else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
8737       outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
8738     else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
8739       outs() << " S_THREAD_LOCAL_REGULAR\n";
8740     else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
8741       outs() << " S_THREAD_LOCAL_ZEROFILL\n";
8742     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
8743       outs() << " S_THREAD_LOCAL_VARIABLES\n";
8744     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8745       outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
8746     else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
8747       outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
8748     else if (section_type == MachO::S_INIT_FUNC_OFFSETS)
8749       outs() << " S_INIT_FUNC_OFFSETS\n";
8750     else
8751       outs() << format("0x%08" PRIx32, section_type) << "\n";
8752     outs() << "attributes";
8753     uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
8754     if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
8755       outs() << " PURE_INSTRUCTIONS";
8756     if (section_attributes & MachO::S_ATTR_NO_TOC)
8757       outs() << " NO_TOC";
8758     if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
8759       outs() << " STRIP_STATIC_SYMS";
8760     if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
8761       outs() << " NO_DEAD_STRIP";
8762     if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
8763       outs() << " LIVE_SUPPORT";
8764     if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
8765       outs() << " SELF_MODIFYING_CODE";
8766     if (section_attributes & MachO::S_ATTR_DEBUG)
8767       outs() << " DEBUG";
8768     if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
8769       outs() << " SOME_INSTRUCTIONS";
8770     if (section_attributes & MachO::S_ATTR_EXT_RELOC)
8771       outs() << " EXT_RELOC";
8772     if (section_attributes & MachO::S_ATTR_LOC_RELOC)
8773       outs() << " LOC_RELOC";
8774     if (section_attributes == 0)
8775       outs() << " (none)";
8776     outs() << "\n";
8777   } else
8778     outs() << "     flags " << format("0x%08" PRIx32, flags) << "\n";
8779   outs() << " reserved1 " << reserved1;
8780   if (section_type == MachO::S_SYMBOL_STUBS ||
8781       section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
8782       section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
8783       section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
8784       section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8785     outs() << " (index into indirect symbol table)\n";
8786   else
8787     outs() << "\n";
8788   outs() << " reserved2 " << reserved2;
8789   if (section_type == MachO::S_SYMBOL_STUBS)
8790     outs() << " (size of stubs)\n";
8791   else
8792     outs() << "\n";
8793 }
8794 
PrintSymtabLoadCommand(MachO::symtab_command st,bool Is64Bit,uint32_t object_size)8795 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
8796                                    uint32_t object_size) {
8797   outs() << "     cmd LC_SYMTAB\n";
8798   outs() << " cmdsize " << st.cmdsize;
8799   if (st.cmdsize != sizeof(struct MachO::symtab_command))
8800     outs() << " Incorrect size\n";
8801   else
8802     outs() << "\n";
8803   outs() << "  symoff " << st.symoff;
8804   if (st.symoff > object_size)
8805     outs() << " (past end of file)\n";
8806   else
8807     outs() << "\n";
8808   outs() << "   nsyms " << st.nsyms;
8809   uint64_t big_size;
8810   if (Is64Bit) {
8811     big_size = st.nsyms;
8812     big_size *= sizeof(struct MachO::nlist_64);
8813     big_size += st.symoff;
8814     if (big_size > object_size)
8815       outs() << " (past end of file)\n";
8816     else
8817       outs() << "\n";
8818   } else {
8819     big_size = st.nsyms;
8820     big_size *= sizeof(struct MachO::nlist);
8821     big_size += st.symoff;
8822     if (big_size > object_size)
8823       outs() << " (past end of file)\n";
8824     else
8825       outs() << "\n";
8826   }
8827   outs() << "  stroff " << st.stroff;
8828   if (st.stroff > object_size)
8829     outs() << " (past end of file)\n";
8830   else
8831     outs() << "\n";
8832   outs() << " strsize " << st.strsize;
8833   big_size = st.stroff;
8834   big_size += st.strsize;
8835   if (big_size > object_size)
8836     outs() << " (past end of file)\n";
8837   else
8838     outs() << "\n";
8839 }
8840 
PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,uint32_t nsyms,uint32_t object_size,bool Is64Bit)8841 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
8842                                      uint32_t nsyms, uint32_t object_size,
8843                                      bool Is64Bit) {
8844   outs() << "            cmd LC_DYSYMTAB\n";
8845   outs() << "        cmdsize " << dyst.cmdsize;
8846   if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
8847     outs() << " Incorrect size\n";
8848   else
8849     outs() << "\n";
8850   outs() << "      ilocalsym " << dyst.ilocalsym;
8851   if (dyst.ilocalsym > nsyms)
8852     outs() << " (greater than the number of symbols)\n";
8853   else
8854     outs() << "\n";
8855   outs() << "      nlocalsym " << dyst.nlocalsym;
8856   uint64_t big_size;
8857   big_size = dyst.ilocalsym;
8858   big_size += dyst.nlocalsym;
8859   if (big_size > nsyms)
8860     outs() << " (past the end of the symbol table)\n";
8861   else
8862     outs() << "\n";
8863   outs() << "     iextdefsym " << dyst.iextdefsym;
8864   if (dyst.iextdefsym > nsyms)
8865     outs() << " (greater than the number of symbols)\n";
8866   else
8867     outs() << "\n";
8868   outs() << "     nextdefsym " << dyst.nextdefsym;
8869   big_size = dyst.iextdefsym;
8870   big_size += dyst.nextdefsym;
8871   if (big_size > nsyms)
8872     outs() << " (past the end of the symbol table)\n";
8873   else
8874     outs() << "\n";
8875   outs() << "      iundefsym " << dyst.iundefsym;
8876   if (dyst.iundefsym > nsyms)
8877     outs() << " (greater than the number of symbols)\n";
8878   else
8879     outs() << "\n";
8880   outs() << "      nundefsym " << dyst.nundefsym;
8881   big_size = dyst.iundefsym;
8882   big_size += dyst.nundefsym;
8883   if (big_size > nsyms)
8884     outs() << " (past the end of the symbol table)\n";
8885   else
8886     outs() << "\n";
8887   outs() << "         tocoff " << dyst.tocoff;
8888   if (dyst.tocoff > object_size)
8889     outs() << " (past end of file)\n";
8890   else
8891     outs() << "\n";
8892   outs() << "           ntoc " << dyst.ntoc;
8893   big_size = dyst.ntoc;
8894   big_size *= sizeof(struct MachO::dylib_table_of_contents);
8895   big_size += dyst.tocoff;
8896   if (big_size > object_size)
8897     outs() << " (past end of file)\n";
8898   else
8899     outs() << "\n";
8900   outs() << "      modtaboff " << dyst.modtaboff;
8901   if (dyst.modtaboff > object_size)
8902     outs() << " (past end of file)\n";
8903   else
8904     outs() << "\n";
8905   outs() << "        nmodtab " << dyst.nmodtab;
8906   uint64_t modtabend;
8907   if (Is64Bit) {
8908     modtabend = dyst.nmodtab;
8909     modtabend *= sizeof(struct MachO::dylib_module_64);
8910     modtabend += dyst.modtaboff;
8911   } else {
8912     modtabend = dyst.nmodtab;
8913     modtabend *= sizeof(struct MachO::dylib_module);
8914     modtabend += dyst.modtaboff;
8915   }
8916   if (modtabend > object_size)
8917     outs() << " (past end of file)\n";
8918   else
8919     outs() << "\n";
8920   outs() << "   extrefsymoff " << dyst.extrefsymoff;
8921   if (dyst.extrefsymoff > object_size)
8922     outs() << " (past end of file)\n";
8923   else
8924     outs() << "\n";
8925   outs() << "    nextrefsyms " << dyst.nextrefsyms;
8926   big_size = dyst.nextrefsyms;
8927   big_size *= sizeof(struct MachO::dylib_reference);
8928   big_size += dyst.extrefsymoff;
8929   if (big_size > object_size)
8930     outs() << " (past end of file)\n";
8931   else
8932     outs() << "\n";
8933   outs() << " indirectsymoff " << dyst.indirectsymoff;
8934   if (dyst.indirectsymoff > object_size)
8935     outs() << " (past end of file)\n";
8936   else
8937     outs() << "\n";
8938   outs() << "  nindirectsyms " << dyst.nindirectsyms;
8939   big_size = dyst.nindirectsyms;
8940   big_size *= sizeof(uint32_t);
8941   big_size += dyst.indirectsymoff;
8942   if (big_size > object_size)
8943     outs() << " (past end of file)\n";
8944   else
8945     outs() << "\n";
8946   outs() << "      extreloff " << dyst.extreloff;
8947   if (dyst.extreloff > object_size)
8948     outs() << " (past end of file)\n";
8949   else
8950     outs() << "\n";
8951   outs() << "        nextrel " << dyst.nextrel;
8952   big_size = dyst.nextrel;
8953   big_size *= sizeof(struct MachO::relocation_info);
8954   big_size += dyst.extreloff;
8955   if (big_size > object_size)
8956     outs() << " (past end of file)\n";
8957   else
8958     outs() << "\n";
8959   outs() << "      locreloff " << dyst.locreloff;
8960   if (dyst.locreloff > object_size)
8961     outs() << " (past end of file)\n";
8962   else
8963     outs() << "\n";
8964   outs() << "        nlocrel " << dyst.nlocrel;
8965   big_size = dyst.nlocrel;
8966   big_size *= sizeof(struct MachO::relocation_info);
8967   big_size += dyst.locreloff;
8968   if (big_size > object_size)
8969     outs() << " (past end of file)\n";
8970   else
8971     outs() << "\n";
8972 }
8973 
PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,uint32_t object_size)8974 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
8975                                      uint32_t object_size) {
8976   if (dc.cmd == MachO::LC_DYLD_INFO)
8977     outs() << "            cmd LC_DYLD_INFO\n";
8978   else
8979     outs() << "            cmd LC_DYLD_INFO_ONLY\n";
8980   outs() << "        cmdsize " << dc.cmdsize;
8981   if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
8982     outs() << " Incorrect size\n";
8983   else
8984     outs() << "\n";
8985   outs() << "     rebase_off " << dc.rebase_off;
8986   if (dc.rebase_off > object_size)
8987     outs() << " (past end of file)\n";
8988   else
8989     outs() << "\n";
8990   outs() << "    rebase_size " << dc.rebase_size;
8991   uint64_t big_size;
8992   big_size = dc.rebase_off;
8993   big_size += dc.rebase_size;
8994   if (big_size > object_size)
8995     outs() << " (past end of file)\n";
8996   else
8997     outs() << "\n";
8998   outs() << "       bind_off " << dc.bind_off;
8999   if (dc.bind_off > object_size)
9000     outs() << " (past end of file)\n";
9001   else
9002     outs() << "\n";
9003   outs() << "      bind_size " << dc.bind_size;
9004   big_size = dc.bind_off;
9005   big_size += dc.bind_size;
9006   if (big_size > object_size)
9007     outs() << " (past end of file)\n";
9008   else
9009     outs() << "\n";
9010   outs() << "  weak_bind_off " << dc.weak_bind_off;
9011   if (dc.weak_bind_off > object_size)
9012     outs() << " (past end of file)\n";
9013   else
9014     outs() << "\n";
9015   outs() << " weak_bind_size " << dc.weak_bind_size;
9016   big_size = dc.weak_bind_off;
9017   big_size += dc.weak_bind_size;
9018   if (big_size > object_size)
9019     outs() << " (past end of file)\n";
9020   else
9021     outs() << "\n";
9022   outs() << "  lazy_bind_off " << dc.lazy_bind_off;
9023   if (dc.lazy_bind_off > object_size)
9024     outs() << " (past end of file)\n";
9025   else
9026     outs() << "\n";
9027   outs() << " lazy_bind_size " << dc.lazy_bind_size;
9028   big_size = dc.lazy_bind_off;
9029   big_size += dc.lazy_bind_size;
9030   if (big_size > object_size)
9031     outs() << " (past end of file)\n";
9032   else
9033     outs() << "\n";
9034   outs() << "     export_off " << dc.export_off;
9035   if (dc.export_off > object_size)
9036     outs() << " (past end of file)\n";
9037   else
9038     outs() << "\n";
9039   outs() << "    export_size " << dc.export_size;
9040   big_size = dc.export_off;
9041   big_size += dc.export_size;
9042   if (big_size > object_size)
9043     outs() << " (past end of file)\n";
9044   else
9045     outs() << "\n";
9046 }
9047 
PrintDyldLoadCommand(MachO::dylinker_command dyld,const char * Ptr)9048 static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
9049                                  const char *Ptr) {
9050   if (dyld.cmd == MachO::LC_ID_DYLINKER)
9051     outs() << "          cmd LC_ID_DYLINKER\n";
9052   else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
9053     outs() << "          cmd LC_LOAD_DYLINKER\n";
9054   else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
9055     outs() << "          cmd LC_DYLD_ENVIRONMENT\n";
9056   else
9057     outs() << "          cmd ?(" << dyld.cmd << ")\n";
9058   outs() << "      cmdsize " << dyld.cmdsize;
9059   if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
9060     outs() << " Incorrect size\n";
9061   else
9062     outs() << "\n";
9063   if (dyld.name >= dyld.cmdsize)
9064     outs() << "         name ?(bad offset " << dyld.name << ")\n";
9065   else {
9066     const char *P = (const char *)(Ptr) + dyld.name;
9067     outs() << "         name " << P << " (offset " << dyld.name << ")\n";
9068   }
9069 }
9070 
PrintUuidLoadCommand(MachO::uuid_command uuid)9071 static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
9072   outs() << "     cmd LC_UUID\n";
9073   outs() << " cmdsize " << uuid.cmdsize;
9074   if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
9075     outs() << " Incorrect size\n";
9076   else
9077     outs() << "\n";
9078   outs() << "    uuid ";
9079   for (int i = 0; i < 16; ++i) {
9080     outs() << format("%02" PRIX32, uuid.uuid[i]);
9081     if (i == 3 || i == 5 || i == 7 || i == 9)
9082       outs() << "-";
9083   }
9084   outs() << "\n";
9085 }
9086 
PrintRpathLoadCommand(MachO::rpath_command rpath,const char * Ptr)9087 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
9088   outs() << "          cmd LC_RPATH\n";
9089   outs() << "      cmdsize " << rpath.cmdsize;
9090   if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
9091     outs() << " Incorrect size\n";
9092   else
9093     outs() << "\n";
9094   if (rpath.path >= rpath.cmdsize)
9095     outs() << "         path ?(bad offset " << rpath.path << ")\n";
9096   else {
9097     const char *P = (const char *)(Ptr) + rpath.path;
9098     outs() << "         path " << P << " (offset " << rpath.path << ")\n";
9099   }
9100 }
9101 
PrintVersionMinLoadCommand(MachO::version_min_command vd)9102 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
9103   StringRef LoadCmdName;
9104   switch (vd.cmd) {
9105   case MachO::LC_VERSION_MIN_MACOSX:
9106     LoadCmdName = "LC_VERSION_MIN_MACOSX";
9107     break;
9108   case MachO::LC_VERSION_MIN_IPHONEOS:
9109     LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
9110     break;
9111   case MachO::LC_VERSION_MIN_TVOS:
9112     LoadCmdName = "LC_VERSION_MIN_TVOS";
9113     break;
9114   case MachO::LC_VERSION_MIN_WATCHOS:
9115     LoadCmdName = "LC_VERSION_MIN_WATCHOS";
9116     break;
9117   default:
9118     llvm_unreachable("Unknown version min load command");
9119   }
9120 
9121   outs() << "      cmd " << LoadCmdName << '\n';
9122   outs() << "  cmdsize " << vd.cmdsize;
9123   if (vd.cmdsize != sizeof(struct MachO::version_min_command))
9124     outs() << " Incorrect size\n";
9125   else
9126     outs() << "\n";
9127   outs() << "  version "
9128          << MachOObjectFile::getVersionMinMajor(vd, false) << "."
9129          << MachOObjectFile::getVersionMinMinor(vd, false);
9130   uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
9131   if (Update != 0)
9132     outs() << "." << Update;
9133   outs() << "\n";
9134   if (vd.sdk == 0)
9135     outs() << "      sdk n/a";
9136   else {
9137     outs() << "      sdk "
9138            << MachOObjectFile::getVersionMinMajor(vd, true) << "."
9139            << MachOObjectFile::getVersionMinMinor(vd, true);
9140   }
9141   Update = MachOObjectFile::getVersionMinUpdate(vd, true);
9142   if (Update != 0)
9143     outs() << "." << Update;
9144   outs() << "\n";
9145 }
9146 
PrintNoteLoadCommand(MachO::note_command Nt)9147 static void PrintNoteLoadCommand(MachO::note_command Nt) {
9148   outs() << "       cmd LC_NOTE\n";
9149   outs() << "   cmdsize " << Nt.cmdsize;
9150   if (Nt.cmdsize != sizeof(struct MachO::note_command))
9151     outs() << " Incorrect size\n";
9152   else
9153     outs() << "\n";
9154   const char *d = Nt.data_owner;
9155   outs() << "data_owner " << format("%.16s\n", d);
9156   outs() << "    offset " << Nt.offset << "\n";
9157   outs() << "      size " << Nt.size << "\n";
9158 }
9159 
PrintBuildToolVersion(MachO::build_tool_version bv,bool verbose)9160 static void PrintBuildToolVersion(MachO::build_tool_version bv, bool verbose) {
9161   outs() << "      tool ";
9162   if (verbose)
9163     outs() << MachOObjectFile::getBuildTool(bv.tool);
9164   else
9165     outs() << bv.tool;
9166   outs() << "\n";
9167   outs() << "   version " << MachOObjectFile::getVersionString(bv.version)
9168          << "\n";
9169 }
9170 
PrintBuildVersionLoadCommand(const MachOObjectFile * obj,MachO::build_version_command bd,bool verbose)9171 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
9172                                          MachO::build_version_command bd,
9173                                          bool verbose) {
9174   outs() << "       cmd LC_BUILD_VERSION\n";
9175   outs() << "   cmdsize " << bd.cmdsize;
9176   if (bd.cmdsize !=
9177       sizeof(struct MachO::build_version_command) +
9178           bd.ntools * sizeof(struct MachO::build_tool_version))
9179     outs() << " Incorrect size\n";
9180   else
9181     outs() << "\n";
9182   outs() << "  platform ";
9183   if (verbose)
9184     outs() << MachOObjectFile::getBuildPlatform(bd.platform);
9185   else
9186     outs() << bd.platform;
9187   outs() << "\n";
9188   if (bd.sdk)
9189     outs() << "       sdk " << MachOObjectFile::getVersionString(bd.sdk)
9190            << "\n";
9191   else
9192     outs() << "       sdk n/a\n";
9193   outs() << "     minos " << MachOObjectFile::getVersionString(bd.minos)
9194          << "\n";
9195   outs() << "    ntools " << bd.ntools << "\n";
9196   for (unsigned i = 0; i < bd.ntools; ++i) {
9197     MachO::build_tool_version bv = obj->getBuildToolVersion(i);
9198     PrintBuildToolVersion(bv, verbose);
9199   }
9200 }
9201 
PrintSourceVersionCommand(MachO::source_version_command sd)9202 static void PrintSourceVersionCommand(MachO::source_version_command sd) {
9203   outs() << "      cmd LC_SOURCE_VERSION\n";
9204   outs() << "  cmdsize " << sd.cmdsize;
9205   if (sd.cmdsize != sizeof(struct MachO::source_version_command))
9206     outs() << " Incorrect size\n";
9207   else
9208     outs() << "\n";
9209   uint64_t a = (sd.version >> 40) & 0xffffff;
9210   uint64_t b = (sd.version >> 30) & 0x3ff;
9211   uint64_t c = (sd.version >> 20) & 0x3ff;
9212   uint64_t d = (sd.version >> 10) & 0x3ff;
9213   uint64_t e = sd.version & 0x3ff;
9214   outs() << "  version " << a << "." << b;
9215   if (e != 0)
9216     outs() << "." << c << "." << d << "." << e;
9217   else if (d != 0)
9218     outs() << "." << c << "." << d;
9219   else if (c != 0)
9220     outs() << "." << c;
9221   outs() << "\n";
9222 }
9223 
PrintEntryPointCommand(MachO::entry_point_command ep)9224 static void PrintEntryPointCommand(MachO::entry_point_command ep) {
9225   outs() << "       cmd LC_MAIN\n";
9226   outs() << "   cmdsize " << ep.cmdsize;
9227   if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
9228     outs() << " Incorrect size\n";
9229   else
9230     outs() << "\n";
9231   outs() << "  entryoff " << ep.entryoff << "\n";
9232   outs() << " stacksize " << ep.stacksize << "\n";
9233 }
9234 
PrintEncryptionInfoCommand(MachO::encryption_info_command ec,uint32_t object_size)9235 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
9236                                        uint32_t object_size) {
9237   outs() << "          cmd LC_ENCRYPTION_INFO\n";
9238   outs() << "      cmdsize " << ec.cmdsize;
9239   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
9240     outs() << " Incorrect size\n";
9241   else
9242     outs() << "\n";
9243   outs() << "     cryptoff " << ec.cryptoff;
9244   if (ec.cryptoff > object_size)
9245     outs() << " (past end of file)\n";
9246   else
9247     outs() << "\n";
9248   outs() << "    cryptsize " << ec.cryptsize;
9249   if (ec.cryptsize > object_size)
9250     outs() << " (past end of file)\n";
9251   else
9252     outs() << "\n";
9253   outs() << "      cryptid " << ec.cryptid << "\n";
9254 }
9255 
PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,uint32_t object_size)9256 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
9257                                          uint32_t object_size) {
9258   outs() << "          cmd LC_ENCRYPTION_INFO_64\n";
9259   outs() << "      cmdsize " << ec.cmdsize;
9260   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
9261     outs() << " Incorrect size\n";
9262   else
9263     outs() << "\n";
9264   outs() << "     cryptoff " << ec.cryptoff;
9265   if (ec.cryptoff > object_size)
9266     outs() << " (past end of file)\n";
9267   else
9268     outs() << "\n";
9269   outs() << "    cryptsize " << ec.cryptsize;
9270   if (ec.cryptsize > object_size)
9271     outs() << " (past end of file)\n";
9272   else
9273     outs() << "\n";
9274   outs() << "      cryptid " << ec.cryptid << "\n";
9275   outs() << "          pad " << ec.pad << "\n";
9276 }
9277 
PrintLinkerOptionCommand(MachO::linker_option_command lo,const char * Ptr)9278 static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
9279                                      const char *Ptr) {
9280   outs() << "     cmd LC_LINKER_OPTION\n";
9281   outs() << " cmdsize " << lo.cmdsize;
9282   if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
9283     outs() << " Incorrect size\n";
9284   else
9285     outs() << "\n";
9286   outs() << "   count " << lo.count << "\n";
9287   const char *string = Ptr + sizeof(struct MachO::linker_option_command);
9288   uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
9289   uint32_t i = 0;
9290   while (left > 0) {
9291     while (*string == '\0' && left > 0) {
9292       string++;
9293       left--;
9294     }
9295     if (left > 0) {
9296       i++;
9297       outs() << "  string #" << i << " " << format("%.*s\n", left, string);
9298       uint32_t NullPos = StringRef(string, left).find('\0');
9299       uint32_t len = std::min(NullPos, left) + 1;
9300       string += len;
9301       left -= len;
9302     }
9303   }
9304   if (lo.count != i)
9305     outs() << "   count " << lo.count << " does not match number of strings "
9306            << i << "\n";
9307 }
9308 
PrintSubFrameworkCommand(MachO::sub_framework_command sub,const char * Ptr)9309 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
9310                                      const char *Ptr) {
9311   outs() << "          cmd LC_SUB_FRAMEWORK\n";
9312   outs() << "      cmdsize " << sub.cmdsize;
9313   if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
9314     outs() << " Incorrect size\n";
9315   else
9316     outs() << "\n";
9317   if (sub.umbrella < sub.cmdsize) {
9318     const char *P = Ptr + sub.umbrella;
9319     outs() << "     umbrella " << P << " (offset " << sub.umbrella << ")\n";
9320   } else {
9321     outs() << "     umbrella ?(bad offset " << sub.umbrella << ")\n";
9322   }
9323 }
9324 
PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,const char * Ptr)9325 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
9326                                     const char *Ptr) {
9327   outs() << "          cmd LC_SUB_UMBRELLA\n";
9328   outs() << "      cmdsize " << sub.cmdsize;
9329   if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
9330     outs() << " Incorrect size\n";
9331   else
9332     outs() << "\n";
9333   if (sub.sub_umbrella < sub.cmdsize) {
9334     const char *P = Ptr + sub.sub_umbrella;
9335     outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
9336   } else {
9337     outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
9338   }
9339 }
9340 
PrintSubLibraryCommand(MachO::sub_library_command sub,const char * Ptr)9341 static void PrintSubLibraryCommand(MachO::sub_library_command sub,
9342                                    const char *Ptr) {
9343   outs() << "          cmd LC_SUB_LIBRARY\n";
9344   outs() << "      cmdsize " << sub.cmdsize;
9345   if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
9346     outs() << " Incorrect size\n";
9347   else
9348     outs() << "\n";
9349   if (sub.sub_library < sub.cmdsize) {
9350     const char *P = Ptr + sub.sub_library;
9351     outs() << "  sub_library " << P << " (offset " << sub.sub_library << ")\n";
9352   } else {
9353     outs() << "  sub_library ?(bad offset " << sub.sub_library << ")\n";
9354   }
9355 }
9356 
PrintSubClientCommand(MachO::sub_client_command sub,const char * Ptr)9357 static void PrintSubClientCommand(MachO::sub_client_command sub,
9358                                   const char *Ptr) {
9359   outs() << "          cmd LC_SUB_CLIENT\n";
9360   outs() << "      cmdsize " << sub.cmdsize;
9361   if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
9362     outs() << " Incorrect size\n";
9363   else
9364     outs() << "\n";
9365   if (sub.client < sub.cmdsize) {
9366     const char *P = Ptr + sub.client;
9367     outs() << "       client " << P << " (offset " << sub.client << ")\n";
9368   } else {
9369     outs() << "       client ?(bad offset " << sub.client << ")\n";
9370   }
9371 }
9372 
PrintRoutinesCommand(MachO::routines_command r)9373 static void PrintRoutinesCommand(MachO::routines_command r) {
9374   outs() << "          cmd LC_ROUTINES\n";
9375   outs() << "      cmdsize " << r.cmdsize;
9376   if (r.cmdsize != sizeof(struct MachO::routines_command))
9377     outs() << " Incorrect size\n";
9378   else
9379     outs() << "\n";
9380   outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
9381   outs() << "  init_module " << r.init_module << "\n";
9382   outs() << "    reserved1 " << r.reserved1 << "\n";
9383   outs() << "    reserved2 " << r.reserved2 << "\n";
9384   outs() << "    reserved3 " << r.reserved3 << "\n";
9385   outs() << "    reserved4 " << r.reserved4 << "\n";
9386   outs() << "    reserved5 " << r.reserved5 << "\n";
9387   outs() << "    reserved6 " << r.reserved6 << "\n";
9388 }
9389 
PrintRoutinesCommand64(MachO::routines_command_64 r)9390 static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
9391   outs() << "          cmd LC_ROUTINES_64\n";
9392   outs() << "      cmdsize " << r.cmdsize;
9393   if (r.cmdsize != sizeof(struct MachO::routines_command_64))
9394     outs() << " Incorrect size\n";
9395   else
9396     outs() << "\n";
9397   outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
9398   outs() << "  init_module " << r.init_module << "\n";
9399   outs() << "    reserved1 " << r.reserved1 << "\n";
9400   outs() << "    reserved2 " << r.reserved2 << "\n";
9401   outs() << "    reserved3 " << r.reserved3 << "\n";
9402   outs() << "    reserved4 " << r.reserved4 << "\n";
9403   outs() << "    reserved5 " << r.reserved5 << "\n";
9404   outs() << "    reserved6 " << r.reserved6 << "\n";
9405 }
9406 
Print_x86_thread_state32_t(MachO::x86_thread_state32_t & cpu32)9407 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
9408   outs() << "\t    eax " << format("0x%08" PRIx32, cpu32.eax);
9409   outs() << " ebx    " << format("0x%08" PRIx32, cpu32.ebx);
9410   outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx);
9411   outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n";
9412   outs() << "\t    edi " << format("0x%08" PRIx32, cpu32.edi);
9413   outs() << " esi    " << format("0x%08" PRIx32, cpu32.esi);
9414   outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp);
9415   outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n";
9416   outs() << "\t    ss  " << format("0x%08" PRIx32, cpu32.ss);
9417   outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags);
9418   outs() << " eip " << format("0x%08" PRIx32, cpu32.eip);
9419   outs() << " cs  " << format("0x%08" PRIx32, cpu32.cs) << "\n";
9420   outs() << "\t    ds  " << format("0x%08" PRIx32, cpu32.ds);
9421   outs() << " es     " << format("0x%08" PRIx32, cpu32.es);
9422   outs() << " fs  " << format("0x%08" PRIx32, cpu32.fs);
9423   outs() << " gs  " << format("0x%08" PRIx32, cpu32.gs) << "\n";
9424 }
9425 
Print_x86_thread_state64_t(MachO::x86_thread_state64_t & cpu64)9426 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
9427   outs() << "   rax  " << format("0x%016" PRIx64, cpu64.rax);
9428   outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
9429   outs() << " rcx  " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
9430   outs() << "   rdx  " << format("0x%016" PRIx64, cpu64.rdx);
9431   outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
9432   outs() << " rsi  " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
9433   outs() << "   rbp  " << format("0x%016" PRIx64, cpu64.rbp);
9434   outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
9435   outs() << " r8   " << format("0x%016" PRIx64, cpu64.r8) << "\n";
9436   outs() << "    r9  " << format("0x%016" PRIx64, cpu64.r9);
9437   outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
9438   outs() << " r11  " << format("0x%016" PRIx64, cpu64.r11) << "\n";
9439   outs() << "   r12  " << format("0x%016" PRIx64, cpu64.r12);
9440   outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
9441   outs() << " r14  " << format("0x%016" PRIx64, cpu64.r14) << "\n";
9442   outs() << "   r15  " << format("0x%016" PRIx64, cpu64.r15);
9443   outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
9444   outs() << "rflags  " << format("0x%016" PRIx64, cpu64.rflags);
9445   outs() << " cs  " << format("0x%016" PRIx64, cpu64.cs);
9446   outs() << " fs   " << format("0x%016" PRIx64, cpu64.fs) << "\n";
9447   outs() << "    gs  " << format("0x%016" PRIx64, cpu64.gs) << "\n";
9448 }
9449 
Print_mmst_reg(MachO::mmst_reg_t & r)9450 static void Print_mmst_reg(MachO::mmst_reg_t &r) {
9451   uint32_t f;
9452   outs() << "\t      mmst_reg  ";
9453   for (f = 0; f < 10; f++)
9454     outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
9455   outs() << "\n";
9456   outs() << "\t      mmst_rsrv ";
9457   for (f = 0; f < 6; f++)
9458     outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
9459   outs() << "\n";
9460 }
9461 
Print_xmm_reg(MachO::xmm_reg_t & r)9462 static void Print_xmm_reg(MachO::xmm_reg_t &r) {
9463   uint32_t f;
9464   outs() << "\t      xmm_reg ";
9465   for (f = 0; f < 16; f++)
9466     outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
9467   outs() << "\n";
9468 }
9469 
Print_x86_float_state_t(MachO::x86_float_state64_t & fpu)9470 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
9471   outs() << "\t    fpu_reserved[0] " << fpu.fpu_reserved[0];
9472   outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
9473   outs() << "\t    control: invalid " << fpu.fpu_fcw.invalid;
9474   outs() << " denorm " << fpu.fpu_fcw.denorm;
9475   outs() << " zdiv " << fpu.fpu_fcw.zdiv;
9476   outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
9477   outs() << " undfl " << fpu.fpu_fcw.undfl;
9478   outs() << " precis " << fpu.fpu_fcw.precis << "\n";
9479   outs() << "\t\t     pc ";
9480   if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
9481     outs() << "FP_PREC_24B ";
9482   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
9483     outs() << "FP_PREC_53B ";
9484   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
9485     outs() << "FP_PREC_64B ";
9486   else
9487     outs() << fpu.fpu_fcw.pc << " ";
9488   outs() << "rc ";
9489   if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
9490     outs() << "FP_RND_NEAR ";
9491   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
9492     outs() << "FP_RND_DOWN ";
9493   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
9494     outs() << "FP_RND_UP ";
9495   else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
9496     outs() << "FP_CHOP ";
9497   outs() << "\n";
9498   outs() << "\t    status: invalid " << fpu.fpu_fsw.invalid;
9499   outs() << " denorm " << fpu.fpu_fsw.denorm;
9500   outs() << " zdiv " << fpu.fpu_fsw.zdiv;
9501   outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
9502   outs() << " undfl " << fpu.fpu_fsw.undfl;
9503   outs() << " precis " << fpu.fpu_fsw.precis;
9504   outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
9505   outs() << "\t            errsumm " << fpu.fpu_fsw.errsumm;
9506   outs() << " c0 " << fpu.fpu_fsw.c0;
9507   outs() << " c1 " << fpu.fpu_fsw.c1;
9508   outs() << " c2 " << fpu.fpu_fsw.c2;
9509   outs() << " tos " << fpu.fpu_fsw.tos;
9510   outs() << " c3 " << fpu.fpu_fsw.c3;
9511   outs() << " busy " << fpu.fpu_fsw.busy << "\n";
9512   outs() << "\t    fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
9513   outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
9514   outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
9515   outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
9516   outs() << "\t    fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
9517   outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
9518   outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
9519   outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
9520   outs() << "\t    fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
9521   outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
9522   outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
9523   outs() << "\n";
9524   outs() << "\t    fpu_stmm0:\n";
9525   Print_mmst_reg(fpu.fpu_stmm0);
9526   outs() << "\t    fpu_stmm1:\n";
9527   Print_mmst_reg(fpu.fpu_stmm1);
9528   outs() << "\t    fpu_stmm2:\n";
9529   Print_mmst_reg(fpu.fpu_stmm2);
9530   outs() << "\t    fpu_stmm3:\n";
9531   Print_mmst_reg(fpu.fpu_stmm3);
9532   outs() << "\t    fpu_stmm4:\n";
9533   Print_mmst_reg(fpu.fpu_stmm4);
9534   outs() << "\t    fpu_stmm5:\n";
9535   Print_mmst_reg(fpu.fpu_stmm5);
9536   outs() << "\t    fpu_stmm6:\n";
9537   Print_mmst_reg(fpu.fpu_stmm6);
9538   outs() << "\t    fpu_stmm7:\n";
9539   Print_mmst_reg(fpu.fpu_stmm7);
9540   outs() << "\t    fpu_xmm0:\n";
9541   Print_xmm_reg(fpu.fpu_xmm0);
9542   outs() << "\t    fpu_xmm1:\n";
9543   Print_xmm_reg(fpu.fpu_xmm1);
9544   outs() << "\t    fpu_xmm2:\n";
9545   Print_xmm_reg(fpu.fpu_xmm2);
9546   outs() << "\t    fpu_xmm3:\n";
9547   Print_xmm_reg(fpu.fpu_xmm3);
9548   outs() << "\t    fpu_xmm4:\n";
9549   Print_xmm_reg(fpu.fpu_xmm4);
9550   outs() << "\t    fpu_xmm5:\n";
9551   Print_xmm_reg(fpu.fpu_xmm5);
9552   outs() << "\t    fpu_xmm6:\n";
9553   Print_xmm_reg(fpu.fpu_xmm6);
9554   outs() << "\t    fpu_xmm7:\n";
9555   Print_xmm_reg(fpu.fpu_xmm7);
9556   outs() << "\t    fpu_xmm8:\n";
9557   Print_xmm_reg(fpu.fpu_xmm8);
9558   outs() << "\t    fpu_xmm9:\n";
9559   Print_xmm_reg(fpu.fpu_xmm9);
9560   outs() << "\t    fpu_xmm10:\n";
9561   Print_xmm_reg(fpu.fpu_xmm10);
9562   outs() << "\t    fpu_xmm11:\n";
9563   Print_xmm_reg(fpu.fpu_xmm11);
9564   outs() << "\t    fpu_xmm12:\n";
9565   Print_xmm_reg(fpu.fpu_xmm12);
9566   outs() << "\t    fpu_xmm13:\n";
9567   Print_xmm_reg(fpu.fpu_xmm13);
9568   outs() << "\t    fpu_xmm14:\n";
9569   Print_xmm_reg(fpu.fpu_xmm14);
9570   outs() << "\t    fpu_xmm15:\n";
9571   Print_xmm_reg(fpu.fpu_xmm15);
9572   outs() << "\t    fpu_rsrv4:\n";
9573   for (uint32_t f = 0; f < 6; f++) {
9574     outs() << "\t            ";
9575     for (uint32_t g = 0; g < 16; g++)
9576       outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
9577     outs() << "\n";
9578   }
9579   outs() << "\t    fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
9580   outs() << "\n";
9581 }
9582 
Print_x86_exception_state_t(MachO::x86_exception_state64_t & exc64)9583 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
9584   outs() << "\t    trapno " << format("0x%08" PRIx32, exc64.trapno);
9585   outs() << " err " << format("0x%08" PRIx32, exc64.err);
9586   outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
9587 }
9588 
Print_arm_thread_state32_t(MachO::arm_thread_state32_t & cpu32)9589 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
9590   outs() << "\t    r0  " << format("0x%08" PRIx32, cpu32.r[0]);
9591   outs() << " r1     "   << format("0x%08" PRIx32, cpu32.r[1]);
9592   outs() << " r2  "      << format("0x%08" PRIx32, cpu32.r[2]);
9593   outs() << " r3  "      << format("0x%08" PRIx32, cpu32.r[3]) << "\n";
9594   outs() << "\t    r4  " << format("0x%08" PRIx32, cpu32.r[4]);
9595   outs() << " r5     "   << format("0x%08" PRIx32, cpu32.r[5]);
9596   outs() << " r6  "      << format("0x%08" PRIx32, cpu32.r[6]);
9597   outs() << " r7  "      << format("0x%08" PRIx32, cpu32.r[7]) << "\n";
9598   outs() << "\t    r8  " << format("0x%08" PRIx32, cpu32.r[8]);
9599   outs() << " r9     "   << format("0x%08" PRIx32, cpu32.r[9]);
9600   outs() << " r10 "      << format("0x%08" PRIx32, cpu32.r[10]);
9601   outs() << " r11 "      << format("0x%08" PRIx32, cpu32.r[11]) << "\n";
9602   outs() << "\t    r12 " << format("0x%08" PRIx32, cpu32.r[12]);
9603   outs() << " sp     "   << format("0x%08" PRIx32, cpu32.sp);
9604   outs() << " lr  "      << format("0x%08" PRIx32, cpu32.lr);
9605   outs() << " pc  "      << format("0x%08" PRIx32, cpu32.pc) << "\n";
9606   outs() << "\t   cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
9607 }
9608 
Print_arm_thread_state64_t(MachO::arm_thread_state64_t & cpu64)9609 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
9610   outs() << "\t    x0  " << format("0x%016" PRIx64, cpu64.x[0]);
9611   outs() << " x1  "      << format("0x%016" PRIx64, cpu64.x[1]);
9612   outs() << " x2  "      << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
9613   outs() << "\t    x3  " << format("0x%016" PRIx64, cpu64.x[3]);
9614   outs() << " x4  "      << format("0x%016" PRIx64, cpu64.x[4]);
9615   outs() << " x5  "      << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
9616   outs() << "\t    x6  " << format("0x%016" PRIx64, cpu64.x[6]);
9617   outs() << " x7  "      << format("0x%016" PRIx64, cpu64.x[7]);
9618   outs() << " x8  "      << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
9619   outs() << "\t    x9  " << format("0x%016" PRIx64, cpu64.x[9]);
9620   outs() << " x10 "      << format("0x%016" PRIx64, cpu64.x[10]);
9621   outs() << " x11 "      << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
9622   outs() << "\t    x12 " << format("0x%016" PRIx64, cpu64.x[12]);
9623   outs() << " x13 "      << format("0x%016" PRIx64, cpu64.x[13]);
9624   outs() << " x14 "      << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
9625   outs() << "\t    x15 " << format("0x%016" PRIx64, cpu64.x[15]);
9626   outs() << " x16 "      << format("0x%016" PRIx64, cpu64.x[16]);
9627   outs() << " x17 "      << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
9628   outs() << "\t    x18 " << format("0x%016" PRIx64, cpu64.x[18]);
9629   outs() << " x19 "      << format("0x%016" PRIx64, cpu64.x[19]);
9630   outs() << " x20 "      << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
9631   outs() << "\t    x21 " << format("0x%016" PRIx64, cpu64.x[21]);
9632   outs() << " x22 "      << format("0x%016" PRIx64, cpu64.x[22]);
9633   outs() << " x23 "      << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
9634   outs() << "\t    x24 " << format("0x%016" PRIx64, cpu64.x[24]);
9635   outs() << " x25 "      << format("0x%016" PRIx64, cpu64.x[25]);
9636   outs() << " x26 "      << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
9637   outs() << "\t    x27 " << format("0x%016" PRIx64, cpu64.x[27]);
9638   outs() << " x28 "      << format("0x%016" PRIx64, cpu64.x[28]);
9639   outs() << "  fp "      << format("0x%016" PRIx64, cpu64.fp) << "\n";
9640   outs() << "\t     lr " << format("0x%016" PRIx64, cpu64.lr);
9641   outs() << " sp  "      << format("0x%016" PRIx64, cpu64.sp);
9642   outs() << "  pc "      << format("0x%016" PRIx64, cpu64.pc) << "\n";
9643   outs() << "\t   cpsr " << format("0x%08"  PRIx32, cpu64.cpsr) << "\n";
9644 }
9645 
PrintThreadCommand(MachO::thread_command t,const char * Ptr,bool isLittleEndian,uint32_t cputype)9646 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
9647                                bool isLittleEndian, uint32_t cputype) {
9648   if (t.cmd == MachO::LC_THREAD)
9649     outs() << "        cmd LC_THREAD\n";
9650   else if (t.cmd == MachO::LC_UNIXTHREAD)
9651     outs() << "        cmd LC_UNIXTHREAD\n";
9652   else
9653     outs() << "        cmd " << t.cmd << " (unknown)\n";
9654   outs() << "    cmdsize " << t.cmdsize;
9655   if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
9656     outs() << " Incorrect size\n";
9657   else
9658     outs() << "\n";
9659 
9660   const char *begin = Ptr + sizeof(struct MachO::thread_command);
9661   const char *end = Ptr + t.cmdsize;
9662   uint32_t flavor, count, left;
9663   if (cputype == MachO::CPU_TYPE_I386) {
9664     while (begin < end) {
9665       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9666         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9667         begin += sizeof(uint32_t);
9668       } else {
9669         flavor = 0;
9670         begin = end;
9671       }
9672       if (isLittleEndian != sys::IsLittleEndianHost)
9673         sys::swapByteOrder(flavor);
9674       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9675         memcpy((char *)&count, begin, sizeof(uint32_t));
9676         begin += sizeof(uint32_t);
9677       } else {
9678         count = 0;
9679         begin = end;
9680       }
9681       if (isLittleEndian != sys::IsLittleEndianHost)
9682         sys::swapByteOrder(count);
9683       if (flavor == MachO::x86_THREAD_STATE32) {
9684         outs() << "     flavor i386_THREAD_STATE\n";
9685         if (count == MachO::x86_THREAD_STATE32_COUNT)
9686           outs() << "      count i386_THREAD_STATE_COUNT\n";
9687         else
9688           outs() << "      count " << count
9689                  << " (not x86_THREAD_STATE32_COUNT)\n";
9690         MachO::x86_thread_state32_t cpu32;
9691         left = end - begin;
9692         if (left >= sizeof(MachO::x86_thread_state32_t)) {
9693           memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
9694           begin += sizeof(MachO::x86_thread_state32_t);
9695         } else {
9696           memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
9697           memcpy(&cpu32, begin, left);
9698           begin += left;
9699         }
9700         if (isLittleEndian != sys::IsLittleEndianHost)
9701           swapStruct(cpu32);
9702         Print_x86_thread_state32_t(cpu32);
9703       } else if (flavor == MachO::x86_THREAD_STATE) {
9704         outs() << "     flavor x86_THREAD_STATE\n";
9705         if (count == MachO::x86_THREAD_STATE_COUNT)
9706           outs() << "      count x86_THREAD_STATE_COUNT\n";
9707         else
9708           outs() << "      count " << count
9709                  << " (not x86_THREAD_STATE_COUNT)\n";
9710         struct MachO::x86_thread_state_t ts;
9711         left = end - begin;
9712         if (left >= sizeof(MachO::x86_thread_state_t)) {
9713           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9714           begin += sizeof(MachO::x86_thread_state_t);
9715         } else {
9716           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9717           memcpy(&ts, begin, left);
9718           begin += left;
9719         }
9720         if (isLittleEndian != sys::IsLittleEndianHost)
9721           swapStruct(ts);
9722         if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
9723           outs() << "\t    tsh.flavor x86_THREAD_STATE32 ";
9724           if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
9725             outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
9726           else
9727             outs() << "tsh.count " << ts.tsh.count
9728                    << " (not x86_THREAD_STATE32_COUNT\n";
9729           Print_x86_thread_state32_t(ts.uts.ts32);
9730         } else {
9731           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9732                  << ts.tsh.count << "\n";
9733         }
9734       } else {
9735         outs() << "     flavor " << flavor << " (unknown)\n";
9736         outs() << "      count " << count << "\n";
9737         outs() << "      state (unknown)\n";
9738         begin += count * sizeof(uint32_t);
9739       }
9740     }
9741   } else if (cputype == MachO::CPU_TYPE_X86_64) {
9742     while (begin < end) {
9743       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9744         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9745         begin += sizeof(uint32_t);
9746       } else {
9747         flavor = 0;
9748         begin = end;
9749       }
9750       if (isLittleEndian != sys::IsLittleEndianHost)
9751         sys::swapByteOrder(flavor);
9752       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9753         memcpy((char *)&count, begin, sizeof(uint32_t));
9754         begin += sizeof(uint32_t);
9755       } else {
9756         count = 0;
9757         begin = end;
9758       }
9759       if (isLittleEndian != sys::IsLittleEndianHost)
9760         sys::swapByteOrder(count);
9761       if (flavor == MachO::x86_THREAD_STATE64) {
9762         outs() << "     flavor x86_THREAD_STATE64\n";
9763         if (count == MachO::x86_THREAD_STATE64_COUNT)
9764           outs() << "      count x86_THREAD_STATE64_COUNT\n";
9765         else
9766           outs() << "      count " << count
9767                  << " (not x86_THREAD_STATE64_COUNT)\n";
9768         MachO::x86_thread_state64_t cpu64;
9769         left = end - begin;
9770         if (left >= sizeof(MachO::x86_thread_state64_t)) {
9771           memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
9772           begin += sizeof(MachO::x86_thread_state64_t);
9773         } else {
9774           memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
9775           memcpy(&cpu64, begin, left);
9776           begin += left;
9777         }
9778         if (isLittleEndian != sys::IsLittleEndianHost)
9779           swapStruct(cpu64);
9780         Print_x86_thread_state64_t(cpu64);
9781       } else if (flavor == MachO::x86_THREAD_STATE) {
9782         outs() << "     flavor x86_THREAD_STATE\n";
9783         if (count == MachO::x86_THREAD_STATE_COUNT)
9784           outs() << "      count x86_THREAD_STATE_COUNT\n";
9785         else
9786           outs() << "      count " << count
9787                  << " (not x86_THREAD_STATE_COUNT)\n";
9788         struct MachO::x86_thread_state_t ts;
9789         left = end - begin;
9790         if (left >= sizeof(MachO::x86_thread_state_t)) {
9791           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9792           begin += sizeof(MachO::x86_thread_state_t);
9793         } else {
9794           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9795           memcpy(&ts, begin, left);
9796           begin += left;
9797         }
9798         if (isLittleEndian != sys::IsLittleEndianHost)
9799           swapStruct(ts);
9800         if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
9801           outs() << "\t    tsh.flavor x86_THREAD_STATE64 ";
9802           if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
9803             outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
9804           else
9805             outs() << "tsh.count " << ts.tsh.count
9806                    << " (not x86_THREAD_STATE64_COUNT\n";
9807           Print_x86_thread_state64_t(ts.uts.ts64);
9808         } else {
9809           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9810                  << ts.tsh.count << "\n";
9811         }
9812       } else if (flavor == MachO::x86_FLOAT_STATE) {
9813         outs() << "     flavor x86_FLOAT_STATE\n";
9814         if (count == MachO::x86_FLOAT_STATE_COUNT)
9815           outs() << "      count x86_FLOAT_STATE_COUNT\n";
9816         else
9817           outs() << "      count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
9818         struct MachO::x86_float_state_t fs;
9819         left = end - begin;
9820         if (left >= sizeof(MachO::x86_float_state_t)) {
9821           memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
9822           begin += sizeof(MachO::x86_float_state_t);
9823         } else {
9824           memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
9825           memcpy(&fs, begin, left);
9826           begin += left;
9827         }
9828         if (isLittleEndian != sys::IsLittleEndianHost)
9829           swapStruct(fs);
9830         if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
9831           outs() << "\t    fsh.flavor x86_FLOAT_STATE64 ";
9832           if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
9833             outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
9834           else
9835             outs() << "fsh.count " << fs.fsh.count
9836                    << " (not x86_FLOAT_STATE64_COUNT\n";
9837           Print_x86_float_state_t(fs.ufs.fs64);
9838         } else {
9839           outs() << "\t    fsh.flavor " << fs.fsh.flavor << "  fsh.count "
9840                  << fs.fsh.count << "\n";
9841         }
9842       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
9843         outs() << "     flavor x86_EXCEPTION_STATE\n";
9844         if (count == MachO::x86_EXCEPTION_STATE_COUNT)
9845           outs() << "      count x86_EXCEPTION_STATE_COUNT\n";
9846         else
9847           outs() << "      count " << count
9848                  << " (not x86_EXCEPTION_STATE_COUNT)\n";
9849         struct MachO::x86_exception_state_t es;
9850         left = end - begin;
9851         if (left >= sizeof(MachO::x86_exception_state_t)) {
9852           memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
9853           begin += sizeof(MachO::x86_exception_state_t);
9854         } else {
9855           memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
9856           memcpy(&es, begin, left);
9857           begin += left;
9858         }
9859         if (isLittleEndian != sys::IsLittleEndianHost)
9860           swapStruct(es);
9861         if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
9862           outs() << "\t    esh.flavor x86_EXCEPTION_STATE64\n";
9863           if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
9864             outs() << "\t    esh.count x86_EXCEPTION_STATE64_COUNT\n";
9865           else
9866             outs() << "\t    esh.count " << es.esh.count
9867                    << " (not x86_EXCEPTION_STATE64_COUNT\n";
9868           Print_x86_exception_state_t(es.ues.es64);
9869         } else {
9870           outs() << "\t    esh.flavor " << es.esh.flavor << "  esh.count "
9871                  << es.esh.count << "\n";
9872         }
9873       } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
9874         outs() << "     flavor x86_EXCEPTION_STATE64\n";
9875         if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
9876           outs() << "      count x86_EXCEPTION_STATE64_COUNT\n";
9877         else
9878           outs() << "      count " << count
9879                  << " (not x86_EXCEPTION_STATE64_COUNT)\n";
9880         struct MachO::x86_exception_state64_t es64;
9881         left = end - begin;
9882         if (left >= sizeof(MachO::x86_exception_state64_t)) {
9883           memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
9884           begin += sizeof(MachO::x86_exception_state64_t);
9885         } else {
9886           memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
9887           memcpy(&es64, begin, left);
9888           begin += left;
9889         }
9890         if (isLittleEndian != sys::IsLittleEndianHost)
9891           swapStruct(es64);
9892         Print_x86_exception_state_t(es64);
9893       } else {
9894         outs() << "     flavor " << flavor << " (unknown)\n";
9895         outs() << "      count " << count << "\n";
9896         outs() << "      state (unknown)\n";
9897         begin += count * sizeof(uint32_t);
9898       }
9899     }
9900   } else if (cputype == MachO::CPU_TYPE_ARM) {
9901     while (begin < end) {
9902       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9903         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9904         begin += sizeof(uint32_t);
9905       } else {
9906         flavor = 0;
9907         begin = end;
9908       }
9909       if (isLittleEndian != sys::IsLittleEndianHost)
9910         sys::swapByteOrder(flavor);
9911       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9912         memcpy((char *)&count, begin, sizeof(uint32_t));
9913         begin += sizeof(uint32_t);
9914       } else {
9915         count = 0;
9916         begin = end;
9917       }
9918       if (isLittleEndian != sys::IsLittleEndianHost)
9919         sys::swapByteOrder(count);
9920       if (flavor == MachO::ARM_THREAD_STATE) {
9921         outs() << "     flavor ARM_THREAD_STATE\n";
9922         if (count == MachO::ARM_THREAD_STATE_COUNT)
9923           outs() << "      count ARM_THREAD_STATE_COUNT\n";
9924         else
9925           outs() << "      count " << count
9926                  << " (not ARM_THREAD_STATE_COUNT)\n";
9927         MachO::arm_thread_state32_t cpu32;
9928         left = end - begin;
9929         if (left >= sizeof(MachO::arm_thread_state32_t)) {
9930           memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
9931           begin += sizeof(MachO::arm_thread_state32_t);
9932         } else {
9933           memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
9934           memcpy(&cpu32, begin, left);
9935           begin += left;
9936         }
9937         if (isLittleEndian != sys::IsLittleEndianHost)
9938           swapStruct(cpu32);
9939         Print_arm_thread_state32_t(cpu32);
9940       } else {
9941         outs() << "     flavor " << flavor << " (unknown)\n";
9942         outs() << "      count " << count << "\n";
9943         outs() << "      state (unknown)\n";
9944         begin += count * sizeof(uint32_t);
9945       }
9946     }
9947   } else if (cputype == MachO::CPU_TYPE_ARM64 ||
9948              cputype == MachO::CPU_TYPE_ARM64_32) {
9949     while (begin < end) {
9950       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9951         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9952         begin += sizeof(uint32_t);
9953       } else {
9954         flavor = 0;
9955         begin = end;
9956       }
9957       if (isLittleEndian != sys::IsLittleEndianHost)
9958         sys::swapByteOrder(flavor);
9959       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9960         memcpy((char *)&count, begin, sizeof(uint32_t));
9961         begin += sizeof(uint32_t);
9962       } else {
9963         count = 0;
9964         begin = end;
9965       }
9966       if (isLittleEndian != sys::IsLittleEndianHost)
9967         sys::swapByteOrder(count);
9968       if (flavor == MachO::ARM_THREAD_STATE64) {
9969         outs() << "     flavor ARM_THREAD_STATE64\n";
9970         if (count == MachO::ARM_THREAD_STATE64_COUNT)
9971           outs() << "      count ARM_THREAD_STATE64_COUNT\n";
9972         else
9973           outs() << "      count " << count
9974                  << " (not ARM_THREAD_STATE64_COUNT)\n";
9975         MachO::arm_thread_state64_t cpu64;
9976         left = end - begin;
9977         if (left >= sizeof(MachO::arm_thread_state64_t)) {
9978           memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
9979           begin += sizeof(MachO::arm_thread_state64_t);
9980         } else {
9981           memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
9982           memcpy(&cpu64, begin, left);
9983           begin += left;
9984         }
9985         if (isLittleEndian != sys::IsLittleEndianHost)
9986           swapStruct(cpu64);
9987         Print_arm_thread_state64_t(cpu64);
9988       } else {
9989         outs() << "     flavor " << flavor << " (unknown)\n";
9990         outs() << "      count " << count << "\n";
9991         outs() << "      state (unknown)\n";
9992         begin += count * sizeof(uint32_t);
9993       }
9994     }
9995   } else {
9996     while (begin < end) {
9997       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9998         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9999         begin += sizeof(uint32_t);
10000       } else {
10001         flavor = 0;
10002         begin = end;
10003       }
10004       if (isLittleEndian != sys::IsLittleEndianHost)
10005         sys::swapByteOrder(flavor);
10006       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10007         memcpy((char *)&count, begin, sizeof(uint32_t));
10008         begin += sizeof(uint32_t);
10009       } else {
10010         count = 0;
10011         begin = end;
10012       }
10013       if (isLittleEndian != sys::IsLittleEndianHost)
10014         sys::swapByteOrder(count);
10015       outs() << "     flavor " << flavor << "\n";
10016       outs() << "      count " << count << "\n";
10017       outs() << "      state (Unknown cputype/cpusubtype)\n";
10018       begin += count * sizeof(uint32_t);
10019     }
10020   }
10021 }
10022 
PrintDylibCommand(MachO::dylib_command dl,const char * Ptr)10023 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
10024   if (dl.cmd == MachO::LC_ID_DYLIB)
10025     outs() << "          cmd LC_ID_DYLIB\n";
10026   else if (dl.cmd == MachO::LC_LOAD_DYLIB)
10027     outs() << "          cmd LC_LOAD_DYLIB\n";
10028   else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
10029     outs() << "          cmd LC_LOAD_WEAK_DYLIB\n";
10030   else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
10031     outs() << "          cmd LC_REEXPORT_DYLIB\n";
10032   else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
10033     outs() << "          cmd LC_LAZY_LOAD_DYLIB\n";
10034   else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
10035     outs() << "          cmd LC_LOAD_UPWARD_DYLIB\n";
10036   else
10037     outs() << "          cmd " << dl.cmd << " (unknown)\n";
10038   outs() << "      cmdsize " << dl.cmdsize;
10039   if (dl.cmdsize < sizeof(struct MachO::dylib_command))
10040     outs() << " Incorrect size\n";
10041   else
10042     outs() << "\n";
10043   if (dl.dylib.name < dl.cmdsize) {
10044     const char *P = (const char *)(Ptr) + dl.dylib.name;
10045     outs() << "         name " << P << " (offset " << dl.dylib.name << ")\n";
10046   } else {
10047     outs() << "         name ?(bad offset " << dl.dylib.name << ")\n";
10048   }
10049   outs() << "   time stamp " << dl.dylib.timestamp << " ";
10050   time_t t = dl.dylib.timestamp;
10051   outs() << ctime(&t);
10052   outs() << "      current version ";
10053   if (dl.dylib.current_version == 0xffffffff)
10054     outs() << "n/a\n";
10055   else
10056     outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
10057            << ((dl.dylib.current_version >> 8) & 0xff) << "."
10058            << (dl.dylib.current_version & 0xff) << "\n";
10059   outs() << "compatibility version ";
10060   if (dl.dylib.compatibility_version == 0xffffffff)
10061     outs() << "n/a\n";
10062   else
10063     outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
10064            << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
10065            << (dl.dylib.compatibility_version & 0xff) << "\n";
10066 }
10067 
PrintLinkEditDataCommand(MachO::linkedit_data_command ld,uint32_t object_size)10068 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
10069                                      uint32_t object_size) {
10070   if (ld.cmd == MachO::LC_CODE_SIGNATURE)
10071     outs() << "      cmd LC_CODE_SIGNATURE\n";
10072   else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
10073     outs() << "      cmd LC_SEGMENT_SPLIT_INFO\n";
10074   else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
10075     outs() << "      cmd LC_FUNCTION_STARTS\n";
10076   else if (ld.cmd == MachO::LC_DATA_IN_CODE)
10077     outs() << "      cmd LC_DATA_IN_CODE\n";
10078   else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
10079     outs() << "      cmd LC_DYLIB_CODE_SIGN_DRS\n";
10080   else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
10081     outs() << "      cmd LC_LINKER_OPTIMIZATION_HINT\n";
10082   else if (ld.cmd == MachO::LC_DYLD_EXPORTS_TRIE)
10083     outs() << "      cmd LC_DYLD_EXPORTS_TRIE\n";
10084   else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS)
10085     outs() << "      cmd LC_DYLD_CHAINED_FIXUPS\n";
10086   else if (ld.cmd == MachO::LC_ATOM_INFO)
10087     outs() << "      cmd LC_ATOM_INFO\n";
10088   else
10089     outs() << "      cmd " << ld.cmd << " (?)\n";
10090   outs() << "  cmdsize " << ld.cmdsize;
10091   if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
10092     outs() << " Incorrect size\n";
10093   else
10094     outs() << "\n";
10095   outs() << "  dataoff " << ld.dataoff;
10096   if (ld.dataoff > object_size)
10097     outs() << " (past end of file)\n";
10098   else
10099     outs() << "\n";
10100   outs() << " datasize " << ld.datasize;
10101   uint64_t big_size = ld.dataoff;
10102   big_size += ld.datasize;
10103   if (big_size > object_size)
10104     outs() << " (past end of file)\n";
10105   else
10106     outs() << "\n";
10107 }
10108 
PrintLoadCommands(const MachOObjectFile * Obj,uint32_t filetype,uint32_t cputype,bool verbose)10109 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
10110                               uint32_t cputype, bool verbose) {
10111   StringRef Buf = Obj->getData();
10112   unsigned Index = 0;
10113   for (const auto &Command : Obj->load_commands()) {
10114     outs() << "Load command " << Index++ << "\n";
10115     if (Command.C.cmd == MachO::LC_SEGMENT) {
10116       MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
10117       const char *sg_segname = SLC.segname;
10118       PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
10119                           SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
10120                           SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
10121                           verbose);
10122       for (unsigned j = 0; j < SLC.nsects; j++) {
10123         MachO::section S = Obj->getSection(Command, j);
10124         PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
10125                      S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
10126                      SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
10127       }
10128     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10129       MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
10130       const char *sg_segname = SLC_64.segname;
10131       PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
10132                           SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
10133                           SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
10134                           SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
10135       for (unsigned j = 0; j < SLC_64.nsects; j++) {
10136         MachO::section_64 S_64 = Obj->getSection64(Command, j);
10137         PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
10138                      S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
10139                      S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
10140                      sg_segname, filetype, Buf.size(), verbose);
10141       }
10142     } else if (Command.C.cmd == MachO::LC_SYMTAB) {
10143       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10144       PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
10145     } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
10146       MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
10147       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10148       PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
10149                                Obj->is64Bit());
10150     } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
10151                Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
10152       MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
10153       PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
10154     } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
10155                Command.C.cmd == MachO::LC_ID_DYLINKER ||
10156                Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
10157       MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
10158       PrintDyldLoadCommand(Dyld, Command.Ptr);
10159     } else if (Command.C.cmd == MachO::LC_UUID) {
10160       MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
10161       PrintUuidLoadCommand(Uuid);
10162     } else if (Command.C.cmd == MachO::LC_RPATH) {
10163       MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
10164       PrintRpathLoadCommand(Rpath, Command.Ptr);
10165     } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
10166                Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
10167                Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
10168                Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
10169       MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
10170       PrintVersionMinLoadCommand(Vd);
10171     } else if (Command.C.cmd == MachO::LC_NOTE) {
10172       MachO::note_command Nt = Obj->getNoteLoadCommand(Command);
10173       PrintNoteLoadCommand(Nt);
10174     } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) {
10175       MachO::build_version_command Bv =
10176           Obj->getBuildVersionLoadCommand(Command);
10177       PrintBuildVersionLoadCommand(Obj, Bv, verbose);
10178     } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
10179       MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
10180       PrintSourceVersionCommand(Sd);
10181     } else if (Command.C.cmd == MachO::LC_MAIN) {
10182       MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
10183       PrintEntryPointCommand(Ep);
10184     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
10185       MachO::encryption_info_command Ei =
10186           Obj->getEncryptionInfoCommand(Command);
10187       PrintEncryptionInfoCommand(Ei, Buf.size());
10188     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
10189       MachO::encryption_info_command_64 Ei =
10190           Obj->getEncryptionInfoCommand64(Command);
10191       PrintEncryptionInfoCommand64(Ei, Buf.size());
10192     } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
10193       MachO::linker_option_command Lo =
10194           Obj->getLinkerOptionLoadCommand(Command);
10195       PrintLinkerOptionCommand(Lo, Command.Ptr);
10196     } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
10197       MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
10198       PrintSubFrameworkCommand(Sf, Command.Ptr);
10199     } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
10200       MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
10201       PrintSubUmbrellaCommand(Sf, Command.Ptr);
10202     } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
10203       MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
10204       PrintSubLibraryCommand(Sl, Command.Ptr);
10205     } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
10206       MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
10207       PrintSubClientCommand(Sc, Command.Ptr);
10208     } else if (Command.C.cmd == MachO::LC_ROUTINES) {
10209       MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
10210       PrintRoutinesCommand(Rc);
10211     } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
10212       MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
10213       PrintRoutinesCommand64(Rc);
10214     } else if (Command.C.cmd == MachO::LC_THREAD ||
10215                Command.C.cmd == MachO::LC_UNIXTHREAD) {
10216       MachO::thread_command Tc = Obj->getThreadCommand(Command);
10217       PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
10218     } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
10219                Command.C.cmd == MachO::LC_ID_DYLIB ||
10220                Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
10221                Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
10222                Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
10223                Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
10224       MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
10225       PrintDylibCommand(Dl, Command.Ptr);
10226     } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
10227                Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
10228                Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
10229                Command.C.cmd == MachO::LC_DATA_IN_CODE ||
10230                Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
10231                Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT ||
10232                Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE ||
10233                Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS ||
10234                Command.C.cmd == MachO::LC_ATOM_INFO) {
10235       MachO::linkedit_data_command Ld =
10236           Obj->getLinkeditDataLoadCommand(Command);
10237       PrintLinkEditDataCommand(Ld, Buf.size());
10238     } else {
10239       outs() << "      cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
10240              << ")\n";
10241       outs() << "  cmdsize " << Command.C.cmdsize << "\n";
10242       // TODO: get and print the raw bytes of the load command.
10243     }
10244     // TODO: print all the other kinds of load commands.
10245   }
10246 }
10247 
PrintMachHeader(const MachOObjectFile * Obj,bool verbose)10248 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
10249   if (Obj->is64Bit()) {
10250     MachO::mach_header_64 H_64;
10251     H_64 = Obj->getHeader64();
10252     PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
10253                     H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
10254   } else {
10255     MachO::mach_header H;
10256     H = Obj->getHeader();
10257     PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
10258                     H.sizeofcmds, H.flags, verbose);
10259   }
10260 }
10261 
printMachOFileHeader(const object::ObjectFile * Obj)10262 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) {
10263   const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10264   PrintMachHeader(file, Verbose);
10265 }
10266 
printPrivateHeaders()10267 void MachODumper::printPrivateHeaders() {
10268   printMachOFileHeader(&Obj);
10269   if (!FirstPrivateHeader)
10270     printMachOLoadCommands(&Obj);
10271 }
10272 
printMachOLoadCommands(const object::ObjectFile * Obj)10273 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) {
10274   const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10275   uint32_t filetype = 0;
10276   uint32_t cputype = 0;
10277   if (file->is64Bit()) {
10278     MachO::mach_header_64 H_64;
10279     H_64 = file->getHeader64();
10280     filetype = H_64.filetype;
10281     cputype = H_64.cputype;
10282   } else {
10283     MachO::mach_header H;
10284     H = file->getHeader();
10285     filetype = H.filetype;
10286     cputype = H.cputype;
10287   }
10288   PrintLoadCommands(file, filetype, cputype, Verbose);
10289 }
10290 
10291 //===----------------------------------------------------------------------===//
10292 // export trie dumping
10293 //===----------------------------------------------------------------------===//
10294 
printMachOExportsTrie(const object::MachOObjectFile * Obj)10295 static void printMachOExportsTrie(const object::MachOObjectFile *Obj) {
10296   uint64_t BaseSegmentAddress = 0;
10297   for (const auto &Command : Obj->load_commands()) {
10298     if (Command.C.cmd == MachO::LC_SEGMENT) {
10299       MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command);
10300       if (Seg.fileoff == 0 && Seg.filesize != 0) {
10301         BaseSegmentAddress = Seg.vmaddr;
10302         break;
10303       }
10304     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10305       MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command);
10306       if (Seg.fileoff == 0 && Seg.filesize != 0) {
10307         BaseSegmentAddress = Seg.vmaddr;
10308         break;
10309       }
10310     }
10311   }
10312   Error Err = Error::success();
10313   for (const object::ExportEntry &Entry : Obj->exports(Err)) {
10314     uint64_t Flags = Entry.flags();
10315     bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
10316     bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
10317     bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10318                         MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
10319     bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10320                 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
10321     bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
10322     if (ReExport)
10323       outs() << "[re-export] ";
10324     else
10325       outs() << format("0x%08llX  ",
10326                        Entry.address() + BaseSegmentAddress);
10327     outs() << Entry.name();
10328     if (WeakDef || ThreadLocal || Resolver || Abs) {
10329       ListSeparator LS;
10330       outs() << " [";
10331       if (WeakDef)
10332         outs() << LS << "weak_def";
10333       if (ThreadLocal)
10334         outs() << LS << "per-thread";
10335       if (Abs)
10336         outs() << LS << "absolute";
10337       if (Resolver)
10338         outs() << LS << format("resolver=0x%08llX", Entry.other());
10339       outs() << "]";
10340     }
10341     if (ReExport) {
10342       StringRef DylibName = "unknown";
10343       int Ordinal = Entry.other() - 1;
10344       Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
10345       if (Entry.otherName().empty())
10346         outs() << " (from " << DylibName << ")";
10347       else
10348         outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
10349     }
10350     outs() << "\n";
10351   }
10352   if (Err)
10353     reportError(std::move(Err), Obj->getFileName());
10354 }
10355 
10356 //===----------------------------------------------------------------------===//
10357 // rebase table dumping
10358 //===----------------------------------------------------------------------===//
10359 
printMachORebaseTable(object::MachOObjectFile * Obj)10360 static void printMachORebaseTable(object::MachOObjectFile *Obj) {
10361   outs() << "segment  section            address     type\n";
10362   Error Err = Error::success();
10363   for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
10364     StringRef SegmentName = Entry.segmentName();
10365     StringRef SectionName = Entry.sectionName();
10366     uint64_t Address = Entry.address();
10367 
10368     // Table lines look like: __DATA  __nl_symbol_ptr  0x0000F00C  pointer
10369     outs() << format("%-8s %-18s 0x%08" PRIX64 "  %s\n",
10370                      SegmentName.str().c_str(), SectionName.str().c_str(),
10371                      Address, Entry.typeName().str().c_str());
10372   }
10373   if (Err)
10374     reportError(std::move(Err), Obj->getFileName());
10375 }
10376 
ordinalName(const object::MachOObjectFile * Obj,int Ordinal)10377 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
10378   StringRef DylibName;
10379   switch (Ordinal) {
10380   case MachO::BIND_SPECIAL_DYLIB_SELF:
10381     return "this-image";
10382   case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
10383     return "main-executable";
10384   case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
10385     return "flat-namespace";
10386   case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP:
10387     return "weak";
10388   default:
10389     if (Ordinal > 0) {
10390       std::error_code EC =
10391           Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
10392       if (EC)
10393         return "<<bad library ordinal>>";
10394       return DylibName;
10395     }
10396   }
10397   return "<<unknown special ordinal>>";
10398 }
10399 
10400 //===----------------------------------------------------------------------===//
10401 // bind table dumping
10402 //===----------------------------------------------------------------------===//
10403 
printMachOBindTable(object::MachOObjectFile * Obj)10404 static void printMachOBindTable(object::MachOObjectFile *Obj) {
10405   // Build table of sections so names can used in final output.
10406   outs() << "segment  section            address    type       "
10407             "addend dylib            symbol\n";
10408   Error Err = Error::success();
10409   for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
10410     StringRef SegmentName = Entry.segmentName();
10411     StringRef SectionName = Entry.sectionName();
10412     uint64_t Address = Entry.address();
10413 
10414     // Table lines look like:
10415     //  __DATA  __got  0x00012010    pointer   0 libSystem ___stack_chk_guard
10416     StringRef Attr;
10417     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
10418       Attr = " (weak_import)";
10419     outs() << left_justify(SegmentName, 8) << " "
10420            << left_justify(SectionName, 18) << " "
10421            << format_hex(Address, 10, true) << " "
10422            << left_justify(Entry.typeName(), 8) << " "
10423            << format_decimal(Entry.addend(), 8) << " "
10424            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10425            << Entry.symbolName() << Attr << "\n";
10426   }
10427   if (Err)
10428     reportError(std::move(Err), Obj->getFileName());
10429 }
10430 
10431 //===----------------------------------------------------------------------===//
10432 // lazy bind table dumping
10433 //===----------------------------------------------------------------------===//
10434 
printMachOLazyBindTable(object::MachOObjectFile * Obj)10435 static void printMachOLazyBindTable(object::MachOObjectFile *Obj) {
10436   outs() << "segment  section            address     "
10437             "dylib            symbol\n";
10438   Error Err = Error::success();
10439   for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
10440     StringRef SegmentName = Entry.segmentName();
10441     StringRef SectionName = Entry.sectionName();
10442     uint64_t Address = Entry.address();
10443 
10444     // Table lines look like:
10445     //  __DATA  __got  0x00012010 libSystem ___stack_chk_guard
10446     outs() << left_justify(SegmentName, 8) << " "
10447            << left_justify(SectionName, 18) << " "
10448            << format_hex(Address, 10, true) << " "
10449            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10450            << Entry.symbolName() << "\n";
10451   }
10452   if (Err)
10453     reportError(std::move(Err), Obj->getFileName());
10454 }
10455 
10456 //===----------------------------------------------------------------------===//
10457 // weak bind table dumping
10458 //===----------------------------------------------------------------------===//
10459 
printMachOWeakBindTable(object::MachOObjectFile * Obj)10460 static void printMachOWeakBindTable(object::MachOObjectFile *Obj) {
10461   outs() << "segment  section            address     "
10462             "type       addend   symbol\n";
10463   Error Err = Error::success();
10464   for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) {
10465     // Strong symbols don't have a location to update.
10466     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
10467       outs() << "                                        strong              "
10468              << Entry.symbolName() << "\n";
10469       continue;
10470     }
10471     StringRef SegmentName = Entry.segmentName();
10472     StringRef SectionName = Entry.sectionName();
10473     uint64_t Address = Entry.address();
10474 
10475     // Table lines look like:
10476     // __DATA  __data  0x00001000  pointer    0   _foo
10477     outs() << left_justify(SegmentName, 8) << " "
10478            << left_justify(SectionName, 18) << " "
10479            << format_hex(Address, 10, true) << " "
10480            << left_justify(Entry.typeName(), 8) << " "
10481            << format_decimal(Entry.addend(), 8) << "   " << Entry.symbolName()
10482            << "\n";
10483   }
10484   if (Err)
10485     reportError(std::move(Err), Obj->getFileName());
10486 }
10487 
10488 // get_dyld_bind_info_symbolname() is used for disassembly and passed an
10489 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
10490 // information for that address. If the address is found its binding symbol
10491 // name is returned.  If not nullptr is returned.
get_dyld_bind_info_symbolname(uint64_t ReferenceValue,struct DisassembleInfo * info)10492 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
10493                                                  struct DisassembleInfo *info) {
10494   if (info->bindtable == nullptr) {
10495     info->bindtable = std::make_unique<SymbolAddressMap>();
10496     Error Err = Error::success();
10497     for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
10498       uint64_t Address = Entry.address();
10499       StringRef name = Entry.symbolName();
10500       if (!name.empty())
10501         (*info->bindtable)[Address] = name;
10502     }
10503     if (Err)
10504       reportError(std::move(Err), info->O->getFileName());
10505   }
10506   auto name = info->bindtable->lookup(ReferenceValue);
10507   return !name.empty() ? name.data() : nullptr;
10508 }
10509 
printLazyBindTable(ObjectFile * o)10510 void objdump::printLazyBindTable(ObjectFile *o) {
10511   outs() << "\nLazy bind table:\n";
10512   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10513     printMachOLazyBindTable(MachO);
10514   else
10515     WithColor::error()
10516         << "This operation is only currently supported "
10517            "for Mach-O executable files.\n";
10518 }
10519 
printWeakBindTable(ObjectFile * o)10520 void objdump::printWeakBindTable(ObjectFile *o) {
10521   outs() << "\nWeak bind table:\n";
10522   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10523     printMachOWeakBindTable(MachO);
10524   else
10525     WithColor::error()
10526         << "This operation is only currently supported "
10527            "for Mach-O executable files.\n";
10528 }
10529 
printExportsTrie(const ObjectFile * o)10530 void objdump::printExportsTrie(const ObjectFile *o) {
10531   outs() << "\nExports trie:\n";
10532   if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10533     printMachOExportsTrie(MachO);
10534   else
10535     WithColor::error()
10536         << "This operation is only currently supported "
10537            "for Mach-O executable files.\n";
10538 }
10539 
printRebaseTable(ObjectFile * o)10540 void objdump::printRebaseTable(ObjectFile *o) {
10541   outs() << "\nRebase table:\n";
10542   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10543     printMachORebaseTable(MachO);
10544   else
10545     WithColor::error()
10546         << "This operation is only currently supported "
10547            "for Mach-O executable files.\n";
10548 }
10549 
printBindTable(ObjectFile * o)10550 void objdump::printBindTable(ObjectFile *o) {
10551   outs() << "\nBind table:\n";
10552   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10553     printMachOBindTable(MachO);
10554   else
10555     WithColor::error()
10556         << "This operation is only currently supported "
10557            "for Mach-O executable files.\n";
10558 }
10559