Bug Summary

File:tools/llvm-objdump/MachODump.cpp
Warning:line 412, column 10
Called C++ object pointer is null

Annotated Source Code

[?] Use j/k keys for keyboard navigation

/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-objdump/MachODump.cpp

1//===-- MachODump.cpp - Object file dumping utility for llvm --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the MachO-specific dumper for llvm-objdump.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm-objdump.h"
15#include "llvm-c/Disassembler.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/ADT/Triple.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/Object/MachO.h"
34#include "llvm/Object/MachOUniversal.h"
35#include "llvm/Support/Casting.h"
36#include "llvm/Support/CommandLine.h"
37#include "llvm/Support/Debug.h"
38#include "llvm/Support/Endian.h"
39#include "llvm/Support/Format.h"
40#include "llvm/Support/FormattedStream.h"
41#include "llvm/Support/GraphWriter.h"
42#include "llvm/Support/LEB128.h"
43#include "llvm/Support/MemoryBuffer.h"
44#include "llvm/Support/TargetRegistry.h"
45#include "llvm/Support/TargetSelect.h"
46#include "llvm/Support/ToolOutputFile.h"
47#include "llvm/Support/raw_ostream.h"
48#include <algorithm>
49#include <cstring>
50#include <system_error>
51
52#ifdef HAVE_LIBXAR
53extern "C" {
54#include <xar/xar.h>
55}
56#endif
57
58using namespace llvm;
59using namespace object;
60
61static cl::opt<bool>
62 UseDbg("g",
63 cl::desc("Print line information from debug info if available"));
64
65static cl::opt<std::string> DSYMFile("dsym",
66 cl::desc("Use .dSYM file for debug info"));
67
68static cl::opt<bool> FullLeadingAddr("full-leading-addr",
69 cl::desc("Print full leading address"));
70
71static cl::opt<bool> NoLeadingHeaders("no-leading-headers",
72 cl::desc("Print no leading headers"));
73
74cl::opt<bool> llvm::UniversalHeaders("universal-headers",
75 cl::desc("Print Mach-O universal headers "
76 "(requires -macho)"));
77
78cl::opt<bool>
79 llvm::ArchiveHeaders("archive-headers",
80 cl::desc("Print archive headers for Mach-O archives "
81 "(requires -macho)"));
82
83cl::opt<bool>
84 ArchiveMemberOffsets("archive-member-offsets",
85 cl::desc("Print the offset to each archive member for "
86 "Mach-O archives (requires -macho and "
87 "-archive-headers)"));
88
89cl::opt<bool>
90 llvm::IndirectSymbols("indirect-symbols",
91 cl::desc("Print indirect symbol table for Mach-O "
92 "objects (requires -macho)"));
93
94cl::opt<bool>
95 llvm::DataInCode("data-in-code",
96 cl::desc("Print the data in code table for Mach-O objects "
97 "(requires -macho)"));
98
99cl::opt<bool>
100 llvm::LinkOptHints("link-opt-hints",
101 cl::desc("Print the linker optimization hints for "
102 "Mach-O objects (requires -macho)"));
103
104cl::opt<bool>
105 llvm::InfoPlist("info-plist",
106 cl::desc("Print the info plist section as strings for "
107 "Mach-O objects (requires -macho)"));
108
109cl::opt<bool>
110 llvm::DylibsUsed("dylibs-used",
111 cl::desc("Print the shared libraries used for linked "
112 "Mach-O files (requires -macho)"));
113
114cl::opt<bool>
115 llvm::DylibId("dylib-id",
116 cl::desc("Print the shared library's id for the dylib Mach-O "
117 "file (requires -macho)"));
118
119cl::opt<bool>
120 llvm::NonVerbose("non-verbose",
121 cl::desc("Print the info for Mach-O objects in "
122 "non-verbose or numeric form (requires -macho)"));
123
124cl::opt<bool>
125 llvm::ObjcMetaData("objc-meta-data",
126 cl::desc("Print the Objective-C runtime meta data for "
127 "Mach-O files (requires -macho)"));
128
129cl::opt<std::string> llvm::DisSymName(
130 "dis-symname",
131 cl::desc("disassemble just this symbol's instructions (requires -macho)"));
132
133static cl::opt<bool> NoSymbolicOperands(
134 "no-symbolic-operands",
135 cl::desc("do not symbolic operands when disassembling (requires -macho)"));
136
137static cl::list<std::string>
138 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
139 cl::ZeroOrMore);
140
141bool ArchAll = false;
142
143static std::string ThumbTripleName;
144
145static const Target *GetTarget(const MachOObjectFile *MachOObj,
146 const char **McpuDefault,
147 const Target **ThumbTarget) {
148 // Figure out the target triple.
149 llvm::Triple TT(TripleName);
150 if (TripleName.empty()) {
151 TT = MachOObj->getArchTriple(McpuDefault);
152 TripleName = TT.str();
153 }
154
155 if (TT.getArch() == Triple::arm) {
156 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
157 // that support ARM are also capable of Thumb mode.
158 llvm::Triple ThumbTriple = TT;
159 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
160 ThumbTriple.setArchName(ThumbName);
161 ThumbTripleName = ThumbTriple.str();
162 }
163
164 // Get the target specific parser.
165 std::string Error;
166 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
167 if (TheTarget && ThumbTripleName.empty())
168 return TheTarget;
169
170 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
171 if (*ThumbTarget)
172 return TheTarget;
173
174 errs() << "llvm-objdump: error: unable to get target for '";
175 if (!TheTarget)
176 errs() << TripleName;
177 else
178 errs() << ThumbTripleName;
179 errs() << "', see --version and --triple.\n";
180 return nullptr;
181}
182
183struct SymbolSorter {
184 bool operator()(const SymbolRef &A, const SymbolRef &B) {
185 Expected<SymbolRef::Type> ATypeOrErr = A.getType();
186 if (!ATypeOrErr)
187 report_error(A.getObject()->getFileName(), ATypeOrErr.takeError());
188 SymbolRef::Type AType = *ATypeOrErr;
189 Expected<SymbolRef::Type> BTypeOrErr = B.getType();
190 if (!BTypeOrErr)
191 report_error(B.getObject()->getFileName(), BTypeOrErr.takeError());
192 SymbolRef::Type BType = *BTypeOrErr;
193 uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
194 uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
195 return AAddr < BAddr;
196 }
197};
198
199// Types for the storted data in code table that is built before disassembly
200// and the predicate function to sort them.
201typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
202typedef std::vector<DiceTableEntry> DiceTable;
203typedef DiceTable::iterator dice_table_iterator;
204
205#ifdef HAVE_LIBXAR
206namespace {
207struct ScopedXarFile {
208 xar_t xar;
209 ScopedXarFile(const char *filename, int32_t flags)
210 : xar(xar_open(filename, flags)) {}
211 ~ScopedXarFile() {
212 if (xar)
213 xar_close(xar);
214 }
215 ScopedXarFile(const ScopedXarFile &) = delete;
216 ScopedXarFile &operator=(const ScopedXarFile &) = delete;
217 operator xar_t() { return xar; }
218};
219
220struct ScopedXarIter {
221 xar_iter_t iter;
222 ScopedXarIter() : iter(xar_iter_new()) {}
223 ~ScopedXarIter() {
224 if (iter)
225 xar_iter_free(iter);
226 }
227 ScopedXarIter(const ScopedXarIter &) = delete;
228 ScopedXarIter &operator=(const ScopedXarIter &) = delete;
229 operator xar_iter_t() { return iter; }
230};
231} // namespace
232#endif // defined(HAVE_LIBXAR)
233
234// This is used to search for a data in code table entry for the PC being
235// disassembled. The j parameter has the PC in j.first. A single data in code
236// table entry can cover many bytes for each of its Kind's. So if the offset,
237// aka the i.first value, of the data in code table entry plus its Length
238// covers the PC being searched for this will return true. If not it will
239// return false.
240static bool compareDiceTableEntries(const DiceTableEntry &i,
241 const DiceTableEntry &j) {
242 uint16_t Length;
243 i.second.getLength(Length);
244
245 return j.first >= i.first && j.first < i.first + Length;
246}
247
248static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
249 unsigned short Kind) {
250 uint32_t Value, Size = 1;
251
252 switch (Kind) {
253 default:
254 case MachO::DICE_KIND_DATA:
255 if (Length >= 4) {
256 if (!NoShowRawInsn)
257 dumpBytes(makeArrayRef(bytes, 4), outs());
258 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
259 outs() << "\t.long " << Value;
260 Size = 4;
261 } else if (Length >= 2) {
262 if (!NoShowRawInsn)
263 dumpBytes(makeArrayRef(bytes, 2), outs());
264 Value = bytes[1] << 8 | bytes[0];
265 outs() << "\t.short " << Value;
266 Size = 2;
267 } else {
268 if (!NoShowRawInsn)
269 dumpBytes(makeArrayRef(bytes, 2), outs());
270 Value = bytes[0];
271 outs() << "\t.byte " << Value;
272 Size = 1;
273 }
274 if (Kind == MachO::DICE_KIND_DATA)
275 outs() << "\t@ KIND_DATA\n";
276 else
277 outs() << "\t@ data in code kind = " << Kind << "\n";
278 break;
279 case MachO::DICE_KIND_JUMP_TABLE8:
280 if (!NoShowRawInsn)
281 dumpBytes(makeArrayRef(bytes, 1), outs());
282 Value = bytes[0];
283 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
284 Size = 1;
285 break;
286 case MachO::DICE_KIND_JUMP_TABLE16:
287 if (!NoShowRawInsn)
288 dumpBytes(makeArrayRef(bytes, 2), outs());
289 Value = bytes[1] << 8 | bytes[0];
290 outs() << "\t.short " << format("%5u", Value & 0xffff)
291 << "\t@ KIND_JUMP_TABLE16\n";
292 Size = 2;
293 break;
294 case MachO::DICE_KIND_JUMP_TABLE32:
295 case MachO::DICE_KIND_ABS_JUMP_TABLE32:
296 if (!NoShowRawInsn)
297 dumpBytes(makeArrayRef(bytes, 4), outs());
298 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
299 outs() << "\t.long " << Value;
300 if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
301 outs() << "\t@ KIND_JUMP_TABLE32\n";
302 else
303 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
304 Size = 4;
305 break;
306 }
307 return Size;
308}
309
310static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
311 std::vector<SectionRef> &Sections,
312 std::vector<SymbolRef> &Symbols,
313 SmallVectorImpl<uint64_t> &FoundFns,
314 uint64_t &BaseSegmentAddress) {
315 for (const SymbolRef &Symbol : MachOObj->symbols()) {
316 Expected<StringRef> SymName = Symbol.getName();
317 if (!SymName)
318 report_error(MachOObj->getFileName(), SymName.takeError());
319 if (!SymName->startswith("ltmp"))
320 Symbols.push_back(Symbol);
321 }
322
323 for (const SectionRef &Section : MachOObj->sections()) {
324 StringRef SectName;
325 Section.getName(SectName);
326 Sections.push_back(Section);
327 }
328
329 bool BaseSegmentAddressSet = false;
330 for (const auto &Command : MachOObj->load_commands()) {
331 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
332 // We found a function starts segment, parse the addresses for later
333 // consumption.
334 MachO::linkedit_data_command LLC =
335 MachOObj->getLinkeditDataLoadCommand(Command);
336
337 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
338 } else if (Command.C.cmd == MachO::LC_SEGMENT) {
339 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
340 StringRef SegName = SLC.segname;
341 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
342 BaseSegmentAddressSet = true;
343 BaseSegmentAddress = SLC.vmaddr;
344 }
345 }
346 }
347}
348
349static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
350 uint32_t n, uint32_t count,
351 uint32_t stride, uint64_t addr) {
352 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
353 uint32_t nindirectsyms = Dysymtab.nindirectsyms;
354 if (n > nindirectsyms)
355 outs() << " (entries start past the end of the indirect symbol "
356 "table) (reserved1 field greater than the table size)";
357 else if (n + count > nindirectsyms)
358 outs() << " (entries extends past the end of the indirect symbol "
359 "table)";
360 outs() << "\n";
361 uint32_t cputype = O->getHeader().cputype;
362 if (cputype & MachO::CPU_ARCH_ABI64)
363 outs() << "address index";
364 else
365 outs() << "address index";
366 if (verbose)
367 outs() << " name\n";
368 else
369 outs() << "\n";
370 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
371 if (cputype & MachO::CPU_ARCH_ABI64)
372 outs() << format("0x%016" PRIx64"l" "x", addr + j * stride) << " ";
373 else
374 outs() << format("0x%08" PRIx32"x", (uint32_t)addr + j * stride) << " ";
375 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
376 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
377 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
378 outs() << "LOCAL\n";
379 continue;
380 }
381 if (indirect_symbol ==
382 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
383 outs() << "LOCAL ABSOLUTE\n";
384 continue;
385 }
386 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
387 outs() << "ABSOLUTE\n";
388 continue;
389 }
390 outs() << format("%5u ", indirect_symbol);
391 if (verbose) {
392 MachO::symtab_command Symtab = O->getSymtabLoadCommand();
393 if (indirect_symbol < Symtab.nsyms) {
394 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
395 SymbolRef Symbol = *Sym;
396 Expected<StringRef> SymName = Symbol.getName();
397 if (!SymName)
398 report_error(O->getFileName(), SymName.takeError());
399 outs() << *SymName;
400 } else {
401 outs() << "?";
402 }
403 }
404 outs() << "\n";
405 }
406}
407
408static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
409 for (const auto &Load : O->load_commands()) {
410 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
411 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
412 for (unsigned J = 0; J < Seg.nsects; ++J) {
413 MachO::section_64 Sec = O->getSection64(Load, J);
414 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
415 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
416 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
417 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
418 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
419 section_type == MachO::S_SYMBOL_STUBS) {
420 uint32_t stride;
421 if (section_type == MachO::S_SYMBOL_STUBS)
422 stride = Sec.reserved2;
423 else
424 stride = 8;
425 if (stride == 0) {
426 outs() << "Can't print indirect symbols for (" << Sec.segname << ","
427 << Sec.sectname << ") "
428 << "(size of stubs in reserved2 field is zero)\n";
429 continue;
430 }
431 uint32_t count = Sec.size / stride;
432 outs() << "Indirect symbols for (" << Sec.segname << ","
433 << Sec.sectname << ") " << count << " entries";
434 uint32_t n = Sec.reserved1;
435 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
436 }
437 }
438 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
439 MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
440 for (unsigned J = 0; J < Seg.nsects; ++J) {
441 MachO::section Sec = O->getSection(Load, J);
442 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
443 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
444 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
445 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
446 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
447 section_type == MachO::S_SYMBOL_STUBS) {
448 uint32_t stride;
449 if (section_type == MachO::S_SYMBOL_STUBS)
450 stride = Sec.reserved2;
451 else
452 stride = 4;
453 if (stride == 0) {
454 outs() << "Can't print indirect symbols for (" << Sec.segname << ","
455 << Sec.sectname << ") "
456 << "(size of stubs in reserved2 field is zero)\n";
457 continue;
458 }
459 uint32_t count = Sec.size / stride;
460 outs() << "Indirect symbols for (" << Sec.segname << ","
461 << Sec.sectname << ") " << count << " entries";
462 uint32_t n = Sec.reserved1;
463 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
464 }
465 }
466 }
467 }
468}
469
470static void PrintRType(const uint64_t cputype, const unsigned r_type) {
471 static char const *generic_r_types[] = {
472 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ",
473 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ",
474 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
475 };
476 static char const *x86_64_r_types[] = {
477 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ",
478 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ",
479 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
480 };
481 static char const *arm_r_types[] = {
482 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
483 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ",
484 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
485 };
486 static char const *arm64_r_types[] = {
487 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ",
488 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF",
489 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
490 };
491
492 if (r_type > 0xf){
493 outs() << format("%-7u", r_type) << " ";
494 return;
495 }
496 switch (cputype) {
497 case MachO::CPU_TYPE_I386:
498 outs() << generic_r_types[r_type];
499 break;
500 case MachO::CPU_TYPE_X86_64:
501 outs() << x86_64_r_types[r_type];
502 break;
503 case MachO::CPU_TYPE_ARM:
504 outs() << arm_r_types[r_type];
505 break;
506 case MachO::CPU_TYPE_ARM64:
507 outs() << arm64_r_types[r_type];
508 break;
509 default:
510 outs() << format("%-7u ", r_type);
511 }
512}
513
514static void PrintRLength(const uint64_t cputype, const unsigned r_type,
515 const unsigned r_length, const bool previous_arm_half){
516 if (cputype == MachO::CPU_TYPE_ARM &&
517 (r_type == llvm::MachO::ARM_RELOC_HALF ||
518 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF ||
519 previous_arm_half == true)) {
520 if ((r_length & 0x1) == 0)
521 outs() << "lo/";
522 else
523 outs() << "hi/";
524 if ((r_length & 0x1) == 0)
525 outs() << "arm ";
526 else
527 outs() << "thm ";
528 } else {
529 switch (r_length) {
530 case 0:
531 outs() << "byte ";
532 break;
533 case 1:
534 outs() << "word ";
535 break;
536 case 2:
537 outs() << "long ";
538 break;
539 case 3:
540 if (cputype == MachO::CPU_TYPE_X86_64)
541 outs() << "quad ";
542 else
543 outs() << format("?(%2d) ", r_length);
544 break;
545 default:
546 outs() << format("?(%2d) ", r_length);
547 }
548 }
549}
550
551static void PrintRelocationEntries(const MachOObjectFile *O,
552 const relocation_iterator Begin,
553 const relocation_iterator End,
554 const uint64_t cputype,
555 const bool verbose) {
556 const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
557 bool previous_arm_half = false;
558 bool previous_sectdiff = false;
559 uint32_t sectdiff_r_type = 0;
560
561 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
562 const DataRefImpl Rel = Reloc->getRawDataRefImpl();
563 const MachO::any_relocation_info RE = O->getRelocation(Rel);
564 const unsigned r_type = O->getAnyRelocationType(RE);
565 const bool r_scattered = O->isRelocationScattered(RE);
566 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
567 const unsigned r_length = O->getAnyRelocationLength(RE);
568 const unsigned r_address = O->getAnyRelocationAddress(RE);
569 const bool r_extern = (r_scattered ? false :
570 O->getPlainRelocationExternal(RE));
571 const uint32_t r_value = (r_scattered ?
572 O->getScatteredRelocationValue(RE) : 0);
573 const unsigned r_symbolnum = (r_scattered ? 0 :
574 O->getPlainRelocationSymbolNum(RE));
575
576 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
577 if (verbose) {
578 // scattered: address
579 if ((cputype == MachO::CPU_TYPE_I386 &&
580 r_type == llvm::MachO::GENERIC_RELOC_PAIR) ||
581 (cputype == MachO::CPU_TYPE_ARM &&
582 r_type == llvm::MachO::ARM_RELOC_PAIR))
583 outs() << " ";
584 else
585 outs() << format("%08x ", (unsigned int)r_address);
586
587 // scattered: pcrel
588 if (r_pcrel)
589 outs() << "True ";
590 else
591 outs() << "False ";
592
593 // scattered: length
594 PrintRLength(cputype, r_type, r_length, previous_arm_half);
595
596 // scattered: extern & type
597 outs() << "n/a ";
598 PrintRType(cputype, r_type);
599
600 // scattered: scattered & value
601 outs() << format("True 0x%08x", (unsigned int)r_value);
602 if (previous_sectdiff == false) {
603 if ((cputype == MachO::CPU_TYPE_ARM &&
604 r_type == llvm::MachO::ARM_RELOC_PAIR))
605 outs() << format(" half = 0x%04x ", (unsigned int)r_address);
606 }
607 else if (cputype == MachO::CPU_TYPE_ARM &&
608 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)
609 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
610 if ((cputype == MachO::CPU_TYPE_I386 &&
611 (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF ||
612 r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
613 (cputype == MachO::CPU_TYPE_ARM &&
614 (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF ||
615 sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF ||
616 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) {
617 previous_sectdiff = true;
618 sectdiff_r_type = r_type;
619 }
620 else {
621 previous_sectdiff = false;
622 sectdiff_r_type = 0;
623 }
624 if (cputype == MachO::CPU_TYPE_ARM &&
625 (r_type == llvm::MachO::ARM_RELOC_HALF ||
626 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
627 previous_arm_half = true;
628 else
629 previous_arm_half = false;
630 outs() << "\n";
631 }
632 else {
633 // scattered: address pcrel length extern type scattered value
634 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n",
635 (unsigned int)r_address, r_pcrel, r_length, r_type,
636 (unsigned int)r_value);
637 }
638 }
639 else {
640 if (verbose) {
641 // plain: address
642 if (cputype == MachO::CPU_TYPE_ARM &&
643 r_type == llvm::MachO::ARM_RELOC_PAIR)
644 outs() << " ";
645 else
646 outs() << format("%08x ", (unsigned int)r_address);
647
648 // plain: pcrel
649 if (r_pcrel)
650 outs() << "True ";
651 else
652 outs() << "False ";
653
654 // plain: length
655 PrintRLength(cputype, r_type, r_length, previous_arm_half);
656
657 if (r_extern) {
658 // plain: extern & type & scattered
659 outs() << "True ";
660 PrintRType(cputype, r_type);
661 outs() << "False ";
662
663 // plain: symbolnum/value
664 if (r_symbolnum > Symtab.nsyms)
665 outs() << format("?(%d)\n", r_symbolnum);
666 else {
667 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
668 Expected<StringRef> SymNameNext = Symbol.getName();
669 const char *name = NULL__null;
670 if (SymNameNext)
671 name = SymNameNext->data();
672 if (name == NULL__null)
673 outs() << format("?(%d)\n", r_symbolnum);
674 else
675 outs() << name << "\n";
676 }
677 }
678 else {
679 // plain: extern & type & scattered
680 outs() << "False ";
681 PrintRType(cputype, r_type);
682 outs() << "False ";
683
684 // plain: symbolnum/value
685 if (cputype == MachO::CPU_TYPE_ARM &&
686 r_type == llvm::MachO::ARM_RELOC_PAIR)
687 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
688 else if (cputype == MachO::CPU_TYPE_ARM64 &&
689 r_type == llvm::MachO::ARM64_RELOC_ADDEND)
690 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
691 else {
692 outs() << format("%d ", r_symbolnum);
693 if (r_symbolnum == llvm::MachO::R_ABS)
694 outs() << "R_ABS\n";
695 else {
696 // in this case, r_symbolnum is actually a 1-based section number
697 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
698 if (r_symbolnum > 0 && r_symbolnum <= nsects) {
699 llvm::object::DataRefImpl DRI;
700 DRI.d.a = r_symbolnum-1;
701 StringRef SegName = O->getSectionFinalSegmentName(DRI);
702 StringRef SectName;
703 if (O->getSectionName(DRI, SectName))
704 outs() << "(?,?)\n";
705 else
706 outs() << "(" << SegName << "," << SectName << ")\n";
707 }
708 else {
709 outs() << "(?,?)\n";
710 }
711 }
712 }
713 }
714 if (cputype == MachO::CPU_TYPE_ARM &&
715 (r_type == llvm::MachO::ARM_RELOC_HALF ||
716 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
717 previous_arm_half = true;
718 else
719 previous_arm_half = false;
720 }
721 else {
722 // plain: address pcrel length extern type scattered symbolnum/section
723 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n",
724 (unsigned int)r_address, r_pcrel, r_length, r_extern,
725 r_type, r_symbolnum);
726 }
727 }
728 }
729}
730
731static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
732 const uint64_t cputype = O->getHeader().cputype;
733 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
734 if (Dysymtab.nextrel != 0) {
735 outs() << "External relocation information " << Dysymtab.nextrel
736 << " entries";
737 outs() << "\naddress pcrel length extern type scattered "
738 "symbolnum/value\n";
739 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
740 verbose);
741 }
742 if (Dysymtab.nlocrel != 0) {
743 outs() << format("Local relocation information %u entries",
744 Dysymtab.nlocrel);
745 outs() << "\naddress pcrel length extern type scattered "
746 "symbolnum/value\n";
747 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
748 verbose);
749 }
750 for (const auto &Load : O->load_commands()) {
751 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
752 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
753 for (unsigned J = 0; J < Seg.nsects; ++J) {
754 const MachO::section_64 Sec = O->getSection64(Load, J);
755 if (Sec.nreloc != 0) {
756 DataRefImpl DRI;
757 DRI.d.a = J;
758 const StringRef SegName = O->getSectionFinalSegmentName(DRI);
759 StringRef SectName;
760 if (O->getSectionName(DRI, SectName))
761 outs() << "Relocation information (" << SegName << ",?) "
762 << format("%u entries", Sec.nreloc);
763 else
764 outs() << "Relocation information (" << SegName << ","
765 << SectName << format(") %u entries", Sec.nreloc);
766 outs() << "\naddress pcrel length extern type scattered "
767 "symbolnum/value\n";
768 PrintRelocationEntries(O, O->section_rel_begin(DRI),
769 O->section_rel_end(DRI), cputype, verbose);
770 }
771 }
772 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
773 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
774 for (unsigned J = 0; J < Seg.nsects; ++J) {
775 const MachO::section Sec = O->getSection(Load, J);
776 if (Sec.nreloc != 0) {
777 DataRefImpl DRI;
778 DRI.d.a = J;
779 const StringRef SegName = O->getSectionFinalSegmentName(DRI);
780 StringRef SectName;
781 if (O->getSectionName(DRI, SectName))
782 outs() << "Relocation information (" << SegName << ",?) "
783 << format("%u entries", Sec.nreloc);
784 else
785 outs() << "Relocation information (" << SegName << ","
786 << SectName << format(") %u entries", Sec.nreloc);
787 outs() << "\naddress pcrel length extern type scattered "
788 "symbolnum/value\n";
789 PrintRelocationEntries(O, O->section_rel_begin(DRI),
790 O->section_rel_end(DRI), cputype, verbose);
791 }
792 }
793 }
794 }
795}
796
797static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
798 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
799 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
800 outs() << "Data in code table (" << nentries << " entries)\n";
801 outs() << "offset length kind\n";
802 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
803 ++DI) {
804 uint32_t Offset;
805 DI->getOffset(Offset);
806 outs() << format("0x%08" PRIx32"x", Offset) << " ";
807 uint16_t Length;
808 DI->getLength(Length);
809 outs() << format("%6u", Length) << " ";
810 uint16_t Kind;
811 DI->getKind(Kind);
812 if (verbose) {
813 switch (Kind) {
814 case MachO::DICE_KIND_DATA:
815 outs() << "DATA";
816 break;
817 case MachO::DICE_KIND_JUMP_TABLE8:
818 outs() << "JUMP_TABLE8";
819 break;
820 case MachO::DICE_KIND_JUMP_TABLE16:
821 outs() << "JUMP_TABLE16";
822 break;
823 case MachO::DICE_KIND_JUMP_TABLE32:
824 outs() << "JUMP_TABLE32";
825 break;
826 case MachO::DICE_KIND_ABS_JUMP_TABLE32:
827 outs() << "ABS_JUMP_TABLE32";
828 break;
829 default:
830 outs() << format("0x%04" PRIx32"x", Kind);
831 break;
832 }
833 } else
834 outs() << format("0x%04" PRIx32"x", Kind);
835 outs() << "\n";
836 }
837}
838
839static void PrintLinkOptHints(MachOObjectFile *O) {
840 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
841 const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
842 uint32_t nloh = LohLC.datasize;
843 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
844 for (uint32_t i = 0; i < nloh;) {
845 unsigned n;
846 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
847 i += n;
848 outs() << " identifier " << identifier << " ";
849 if (i >= nloh)
850 return;
851 switch (identifier) {
852 case 1:
853 outs() << "AdrpAdrp\n";
854 break;
855 case 2:
856 outs() << "AdrpLdr\n";
857 break;
858 case 3:
859 outs() << "AdrpAddLdr\n";
860 break;
861 case 4:
862 outs() << "AdrpLdrGotLdr\n";
863 break;
864 case 5:
865 outs() << "AdrpAddStr\n";
866 break;
867 case 6:
868 outs() << "AdrpLdrGotStr\n";
869 break;
870 case 7:
871 outs() << "AdrpAdd\n";
872 break;
873 case 8:
874 outs() << "AdrpLdrGot\n";
875 break;
876 default:
877 outs() << "Unknown identifier value\n";
878 break;
879 }
880 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
881 i += n;
882 outs() << " narguments " << narguments << "\n";
883 if (i >= nloh)
884 return;
885
886 for (uint32_t j = 0; j < narguments; j++) {
887 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
888 i += n;
889 outs() << "\tvalue " << format("0x%" PRIx64"l" "x", value) << "\n";
890 if (i >= nloh)
891 return;
892 }
893 }
894}
895
896static void PrintDylibs(MachOObjectFile *O, bool JustId) {
897 unsigned Index = 0;
898 for (const auto &Load : O->load_commands()) {
899 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
900 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
901 Load.C.cmd == MachO::LC_LOAD_DYLIB ||
902 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
903 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
904 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
905 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
906 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
907 if (dl.dylib.name < dl.cmdsize) {
908 const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
909 if (JustId)
910 outs() << p << "\n";
911 else {
912 outs() << "\t" << p;
913 outs() << " (compatibility version "
914 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
915 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
916 << (dl.dylib.compatibility_version & 0xff) << ",";
917 outs() << " current version "
918 << ((dl.dylib.current_version >> 16) & 0xffff) << "."
919 << ((dl.dylib.current_version >> 8) & 0xff) << "."
920 << (dl.dylib.current_version & 0xff) << ")\n";
921 }
922 } else {
923 outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
924 if (Load.C.cmd == MachO::LC_ID_DYLIB)
925 outs() << "LC_ID_DYLIB ";
926 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
927 outs() << "LC_LOAD_DYLIB ";
928 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
929 outs() << "LC_LOAD_WEAK_DYLIB ";
930 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
931 outs() << "LC_LAZY_LOAD_DYLIB ";
932 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
933 outs() << "LC_REEXPORT_DYLIB ";
934 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
935 outs() << "LC_LOAD_UPWARD_DYLIB ";
936 else
937 outs() << "LC_??? ";
938 outs() << "command " << Index++ << "\n";
939 }
940 }
941 }
942}
943
944typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
945
946static void CreateSymbolAddressMap(MachOObjectFile *O,
947 SymbolAddressMap *AddrMap) {
948 // Create a map of symbol addresses to symbol names.
949 for (const SymbolRef &Symbol : O->symbols()) {
950 Expected<SymbolRef::Type> STOrErr = Symbol.getType();
951 if (!STOrErr)
952 report_error(O->getFileName(), STOrErr.takeError());
953 SymbolRef::Type ST = *STOrErr;
954 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
955 ST == SymbolRef::ST_Other) {
956 uint64_t Address = Symbol.getValue();
957 Expected<StringRef> SymNameOrErr = Symbol.getName();
958 if (!SymNameOrErr)
959 report_error(O->getFileName(), SymNameOrErr.takeError());
960 StringRef SymName = *SymNameOrErr;
961 if (!SymName.startswith(".objc"))
962 (*AddrMap)[Address] = SymName;
963 }
964 }
965}
966
967// GuessSymbolName is passed the address of what might be a symbol and a
968// pointer to the SymbolAddressMap. It returns the name of a symbol
969// with that address or nullptr if no symbol is found with that address.
970static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
971 const char *SymbolName = nullptr;
972 // A DenseMap can't lookup up some values.
973 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
974 StringRef name = AddrMap->lookup(value);
975 if (!name.empty())
976 SymbolName = name.data();
977 }
978 return SymbolName;
979}
980
981static void DumpCstringChar(const char c) {
982 char p[2];
983 p[0] = c;
984 p[1] = '\0';
985 outs().write_escaped(p);
986}
987
988static void DumpCstringSection(MachOObjectFile *O, const char *sect,
989 uint32_t sect_size, uint64_t sect_addr,
990 bool print_addresses) {
991 for (uint32_t i = 0; i < sect_size; i++) {
992 if (print_addresses) {
993 if (O->is64Bit())
994 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
995 else
996 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
997 }
998 for (; i < sect_size && sect[i] != '\0'; i++)
999 DumpCstringChar(sect[i]);
1000 if (i < sect_size && sect[i] == '\0')
1001 outs() << "\n";
1002 }
1003}
1004
1005static void DumpLiteral4(uint32_t l, float f) {
1006 outs() << format("0x%08" PRIx32"x", l);
1007 if ((l & 0x7f800000) != 0x7f800000)
1008 outs() << format(" (%.16e)\n", f);
1009 else {
1010 if (l == 0x7f800000)
1011 outs() << " (+Infinity)\n";
1012 else if (l == 0xff800000)
1013 outs() << " (-Infinity)\n";
1014 else if ((l & 0x00400000) == 0x00400000)
1015 outs() << " (non-signaling Not-a-Number)\n";
1016 else
1017 outs() << " (signaling Not-a-Number)\n";
1018 }
1019}
1020
1021static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
1022 uint32_t sect_size, uint64_t sect_addr,
1023 bool print_addresses) {
1024 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
1025 if (print_addresses) {
1026 if (O->is64Bit())
1027 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
1028 else
1029 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
1030 }
1031 float f;
1032 memcpy(&f, sect + i, sizeof(float));
1033 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1034 sys::swapByteOrder(f);
1035 uint32_t l;
1036 memcpy(&l, sect + i, sizeof(uint32_t));
1037 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1038 sys::swapByteOrder(l);
1039 DumpLiteral4(l, f);
1040 }
1041}
1042
1043static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
1044 double d) {
1045 outs() << format("0x%08" PRIx32"x", l0) << " " << format("0x%08" PRIx32"x", l1);
1046 uint32_t Hi, Lo;
1047 Hi = (O->isLittleEndian()) ? l1 : l0;
1048 Lo = (O->isLittleEndian()) ? l0 : l1;
1049
1050 // Hi is the high word, so this is equivalent to if(isfinite(d))
1051 if ((Hi & 0x7ff00000) != 0x7ff00000)
1052 outs() << format(" (%.16e)\n", d);
1053 else {
1054 if (Hi == 0x7ff00000 && Lo == 0)
1055 outs() << " (+Infinity)\n";
1056 else if (Hi == 0xfff00000 && Lo == 0)
1057 outs() << " (-Infinity)\n";
1058 else if ((Hi & 0x00080000) == 0x00080000)
1059 outs() << " (non-signaling Not-a-Number)\n";
1060 else
1061 outs() << " (signaling Not-a-Number)\n";
1062 }
1063}
1064
1065static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
1066 uint32_t sect_size, uint64_t sect_addr,
1067 bool print_addresses) {
1068 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
1069 if (print_addresses) {
1070 if (O->is64Bit())
1071 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
1072 else
1073 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
1074 }
1075 double d;
1076 memcpy(&d, sect + i, sizeof(double));
1077 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1078 sys::swapByteOrder(d);
1079 uint32_t l0, l1;
1080 memcpy(&l0, sect + i, sizeof(uint32_t));
1081 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1082 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1083 sys::swapByteOrder(l0);
1084 sys::swapByteOrder(l1);
1085 }
1086 DumpLiteral8(O, l0, l1, d);
1087 }
1088}
1089
1090static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
1091 outs() << format("0x%08" PRIx32"x", l0) << " ";
1092 outs() << format("0x%08" PRIx32"x", l1) << " ";
1093 outs() << format("0x%08" PRIx32"x", l2) << " ";
1094 outs() << format("0x%08" PRIx32"x", l3) << "\n";
1095}
1096
1097static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
1098 uint32_t sect_size, uint64_t sect_addr,
1099 bool print_addresses) {
1100 for (uint32_t i = 0; i < sect_size; i += 16) {
1101 if (print_addresses) {
1102 if (O->is64Bit())
1103 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
1104 else
1105 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
1106 }
1107 uint32_t l0, l1, l2, l3;
1108 memcpy(&l0, sect + i, sizeof(uint32_t));
1109 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1110 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
1111 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
1112 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1113 sys::swapByteOrder(l0);
1114 sys::swapByteOrder(l1);
1115 sys::swapByteOrder(l2);
1116 sys::swapByteOrder(l3);
1117 }
1118 DumpLiteral16(l0, l1, l2, l3);
1119 }
1120}
1121
1122static void DumpLiteralPointerSection(MachOObjectFile *O,
1123 const SectionRef &Section,
1124 const char *sect, uint32_t sect_size,
1125 uint64_t sect_addr,
1126 bool print_addresses) {
1127 // Collect the literal sections in this Mach-O file.
1128 std::vector<SectionRef> LiteralSections;
1129 for (const SectionRef &Section : O->sections()) {
1130 DataRefImpl Ref = Section.getRawDataRefImpl();
1131 uint32_t section_type;
1132 if (O->is64Bit()) {
1133 const MachO::section_64 Sec = O->getSection64(Ref);
1134 section_type = Sec.flags & MachO::SECTION_TYPE;
1135 } else {
1136 const MachO::section Sec = O->getSection(Ref);
1137 section_type = Sec.flags & MachO::SECTION_TYPE;
1138 }
1139 if (section_type == MachO::S_CSTRING_LITERALS ||
1140 section_type == MachO::S_4BYTE_LITERALS ||
1141 section_type == MachO::S_8BYTE_LITERALS ||
1142 section_type == MachO::S_16BYTE_LITERALS)
1143 LiteralSections.push_back(Section);
1144 }
1145
1146 // Set the size of the literal pointer.
1147 uint32_t lp_size = O->is64Bit() ? 8 : 4;
1148
1149 // Collect the external relocation symbols for the literal pointers.
1150 std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1151 for (const RelocationRef &Reloc : Section.relocations()) {
1152 DataRefImpl Rel;
1153 MachO::any_relocation_info RE;
1154 bool isExtern = false;
1155 Rel = Reloc.getRawDataRefImpl();
1156 RE = O->getRelocation(Rel);
1157 isExtern = O->getPlainRelocationExternal(RE);
1158 if (isExtern) {
1159 uint64_t RelocOffset = Reloc.getOffset();
1160 symbol_iterator RelocSym = Reloc.getSymbol();
1161 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1162 }
1163 }
1164 array_pod_sort(Relocs.begin(), Relocs.end());
1165
1166 // Dump each literal pointer.
1167 for (uint32_t i = 0; i < sect_size; i += lp_size) {
1168 if (print_addresses) {
1169 if (O->is64Bit())
1170 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
1171 else
1172 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
1173 }
1174 uint64_t lp;
1175 if (O->is64Bit()) {
1176 memcpy(&lp, sect + i, sizeof(uint64_t));
1177 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1178 sys::swapByteOrder(lp);
1179 } else {
1180 uint32_t li;
1181 memcpy(&li, sect + i, sizeof(uint32_t));
1182 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1183 sys::swapByteOrder(li);
1184 lp = li;
1185 }
1186
1187 // First look for an external relocation entry for this literal pointer.
1188 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1189 return P.first == i;
1190 });
1191 if (Reloc != Relocs.end()) {
1192 symbol_iterator RelocSym = Reloc->second;
1193 Expected<StringRef> SymName = RelocSym->getName();
1194 if (!SymName)
1195 report_error(O->getFileName(), SymName.takeError());
1196 outs() << "external relocation entry for symbol:" << *SymName << "\n";
1197 continue;
1198 }
1199
1200 // For local references see what the section the literal pointer points to.
1201 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
1202 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
1203 });
1204 if (Sect == LiteralSections.end()) {
1205 outs() << format("0x%" PRIx64"l" "x", lp) << " (not in a literal section)\n";
1206 continue;
1207 }
1208
1209 uint64_t SectAddress = Sect->getAddress();
1210 uint64_t SectSize = Sect->getSize();
1211
1212 StringRef SectName;
1213 Sect->getName(SectName);
1214 DataRefImpl Ref = Sect->getRawDataRefImpl();
1215 StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
1216 outs() << SegmentName << ":" << SectName << ":";
1217
1218 uint32_t section_type;
1219 if (O->is64Bit()) {
1220 const MachO::section_64 Sec = O->getSection64(Ref);
1221 section_type = Sec.flags & MachO::SECTION_TYPE;
1222 } else {
1223 const MachO::section Sec = O->getSection(Ref);
1224 section_type = Sec.flags & MachO::SECTION_TYPE;
1225 }
1226
1227 StringRef BytesStr;
1228 Sect->getContents(BytesStr);
1229 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
1230
1231 switch (section_type) {
1232 case MachO::S_CSTRING_LITERALS:
1233 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
1234 i++) {
1235 DumpCstringChar(Contents[i]);
1236 }
1237 outs() << "\n";
1238 break;
1239 case MachO::S_4BYTE_LITERALS:
1240 float f;
1241 memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
1242 uint32_t l;
1243 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
1244 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1245 sys::swapByteOrder(f);
1246 sys::swapByteOrder(l);
1247 }
1248 DumpLiteral4(l, f);
1249 break;
1250 case MachO::S_8BYTE_LITERALS: {
1251 double d;
1252 memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
1253 uint32_t l0, l1;
1254 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1255 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1256 sizeof(uint32_t));
1257 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1258 sys::swapByteOrder(f);
1259 sys::swapByteOrder(l0);
1260 sys::swapByteOrder(l1);
1261 }
1262 DumpLiteral8(O, l0, l1, d);
1263 break;
1264 }
1265 case MachO::S_16BYTE_LITERALS: {
1266 uint32_t l0, l1, l2, l3;
1267 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1268 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1269 sizeof(uint32_t));
1270 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
1271 sizeof(uint32_t));
1272 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
1273 sizeof(uint32_t));
1274 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1275 sys::swapByteOrder(l0);
1276 sys::swapByteOrder(l1);
1277 sys::swapByteOrder(l2);
1278 sys::swapByteOrder(l3);
1279 }
1280 DumpLiteral16(l0, l1, l2, l3);
1281 break;
1282 }
1283 }
1284 }
1285}
1286
1287static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
1288 uint32_t sect_size, uint64_t sect_addr,
1289 SymbolAddressMap *AddrMap,
1290 bool verbose) {
1291 uint32_t stride;
1292 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
1293 for (uint32_t i = 0; i < sect_size; i += stride) {
1294 const char *SymbolName = nullptr;
1295 if (O->is64Bit()) {
1296 outs() << format("0x%016" PRIx64"l" "x", sect_addr + i * stride) << " ";
1297 uint64_t pointer_value;
1298 memcpy(&pointer_value, sect + i, stride);
1299 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1300 sys::swapByteOrder(pointer_value);
1301 outs() << format("0x%016" PRIx64"l" "x", pointer_value);
1302 if (verbose)
1303 SymbolName = GuessSymbolName(pointer_value, AddrMap);
1304 } else {
1305 outs() << format("0x%08" PRIx64"l" "x", sect_addr + i * stride) << " ";
1306 uint32_t pointer_value;
1307 memcpy(&pointer_value, sect + i, stride);
1308 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1309 sys::swapByteOrder(pointer_value);
1310 outs() << format("0x%08" PRIx32"x", pointer_value);
1311 if (verbose)
1312 SymbolName = GuessSymbolName(pointer_value, AddrMap);
1313 }
1314 if (SymbolName)
1315 outs() << " " << SymbolName;
1316 outs() << "\n";
1317 }
1318}
1319
1320static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1321 uint32_t size, uint64_t addr) {
1322 uint32_t cputype = O->getHeader().cputype;
1323 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1324 uint32_t j;
1325 for (uint32_t i = 0; i < size; i += j, addr += j) {
1326 if (O->is64Bit())
1327 outs() << format("%016" PRIx64"l" "x", addr) << "\t";
1328 else
1329 outs() << format("%08" PRIx64"l" "x", addr) << "\t";
1330 for (j = 0; j < 16 && i + j < size; j++) {
1331 uint8_t byte_word = *(sect + i + j);
1332 outs() << format("%02" PRIx32"x", (uint32_t)byte_word) << " ";
1333 }
1334 outs() << "\n";
1335 }
1336 } else {
1337 uint32_t j;
1338 for (uint32_t i = 0; i < size; i += j, addr += j) {
1339 if (O->is64Bit())
1340 outs() << format("%016" PRIx64"l" "x", addr) << "\t";
1341 else
1342 outs() << format("%08" PRIx64"l" "x", addr) << "\t";
1343 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1344 j += sizeof(int32_t)) {
1345 if (i + j + sizeof(int32_t) <= size) {
1346 uint32_t long_word;
1347 memcpy(&long_word, sect + i + j, sizeof(int32_t));
1348 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1349 sys::swapByteOrder(long_word);
1350 outs() << format("%08" PRIx32"x", long_word) << " ";
1351 } else {
1352 for (uint32_t k = 0; i + j + k < size; k++) {
1353 uint8_t byte_word = *(sect + i + j + k);
1354 outs() << format("%02" PRIx32"x", (uint32_t)byte_word) << " ";
1355 }
1356 }
1357 }
1358 outs() << "\n";
1359 }
1360 }
1361}
1362
1363static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1364 StringRef DisSegName, StringRef DisSectName);
1365static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1366 uint32_t size, uint32_t addr);
1367#ifdef HAVE_LIBXAR
1368static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
1369 uint32_t size, bool verbose,
1370 bool PrintXarHeader, bool PrintXarFileHeaders,
1371 std::string XarMemberName);
1372#endif // defined(HAVE_LIBXAR)
1373
1374static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1375 bool verbose) {
1376 SymbolAddressMap AddrMap;
1377 if (verbose)
1378 CreateSymbolAddressMap(O, &AddrMap);
1379
1380 for (unsigned i = 0; i < FilterSections.size(); ++i) {
1381 StringRef DumpSection = FilterSections[i];
1382 std::pair<StringRef, StringRef> DumpSegSectName;
1383 DumpSegSectName = DumpSection.split(',');
1384 StringRef DumpSegName, DumpSectName;
1385 if (DumpSegSectName.second.size()) {
1386 DumpSegName = DumpSegSectName.first;
1387 DumpSectName = DumpSegSectName.second;
1388 } else {
1389 DumpSegName = "";
1390 DumpSectName = DumpSegSectName.first;
1391 }
1392 for (const SectionRef &Section : O->sections()) {
1393 StringRef SectName;
1394 Section.getName(SectName);
1395 DataRefImpl Ref = Section.getRawDataRefImpl();
1396 StringRef SegName = O->getSectionFinalSegmentName(Ref);
1397 if ((DumpSegName.empty() || SegName == DumpSegName) &&
1398 (SectName == DumpSectName)) {
1399
1400 uint32_t section_flags;
1401 if (O->is64Bit()) {
1402 const MachO::section_64 Sec = O->getSection64(Ref);
1403 section_flags = Sec.flags;
1404
1405 } else {
1406 const MachO::section Sec = O->getSection(Ref);
1407 section_flags = Sec.flags;
1408 }
1409 uint32_t section_type = section_flags & MachO::SECTION_TYPE;
1410
1411 StringRef BytesStr;
1412 Section.getContents(BytesStr);
1413 const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1414 uint32_t sect_size = BytesStr.size();
1415 uint64_t sect_addr = Section.getAddress();
1416
1417 outs() << "Contents of (" << SegName << "," << SectName
1418 << ") section\n";
1419
1420 if (verbose) {
1421 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
1422 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
1423 DisassembleMachO(Filename, O, SegName, SectName);
1424 continue;
1425 }
1426 if (SegName == "__TEXT" && SectName == "__info_plist") {
1427 outs() << sect;
1428 continue;
1429 }
1430 if (SegName == "__OBJC" && SectName == "__protocol") {
1431 DumpProtocolSection(O, sect, sect_size, sect_addr);
1432 continue;
1433 }
1434#ifdef HAVE_LIBXAR
1435 if (SegName == "__LLVM" && SectName == "__bundle") {
1436 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
1437 ArchiveHeaders, "");
1438 continue;
1439 }
1440#endif // defined(HAVE_LIBXAR)
1441 switch (section_type) {
1442 case MachO::S_REGULAR:
1443 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1444 break;
1445 case MachO::S_ZEROFILL:
1446 outs() << "zerofill section and has no contents in the file\n";
1447 break;
1448 case MachO::S_CSTRING_LITERALS:
1449 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1450 break;
1451 case MachO::S_4BYTE_LITERALS:
1452 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1453 break;
1454 case MachO::S_8BYTE_LITERALS:
1455 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1456 break;
1457 case MachO::S_16BYTE_LITERALS:
1458 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1459 break;
1460 case MachO::S_LITERAL_POINTERS:
1461 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
1462 !NoLeadingAddr);
1463 break;
1464 case MachO::S_MOD_INIT_FUNC_POINTERS:
1465 case MachO::S_MOD_TERM_FUNC_POINTERS:
1466 DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,
1467 verbose);
1468 break;
1469 default:
1470 outs() << "Unknown section type ("
1471 << format("0x%08" PRIx32"x", section_type) << ")\n";
1472 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1473 break;
1474 }
1475 } else {
1476 if (section_type == MachO::S_ZEROFILL)
1477 outs() << "zerofill section and has no contents in the file\n";
1478 else
1479 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1480 }
1481 }
1482 }
1483 }
1484}
1485
1486static void DumpInfoPlistSectionContents(StringRef Filename,
1487 MachOObjectFile *O) {
1488 for (const SectionRef &Section : O->sections()) {
1489 StringRef SectName;
1490 Section.getName(SectName);
1491 DataRefImpl Ref = Section.getRawDataRefImpl();
1492 StringRef SegName = O->getSectionFinalSegmentName(Ref);
1493 if (SegName == "__TEXT" && SectName == "__info_plist") {
1494 if (!NoLeadingHeaders)
1495 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
1496 StringRef BytesStr;
1497 Section.getContents(BytesStr);
1498 const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1499 outs() << format("%.*s", BytesStr.size(), sect) << "\n";
1500 return;
1501 }
1502 }
1503}
1504
1505// checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
1506// and if it is and there is a list of architecture flags is specified then
1507// check to make sure this Mach-O file is one of those architectures or all
1508// architectures were specified. If not then an error is generated and this
1509// routine returns false. Else it returns true.
1510static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
1511 auto *MachO = dyn_cast<MachOObjectFile>(O);
1512
1513 if (!MachO || ArchAll || ArchFlags.empty())
1514 return true;
1515
1516 MachO::mach_header H;
1517 MachO::mach_header_64 H_64;
1518 Triple T;
1519 const char *McpuDefault, *ArchFlag;
1520 if (MachO->is64Bit()) {
1521 H_64 = MachO->MachOObjectFile::getHeader64();
1522 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
1523 &McpuDefault, &ArchFlag);
1524 } else {
1525 H = MachO->MachOObjectFile::getHeader();
1526 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
1527 &McpuDefault, &ArchFlag);
1528 }
1529 const std::string ArchFlagName(ArchFlag);
1530 if (none_of(ArchFlags, [&](const std::string &Name) {
1531 return Name == ArchFlagName;
1532 })) {
1533 errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n";
1534 return false;
1535 }
1536 return true;
1537}
1538
1539static void printObjcMetaData(MachOObjectFile *O, bool verbose);
1540
1541// ProcessMachO() is passed a single opened Mach-O file, which may be an
1542// archive member and or in a slice of a universal file. It prints the
1543// the file name and header info and then processes it according to the
1544// command line options.
1545static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
1546 StringRef ArchiveMemberName = StringRef(),
1547 StringRef ArchitectureName = StringRef()) {
1548 // If we are doing some processing here on the Mach-O file print the header
1549 // info. And don't print it otherwise like in the case of printing the
1550 // UniversalHeaders or ArchiveHeaders.
1551 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
14
Assuming the condition is false
15
Assuming the condition is false
16
Assuming the condition is false
17
Assuming the condition is false
18
Assuming the condition is false
30
Taking false branch
1552 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
19
Assuming the condition is false
20
Assuming the condition is false
21
Assuming the condition is false
22
Assuming the condition is false
23
Assuming the condition is false
1553 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData ||
24
Assuming the condition is false
25
Assuming the condition is false
26
Assuming the condition is false
27
Assuming the condition is false
28
Assuming the condition is false
1554 (FilterSections.size() != 0)) {
29
Assuming the condition is false
1555 if (!NoLeadingHeaders) {
1556 outs() << Name;
1557 if (!ArchiveMemberName.empty())
1558 outs() << '(' << ArchiveMemberName << ')';
1559 if (!ArchitectureName.empty())
1560 outs() << " (architecture " << ArchitectureName << ")";
1561 outs() << ":\n";
1562 }
1563 }
1564 // To use the report_error() form with an ArchiveName and FileName set
1565 // these up based on what is passed for Name and ArchiveMemberName.
1566 StringRef ArchiveName;
1567 StringRef FileName;
1568 if (!ArchiveMemberName.empty()) {
31
Assuming the condition is false
32
Taking false branch
1569 ArchiveName = Name;
1570 FileName = ArchiveMemberName;
1571 } else {
1572 ArchiveName = StringRef();
1573 FileName = Name;
1574 }
1575
1576 // If we need the symbol table to do the operation then check it here to
1577 // produce a good error message as to where the Mach-O file comes from in
1578 // the error message.
1579 if (Disassemble || IndirectSymbols || FilterSections.size() != 0 ||
33
Assuming the condition is false
34
Assuming the condition is false
35
Assuming the condition is false
37
Taking false branch
1580 UnwindInfo)
36
Assuming the condition is false
1581 if (Error Err = MachOOF->checkSymbolTable())
1582 report_error(ArchiveName, FileName, std::move(Err), ArchitectureName);
1583
1584 if (Disassemble) {
38
Assuming the condition is false
39
Taking false branch
1585 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE &&
1586 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64)
1587 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text");
1588 else
1589 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
1590 }
1591 if (IndirectSymbols)
40
Assuming the condition is false
41
Taking false branch
1592 PrintIndirectSymbols(MachOOF, !NonVerbose);
1593 if (DataInCode)
42
Assuming the condition is false
43
Taking false branch
1594 PrintDataInCodeTable(MachOOF, !NonVerbose);
1595 if (LinkOptHints)
44
Assuming the condition is false
45
Taking false branch
1596 PrintLinkOptHints(MachOOF);
1597 if (Relocations)
46
Assuming the condition is false
47
Taking false branch
1598 PrintRelocations(MachOOF, !NonVerbose);
1599 if (SectionHeaders)
48
Assuming the condition is false
49
Taking false branch
1600 PrintSectionHeaders(MachOOF);
1601 if (SectionContents)
50
Assuming the condition is false
51
Taking false branch
1602 PrintSectionContents(MachOOF);
1603 if (FilterSections.size() != 0)
52
Assuming the condition is false
53
Taking false branch
1604 DumpSectionContents(FileName, MachOOF, !NonVerbose);
1605 if (InfoPlist)
54
Assuming the condition is false
55
Taking false branch
1606 DumpInfoPlistSectionContents(FileName, MachOOF);
1607 if (DylibsUsed)
56
Assuming the condition is false
57
Taking false branch
1608 PrintDylibs(MachOOF, false);
1609 if (DylibId)
58
Assuming the condition is false
59
Taking false branch
1610 PrintDylibs(MachOOF, true);
1611 if (SymbolTable)
60
Assuming the condition is false
61
Taking false branch
1612 PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName);
1613 if (UnwindInfo)
62
Assuming the condition is false
63
Taking false branch
1614 printMachOUnwindInfo(MachOOF);
1615 if (PrivateHeaders) {
64
Assuming the condition is false
65
Taking false branch
1616 printMachOFileHeader(MachOOF);
1617 printMachOLoadCommands(MachOOF);
1618 }
1619 if (FirstPrivateHeader)
66
Assuming the condition is false
67
Taking false branch
1620 printMachOFileHeader(MachOOF);
1621 if (ObjcMetaData)
68
Assuming the condition is true
69
Taking true branch
1622 printObjcMetaData(MachOOF, !NonVerbose);
70
Assuming the condition is false
71
Calling 'printObjcMetaData'
1623 if (ExportsTrie)
1624 printExportsTrie(MachOOF);
1625 if (Rebase)
1626 printRebaseTable(MachOOF);
1627 if (Bind)
1628 printBindTable(MachOOF);
1629 if (LazyBind)
1630 printLazyBindTable(MachOOF);
1631 if (WeakBind)
1632 printWeakBindTable(MachOOF);
1633
1634 if (DwarfDumpType != DIDT_Null) {
1635 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
1636 // Dump the complete DWARF structure.
1637 DIDumpOptions DumpOpts;
1638 DumpOpts.DumpType = DwarfDumpType;
1639 DICtx->dump(outs(), DumpOpts);
1640 }
1641}
1642
1643// printUnknownCPUType() helps print_fat_headers for unknown CPU's.
1644static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
1645 outs() << " cputype (" << cputype << ")\n";
1646 outs() << " cpusubtype (" << cpusubtype << ")\n";
1647}
1648
1649// printCPUType() helps print_fat_headers by printing the cputype and
1650// pusubtype (symbolically for the one's it knows about).
1651static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
1652 switch (cputype) {
1653 case MachO::CPU_TYPE_I386:
1654 switch (cpusubtype) {
1655 case MachO::CPU_SUBTYPE_I386_ALL:
1656 outs() << " cputype CPU_TYPE_I386\n";
1657 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n";
1658 break;
1659 default:
1660 printUnknownCPUType(cputype, cpusubtype);
1661 break;
1662 }
1663 break;
1664 case MachO::CPU_TYPE_X86_64:
1665 switch (cpusubtype) {
1666 case MachO::CPU_SUBTYPE_X86_64_ALL:
1667 outs() << " cputype CPU_TYPE_X86_64\n";
1668 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
1669 break;
1670 case MachO::CPU_SUBTYPE_X86_64_H:
1671 outs() << " cputype CPU_TYPE_X86_64\n";
1672 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n";
1673 break;
1674 default:
1675 printUnknownCPUType(cputype, cpusubtype);
1676 break;
1677 }
1678 break;
1679 case MachO::CPU_TYPE_ARM:
1680 switch (cpusubtype) {
1681 case MachO::CPU_SUBTYPE_ARM_ALL:
1682 outs() << " cputype CPU_TYPE_ARM\n";
1683 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n";
1684 break;
1685 case MachO::CPU_SUBTYPE_ARM_V4T:
1686 outs() << " cputype CPU_TYPE_ARM\n";
1687 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n";
1688 break;
1689 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1690 outs() << " cputype CPU_TYPE_ARM\n";
1691 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
1692 break;
1693 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1694 outs() << " cputype CPU_TYPE_ARM\n";
1695 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
1696 break;
1697 case MachO::CPU_SUBTYPE_ARM_V6:
1698 outs() << " cputype CPU_TYPE_ARM\n";
1699 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n";
1700 break;
1701 case MachO::CPU_SUBTYPE_ARM_V6M:
1702 outs() << " cputype CPU_TYPE_ARM\n";
1703 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n";
1704 break;
1705 case MachO::CPU_SUBTYPE_ARM_V7:
1706 outs() << " cputype CPU_TYPE_ARM\n";
1707 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n";
1708 break;
1709 case MachO::CPU_SUBTYPE_ARM_V7EM:
1710 outs() << " cputype CPU_TYPE_ARM\n";
1711 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
1712 break;
1713 case MachO::CPU_SUBTYPE_ARM_V7K:
1714 outs() << " cputype CPU_TYPE_ARM\n";
1715 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n";
1716 break;
1717 case MachO::CPU_SUBTYPE_ARM_V7M:
1718 outs() << " cputype CPU_TYPE_ARM\n";
1719 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n";
1720 break;
1721 case MachO::CPU_SUBTYPE_ARM_V7S:
1722 outs() << " cputype CPU_TYPE_ARM\n";
1723 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n";
1724 break;
1725 default:
1726 printUnknownCPUType(cputype, cpusubtype);
1727 break;
1728 }
1729 break;
1730 case MachO::CPU_TYPE_ARM64:
1731 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
1732 case MachO::CPU_SUBTYPE_ARM64_ALL:
1733 outs() << " cputype CPU_TYPE_ARM64\n";
1734 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
1735 break;
1736 default:
1737 printUnknownCPUType(cputype, cpusubtype);
1738 break;
1739 }
1740 break;
1741 default:
1742 printUnknownCPUType(cputype, cpusubtype);
1743 break;
1744 }
1745}
1746
1747static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
1748 bool verbose) {
1749 outs() << "Fat headers\n";
1750 if (verbose) {
1751 if (UB->getMagic() == MachO::FAT_MAGIC)
1752 outs() << "fat_magic FAT_MAGIC\n";
1753 else // UB->getMagic() == MachO::FAT_MAGIC_64
1754 outs() << "fat_magic FAT_MAGIC_64\n";
1755 } else
1756 outs() << "fat_magic " << format("0x%" PRIx32"x", MachO::FAT_MAGIC) << "\n";
1757
1758 uint32_t nfat_arch = UB->getNumberOfObjects();
1759 StringRef Buf = UB->getData();
1760 uint64_t size = Buf.size();
1761 uint64_t big_size = sizeof(struct MachO::fat_header) +
1762 nfat_arch * sizeof(struct MachO::fat_arch);
1763 outs() << "nfat_arch " << UB->getNumberOfObjects();
1764 if (nfat_arch == 0)
1765 outs() << " (malformed, contains zero architecture types)\n";
1766 else if (big_size > size)
1767 outs() << " (malformed, architectures past end of file)\n";
1768 else
1769 outs() << "\n";
1770
1771 for (uint32_t i = 0; i < nfat_arch; ++i) {
1772 MachOUniversalBinary::ObjectForArch OFA(UB, i);
1773 uint32_t cputype = OFA.getCPUType();
1774 uint32_t cpusubtype = OFA.getCPUSubType();
1775 outs() << "architecture ";
1776 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
1777 MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
1778 uint32_t other_cputype = other_OFA.getCPUType();
1779 uint32_t other_cpusubtype = other_OFA.getCPUSubType();
1780 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
1781 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
1782 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
1783 outs() << "(illegal duplicate architecture) ";
1784 break;
1785 }
1786 }
1787 if (verbose) {
1788 outs() << OFA.getArchFlagName() << "\n";
1789 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
1790 } else {
1791 outs() << i << "\n";
1792 outs() << " cputype " << cputype << "\n";
1793 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
1794 << "\n";
1795 }
1796 if (verbose &&
1797 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
1798 outs() << " capabilities CPU_SUBTYPE_LIB64\n";
1799 else
1800 outs() << " capabilities "
1801 << format("0x%" PRIx32"x",
1802 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
1803 outs() << " offset " << OFA.getOffset();
1804 if (OFA.getOffset() > size)
1805 outs() << " (past end of file)";
1806 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0)
1807 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
1808 outs() << "\n";
1809 outs() << " size " << OFA.getSize();
1810 big_size = OFA.getOffset() + OFA.getSize();
1811 if (big_size > size)
1812 outs() << " (past end of file)";
1813 outs() << "\n";
1814 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
1815 << ")\n";
1816 }
1817}
1818
1819static void printArchiveChild(StringRef Filename, const Archive::Child &C,
1820 bool verbose, bool print_offset,
1821 StringRef ArchitectureName = StringRef()) {
1822 if (print_offset)
1823 outs() << C.getChildOffset() << "\t";
1824 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
1825 if (!ModeOrErr)
1826 report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName);
1827 sys::fs::perms Mode = ModeOrErr.get();
1828 if (verbose) {
1829 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
1830 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
1831 outs() << "-";
1832 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
1833 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
1834 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
1835 outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
1836 outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
1837 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
1838 outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
1839 outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
1840 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
1841 } else {
1842 outs() << format("0%o ", Mode);
1843 }
1844
1845 Expected<unsigned> UIDOrErr = C.getUID();
1846 if (!UIDOrErr)
1847 report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName);
1848 unsigned UID = UIDOrErr.get();
1849 outs() << format("%3d/", UID);
1850 Expected<unsigned> GIDOrErr = C.getGID();
1851 if (!GIDOrErr)
1852 report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName);
1853 unsigned GID = GIDOrErr.get();
1854 outs() << format("%-3d ", GID);
1855 Expected<uint64_t> Size = C.getRawSize();
1856 if (!Size)
1857 report_error(Filename, C, Size.takeError(), ArchitectureName);
1858 outs() << format("%5" PRId64"l" "d", Size.get()) << " ";
1859
1860 StringRef RawLastModified = C.getRawLastModified();
1861 if (verbose) {
1862 unsigned Seconds;
1863 if (RawLastModified.getAsInteger(10, Seconds))
1864 outs() << "(date: \"" << RawLastModified
1865 << "\" contains non-decimal chars) ";
1866 else {
1867 // Since cime(3) returns a 26 character string of the form:
1868 // "Sun Sep 16 01:03:52 1973\n\0"
1869 // just print 24 characters.
1870 time_t t = Seconds;
1871 outs() << format("%.24s ", ctime(&t));
1872 }
1873 } else {
1874 outs() << RawLastModified << " ";
1875 }
1876
1877 if (verbose) {
1878 Expected<StringRef> NameOrErr = C.getName();
1879 if (!NameOrErr) {
1880 consumeError(NameOrErr.takeError());
1881 Expected<StringRef> NameOrErr = C.getRawName();
1882 if (!NameOrErr)
1883 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
1884 StringRef RawName = NameOrErr.get();
1885 outs() << RawName << "\n";
1886 } else {
1887 StringRef Name = NameOrErr.get();
1888 outs() << Name << "\n";
1889 }
1890 } else {
1891 Expected<StringRef> NameOrErr = C.getRawName();
1892 if (!NameOrErr)
1893 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
1894 StringRef RawName = NameOrErr.get();
1895 outs() << RawName << "\n";
1896 }
1897}
1898
1899static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
1900 bool print_offset,
1901 StringRef ArchitectureName = StringRef()) {
1902 Error Err = Error::success();
1903 ;
1904 for (const auto &C : A->children(Err, false))
1905 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName);
1906
1907 if (Err)
1908 report_error(StringRef(), Filename, std::move(Err), ArchitectureName);
1909}
1910
1911// ParseInputMachO() parses the named Mach-O file in Filename and handles the
1912// -arch flags selecting just those slices as specified by them and also parses
1913// archive files. Then for each individual Mach-O file ProcessMachO() is
1914// called to process the file based on the command line options.
1915void llvm::ParseInputMachO(StringRef Filename) {
1916 // Check for -arch all and verifiy the -arch flags are valid.
1917 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
1
Assuming the condition is false
2
Loop condition is false. Execution continues on line 1930
1918 if (ArchFlags[i] == "all") {
1919 ArchAll = true;
1920 } else {
1921 if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
1922 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] +
1923 "'for the -arch option\n";
1924 return;
1925 }
1926 }
1927 }
1928
1929 // Attempt to open the binary.
1930 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
1931 if (!BinaryOrErr) {
3
Taking false branch
1932 if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
1933 report_error(Filename, std::move(E));
1934 else
1935 outs() << Filename << ": is not an object file\n";
1936 return;
1937 }
1938 Binary &Bin = *BinaryOrErr.get().getBinary();
1939
1940 if (Archive *A = dyn_cast<Archive>(&Bin)) {
4
Taking false branch
1941 outs() << "Archive : " << Filename << "\n";
1942 if (ArchiveHeaders)
1943 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets);
1944
1945 Error Err = Error::success();
1946 for (auto &C : A->children(Err)) {
1947 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
1948 if (!ChildOrErr) {
1949 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1950 report_error(Filename, C, std::move(E));
1951 continue;
1952 }
1953 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
1954 if (!checkMachOAndArchFlags(O, Filename))
1955 return;
1956 ProcessMachO(Filename, O, O->getFileName());
1957 }
1958 }
1959 if (Err)
1960 report_error(Filename, std::move(Err));
1961 return;
1962 }
1963 if (UniversalHeaders) {
5
Assuming the condition is false
6
Taking false branch
1964 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
1965 printMachOUniversalHeaders(UB, !NonVerbose);
1966 }
1967 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
7
Taking false branch
1968 // If we have a list of architecture flags specified dump only those.
1969 if (!ArchAll && ArchFlags.size() != 0) {
1970 // Look for a slice in the universal binary that matches each ArchFlag.
1971 bool ArchFound;
1972 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
1973 ArchFound = false;
1974 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
1975 E = UB->end_objects();
1976 I != E; ++I) {
1977 if (ArchFlags[i] == I->getArchFlagName()) {
1978 ArchFound = true;
1979 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
1980 I->getAsObjectFile();
1981 std::string ArchitectureName = "";
1982 if (ArchFlags.size() > 1)
1983 ArchitectureName = I->getArchFlagName();
1984 if (ObjOrErr) {
1985 ObjectFile &O = *ObjOrErr.get();
1986 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
1987 ProcessMachO(Filename, MachOOF, "", ArchitectureName);
1988 } else if (auto E = isNotObjectErrorInvalidFileType(
1989 ObjOrErr.takeError())) {
1990 report_error(Filename, StringRef(), std::move(E),
1991 ArchitectureName);
1992 continue;
1993 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
1994 I->getAsArchive()) {
1995 std::unique_ptr<Archive> &A = *AOrErr;
1996 outs() << "Archive : " << Filename;
1997 if (!ArchitectureName.empty())
1998 outs() << " (architecture " << ArchitectureName << ")";
1999 outs() << "\n";
2000 if (ArchiveHeaders)
2001 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2002 ArchiveMemberOffsets, ArchitectureName);
2003 Error Err = Error::success();
2004 for (auto &C : A->children(Err)) {
2005 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2006 if (!ChildOrErr) {
2007 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2008 report_error(Filename, C, std::move(E), ArchitectureName);
2009 continue;
2010 }
2011 if (MachOObjectFile *O =
2012 dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2013 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
2014 }
2015 if (Err)
2016 report_error(Filename, std::move(Err));
2017 } else {
2018 consumeError(AOrErr.takeError());
2019 error("Mach-O universal file: " + Filename + " for " +
2020 "architecture " + StringRef(I->getArchFlagName()) +
2021 " is not a Mach-O file or an archive file");
2022 }
2023 }
2024 }
2025 if (!ArchFound) {
2026 errs() << "llvm-objdump: file: " + Filename + " does not contain "
2027 << "architecture: " + ArchFlags[i] + "\n";
2028 return;
2029 }
2030 }
2031 return;
2032 }
2033 // No architecture flags were specified so if this contains a slice that
2034 // matches the host architecture dump only that.
2035 if (!ArchAll) {
2036 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2037 E = UB->end_objects();
2038 I != E; ++I) {
2039 if (MachOObjectFile::getHostArch().getArchName() ==
2040 I->getArchFlagName()) {
2041 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2042 std::string ArchiveName;
2043 ArchiveName.clear();
2044 if (ObjOrErr) {
2045 ObjectFile &O = *ObjOrErr.get();
2046 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2047 ProcessMachO(Filename, MachOOF);
2048 } else if (auto E = isNotObjectErrorInvalidFileType(
2049 ObjOrErr.takeError())) {
2050 report_error(Filename, std::move(E));
2051 continue;
2052 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2053 I->getAsArchive()) {
2054 std::unique_ptr<Archive> &A = *AOrErr;
2055 outs() << "Archive : " << Filename << "\n";
2056 if (ArchiveHeaders)
2057 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2058 ArchiveMemberOffsets);
2059 Error Err = Error::success();
2060 for (auto &C : A->children(Err)) {
2061 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2062 if (!ChildOrErr) {
2063 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2064 report_error(Filename, C, std::move(E));
2065 continue;
2066 }
2067 if (MachOObjectFile *O =
2068 dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2069 ProcessMachO(Filename, O, O->getFileName());
2070 }
2071 if (Err)
2072 report_error(Filename, std::move(Err));
2073 } else {
2074 consumeError(AOrErr.takeError());
2075 error("Mach-O universal file: " + Filename + " for architecture " +
2076 StringRef(I->getArchFlagName()) +
2077 " is not a Mach-O file or an archive file");
2078 }
2079 return;
2080 }
2081 }
2082 }
2083 // Either all architectures have been specified or none have been specified
2084 // and this does not contain the host architecture so dump all the slices.
2085 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2086 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2087 E = UB->end_objects();
2088 I != E; ++I) {
2089 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2090 std::string ArchitectureName = "";
2091 if (moreThanOneArch)
2092 ArchitectureName = I->getArchFlagName();
2093 if (ObjOrErr) {
2094 ObjectFile &Obj = *ObjOrErr.get();
2095 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
2096 ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2097 } else if (auto E = isNotObjectErrorInvalidFileType(
2098 ObjOrErr.takeError())) {
2099 report_error(StringRef(), Filename, std::move(E), ArchitectureName);
2100 continue;
2101 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2102 I->getAsArchive()) {
2103 std::unique_ptr<Archive> &A = *AOrErr;
2104 outs() << "Archive : " << Filename;
2105 if (!ArchitectureName.empty())
2106 outs() << " (architecture " << ArchitectureName << ")";
2107 outs() << "\n";
2108 if (ArchiveHeaders)
2109 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2110 ArchiveMemberOffsets, ArchitectureName);
2111 Error Err = Error::success();
2112 for (auto &C : A->children(Err)) {
2113 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2114 if (!ChildOrErr) {
2115 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2116 report_error(Filename, C, std::move(E), ArchitectureName);
2117 continue;
2118 }
2119 if (MachOObjectFile *O =
2120 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2121 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
2122 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
2123 ArchitectureName);
2124 }
2125 }
2126 if (Err)
2127 report_error(Filename, std::move(Err));
2128 } else {
2129 consumeError(AOrErr.takeError());
2130 error("Mach-O universal file: " + Filename + " for architecture " +
2131 StringRef(I->getArchFlagName()) +
2132 " is not a Mach-O file or an archive file");
2133 }
2134 }
2135 return;
2136 }
2137 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
8
Assuming 'O' is non-null
9
Taking true branch
2138 if (!checkMachOAndArchFlags(O, Filename))
10
Taking false branch
2139 return;
2140 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) {
11
Assuming 'MachOOF' is non-null
12
Taking true branch
2141 ProcessMachO(Filename, MachOOF);
13
Calling 'ProcessMachO'
2142 } else
2143 errs() << "llvm-objdump: '" << Filename << "': "
2144 << "Object is not a Mach-O file type.\n";
2145 return;
2146 }
2147 llvm_unreachable("Input object can't be invalid at this point")::llvm::llvm_unreachable_internal("Input object can't be invalid at this point"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-objdump/MachODump.cpp"
, 2147)
;
2148}
2149
2150// The block of info used by the Symbolizer call backs.
2151struct DisassembleInfo {
2152 bool verbose;
2153 MachOObjectFile *O;
2154 SectionRef S;
2155 SymbolAddressMap *AddrMap;
2156 std::vector<SectionRef> *Sections;
2157 const char *class_name;
2158 const char *selector_name;
2159 char *method;
2160 char *demangled_name;
2161 uint64_t adrp_addr;
2162 uint32_t adrp_inst;
2163 std::unique_ptr<SymbolAddressMap> bindtable;
2164 uint32_t depth;
2165};
2166
2167// SymbolizerGetOpInfo() is the operand information call back function.
2168// This is called to get the symbolic information for operand(s) of an
2169// instruction when it is being done. This routine does this from
2170// the relocation information, symbol table, etc. That block of information
2171// is a pointer to the struct DisassembleInfo that was passed when the
2172// disassembler context was created and passed to back to here when
2173// called back by the disassembler for instruction operands that could have
2174// relocation information. The address of the instruction containing operand is
2175// at the Pc parameter. The immediate value the operand has is passed in
2176// op_info->Value and is at Offset past the start of the instruction and has a
2177// byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
2178// LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
2179// names and addends of the symbolic expression to add for the operand. The
2180// value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
2181// information is returned then this function returns 1 else it returns 0.
2182static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
2183 uint64_t Size, int TagType, void *TagBuf) {
2184 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
2185 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
2186 uint64_t value = op_info->Value;
2187
2188 // Make sure all fields returned are zero if we don't set them.
2189 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
2190 op_info->Value = value;
2191
2192 // If the TagType is not the value 1 which it code knows about or if no
2193 // verbose symbolic information is wanted then just return 0, indicating no
2194 // information is being returned.
2195 if (TagType != 1 || !info->verbose)
2196 return 0;
2197
2198 unsigned int Arch = info->O->getArch();
2199 if (Arch == Triple::x86) {
2200 if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
2201 return 0;
2202 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2203 // TODO:
2204 // Search the external relocation entries of a fully linked image
2205 // (if any) for an entry that matches this segment offset.
2206 // uint32_t seg_offset = (Pc + Offset);
2207 return 0;
2208 }
2209 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2210 // for an entry for this section offset.
2211 uint32_t sect_addr = info->S.getAddress();
2212 uint32_t sect_offset = (Pc + Offset) - sect_addr;
2213 bool reloc_found = false;
2214 DataRefImpl Rel;
2215 MachO::any_relocation_info RE;
2216 bool isExtern = false;
2217 SymbolRef Symbol;
2218 bool r_scattered = false;
2219 uint32_t r_value, pair_r_value, r_type;
2220 for (const RelocationRef &Reloc : info->S.relocations()) {
2221 uint64_t RelocOffset = Reloc.getOffset();
2222 if (RelocOffset == sect_offset) {
2223 Rel = Reloc.getRawDataRefImpl();
2224 RE = info->O->getRelocation(Rel);
2225 r_type = info->O->getAnyRelocationType(RE);
2226 r_scattered = info->O->isRelocationScattered(RE);
2227 if (r_scattered) {
2228 r_value = info->O->getScatteredRelocationValue(RE);
2229 if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2230 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
2231 DataRefImpl RelNext = Rel;
2232 info->O->moveRelocationNext(RelNext);
2233 MachO::any_relocation_info RENext;
2234 RENext = info->O->getRelocation(RelNext);
2235 if (info->O->isRelocationScattered(RENext))
2236 pair_r_value = info->O->getScatteredRelocationValue(RENext);
2237 else
2238 return 0;
2239 }
2240 } else {
2241 isExtern = info->O->getPlainRelocationExternal(RE);
2242 if (isExtern) {
2243 symbol_iterator RelocSym = Reloc.getSymbol();
2244 Symbol = *RelocSym;
2245 }
2246 }
2247 reloc_found = true;
2248 break;
2249 }
2250 }
2251 if (reloc_found && isExtern) {
2252 Expected<StringRef> SymName = Symbol.getName();
2253 if (!SymName)
2254 report_error(info->O->getFileName(), SymName.takeError());
2255 const char *name = SymName->data();
2256 op_info->AddSymbol.Present = 1;
2257 op_info->AddSymbol.Name = name;
2258 // For i386 extern relocation entries the value in the instruction is
2259 // the offset from the symbol, and value is already set in op_info->Value.
2260 return 1;
2261 }
2262 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2263 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
2264 const char *add = GuessSymbolName(r_value, info->AddrMap);
2265 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2266 uint32_t offset = value - (r_value - pair_r_value);
2267 op_info->AddSymbol.Present = 1;
2268 if (add != nullptr)
2269 op_info->AddSymbol.Name = add;
2270 else
2271 op_info->AddSymbol.Value = r_value;
2272 op_info->SubtractSymbol.Present = 1;
2273 if (sub != nullptr)
2274 op_info->SubtractSymbol.Name = sub;
2275 else
2276 op_info->SubtractSymbol.Value = pair_r_value;
2277 op_info->Value = offset;
2278 return 1;
2279 }
2280 return 0;
2281 }
2282 if (Arch == Triple::x86_64) {
2283 if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
2284 return 0;
2285 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external
2286 // relocation entries of a linked image (if any) for an entry that matches
2287 // this segment offset.
2288 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2289 uint64_t seg_offset = Pc + Offset;
2290 bool reloc_found = false;
2291 DataRefImpl Rel;
2292 MachO::any_relocation_info RE;
2293 bool isExtern = false;
2294 SymbolRef Symbol;
2295 for (const RelocationRef &Reloc : info->O->external_relocations()) {
2296 uint64_t RelocOffset = Reloc.getOffset();
2297 if (RelocOffset == seg_offset) {
2298 Rel = Reloc.getRawDataRefImpl();
2299 RE = info->O->getRelocation(Rel);
2300 // external relocation entries should always be external.
2301 isExtern = info->O->getPlainRelocationExternal(RE);
2302 if (isExtern) {
2303 symbol_iterator RelocSym = Reloc.getSymbol();
2304 Symbol = *RelocSym;
2305 }
2306 reloc_found = true;
2307 break;
2308 }
2309 }
2310 if (reloc_found && isExtern) {
2311 // The Value passed in will be adjusted by the Pc if the instruction
2312 // adds the Pc. But for x86_64 external relocation entries the Value
2313 // is the offset from the external symbol.
2314 if (info->O->getAnyRelocationPCRel(RE))
2315 op_info->Value -= Pc + Offset + Size;
2316 Expected<StringRef> SymName = Symbol.getName();
2317 if (!SymName)
2318 report_error(info->O->getFileName(), SymName.takeError());
2319 const char *name = SymName->data();
2320 op_info->AddSymbol.Present = 1;
2321 op_info->AddSymbol.Name = name;
2322 return 1;
2323 }
2324 return 0;
2325 }
2326 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2327 // for an entry for this section offset.
2328 uint64_t sect_addr = info->S.getAddress();
2329 uint64_t sect_offset = (Pc + Offset) - sect_addr;
2330 bool reloc_found = false;
2331 DataRefImpl Rel;
2332 MachO::any_relocation_info RE;
2333 bool isExtern = false;
2334 SymbolRef Symbol;
2335 for (const RelocationRef &Reloc : info->S.relocations()) {
2336 uint64_t RelocOffset = Reloc.getOffset();
2337 if (RelocOffset == sect_offset) {
2338 Rel = Reloc.getRawDataRefImpl();
2339 RE = info->O->getRelocation(Rel);
2340 // NOTE: Scattered relocations don't exist on x86_64.
2341 isExtern = info->O->getPlainRelocationExternal(RE);
2342 if (isExtern) {
2343 symbol_iterator RelocSym = Reloc.getSymbol();
2344 Symbol = *RelocSym;
2345 }
2346 reloc_found = true;
2347 break;
2348 }
2349 }
2350 if (reloc_found && isExtern) {
2351 // The Value passed in will be adjusted by the Pc if the instruction
2352 // adds the Pc. But for x86_64 external relocation entries the Value
2353 // is the offset from the external symbol.
2354 if (info->O->getAnyRelocationPCRel(RE))
2355 op_info->Value -= Pc + Offset + Size;
2356 Expected<StringRef> SymName = Symbol.getName();
2357 if (!SymName)
2358 report_error(info->O->getFileName(), SymName.takeError());
2359 const char *name = SymName->data();
2360 unsigned Type = info->O->getAnyRelocationType(RE);
2361 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
2362 DataRefImpl RelNext = Rel;
2363 info->O->moveRelocationNext(RelNext);
2364 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2365 unsigned TypeNext = info->O->getAnyRelocationType(RENext);
2366 bool isExternNext = info->O->getPlainRelocationExternal(RENext);
2367 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
2368 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
2369 op_info->SubtractSymbol.Present = 1;
2370 op_info->SubtractSymbol.Name = name;
2371 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
2372 Symbol = *RelocSymNext;
2373 Expected<StringRef> SymNameNext = Symbol.getName();
2374 if (!SymNameNext)
2375 report_error(info->O->getFileName(), SymNameNext.takeError());
2376 name = SymNameNext->data();
2377 }
2378 }
2379 // TODO: add the VariantKinds to op_info->VariantKind for relocation types
2380 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
2381 op_info->AddSymbol.Present = 1;
2382 op_info->AddSymbol.Name = name;
2383 return 1;
2384 }
2385 return 0;
2386 }
2387 if (Arch == Triple::arm) {
2388 if (Offset != 0 || (Size != 4 && Size != 2))
2389 return 0;
2390 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2391 // TODO:
2392 // Search the external relocation entries of a fully linked image
2393 // (if any) for an entry that matches this segment offset.
2394 // uint32_t seg_offset = (Pc + Offset);
2395 return 0;
2396 }
2397 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2398 // for an entry for this section offset.
2399 uint32_t sect_addr = info->S.getAddress();
2400 uint32_t sect_offset = (Pc + Offset) - sect_addr;
2401 DataRefImpl Rel;
2402 MachO::any_relocation_info RE;
2403 bool isExtern = false;
2404 SymbolRef Symbol;
2405 bool r_scattered = false;
2406 uint32_t r_value, pair_r_value, r_type, r_length, other_half;
2407 auto Reloc =
2408 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
2409 uint64_t RelocOffset = Reloc.getOffset();
2410 return RelocOffset == sect_offset;
2411 });
2412
2413 if (Reloc == info->S.relocations().end())
2414 return 0;
2415
2416 Rel = Reloc->getRawDataRefImpl();
2417 RE = info->O->getRelocation(Rel);
2418 r_length = info->O->getAnyRelocationLength(RE);
2419 r_scattered = info->O->isRelocationScattered(RE);
2420 if (r_scattered) {
2421 r_value = info->O->getScatteredRelocationValue(RE);
2422 r_type = info->O->getScatteredRelocationType(RE);
2423 } else {
2424 r_type = info->O->getAnyRelocationType(RE);
2425 isExtern = info->O->getPlainRelocationExternal(RE);
2426 if (isExtern) {
2427 symbol_iterator RelocSym = Reloc->getSymbol();
2428 Symbol = *RelocSym;
2429 }
2430 }
2431 if (r_type == MachO::ARM_RELOC_HALF ||
2432 r_type == MachO::ARM_RELOC_SECTDIFF ||
2433 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
2434 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2435 DataRefImpl RelNext = Rel;
2436 info->O->moveRelocationNext(RelNext);
2437 MachO::any_relocation_info RENext;
2438 RENext = info->O->getRelocation(RelNext);
2439 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
2440 if (info->O->isRelocationScattered(RENext))
2441 pair_r_value = info->O->getScatteredRelocationValue(RENext);
2442 }
2443
2444 if (isExtern) {
2445 Expected<StringRef> SymName = Symbol.getName();
2446 if (!SymName)
2447 report_error(info->O->getFileName(), SymName.takeError());
2448 const char *name = SymName->data();
2449 op_info->AddSymbol.Present = 1;
2450 op_info->AddSymbol.Name = name;
2451 switch (r_type) {
2452 case MachO::ARM_RELOC_HALF:
2453 if ((r_length & 0x1) == 1) {
2454 op_info->Value = value << 16 | other_half;
2455 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI161;
2456 } else {
2457 op_info->Value = other_half << 16 | value;
2458 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO162;
2459 }
2460 break;
2461 default:
2462 break;
2463 }
2464 return 1;
2465 }
2466 // If we have a branch that is not an external relocation entry then
2467 // return 0 so the code in tryAddingSymbolicOperand() can use the
2468 // SymbolLookUp call back with the branch target address to look up the
2469 // symbol and possibility add an annotation for a symbol stub.
2470 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
2471 r_type == MachO::ARM_THUMB_RELOC_BR22))
2472 return 0;
2473
2474 uint32_t offset = 0;
2475 if (r_type == MachO::ARM_RELOC_HALF ||
2476 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2477 if ((r_length & 0x1) == 1)
2478 value = value << 16 | other_half;
2479 else
2480 value = other_half << 16 | value;
2481 }
2482 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
2483 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
2484 offset = value - r_value;
2485 value = r_value;
2486 }
2487
2488 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2489 if ((r_length & 0x1) == 1)
2490 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI161;
2491 else
2492 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO162;
2493 const char *add = GuessSymbolName(r_value, info->AddrMap);
2494 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2495 int32_t offset = value - (r_value - pair_r_value);
2496 op_info->AddSymbol.Present = 1;
2497 if (add != nullptr)
2498 op_info->AddSymbol.Name = add;
2499 else
2500 op_info->AddSymbol.Value = r_value;
2501 op_info->SubtractSymbol.Present = 1;
2502 if (sub != nullptr)
2503 op_info->SubtractSymbol.Name = sub;
2504 else
2505 op_info->SubtractSymbol.Value = pair_r_value;
2506 op_info->Value = offset;
2507 return 1;
2508 }
2509
2510 op_info->AddSymbol.Present = 1;
2511 op_info->Value = offset;
2512 if (r_type == MachO::ARM_RELOC_HALF) {
2513 if ((r_length & 0x1) == 1)
2514 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI161;
2515 else
2516 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO162;
2517 }
2518 const char *add = GuessSymbolName(value, info->AddrMap);
2519 if (add != nullptr) {
2520 op_info->AddSymbol.Name = add;
2521 return 1;
2522 }
2523 op_info->AddSymbol.Value = value;
2524 return 1;
2525 }
2526 if (Arch == Triple::aarch64) {
2527 if (Offset != 0 || Size != 4)
2528 return 0;
2529 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2530 // TODO:
2531 // Search the external relocation entries of a fully linked image
2532 // (if any) for an entry that matches this segment offset.
2533 // uint64_t seg_offset = (Pc + Offset);
2534 return 0;
2535 }
2536 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2537 // for an entry for this section offset.
2538 uint64_t sect_addr = info->S.getAddress();
2539 uint64_t sect_offset = (Pc + Offset) - sect_addr;
2540 auto Reloc =
2541 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
2542 uint64_t RelocOffset = Reloc.getOffset();
2543 return RelocOffset == sect_offset;
2544 });
2545
2546 if (Reloc == info->S.relocations().end())
2547 return 0;
2548
2549 DataRefImpl Rel = Reloc->getRawDataRefImpl();
2550 MachO::any_relocation_info RE = info->O->getRelocation(Rel);
2551 uint32_t r_type = info->O->getAnyRelocationType(RE);
2552 if (r_type == MachO::ARM64_RELOC_ADDEND) {
2553 DataRefImpl RelNext = Rel;
2554 info->O->moveRelocationNext(RelNext);
2555 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2556 if (value == 0) {
2557 value = info->O->getPlainRelocationSymbolNum(RENext);
2558 op_info->Value = value;
2559 }
2560 }
2561 // NOTE: Scattered relocations don't exist on arm64.
2562 if (!info->O->getPlainRelocationExternal(RE))
2563 return 0;
2564 Expected<StringRef> SymName = Reloc->getSymbol()->getName();
2565 if (!SymName)
2566 report_error(info->O->getFileName(), SymName.takeError());
2567 const char *name = SymName->data();
2568 op_info->AddSymbol.Present = 1;
2569 op_info->AddSymbol.Name = name;
2570
2571 switch (r_type) {
2572 case MachO::ARM64_RELOC_PAGE21:
2573 /* @page */
2574 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE1;
2575 break;
2576 case MachO::ARM64_RELOC_PAGEOFF12:
2577 /* @pageoff */
2578 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF2;
2579 break;
2580 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
2581 /* @gotpage */
2582 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE3;
2583 break;
2584 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
2585 /* @gotpageoff */
2586 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF4;
2587 break;
2588 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
2589 /* @tvlppage is not implemented in llvm-mc */
2590 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP5;
2591 break;
2592 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
2593 /* @tvlppageoff is not implemented in llvm-mc */
2594 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF6;
2595 break;
2596 default:
2597 case MachO::ARM64_RELOC_BRANCH26:
2598 op_info->VariantKind = LLVMDisassembler_VariantKind_None0;
2599 break;
2600 }
2601 return 1;
2602 }
2603 return 0;
2604}
2605
2606// GuessCstringPointer is passed the address of what might be a pointer to a
2607// literal string in a cstring section. If that address is in a cstring section
2608// it returns a pointer to that string. Else it returns nullptr.
2609static const char *GuessCstringPointer(uint64_t ReferenceValue,
2610 struct DisassembleInfo *info) {
2611 for (const auto &Load : info->O->load_commands()) {
2612 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2613 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2614 for (unsigned J = 0; J < Seg.nsects; ++J) {
2615 MachO::section_64 Sec = info->O->getSection64(Load, J);
2616 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2617 if (section_type == MachO::S_CSTRING_LITERALS &&
2618 ReferenceValue >= Sec.addr &&
2619 ReferenceValue < Sec.addr + Sec.size) {
2620 uint64_t sect_offset = ReferenceValue - Sec.addr;
2621 uint64_t object_offset = Sec.offset + sect_offset;
2622 StringRef MachOContents = info->O->getData();
2623 uint64_t object_size = MachOContents.size();
2624 const char *object_addr = (const char *)MachOContents.data();
2625 if (object_offset < object_size) {
2626 const char *name = object_addr + object_offset;
2627 return name;
2628 } else {
2629 return nullptr;
2630 }
2631 }
2632 }
2633 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2634 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2635 for (unsigned J = 0; J < Seg.nsects; ++J) {
2636 MachO::section Sec = info->O->getSection(Load, J);
2637 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2638 if (section_type == MachO::S_CSTRING_LITERALS &&
2639 ReferenceValue >= Sec.addr &&
2640 ReferenceValue < Sec.addr + Sec.size) {
2641 uint64_t sect_offset = ReferenceValue - Sec.addr;
2642 uint64_t object_offset = Sec.offset + sect_offset;
2643 StringRef MachOContents = info->O->getData();
2644 uint64_t object_size = MachOContents.size();
2645 const char *object_addr = (const char *)MachOContents.data();
2646 if (object_offset < object_size) {
2647 const char *name = object_addr + object_offset;
2648 return name;
2649 } else {
2650 return nullptr;
2651 }
2652 }
2653 }
2654 }
2655 }
2656 return nullptr;
2657}
2658
2659// GuessIndirectSymbol returns the name of the indirect symbol for the
2660// ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe
2661// an address of a symbol stub or a lazy or non-lazy pointer to associate the
2662// symbol name being referenced by the stub or pointer.
2663static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
2664 struct DisassembleInfo *info) {
2665 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
2666 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
2667 for (const auto &Load : info->O->load_commands()) {
2668 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2669 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2670 for (unsigned J = 0; J < Seg.nsects; ++J) {
2671 MachO::section_64 Sec = info->O->getSection64(Load, J);
2672 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2673 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2674 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2675 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2676 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2677 section_type == MachO::S_SYMBOL_STUBS) &&
2678 ReferenceValue >= Sec.addr &&
2679 ReferenceValue < Sec.addr + Sec.size) {
2680 uint32_t stride;
2681 if (section_type == MachO::S_SYMBOL_STUBS)
2682 stride = Sec.reserved2;
2683 else
2684 stride = 8;
2685 if (stride == 0)
2686 return nullptr;
2687 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2688 if (index < Dysymtab.nindirectsyms) {
2689 uint32_t indirect_symbol =
2690 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2691 if (indirect_symbol < Symtab.nsyms) {
2692 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2693 SymbolRef Symbol = *Sym;
2694 Expected<StringRef> SymName = Symbol.getName();
2695 if (!SymName)
2696 report_error(info->O->getFileName(), SymName.takeError());
2697 const char *name = SymName->data();
2698 return name;
2699 }
2700 }
2701 }
2702 }
2703 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2704 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2705 for (unsigned J = 0; J < Seg.nsects; ++J) {
2706 MachO::section Sec = info->O->getSection(Load, J);
2707 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2708 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2709 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2710 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2711 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2712 section_type == MachO::S_SYMBOL_STUBS) &&
2713 ReferenceValue >= Sec.addr &&
2714 ReferenceValue < Sec.addr + Sec.size) {
2715 uint32_t stride;
2716 if (section_type == MachO::S_SYMBOL_STUBS)
2717 stride = Sec.reserved2;
2718 else
2719 stride = 4;
2720 if (stride == 0)
2721 return nullptr;
2722 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2723 if (index < Dysymtab.nindirectsyms) {
2724 uint32_t indirect_symbol =
2725 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2726 if (indirect_symbol < Symtab.nsyms) {
2727 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2728 SymbolRef Symbol = *Sym;
2729 Expected<StringRef> SymName = Symbol.getName();
2730 if (!SymName)
2731 report_error(info->O->getFileName(), SymName.takeError());
2732 const char *name = SymName->data();
2733 return name;
2734 }
2735 }
2736 }
2737 }
2738 }
2739 }
2740 return nullptr;
2741}
2742
2743// method_reference() is called passing it the ReferenceName that might be
2744// a reference it to an Objective-C method call. If so then it allocates and
2745// assembles a method call string with the values last seen and saved in
2746// the DisassembleInfo's class_name and selector_name fields. This is saved
2747// into the method field of the info and any previous string is free'ed.
2748// Then the class_name field in the info is set to nullptr. The method call
2749// string is set into ReferenceName and ReferenceType is set to
2750// LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call
2751// then both ReferenceType and ReferenceName are left unchanged.
2752static void method_reference(struct DisassembleInfo *info,
2753 uint64_t *ReferenceType,
2754 const char **ReferenceName) {
2755 unsigned int Arch = info->O->getArch();
2756 if (*ReferenceName != nullptr) {
2757 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
2758 if (info->selector_name != nullptr) {
2759 if (info->method != nullptr)
2760 free(info->method);
2761 if (info->class_name != nullptr) {
2762 info->method = (char *)malloc(5 + strlen(info->class_name) +
2763 strlen(info->selector_name));
2764 if (info->method != nullptr) {
2765 strcpy(info->method, "+[");
2766 strcat(info->method, info->class_name);
2767 strcat(info->method, " ");
2768 strcat(info->method, info->selector_name);
2769 strcat(info->method, "]");
2770 *ReferenceName = info->method;
2771 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message5;
2772 }
2773 } else {
2774 info->method = (char *)malloc(9 + strlen(info->selector_name));
2775 if (info->method != nullptr) {
2776 if (Arch == Triple::x86_64)
2777 strcpy(info->method, "-[%rdi ");
2778 else if (Arch == Triple::aarch64)
2779 strcpy(info->method, "-[x0 ");
2780 else
2781 strcpy(info->method, "-[r? ");
2782 strcat(info->method, info->selector_name);
2783 strcat(info->method, "]");
2784 *ReferenceName = info->method;
2785 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message5;
2786 }
2787 }
2788 info->class_name = nullptr;
2789 }
2790 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
2791 if (info->selector_name != nullptr) {
2792 if (info->method != nullptr)
2793 free(info->method);
2794 info->method = (char *)malloc(17 + strlen(info->selector_name));
2795 if (info->method != nullptr) {
2796 if (Arch == Triple::x86_64)
2797 strcpy(info->method, "-[[%rdi super] ");
2798 else if (Arch == Triple::aarch64)
2799 strcpy(info->method, "-[[x0 super] ");
2800 else
2801 strcpy(info->method, "-[[r? super] ");
2802 strcat(info->method, info->selector_name);
2803 strcat(info->method, "]");
2804 *ReferenceName = info->method;
2805 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message5;
2806 }
2807 info->class_name = nullptr;
2808 }
2809 }
2810 }
2811}
2812
2813// GuessPointerPointer() is passed the address of what might be a pointer to
2814// a reference to an Objective-C class, selector, message ref or cfstring.
2815// If so the value of the pointer is returned and one of the booleans are set
2816// to true. If not zero is returned and all the booleans are set to false.
2817static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
2818 struct DisassembleInfo *info,
2819 bool &classref, bool &selref, bool &msgref,
2820 bool &cfstring) {
2821 classref = false;
2822 selref = false;
2823 msgref = false;
2824 cfstring = false;
2825 for (const auto &Load : info->O->load_commands()) {
2826 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2827 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2828 for (unsigned J = 0; J < Seg.nsects; ++J) {
2829 MachO::section_64 Sec = info->O->getSection64(Load, J);
2830 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
2831 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2832 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
2833 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
2834 strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
2835 ReferenceValue >= Sec.addr &&
2836 ReferenceValue < Sec.addr + Sec.size) {
2837 uint64_t sect_offset = ReferenceValue - Sec.addr;
2838 uint64_t object_offset = Sec.offset + sect_offset;
2839 StringRef MachOContents = info->O->getData();
2840 uint64_t object_size = MachOContents.size();
2841 const char *object_addr = (const char *)MachOContents.data();
2842 if (object_offset < object_size) {
2843 uint64_t pointer_value;
2844 memcpy(&pointer_value, object_addr + object_offset,
2845 sizeof(uint64_t));
2846 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2847 sys::swapByteOrder(pointer_value);
2848 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
2849 selref = true;
2850 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2851 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
2852 classref = true;
2853 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
2854 ReferenceValue + 8 < Sec.addr + Sec.size) {
2855 msgref = true;
2856 memcpy(&pointer_value, object_addr + object_offset + 8,
2857 sizeof(uint64_t));
2858 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2859 sys::swapByteOrder(pointer_value);
2860 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
2861 cfstring = true;
2862 return pointer_value;
2863 } else {
2864 return 0;
2865 }
2866 }
2867 }
2868 }
2869 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
2870 }
2871 return 0;
2872}
2873
2874// get_pointer_64 returns a pointer to the bytes in the object file at the
2875// Address from a section in the Mach-O file. And indirectly returns the
2876// offset into the section, number of bytes left in the section past the offset
2877// and which section is was being referenced. If the Address is not in a
2878// section nullptr is returned.
2879static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
2880 uint32_t &left, SectionRef &S,
2881 DisassembleInfo *info,
2882 bool objc_only = false) {
2883 offset = 0;
2884 left = 0;
2885 S = SectionRef();
2886 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
2887 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
2888 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
2889 if (SectSize == 0)
2890 continue;
2891 if (objc_only) {
2892 StringRef SectName;
2893 ((*(info->Sections))[SectIdx]).getName(SectName);
2894 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
2895 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
2896 if (SegName != "__OBJC" && SectName != "__cstring")
2897 continue;
2898 }
2899 if (Address >= SectAddress && Address < SectAddress + SectSize) {
2900 S = (*(info->Sections))[SectIdx];
2901 offset = Address - SectAddress;
2902 left = SectSize - offset;
2903 StringRef SectContents;
2904 ((*(info->Sections))[SectIdx]).getContents(SectContents);
2905 return SectContents.data() + offset;
2906 }
2907 }
2908 return nullptr;
2909}
2910
2911static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
2912 uint32_t &left, SectionRef &S,
2913 DisassembleInfo *info,
2914 bool objc_only = false) {
2915 return get_pointer_64(Address, offset, left, S, info, objc_only);
2916}
2917
2918// get_symbol_64() returns the name of a symbol (or nullptr) and the address of
2919// the symbol indirectly through n_value. Based on the relocation information
2920// for the specified section offset in the specified section reference.
2921// If no relocation information is found and a non-zero ReferenceValue for the
2922// symbol is passed, look up that address in the info's AddrMap.
2923static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
2924 DisassembleInfo *info, uint64_t &n_value,
2925 uint64_t ReferenceValue = 0) {
2926 n_value = 0;
2927 if (!info->verbose)
2928 return nullptr;
2929
2930 // See if there is an external relocation entry at the sect_offset.
2931 bool reloc_found = false;
2932 DataRefImpl Rel;
2933 MachO::any_relocation_info RE;
2934 bool isExtern = false;
2935 SymbolRef Symbol;
2936 for (const RelocationRef &Reloc : S.relocations()) {
2937 uint64_t RelocOffset = Reloc.getOffset();
2938 if (RelocOffset == sect_offset) {
2939 Rel = Reloc.getRawDataRefImpl();
2940 RE = info->O->getRelocation(Rel);
2941 if (info->O->isRelocationScattered(RE))
2942 continue;
2943 isExtern = info->O->getPlainRelocationExternal(RE);
2944 if (isExtern) {
2945 symbol_iterator RelocSym = Reloc.getSymbol();
2946 Symbol = *RelocSym;
2947 }
2948 reloc_found = true;
2949 break;
2950 }
2951 }
2952 // If there is an external relocation entry for a symbol in this section
2953 // at this section_offset then use that symbol's value for the n_value
2954 // and return its name.
2955 const char *SymbolName = nullptr;
2956 if (reloc_found && isExtern) {
2957 n_value = Symbol.getValue();
2958 Expected<StringRef> NameOrError = Symbol.getName();
2959 if (!NameOrError)
2960 report_error(info->O->getFileName(), NameOrError.takeError());
2961 StringRef Name = *NameOrError;
2962 if (!Name.empty()) {
2963 SymbolName = Name.data();
2964 return SymbolName;
2965 }
2966 }
2967
2968 // TODO: For fully linked images, look through the external relocation
2969 // entries off the dynamic symtab command. For these the r_offset is from the
2970 // start of the first writeable segment in the Mach-O file. So the offset
2971 // to this section from that segment is passed to this routine by the caller,
2972 // as the database_offset. Which is the difference of the section's starting
2973 // address and the first writable segment.
2974 //
2975 // NOTE: need add passing the database_offset to this routine.
2976
2977 // We did not find an external relocation entry so look up the ReferenceValue
2978 // as an address of a symbol and if found return that symbol's name.
2979 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
2980
2981 return SymbolName;
2982}
2983
2984static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
2985 DisassembleInfo *info,
2986 uint32_t ReferenceValue) {
2987 uint64_t n_value64;
2988 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
2989}
2990
2991// These are structs in the Objective-C meta data and read to produce the
2992// comments for disassembly. While these are part of the ABI they are no
2993// public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h
2994// .
2995
2996// The cfstring object in a 64-bit Mach-O file.
2997struct cfstring64_t {
2998 uint64_t isa; // class64_t * (64-bit pointer)
2999 uint64_t flags; // flag bits
3000 uint64_t characters; // char * (64-bit pointer)
3001 uint64_t length; // number of non-NULL characters in above
3002};
3003
3004// The class object in a 64-bit Mach-O file.
3005struct class64_t {
3006 uint64_t isa; // class64_t * (64-bit pointer)
3007 uint64_t superclass; // class64_t * (64-bit pointer)
3008 uint64_t cache; // Cache (64-bit pointer)
3009 uint64_t vtable; // IMP * (64-bit pointer)
3010 uint64_t data; // class_ro64_t * (64-bit pointer)
3011};
3012
3013struct class32_t {
3014 uint32_t isa; /* class32_t * (32-bit pointer) */
3015 uint32_t superclass; /* class32_t * (32-bit pointer) */
3016 uint32_t cache; /* Cache (32-bit pointer) */
3017 uint32_t vtable; /* IMP * (32-bit pointer) */
3018 uint32_t data; /* class_ro32_t * (32-bit pointer) */
3019};
3020
3021struct class_ro64_t {
3022 uint32_t flags;
3023 uint32_t instanceStart;
3024 uint32_t instanceSize;
3025 uint32_t reserved;
3026 uint64_t ivarLayout; // const uint8_t * (64-bit pointer)
3027 uint64_t name; // const char * (64-bit pointer)
3028 uint64_t baseMethods; // const method_list_t * (64-bit pointer)
3029 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer)
3030 uint64_t ivars; // const ivar_list_t * (64-bit pointer)
3031 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
3032 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
3033};
3034
3035struct class_ro32_t {
3036 uint32_t flags;
3037 uint32_t instanceStart;
3038 uint32_t instanceSize;
3039 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */
3040 uint32_t name; /* const char * (32-bit pointer) */
3041 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */
3042 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */
3043 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */
3044 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
3045 uint32_t baseProperties; /* const struct objc_property_list *
3046 (32-bit pointer) */
3047};
3048
3049/* Values for class_ro{64,32}_t->flags */
3050#define RO_META(1 << 0) (1 << 0)
3051#define RO_ROOT(1 << 1) (1 << 1)
3052#define RO_HAS_CXX_STRUCTORS(1 << 2) (1 << 2)
3053
3054struct method_list64_t {
3055 uint32_t entsize;
3056 uint32_t count;
3057 /* struct method64_t first; These structures follow inline */
3058};
3059
3060struct method_list32_t {
3061 uint32_t entsize;
3062 uint32_t count;
3063 /* struct method32_t first; These structures follow inline */
3064};
3065
3066struct method64_t {
3067 uint64_t name; /* SEL (64-bit pointer) */
3068 uint64_t types; /* const char * (64-bit pointer) */
3069 uint64_t imp; /* IMP (64-bit pointer) */
3070};
3071
3072struct method32_t {
3073 uint32_t name; /* SEL (32-bit pointer) */
3074 uint32_t types; /* const char * (32-bit pointer) */
3075 uint32_t imp; /* IMP (32-bit pointer) */
3076};
3077
3078struct protocol_list64_t {
3079 uint64_t count; /* uintptr_t (a 64-bit value) */
3080 /* struct protocol64_t * list[0]; These pointers follow inline */
3081};
3082
3083struct protocol_list32_t {
3084 uint32_t count; /* uintptr_t (a 32-bit value) */
3085 /* struct protocol32_t * list[0]; These pointers follow inline */
3086};
3087
3088struct protocol64_t {
3089 uint64_t isa; /* id * (64-bit pointer) */
3090 uint64_t name; /* const char * (64-bit pointer) */
3091 uint64_t protocols; /* struct protocol_list64_t *
3092 (64-bit pointer) */
3093 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */
3094 uint64_t classMethods; /* method_list_t * (64-bit pointer) */
3095 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3096 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */
3097 uint64_t instanceProperties; /* struct objc_property_list *
3098 (64-bit pointer) */
3099};
3100
3101struct protocol32_t {
3102 uint32_t isa; /* id * (32-bit pointer) */
3103 uint32_t name; /* const char * (32-bit pointer) */
3104 uint32_t protocols; /* struct protocol_list_t *
3105 (32-bit pointer) */
3106 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */
3107 uint32_t classMethods; /* method_list_t * (32-bit pointer) */
3108 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3109 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */
3110 uint32_t instanceProperties; /* struct objc_property_list *
3111 (32-bit pointer) */
3112};
3113
3114struct ivar_list64_t {
3115 uint32_t entsize;
3116 uint32_t count;
3117 /* struct ivar64_t first; These structures follow inline */
3118};
3119
3120struct ivar_list32_t {
3121 uint32_t entsize;
3122 uint32_t count;
3123 /* struct ivar32_t first; These structures follow inline */
3124};
3125
3126struct ivar64_t {
3127 uint64_t offset; /* uintptr_t * (64-bit pointer) */
3128 uint64_t name; /* const char * (64-bit pointer) */
3129 uint64_t type; /* const char * (64-bit pointer) */
3130 uint32_t alignment;
3131 uint32_t size;
3132};
3133
3134struct ivar32_t {
3135 uint32_t offset; /* uintptr_t * (32-bit pointer) */
3136 uint32_t name; /* const char * (32-bit pointer) */
3137 uint32_t type; /* const char * (32-bit pointer) */
3138 uint32_t alignment;
3139 uint32_t size;
3140};
3141
3142struct objc_property_list64 {
3143 uint32_t entsize;
3144 uint32_t count;
3145 /* struct objc_property64 first; These structures follow inline */
3146};
3147
3148struct objc_property_list32 {
3149 uint32_t entsize;
3150 uint32_t count;
3151 /* struct objc_property32 first; These structures follow inline */
3152};
3153
3154struct objc_property64 {
3155 uint64_t name; /* const char * (64-bit pointer) */
3156 uint64_t attributes; /* const char * (64-bit pointer) */
3157};
3158
3159struct objc_property32 {
3160 uint32_t name; /* const char * (32-bit pointer) */
3161 uint32_t attributes; /* const char * (32-bit pointer) */
3162};
3163
3164struct category64_t {
3165 uint64_t name; /* const char * (64-bit pointer) */
3166 uint64_t cls; /* struct class_t * (64-bit pointer) */
3167 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */
3168 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */
3169 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */
3170 uint64_t instanceProperties; /* struct objc_property_list *
3171 (64-bit pointer) */
3172};
3173
3174struct category32_t {
3175 uint32_t name; /* const char * (32-bit pointer) */
3176 uint32_t cls; /* struct class_t * (32-bit pointer) */
3177 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */
3178 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */
3179 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */
3180 uint32_t instanceProperties; /* struct objc_property_list *
3181 (32-bit pointer) */
3182};
3183
3184struct objc_image_info64 {
3185 uint32_t version;
3186 uint32_t flags;
3187};
3188struct objc_image_info32 {
3189 uint32_t version;
3190 uint32_t flags;
3191};
3192struct imageInfo_t {
3193 uint32_t version;
3194 uint32_t flags;
3195};
3196/* masks for objc_image_info.flags */
3197#define OBJC_IMAGE_IS_REPLACEMENT(1 << 0) (1 << 0)
3198#define OBJC_IMAGE_SUPPORTS_GC(1 << 1) (1 << 1)
3199
3200struct message_ref64 {
3201 uint64_t imp; /* IMP (64-bit pointer) */
3202 uint64_t sel; /* SEL (64-bit pointer) */
3203};
3204
3205struct message_ref32 {
3206 uint32_t imp; /* IMP (32-bit pointer) */
3207 uint32_t sel; /* SEL (32-bit pointer) */
3208};
3209
3210// Objective-C 1 (32-bit only) meta data structs.
3211
3212struct objc_module_t {
3213 uint32_t version;
3214 uint32_t size;
3215 uint32_t name; /* char * (32-bit pointer) */
3216 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3217};
3218
3219struct objc_symtab_t {
3220 uint32_t sel_ref_cnt;
3221 uint32_t refs; /* SEL * (32-bit pointer) */
3222 uint16_t cls_def_cnt;
3223 uint16_t cat_def_cnt;
3224 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */
3225};
3226
3227struct objc_class_t {
3228 uint32_t isa; /* struct objc_class * (32-bit pointer) */
3229 uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3230 uint32_t name; /* const char * (32-bit pointer) */
3231 int32_t version;
3232 int32_t info;
3233 int32_t instance_size;
3234 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */
3235 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3236 uint32_t cache; /* struct objc_cache * (32-bit pointer) */
3237 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */
3238};
3239
3240#define CLS_GETINFO(cls, infomask)((cls)->info & (infomask)) ((cls)->info & (infomask))
3241// class is not a metaclass
3242#define CLS_CLASS0x1 0x1
3243// class is a metaclass
3244#define CLS_META0x2 0x2
3245
3246struct objc_category_t {
3247 uint32_t category_name; /* char * (32-bit pointer) */
3248 uint32_t class_name; /* char * (32-bit pointer) */
3249 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3250 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */
3251 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */
3252};
3253
3254struct objc_ivar_t {
3255 uint32_t ivar_name; /* char * (32-bit pointer) */
3256 uint32_t ivar_type; /* char * (32-bit pointer) */
3257 int32_t ivar_offset;
3258};
3259
3260struct objc_ivar_list_t {
3261 int32_t ivar_count;
3262 // struct objc_ivar_t ivar_list[1]; /* variable length structure */
3263};
3264
3265struct objc_method_list_t {
3266 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3267 int32_t method_count;
3268 // struct objc_method_t method_list[1]; /* variable length structure */
3269};
3270
3271struct objc_method_t {
3272 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */
3273 uint32_t method_types; /* char * (32-bit pointer) */
3274 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3275 (32-bit pointer) */
3276};
3277
3278struct objc_protocol_list_t {
3279 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3280 int32_t count;
3281 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t *
3282 // (32-bit pointer) */
3283};
3284
3285struct objc_protocol_t {
3286 uint32_t isa; /* struct objc_class * (32-bit pointer) */
3287 uint32_t protocol_name; /* char * (32-bit pointer) */
3288 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */
3289 uint32_t instance_methods; /* struct objc_method_description_list *
3290 (32-bit pointer) */
3291 uint32_t class_methods; /* struct objc_method_description_list *
3292 (32-bit pointer) */
3293};
3294
3295struct objc_method_description_list_t {
3296 int32_t count;
3297 // struct objc_method_description_t list[1];
3298};
3299
3300struct objc_method_description_t {
3301 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */
3302 uint32_t types; /* char * (32-bit pointer) */
3303};
3304
3305inline void swapStruct(struct cfstring64_t &cfs) {
3306 sys::swapByteOrder(cfs.isa);
3307 sys::swapByteOrder(cfs.flags);
3308 sys::swapByteOrder(cfs.characters);
3309 sys::swapByteOrder(cfs.length);
3310}
3311
3312inline void swapStruct(struct class64_t &c) {
3313 sys::swapByteOrder(c.isa);
3314 sys::swapByteOrder(c.superclass);
3315 sys::swapByteOrder(c.cache);
3316 sys::swapByteOrder(c.vtable);
3317 sys::swapByteOrder(c.data);
3318}
3319
3320inline void swapStruct(struct class32_t &c) {
3321 sys::swapByteOrder(c.isa);
3322 sys::swapByteOrder(c.superclass);
3323 sys::swapByteOrder(c.cache);
3324 sys::swapByteOrder(c.vtable);
3325 sys::swapByteOrder(c.data);
3326}
3327
3328inline void swapStruct(struct class_ro64_t &cro) {
3329 sys::swapByteOrder(cro.flags);
3330 sys::swapByteOrder(cro.instanceStart);
3331 sys::swapByteOrder(cro.instanceSize);
3332 sys::swapByteOrder(cro.reserved);
3333 sys::swapByteOrder(cro.ivarLayout);
3334 sys::swapByteOrder(cro.name);
3335 sys::swapByteOrder(cro.baseMethods);
3336 sys::swapByteOrder(cro.baseProtocols);
3337 sys::swapByteOrder(cro.ivars);
3338 sys::swapByteOrder(cro.weakIvarLayout);
3339 sys::swapByteOrder(cro.baseProperties);
3340}
3341
3342inline void swapStruct(struct class_ro32_t &cro) {
3343 sys::swapByteOrder(cro.flags);
3344 sys::swapByteOrder(cro.instanceStart);
3345 sys::swapByteOrder(cro.instanceSize);
3346 sys::swapByteOrder(cro.ivarLayout);
3347 sys::swapByteOrder(cro.name);
3348 sys::swapByteOrder(cro.baseMethods);
3349 sys::swapByteOrder(cro.baseProtocols);
3350 sys::swapByteOrder(cro.ivars);
3351 sys::swapByteOrder(cro.weakIvarLayout);
3352 sys::swapByteOrder(cro.baseProperties);
3353}
3354
3355inline void swapStruct(struct method_list64_t &ml) {
3356 sys::swapByteOrder(ml.entsize);
3357 sys::swapByteOrder(ml.count);
3358}
3359
3360inline void swapStruct(struct method_list32_t &ml) {
3361 sys::swapByteOrder(ml.entsize);
3362 sys::swapByteOrder(ml.count);
3363}
3364
3365inline void swapStruct(struct method64_t &m) {
3366 sys::swapByteOrder(m.name);
3367 sys::swapByteOrder(m.types);
3368 sys::swapByteOrder(m.imp);
3369}
3370
3371inline void swapStruct(struct method32_t &m) {
3372 sys::swapByteOrder(m.name);
3373 sys::swapByteOrder(m.types);
3374 sys::swapByteOrder(m.imp);
3375}
3376
3377inline void swapStruct(struct protocol_list64_t &pl) {
3378 sys::swapByteOrder(pl.count);
3379}
3380
3381inline void swapStruct(struct protocol_list32_t &pl) {
3382 sys::swapByteOrder(pl.count);
3383}
3384
3385inline void swapStruct(struct protocol64_t &p) {
3386 sys::swapByteOrder(p.isa);
3387 sys::swapByteOrder(p.name);
3388 sys::swapByteOrder(p.protocols);
3389 sys::swapByteOrder(p.instanceMethods);
3390 sys::swapByteOrder(p.classMethods);
3391 sys::swapByteOrder(p.optionalInstanceMethods);
3392 sys::swapByteOrder(p.optionalClassMethods);
3393 sys::swapByteOrder(p.instanceProperties);
3394}
3395
3396inline void swapStruct(struct protocol32_t &p) {
3397 sys::swapByteOrder(p.isa);
3398 sys::swapByteOrder(p.name);
3399 sys::swapByteOrder(p.protocols);
3400 sys::swapByteOrder(p.instanceMethods);
3401 sys::swapByteOrder(p.classMethods);
3402 sys::swapByteOrder(p.optionalInstanceMethods);
3403 sys::swapByteOrder(p.optionalClassMethods);
3404 sys::swapByteOrder(p.instanceProperties);
3405}
3406
3407inline void swapStruct(struct ivar_list64_t &il) {
3408 sys::swapByteOrder(il.entsize);
3409 sys::swapByteOrder(il.count);
3410}
3411
3412inline void swapStruct(struct ivar_list32_t &il) {
3413 sys::swapByteOrder(il.entsize);
3414 sys::swapByteOrder(il.count);
3415}
3416
3417inline void swapStruct(struct ivar64_t &i) {
3418 sys::swapByteOrder(i.offset);
3419 sys::swapByteOrder(i.name);
3420 sys::swapByteOrder(i.type);
3421 sys::swapByteOrder(i.alignment);
3422 sys::swapByteOrder(i.size);
3423}
3424
3425inline void swapStruct(struct ivar32_t &i) {
3426 sys::swapByteOrder(i.offset);
3427 sys::swapByteOrder(i.name);
3428 sys::swapByteOrder(i.type);
3429 sys::swapByteOrder(i.alignment);
3430 sys::swapByteOrder(i.size);
3431}
3432
3433inline void swapStruct(struct objc_property_list64 &pl) {
3434 sys::swapByteOrder(pl.entsize);
3435 sys::swapByteOrder(pl.count);
3436}
3437
3438inline void swapStruct(struct objc_property_list32 &pl) {
3439 sys::swapByteOrder(pl.entsize);
3440 sys::swapByteOrder(pl.count);
3441}
3442
3443inline void swapStruct(struct objc_property64 &op) {
3444 sys::swapByteOrder(op.name);
3445 sys::swapByteOrder(op.attributes);
3446}
3447
3448inline void swapStruct(struct objc_property32 &op) {
3449 sys::swapByteOrder(op.name);
3450 sys::swapByteOrder(op.attributes);
3451}
3452
3453inline void swapStruct(struct category64_t &c) {
3454 sys::swapByteOrder(c.name);
3455 sys::swapByteOrder(c.cls);
3456 sys::swapByteOrder(c.instanceMethods);
3457 sys::swapByteOrder(c.classMethods);
3458 sys::swapByteOrder(c.protocols);
3459 sys::swapByteOrder(c.instanceProperties);
3460}
3461
3462inline void swapStruct(struct category32_t &c) {
3463 sys::swapByteOrder(c.name);
3464 sys::swapByteOrder(c.cls);
3465 sys::swapByteOrder(c.instanceMethods);
3466 sys::swapByteOrder(c.classMethods);
3467 sys::swapByteOrder(c.protocols);
3468 sys::swapByteOrder(c.instanceProperties);
3469}
3470
3471inline void swapStruct(struct objc_image_info64 &o) {
3472 sys::swapByteOrder(o.version);
3473 sys::swapByteOrder(o.flags);
3474}
3475
3476inline void swapStruct(struct objc_image_info32 &o) {
3477 sys::swapByteOrder(o.version);
3478 sys::swapByteOrder(o.flags);
3479}
3480
3481inline void swapStruct(struct imageInfo_t &o) {
3482 sys::swapByteOrder(o.version);
3483 sys::swapByteOrder(o.flags);
3484}
3485
3486inline void swapStruct(struct message_ref64 &mr) {
3487 sys::swapByteOrder(mr.imp);
3488 sys::swapByteOrder(mr.sel);
3489}
3490
3491inline void swapStruct(struct message_ref32 &mr) {
3492 sys::swapByteOrder(mr.imp);
3493 sys::swapByteOrder(mr.sel);
3494}
3495
3496inline void swapStruct(struct objc_module_t &module) {
3497 sys::swapByteOrder(module.version);
3498 sys::swapByteOrder(module.size);
3499 sys::swapByteOrder(module.name);
3500 sys::swapByteOrder(module.symtab);
3501}
3502
3503inline void swapStruct(struct objc_symtab_t &symtab) {
3504 sys::swapByteOrder(symtab.sel_ref_cnt);
3505 sys::swapByteOrder(symtab.refs);
3506 sys::swapByteOrder(symtab.cls_def_cnt);
3507 sys::swapByteOrder(symtab.cat_def_cnt);
3508}
3509
3510inline void swapStruct(struct objc_class_t &objc_class) {
3511 sys::swapByteOrder(objc_class.isa);
3512 sys::swapByteOrder(objc_class.super_class);
3513 sys::swapByteOrder(objc_class.name);
3514 sys::swapByteOrder(objc_class.version);
3515 sys::swapByteOrder(objc_class.info);
3516 sys::swapByteOrder(objc_class.instance_size);
3517 sys::swapByteOrder(objc_class.ivars);
3518 sys::swapByteOrder(objc_class.methodLists);
3519 sys::swapByteOrder(objc_class.cache);
3520 sys::swapByteOrder(objc_class.protocols);
3521}
3522
3523inline void swapStruct(struct objc_category_t &objc_category) {
3524 sys::swapByteOrder(objc_category.category_name);
3525 sys::swapByteOrder(objc_category.class_name);
3526 sys::swapByteOrder(objc_category.instance_methods);
3527 sys::swapByteOrder(objc_category.class_methods);
3528 sys::swapByteOrder(objc_category.protocols);
3529}
3530
3531inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
3532 sys::swapByteOrder(objc_ivar_list.ivar_count);
3533}
3534
3535inline void swapStruct(struct objc_ivar_t &objc_ivar) {
3536 sys::swapByteOrder(objc_ivar.ivar_name);
3537 sys::swapByteOrder(objc_ivar.ivar_type);
3538 sys::swapByteOrder(objc_ivar.ivar_offset);
3539}
3540
3541inline void swapStruct(struct objc_method_list_t &method_list) {
3542 sys::swapByteOrder(method_list.obsolete);
3543 sys::swapByteOrder(method_list.method_count);
3544}
3545
3546inline void swapStruct(struct objc_method_t &method) {
3547 sys::swapByteOrder(method.method_name);
3548 sys::swapByteOrder(method.method_types);
3549 sys::swapByteOrder(method.method_imp);
3550}
3551
3552inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
3553 sys::swapByteOrder(protocol_list.next);
3554 sys::swapByteOrder(protocol_list.count);
3555}
3556
3557inline void swapStruct(struct objc_protocol_t &protocol) {
3558 sys::swapByteOrder(protocol.isa);
3559 sys::swapByteOrder(protocol.protocol_name);
3560 sys::swapByteOrder(protocol.protocol_list);
3561 sys::swapByteOrder(protocol.instance_methods);
3562 sys::swapByteOrder(protocol.class_methods);
3563}
3564
3565inline void swapStruct(struct objc_method_description_list_t &mdl) {
3566 sys::swapByteOrder(mdl.count);
3567}
3568
3569inline void swapStruct(struct objc_method_description_t &md) {
3570 sys::swapByteOrder(md.name);
3571 sys::swapByteOrder(md.types);
3572}
3573
3574static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
3575 struct DisassembleInfo *info);
3576
3577// get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
3578// to an Objective-C class and returns the class name. It is also passed the
3579// address of the pointer, so when the pointer is zero as it can be in an .o
3580// file, that is used to look for an external relocation entry with a symbol
3581// name.
3582static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
3583 uint64_t ReferenceValue,
3584 struct DisassembleInfo *info) {
3585 const char *r;
3586 uint32_t offset, left;
3587 SectionRef S;
3588
3589 // The pointer_value can be 0 in an object file and have a relocation
3590 // entry for the class symbol at the ReferenceValue (the address of the
3591 // pointer).
3592 if (pointer_value == 0) {
3593 r = get_pointer_64(ReferenceValue, offset, left, S, info);
3594 if (r == nullptr || left < sizeof(uint64_t))
3595 return nullptr;
3596 uint64_t n_value;
3597 const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3598 if (symbol_name == nullptr)
3599 return nullptr;
3600 const char *class_name = strrchr(symbol_name, '$');
3601 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
3602 return class_name + 2;
3603 else
3604 return nullptr;
3605 }
3606
3607 // The case were the pointer_value is non-zero and points to a class defined
3608 // in this Mach-O file.
3609 r = get_pointer_64(pointer_value, offset, left, S, info);
3610 if (r == nullptr || left < sizeof(struct class64_t))
3611 return nullptr;
3612 struct class64_t c;
3613 memcpy(&c, r, sizeof(struct class64_t));
3614 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3615 swapStruct(c);
3616 if (c.data == 0)
3617 return nullptr;
3618 r = get_pointer_64(c.data, offset, left, S, info);
3619 if (r == nullptr || left < sizeof(struct class_ro64_t))
3620 return nullptr;
3621 struct class_ro64_t cro;
3622 memcpy(&cro, r, sizeof(struct class_ro64_t));
3623 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3624 swapStruct(cro);
3625 if (cro.name == 0)
3626 return nullptr;
3627 const char *name = get_pointer_64(cro.name, offset, left, S, info);
3628 return name;
3629}
3630
3631// get_objc2_64bit_cfstring_name is used for disassembly and is passed a
3632// pointer to a cfstring and returns its name or nullptr.
3633static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
3634 struct DisassembleInfo *info) {
3635 const char *r, *name;
3636 uint32_t offset, left;
3637 SectionRef S;
3638 struct cfstring64_t cfs;
3639 uint64_t cfs_characters;
3640
3641 r = get_pointer_64(ReferenceValue, offset, left, S, info);
3642 if (r == nullptr || left < sizeof(struct cfstring64_t))
3643 return nullptr;
3644 memcpy(&cfs, r, sizeof(struct cfstring64_t));
3645 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3646 swapStruct(cfs);
3647 if (cfs.characters == 0) {
3648 uint64_t n_value;
3649 const char *symbol_name = get_symbol_64(
3650 offset + offsetof(struct cfstring64_t, characters)__builtin_offsetof(struct cfstring64_t, characters), S, info, n_value);
3651 if (symbol_name == nullptr)
3652 return nullptr;
3653 cfs_characters = n_value;
3654 } else
3655 cfs_characters = cfs.characters;
3656 name = get_pointer_64(cfs_characters, offset, left, S, info);
3657
3658 return name;
3659}
3660
3661// get_objc2_64bit_selref() is used for disassembly and is passed a the address
3662// of a pointer to an Objective-C selector reference when the pointer value is
3663// zero as in a .o file and is likely to have a external relocation entry with
3664// who's symbol's n_value is the real pointer to the selector name. If that is
3665// the case the real pointer to the selector name is returned else 0 is
3666// returned
3667static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
3668 struct DisassembleInfo *info) {
3669 uint32_t offset, left;
3670 SectionRef S;
3671
3672 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
3673 if (r == nullptr || left < sizeof(uint64_t))
3674 return 0;
3675 uint64_t n_value;
3676 const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3677 if (symbol_name == nullptr)
3678 return 0;
3679 return n_value;
3680}
3681
3682static const SectionRef get_section(MachOObjectFile *O, const char *segname,
3683 const char *sectname) {
3684 for (const SectionRef &Section : O->sections()) {
3685 StringRef SectName;
3686 Section.getName(SectName);
3687 DataRefImpl Ref = Section.getRawDataRefImpl();
3688 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3689 if (SegName == segname && SectName == sectname)
3690 return Section;
3691 }
3692 return SectionRef();
3693}
3694
3695static void
3696walk_pointer_list_64(const char *listname, const SectionRef S,
3697 MachOObjectFile *O, struct DisassembleInfo *info,
3698 void (*func)(uint64_t, struct DisassembleInfo *info)) {
3699 if (S == SectionRef())
3700 return;
3701
3702 StringRef SectName;
3703 S.getName(SectName);
3704 DataRefImpl Ref = S.getRawDataRefImpl();
3705 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3706 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3707
3708 StringRef BytesStr;
3709 S.getContents(BytesStr);
3710 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3711
3712 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
3713 uint32_t left = S.getSize() - i;
3714 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
3715 uint64_t p = 0;
3716 memcpy(&p, Contents + i, size);
3717 if (i + sizeof(uint64_t) > S.getSize())
3718 outs() << listname << " list pointer extends past end of (" << SegName
3719 << "," << SectName << ") section\n";
3720 outs() << format("%016" PRIx64"l" "x", S.getAddress() + i) << " ";
3721
3722 if (O->isLittleEndian() != sys::IsLittleEndianHost)
3723 sys::swapByteOrder(p);
3724
3725 uint64_t n_value = 0;
3726 const char *name = get_symbol_64(i, S, info, n_value, p);
3727 if (name == nullptr)
3728 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
3729
3730 if (n_value != 0) {
3731 outs() << format("0x%" PRIx64"l" "x", n_value);
3732 if (p != 0)
3733 outs() << " + " << format("0x%" PRIx64"l" "x", p);
3734 } else
3735 outs() << format("0x%" PRIx64"l" "x", p);
3736 if (name != nullptr)
3737 outs() << " " << name;
3738 outs() << "\n";
3739
3740 p += n_value;
3741 if (func)
3742 func(p, info);
3743 }
3744}
3745
3746static void
3747walk_pointer_list_32(const char *listname, const SectionRef S,
3748 MachOObjectFile *O, struct DisassembleInfo *info,
3749 void (*func)(uint32_t, struct DisassembleInfo *info)) {
3750 if (S == SectionRef())
3751 return;
3752
3753 StringRef SectName;
3754 S.getName(SectName);
3755 DataRefImpl Ref = S.getRawDataRefImpl();
3756 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3757 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3758
3759 StringRef BytesStr;
3760 S.getContents(BytesStr);
3761 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3762
3763 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
3764 uint32_t left = S.getSize() - i;
3765 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
3766 uint32_t p = 0;
3767 memcpy(&p, Contents + i, size);
3768 if (i + sizeof(uint32_t) > S.getSize())
3769 outs() << listname << " list pointer extends past end of (" << SegName
3770 << "," << SectName << ") section\n";
3771 uint32_t Address = S.getAddress() + i;
3772 outs() << format("%08" PRIx32"x", Address) << " ";
3773
3774 if (O->isLittleEndian() != sys::IsLittleEndianHost)
3775 sys::swapByteOrder(p);
3776 outs() << format("0x%" PRIx32"x", p);
3777
3778 const char *name = get_symbol_32(i, S, info, p);
3779 if (name != nullptr)
3780 outs() << " " << name;
3781 outs() << "\n";
3782
3783 if (func)
3784 func(p, info);
3785 }
3786}
3787
3788static void print_layout_map(const char *layout_map, uint32_t left) {
3789 if (layout_map == nullptr)
3790 return;
3791 outs() << " layout map: ";
3792 do {
3793 outs() << format("0x%02" PRIx32"x", (*layout_map) & 0xff) << " ";
3794 left--;
3795 layout_map++;
3796 } while (*layout_map != '\0' && left != 0);
3797 outs() << "\n";
3798}
3799
3800static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
3801 uint32_t offset, left;
3802 SectionRef S;
3803 const char *layout_map;
3804
3805 if (p == 0)
3806 return;
3807 layout_map = get_pointer_64(p, offset, left, S, info);
3808 print_layout_map(layout_map, left);
3809}
3810
3811static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
3812 uint32_t offset, left;
3813 SectionRef S;
3814 const char *layout_map;
3815
3816 if (p == 0)
3817 return;
3818 layout_map = get_pointer_32(p, offset, left, S, info);
3819 print_layout_map(layout_map, left);
3820}
3821
3822static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
3823 const char *indent) {
3824 struct method_list64_t ml;
3825 struct method64_t m;
3826 const char *r;
3827 uint32_t offset, xoffset, left, i;
3828 SectionRef S, xS;
3829 const char *name, *sym_name;
3830 uint64_t n_value;
3831
3832 r = get_pointer_64(p, offset, left, S, info);
3833 if (r == nullptr)
3834 return;
3835 memset(&ml, '\0', sizeof(struct method_list64_t));
3836 if (left < sizeof(struct method_list64_t)) {
3837 memcpy(&ml, r, left);
3838 outs() << " (method_list_t entends past the end of the section)\n";
3839 } else
3840 memcpy(&ml, r, sizeof(struct method_list64_t));
3841 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3842 swapStruct(ml);
3843 outs() << indent << "\t\t entsize " << ml.entsize << "\n";
3844 outs() << indent << "\t\t count " << ml.count << "\n";
3845
3846 p += sizeof(struct method_list64_t);
3847 offset += sizeof(struct method_list64_t);
3848 for (i = 0; i < ml.count; i++) {
3849 r = get_pointer_64(p, offset, left, S, info);
3850 if (r == nullptr)
3851 return;
3852 memset(&m, '\0', sizeof(struct method64_t));
3853 if (left < sizeof(struct method64_t)) {
3854 memcpy(&m, r, left);
3855 outs() << indent << " (method_t extends past the end of the section)\n";
3856 } else
3857 memcpy(&m, r, sizeof(struct method64_t));
3858 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3859 swapStruct(m);
3860
3861 outs() << indent << "\t\t name ";
3862 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name)__builtin_offsetof(struct method64_t, name), S,
3863 info, n_value, m.name);
3864 if (n_value != 0) {
3865 if (info->verbose && sym_name != nullptr)
3866 outs() << sym_name;
3867 else
3868 outs() << format("0x%" PRIx64"l" "x", n_value);
3869 if (m.name != 0)
3870 outs() << " + " << format("0x%" PRIx64"l" "x", m.name);
3871 } else
3872 outs() << format("0x%" PRIx64"l" "x", m.name);
3873 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
3874 if (name != nullptr)
3875 outs() << format(" %.*s", left, name);
3876 outs() << "\n";
3877
3878 outs() << indent << "\t\t types ";
3879 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types)__builtin_offsetof(struct method64_t, types), S,
3880 info, n_value, m.types);
3881 if (n_value != 0) {
3882 if (info->verbose && sym_name != nullptr)
3883 outs() << sym_name;
3884 else
3885 outs() << format("0x%" PRIx64"l" "x", n_value);
3886 if (m.types != 0)
3887 outs() << " + " << format("0x%" PRIx64"l" "x", m.types);
3888 } else
3889 outs() << format("0x%" PRIx64"l" "x", m.types);
3890 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
3891 if (name != nullptr)
3892 outs() << format(" %.*s", left, name);
3893 outs() << "\n";
3894
3895 outs() << indent << "\t\t imp ";
3896 name = get_symbol_64(offset + offsetof(struct method64_t, imp)__builtin_offsetof(struct method64_t, imp), S, info,
3897 n_value, m.imp);
3898 if (info->verbose && name == nullptr) {
3899 if (n_value != 0) {
3900 outs() << format("0x%" PRIx64"l" "x", n_value) << " ";
3901 if (m.imp != 0)
3902 outs() << "+ " << format("0x%" PRIx64"l" "x", m.imp) << " ";
3903 } else
3904 outs() << format("0x%" PRIx64"l" "x", m.imp) << " ";
3905 }
3906 if (name != nullptr)
3907 outs() << name;
3908 outs() << "\n";
3909
3910 p += sizeof(struct method64_t);
3911 offset += sizeof(struct method64_t);
3912 }
3913}
3914
3915static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
3916 const char *indent) {
3917 struct method_list32_t ml;
3918 struct method32_t m;
3919 const char *r, *name;
3920 uint32_t offset, xoffset, left, i;
3921 SectionRef S, xS;
3922
3923 r = get_pointer_32(p, offset, left, S, info);
3924 if (r == nullptr)
3925 return;
3926 memset(&ml, '\0', sizeof(struct method_list32_t));
3927 if (left < sizeof(struct method_list32_t)) {
3928 memcpy(&ml, r, left);
3929 outs() << " (method_list_t entends past the end of the section)\n";
3930 } else
3931 memcpy(&ml, r, sizeof(struct method_list32_t));
3932 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3933 swapStruct(ml);
3934 outs() << indent << "\t\t entsize " << ml.entsize << "\n";
3935 outs() << indent << "\t\t count " << ml.count << "\n";
3936
3937 p += sizeof(struct method_list32_t);
3938 offset += sizeof(struct method_list32_t);
3939 for (i = 0; i < ml.count; i++) {
3940 r = get_pointer_32(p, offset, left, S, info);
3941 if (r == nullptr)
3942 return;
3943 memset(&m, '\0', sizeof(struct method32_t));
3944 if (left < sizeof(struct method32_t)) {
3945 memcpy(&ml, r, left);
3946 outs() << indent << " (method_t entends past the end of the section)\n";
3947 } else
3948 memcpy(&m, r, sizeof(struct method32_t));
3949 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3950 swapStruct(m);
3951
3952 outs() << indent << "\t\t name " << format("0x%" PRIx32"x", m.name);
3953 name = get_pointer_32(m.name, xoffset, left, xS, info);
3954 if (name != nullptr)
3955 outs() << format(" %.*s", left, name);
3956 outs() << "\n";
3957
3958 outs() << indent << "\t\t types " << format("0x%" PRIx32"x", m.types);
3959 name = get_pointer_32(m.types, xoffset, left, xS, info);
3960 if (name != nullptr)
3961 outs() << format(" %.*s", left, name);
3962 outs() << "\n";
3963
3964 outs() << indent << "\t\t imp " << format("0x%" PRIx32"x", m.imp);
3965 name = get_symbol_32(offset + offsetof(struct method32_t, imp)__builtin_offsetof(struct method32_t, imp), S, info,
3966 m.imp);
3967 if (name != nullptr)
3968 outs() << " " << name;
3969 outs() << "\n";
3970
3971 p += sizeof(struct method32_t);
3972 offset += sizeof(struct method32_t);
3973 }
3974}
3975
3976static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
3977 uint32_t offset, left, xleft;
3978 SectionRef S;
3979 struct objc_method_list_t method_list;
3980 struct objc_method_t method;
3981 const char *r, *methods, *name, *SymbolName;
3982 int32_t i;
3983
3984 r = get_pointer_32(p, offset, left, S, info, true);
3985 if (r == nullptr)
3986 return true;
3987
3988 outs() << "\n";
3989 if (left > sizeof(struct objc_method_list_t)) {
3990 memcpy(&method_list, r, sizeof(struct objc_method_list_t));
3991 } else {
3992 outs() << "\t\t objc_method_list extends past end of the section\n";
3993 memset(&method_list, '\0', sizeof(struct objc_method_list_t));
3994 memcpy(&method_list, r, left);
3995 }
3996 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3997 swapStruct(method_list);
3998
3999 outs() << "\t\t obsolete "
4000 << format("0x%08" PRIx32"x", method_list.obsolete) << "\n";
4001 outs() << "\t\t method_count " << method_list.method_count << "\n";
4002
4003 methods = r + sizeof(struct objc_method_list_t);
4004 for (i = 0; i < method_list.method_count; i++) {
4005 if ((i + 1) * sizeof(struct objc_method_t) > left) {
4006 outs() << "\t\t remaining method's extend past the of the section\n";
4007 break;
4008 }
4009 memcpy(&method, methods + i * sizeof(struct objc_method_t),
4010 sizeof(struct objc_method_t));
4011 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4012 swapStruct(method);
4013
4014 outs() << "\t\t method_name "
4015 << format("0x%08" PRIx32"x", method.method_name);
4016 if (info->verbose) {
4017 name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4018 if (name != nullptr)
4019 outs() << format(" %.*s", xleft, name);
4020 else
4021 outs() << " (not in an __OBJC section)";
4022 }
4023 outs() << "\n";
4024
4025 outs() << "\t\t method_types "
4026 << format("0x%08" PRIx32"x", method.method_types);
4027 if (info->verbose) {
4028 name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4029 if (name != nullptr)
4030 outs() << format(" %.*s", xleft, name);
4031 else
4032 outs() << " (not in an __OBJC section)";
4033 }
4034 outs() << "\n";
4035
4036 outs() << "\t\t method_imp "
4037 << format("0x%08" PRIx32"x", method.method_imp) << " ";
4038 if (info->verbose) {
4039 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4040 if (SymbolName != nullptr)
4041 outs() << SymbolName;
4042 }
4043 outs() << "\n";
4044 }
4045 return false;
4046}
4047
4048static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4049 struct protocol_list64_t pl;
4050 uint64_t q, n_value;
4051 struct protocol64_t pc;
4052 const char *r;
4053 uint32_t offset, xoffset, left, i;
4054 SectionRef S, xS;
4055 const char *name, *sym_name;
4056
4057 r = get_pointer_64(p, offset, left, S, info);
4058 if (r == nullptr)
4059 return;
4060 memset(&pl, '\0', sizeof(struct protocol_list64_t));
4061 if (left < sizeof(struct protocol_list64_t)) {
4062 memcpy(&pl, r, left);
4063 outs() << " (protocol_list_t entends past the end of the section)\n";
4064 } else
4065 memcpy(&pl, r, sizeof(struct protocol_list64_t));
4066 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4067 swapStruct(pl);
4068 outs() << " count " << pl.count << "\n";
4069
4070 p += sizeof(struct protocol_list64_t);
4071 offset += sizeof(struct protocol_list64_t);
4072 for (i = 0; i < pl.count; i++) {
4073 r = get_pointer_64(p, offset, left, S, info);
4074 if (r == nullptr)
4075 return;
4076 q = 0;
4077 if (left < sizeof(uint64_t)) {
4078 memcpy(&q, r, left);
4079 outs() << " (protocol_t * entends past the end of the section)\n";
4080 } else
4081 memcpy(&q, r, sizeof(uint64_t));
4082 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4083 sys::swapByteOrder(q);
4084
4085 outs() << "\t\t list[" << i << "] ";
4086 sym_name = get_symbol_64(offset, S, info, n_value, q);
4087 if (n_value != 0) {
4088 if (info->verbose && sym_name != nullptr)
4089 outs() << sym_name;
4090 else
4091 outs() << format("0x%" PRIx64"l" "x", n_value);
4092 if (q != 0)
4093 outs() << " + " << format("0x%" PRIx64"l" "x", q);
4094 } else
4095 outs() << format("0x%" PRIx64"l" "x", q);
4096 outs() << " (struct protocol_t *)\n";
4097
4098 r = get_pointer_64(q + n_value, offset, left, S, info);
4099 if (r == nullptr)
4100 return;
4101 memset(&pc, '\0', sizeof(struct protocol64_t));
4102 if (left < sizeof(struct protocol64_t)) {
4103 memcpy(&pc, r, left);
4104 outs() << " (protocol_t entends past the end of the section)\n";
4105 } else
4106 memcpy(&pc, r, sizeof(struct protocol64_t));
4107 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4108 swapStruct(pc);
4109
4110 outs() << "\t\t\t isa " << format("0x%" PRIx64"l" "x", pc.isa) << "\n";
4111
4112 outs() << "\t\t\t name ";
4113 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name)__builtin_offsetof(struct protocol64_t, name), S,
4114 info, n_value, pc.name);
4115 if (n_value != 0) {
4116 if (info->verbose && sym_name != nullptr)
4117 outs() << sym_name;
4118 else
4119 outs() << format("0x%" PRIx64"l" "x", n_value);
4120 if (pc.name != 0)
4121 outs() << " + " << format("0x%" PRIx64"l" "x", pc.name);
4122 } else
4123 outs() << format("0x%" PRIx64"l" "x", pc.name);
4124 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4125 if (name != nullptr)
4126 outs() << format(" %.*s", left, name);
4127 outs() << "\n";
4128
4129 outs() << "\t\t\tprotocols " << format("0x%" PRIx64"l" "x", pc.protocols) << "\n";
4130
4131 outs() << "\t\t instanceMethods ";
4132 sym_name =
4133 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods)__builtin_offsetof(struct protocol64_t, instanceMethods),
4134 S, info, n_value, pc.instanceMethods);
4135 if (n_value != 0) {
4136 if (info->verbose && sym_name != nullptr)
4137 outs() << sym_name;
4138 else
4139 outs() << format("0x%" PRIx64"l" "x", n_value);
4140 if (pc.instanceMethods != 0)
4141 outs() << " + " << format("0x%" PRIx64"l" "x", pc.instanceMethods);
4142 } else
4143 outs() << format("0x%" PRIx64"l" "x", pc.instanceMethods);
4144 outs() << " (struct method_list_t *)\n";
4145 if (pc.instanceMethods + n_value != 0)
4146 print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4147
4148 outs() << "\t\t classMethods ";
4149 sym_name =
4150 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods)__builtin_offsetof(struct protocol64_t, classMethods), S,
4151 info, n_value, pc.classMethods);
4152 if (n_value != 0) {
4153 if (info->verbose && sym_name != nullptr)
4154 outs() << sym_name;
4155 else
4156 outs() << format("0x%" PRIx64"l" "x", n_value);
4157 if (pc.classMethods != 0)
4158 outs() << " + " << format("0x%" PRIx64"l" "x", pc.classMethods);
4159 } else
4160 outs() << format("0x%" PRIx64"l" "x", pc.classMethods);
4161 outs() << " (struct method_list_t *)\n";
4162 if (pc.classMethods + n_value != 0)
4163 print_method_list64_t(pc.classMethods + n_value, info, "\t");
4164
4165 outs() << "\t optionalInstanceMethods "
4166 << format("0x%" PRIx64"l" "x", pc.optionalInstanceMethods) << "\n";
4167 outs() << "\t optionalClassMethods "
4168 << format("0x%" PRIx64"l" "x", pc.optionalClassMethods) << "\n";
4169 outs() << "\t instanceProperties "
4170 << format("0x%" PRIx64"l" "x", pc.instanceProperties) << "\n";
4171
4172 p += sizeof(uint64_t);
4173 offset += sizeof(uint64_t);
4174 }
4175}
4176
4177static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4178 struct protocol_list32_t pl;
4179 uint32_t q;
4180 struct protocol32_t pc;
4181 const char *r;
4182 uint32_t offset, xoffset, left, i;
4183 SectionRef S, xS;
4184 const char *name;
4185
4186 r = get_pointer_32(p, offset, left, S, info);
4187 if (r == nullptr)
4188 return;
4189 memset(&pl, '\0', sizeof(struct protocol_list32_t));
4190 if (left < sizeof(struct protocol_list32_t)) {
4191 memcpy(&pl, r, left);
4192 outs() << " (protocol_list_t entends past the end of the section)\n";
4193 } else
4194 memcpy(&pl, r, sizeof(struct protocol_list32_t));
4195 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4196 swapStruct(pl);
4197 outs() << " count " << pl.count << "\n";
4198
4199 p += sizeof(struct protocol_list32_t);
4200 offset += sizeof(struct protocol_list32_t);
4201 for (i = 0; i < pl.count; i++) {
4202 r = get_pointer_32(p, offset, left, S, info);
4203 if (r == nullptr)
4204 return;
4205 q = 0;
4206 if (left < sizeof(uint32_t)) {
4207 memcpy(&q, r, left);
4208 outs() << " (protocol_t * entends past the end of the section)\n";
4209 } else
4210 memcpy(&q, r, sizeof(uint32_t));
4211 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4212 sys::swapByteOrder(q);
4213 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32"x", q)
4214 << " (struct protocol_t *)\n";
4215 r = get_pointer_32(q, offset, left, S, info);
4216 if (r == nullptr)
4217 return;
4218 memset(&pc, '\0', sizeof(struct protocol32_t));
4219 if (left < sizeof(struct protocol32_t)) {
4220 memcpy(&pc, r, left);
4221 outs() << " (protocol_t entends past the end of the section)\n";
4222 } else
4223 memcpy(&pc, r, sizeof(struct protocol32_t));
4224 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4225 swapStruct(pc);
4226 outs() << "\t\t\t isa " << format("0x%" PRIx32"x", pc.isa) << "\n";
4227 outs() << "\t\t\t name " << format("0x%" PRIx32"x", pc.name);
4228 name = get_pointer_32(pc.name, xoffset, left, xS, info);
4229 if (name != nullptr)
4230 outs() << format(" %.*s", left, name);
4231 outs() << "\n";
4232 outs() << "\t\t\tprotocols " << format("0x%" PRIx32"x", pc.protocols) << "\n";
4233 outs() << "\t\t instanceMethods "
4234 << format("0x%" PRIx32"x", pc.instanceMethods)
4235 << " (struct method_list_t *)\n";
4236 if (pc.instanceMethods != 0)
4237 print_method_list32_t(pc.instanceMethods, info, "\t");
4238 outs() << "\t\t classMethods " << format("0x%" PRIx32"x", pc.classMethods)
4239 << " (struct method_list_t *)\n";
4240 if (pc.classMethods != 0)
4241 print_method_list32_t(pc.classMethods, info, "\t");
4242 outs() << "\t optionalInstanceMethods "
4243 << format("0x%" PRIx32"x", pc.optionalInstanceMethods) << "\n";
4244 outs() << "\t optionalClassMethods "
4245 << format("0x%" PRIx32"x", pc.optionalClassMethods) << "\n";
4246 outs() << "\t instanceProperties "
4247 << format("0x%" PRIx32"x", pc.instanceProperties) << "\n";
4248 p += sizeof(uint32_t);
4249 offset += sizeof(uint32_t);
4250 }
4251}
4252
4253static void print_indent(uint32_t indent) {
4254 for (uint32_t i = 0; i < indent;) {
4255 if (indent - i >= 8) {
4256 outs() << "\t";
4257 i += 8;
4258 } else {
4259 for (uint32_t j = i; j < indent; j++)
4260 outs() << " ";
4261 return;
4262 }
4263 }
4264}
4265
4266static bool print_method_description_list(uint32_t p, uint32_t indent,
4267 struct DisassembleInfo *info) {
4268 uint32_t offset, left, xleft;
4269 SectionRef S;
4270 struct objc_method_description_list_t mdl;
4271 struct objc_method_description_t md;
4272 const char *r, *list, *name;
4273 int32_t i;
4274
4275 r = get_pointer_32(p, offset, left, S, info, true);
4276 if (r == nullptr)
4277 return true;
4278
4279 outs() << "\n";
4280 if (left > sizeof(struct objc_method_description_list_t)) {
4281 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
4282 } else {
4283 print_indent(indent);
4284 outs() << " objc_method_description_list extends past end of the section\n";
4285 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
4286 memcpy(&mdl, r, left);
4287 }
4288 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4289 swapStruct(mdl);
4290
4291 print_indent(indent);
4292 outs() << " count " << mdl.count << "\n";
4293
4294 list = r + sizeof(struct objc_method_description_list_t);
4295 for (i = 0; i < mdl.count; i++) {
4296 if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
4297 print_indent(indent);
4298 outs() << " remaining list entries extend past the of the section\n";
4299 break;
4300 }
4301 print_indent(indent);
4302 outs() << " list[" << i << "]\n";
4303 memcpy(&md, list + i * sizeof(struct objc_method_description_t),
4304 sizeof(struct objc_method_description_t));
4305 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4306 swapStruct(md);
4307
4308 print_indent(indent);
4309 outs() << " name " << format("0x%08" PRIx32"x", md.name);
4310 if (info->verbose) {
4311 name = get_pointer_32(md.name, offset, xleft, S, info, true);
4312 if (name != nullptr)
4313 outs() << format(" %.*s", xleft, name);
4314 else
4315 outs() << " (not in an __OBJC section)";
4316 }
4317 outs() << "\n";
4318
4319 print_indent(indent);
4320 outs() << " types " << format("0x%08" PRIx32"x", md.types);
4321 if (info->verbose) {
4322 name = get_pointer_32(md.types, offset, xleft, S, info, true);
4323 if (name != nullptr)
4324 outs() << format(" %.*s", xleft, name);
4325 else
4326 outs() << " (not in an __OBJC section)";
4327 }
4328 outs() << "\n";
4329 }
4330 return false;
4331}
4332
4333static bool print_protocol_list(uint32_t p, uint32_t indent,
4334 struct DisassembleInfo *info);
4335
4336static bool print_protocol(uint32_t p, uint32_t indent,
4337 struct DisassembleInfo *info) {
4338 uint32_t offset, left;
4339 SectionRef S;
4340 struct objc_protocol_t protocol;
4341 const char *r, *name;
4342
4343 r = get_pointer_32(p, offset, left, S, info, true);
4344 if (r == nullptr)
4345 return true;
4346
4347 outs() << "\n";
4348 if (left >= sizeof(struct objc_protocol_t)) {
4349 memcpy(&protocol, r, sizeof(struct objc_protocol_t));
4350 } else {
4351 print_indent(indent);
4352 outs() << " Protocol extends past end of the section\n";
4353 memset(&protocol, '\0', sizeof(struct objc_protocol_t));
4354 memcpy(&protocol, r, left);
4355 }
4356 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4357 swapStruct(protocol);
4358
4359 print_indent(indent);
4360 outs() << " isa " << format("0x%08" PRIx32"x", protocol.isa)
4361 << "\n";
4362
4363 print_indent(indent);
4364 outs() << " protocol_name "
4365 << format("0x%08" PRIx32"x", protocol.protocol_name);
4366 if (info->verbose) {
4367 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
4368 if (name != nullptr)
4369 outs() << format(" %.*s", left, name);
4370 else
4371 outs() << " (not in an __OBJC section)";
4372 }
4373 outs() << "\n";
4374
4375 print_indent(indent);
4376 outs() << " protocol_list "
4377 << format("0x%08" PRIx32"x", protocol.protocol_list);
4378 if (print_protocol_list(protocol.protocol_list, indent + 4, info))
4379 outs() << " (not in an __OBJC section)\n";
4380
4381 print_indent(indent);
4382 outs() << " instance_methods "
4383 << format("0x%08" PRIx32"x", protocol.instance_methods);
4384 if (print_method_description_list(protocol.instance_methods, indent, info))
4385 outs() << " (not in an __OBJC section)\n";
4386
4387 print_indent(indent);
4388 outs() << " class_methods "
4389 << format("0x%08" PRIx32"x", protocol.class_methods);
4390 if (print_method_description_list(protocol.class_methods, indent, info))
4391 outs() << " (not in an __OBJC section)\n";
4392
4393 return false;
4394}
4395
4396static bool print_protocol_list(uint32_t p, uint32_t indent,
4397 struct DisassembleInfo *info) {
4398 uint32_t offset, left, l;
4399 SectionRef S;
4400 struct objc_protocol_list_t protocol_list;
4401 const char *r, *list;
4402 int32_t i;
4403
4404 r = get_pointer_32(p, offset, left, S, info, true);
4405 if (r == nullptr)
4406 return true;
4407
4408 outs() << "\n";
4409 if (left > sizeof(struct objc_protocol_list_t)) {
4410 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
4411 } else {
4412 outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
4413 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
4414 memcpy(&protocol_list, r, left);
4415 }
4416 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4417 swapStruct(protocol_list);
4418
4419 print_indent(indent);
4420 outs() << " next " << format("0x%08" PRIx32"x", protocol_list.next)
4421 << "\n";
4422 print_indent(indent);
4423 outs() << " count " << protocol_list.count << "\n";
4424
4425 list = r + sizeof(struct objc_protocol_list_t);
4426 for (i = 0; i < protocol_list.count; i++) {
4427 if ((i + 1) * sizeof(uint32_t) > left) {
4428 outs() << "\t\t remaining list entries extend past the of the section\n";
4429 break;
4430 }
4431 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
4432 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4433 sys::swapByteOrder(l);
4434
4435 print_indent(indent);
4436 outs() << " list[" << i << "] " << format("0x%08" PRIx32"x", l);
4437 if (print_protocol(l, indent, info))
4438 outs() << "(not in an __OBJC section)\n";
4439 }
4440 return false;
4441}
4442
4443static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
4444 struct ivar_list64_t il;
4445 struct ivar64_t i;
4446 const char *r;
4447 uint32_t offset, xoffset, left, j;
4448 SectionRef S, xS;
4449 const char *name, *sym_name, *ivar_offset_p;
4450 uint64_t ivar_offset, n_value;
4451
4452 r = get_pointer_64(p, offset, left, S, info);
4453 if (r == nullptr)
4454 return;
4455 memset(&il, '\0', sizeof(struct ivar_list64_t));
4456 if (left < sizeof(struct ivar_list64_t)) {
4457 memcpy(&il, r, left);
4458 outs() << " (ivar_list_t entends past the end of the section)\n";
4459 } else
4460 memcpy(&il, r, sizeof(struct ivar_list64_t));
4461 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4462 swapStruct(il);
4463 outs() << " entsize " << il.entsize << "\n";
4464 outs() << " count " << il.count << "\n";
4465
4466 p += sizeof(struct ivar_list64_t);
4467 offset += sizeof(struct ivar_list64_t);
4468 for (j = 0; j < il.count; j++) {
4469 r = get_pointer_64(p, offset, left, S, info);
4470 if (r == nullptr)
4471 return;
4472 memset(&i, '\0', sizeof(struct ivar64_t));
4473 if (left < sizeof(struct ivar64_t)) {
4474 memcpy(&i, r, left);
4475 outs() << " (ivar_t entends past the end of the section)\n";
4476 } else
4477 memcpy(&i, r, sizeof(struct ivar64_t));
4478 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4479 swapStruct(i);
4480
4481 outs() << "\t\t\t offset ";
4482 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset)__builtin_offsetof(struct ivar64_t, offset), S,
4483 info, n_value, i.offset);
4484 if (n_value != 0) {
4485 if (info->verbose && sym_name != nullptr)
4486 outs() << sym_name;
4487 else
4488 outs() << format("0x%" PRIx64"l" "x", n_value);
4489 if (i.offset != 0)
4490 outs() << " + " << format("0x%" PRIx64"l" "x", i.offset);
4491 } else
4492 outs() << format("0x%" PRIx64"l" "x", i.offset);
4493 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
4494 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4495 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4496 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4497 sys::swapByteOrder(ivar_offset);
4498 outs() << " " << ivar_offset << "\n";
4499 } else
4500 outs() << "\n";
4501
4502 outs() << "\t\t\t name ";
4503 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name)__builtin_offsetof(struct ivar64_t, name), S, info,
4504 n_value, i.name);
4505 if (n_value != 0) {
4506 if (info->verbose && sym_name != nullptr)
4507 outs() << sym_name;
4508 else
4509 outs() << format("0x%" PRIx64"l" "x", n_value);
4510 if (i.name != 0)
4511 outs() << " + " << format("0x%" PRIx64"l" "x", i.name);
4512 } else
4513 outs() << format("0x%" PRIx64"l" "x", i.name);
4514 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
4515 if (name != nullptr)
4516 outs() << format(" %.*s", left, name);
4517 outs() << "\n";
4518
4519 outs() << "\t\t\t type ";
4520 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type)__builtin_offsetof(struct ivar64_t, type), S, info,
4521 n_value, i.name);
4522 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
4523 if (n_value != 0) {
4524 if (info->verbose && sym_name != nullptr)
4525 outs() << sym_name;
4526 else
4527 outs() << format("0x%" PRIx64"l" "x", n_value);
4528 if (i.type != 0)
4529 outs() << " + " << format("0x%" PRIx64"l" "x", i.type);
4530 } else
4531 outs() << format("0x%" PRIx64"l" "x", i.type);
4532 if (name != nullptr)
4533 outs() << format(" %.*s", left, name);
4534 outs() << "\n";
4535
4536 outs() << "\t\t\talignment " << i.alignment << "\n";
4537 outs() << "\t\t\t size " << i.size << "\n";
4538
4539 p += sizeof(struct ivar64_t);
4540 offset += sizeof(struct ivar64_t);
4541 }
4542}
4543
4544static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
4545 struct ivar_list32_t il;
4546 struct ivar32_t i;
4547 const char *r;
4548 uint32_t offset, xoffset, left, j;
4549 SectionRef S, xS;
4550 const char *name, *ivar_offset_p;
4551 uint32_t ivar_offset;
4552
4553 r = get_pointer_32(p, offset, left, S, info);
4554 if (r == nullptr)
4555 return;
4556 memset(&il, '\0', sizeof(struct ivar_list32_t));
4557 if (left < sizeof(struct ivar_list32_t)) {
4558 memcpy(&il, r, left);
4559 outs() << " (ivar_list_t entends past the end of the section)\n";
4560 } else
4561 memcpy(&il, r, sizeof(struct ivar_list32_t));
4562 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4563 swapStruct(il);
4564 outs() << " entsize " << il.entsize << "\n";
4565 outs() << " count " << il.count << "\n";
4566
4567 p += sizeof(struct ivar_list32_t);
4568 offset += sizeof(struct ivar_list32_t);
4569 for (j = 0; j < il.count; j++) {
4570 r = get_pointer_32(p, offset, left, S, info);
4571 if (r == nullptr)
4572 return;
4573 memset(&i, '\0', sizeof(struct ivar32_t));
4574 if (left < sizeof(struct ivar32_t)) {
4575 memcpy(&i, r, left);
4576 outs() << " (ivar_t entends past the end of the section)\n";
4577 } else
4578 memcpy(&i, r, sizeof(struct ivar32_t));
4579 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4580 swapStruct(i);
4581
4582 outs() << "\t\t\t offset " << format("0x%" PRIx32"x", i.offset);
4583 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
4584 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4585 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4586 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4587 sys::swapByteOrder(ivar_offset);
4588 outs() << " " << ivar_offset << "\n";
4589 } else
4590 outs() << "\n";
4591
4592 outs() << "\t\t\t name " << format("0x%" PRIx32"x", i.name);
4593 name = get_pointer_32(i.name, xoffset, left, xS, info);
4594 if (name != nullptr)
4595 outs() << format(" %.*s", left, name);
4596 outs() << "\n";
4597
4598 outs() << "\t\t\t type " << format("0x%" PRIx32"x", i.type);
4599 name = get_pointer_32(i.type, xoffset, left, xS, info);
4600 if (name != nullptr)
4601 outs() << format(" %.*s", left, name);
4602 outs() << "\n";
4603
4604 outs() << "\t\t\talignment " << i.alignment << "\n";
4605 outs() << "\t\t\t size " << i.size << "\n";
4606
4607 p += sizeof(struct ivar32_t);
4608 offset += sizeof(struct ivar32_t);
4609 }
4610}
4611
4612static void print_objc_property_list64(uint64_t p,
4613 struct DisassembleInfo *info) {
4614 struct objc_property_list64 opl;
4615 struct objc_property64 op;
4616 const char *r;
4617 uint32_t offset, xoffset, left, j;
4618 SectionRef S, xS;
4619 const char *name, *sym_name;
4620 uint64_t n_value;
4621
4622 r = get_pointer_64(p, offset, left, S, info);
4623 if (r == nullptr)
4624 return;
4625 memset(&opl, '\0', sizeof(struct objc_property_list64));
4626 if (left < sizeof(struct objc_property_list64)) {
4627 memcpy(&opl, r, left);
4628 outs() << " (objc_property_list entends past the end of the section)\n";
4629 } else
4630 memcpy(&opl, r, sizeof(struct objc_property_list64));
4631 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4632 swapStruct(opl);
4633 outs() << " entsize " << opl.entsize << "\n";
4634 outs() << " count " << opl.count << "\n";
4635
4636 p += sizeof(struct objc_property_list64);
4637 offset += sizeof(struct objc_property_list64);
4638 for (j = 0; j < opl.count; j++) {
4639 r = get_pointer_64(p, offset, left, S, info);
4640 if (r == nullptr)
4641 return;
4642 memset(&op, '\0', sizeof(struct objc_property64));
4643 if (left < sizeof(struct objc_property64)) {
4644 memcpy(&op, r, left);
4645 outs() << " (objc_property entends past the end of the section)\n";
4646 } else
4647 memcpy(&op, r, sizeof(struct objc_property64));
4648 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4649 swapStruct(op);
4650
4651 outs() << "\t\t\t name ";
4652 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name)__builtin_offsetof(struct objc_property64, name), S,
4653 info, n_value, op.name);
4654 if (n_value != 0) {
4655 if (info->verbose && sym_name != nullptr)
4656 outs() << sym_name;
4657 else
4658 outs() << format("0x%" PRIx64"l" "x", n_value);
4659 if (op.name != 0)
4660 outs() << " + " << format("0x%" PRIx64"l" "x", op.name);
4661 } else
4662 outs() << format("0x%" PRIx64"l" "x", op.name);
4663 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
4664 if (name != nullptr)
4665 outs() << format(" %.*s", left, name);
4666 outs() << "\n";
4667
4668 outs() << "\t\t\tattributes ";
4669 sym_name =
4670 get_symbol_64(offset + offsetof(struct objc_property64, attributes)__builtin_offsetof(struct objc_property64, attributes), S,
4671 info, n_value, op.attributes);
4672 if (n_value != 0) {
4673 if (info->verbose && sym_name != nullptr)
4674 outs() << sym_name;
4675 else
4676 outs() << format("0x%" PRIx64"l" "x", n_value);
4677 if (op.attributes != 0)
4678 outs() << " + " << format("0x%" PRIx64"l" "x", op.attributes);
4679 } else
4680 outs() << format("0x%" PRIx64"l" "x", op.attributes);
4681 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
4682 if (name != nullptr)
4683 outs() << format(" %.*s", left, name);
4684 outs() << "\n";
4685
4686 p += sizeof(struct objc_property64);
4687 offset += sizeof(struct objc_property64);
4688 }
4689}
4690
4691static void print_objc_property_list32(uint32_t p,
4692 struct DisassembleInfo *info) {
4693 struct objc_property_list32 opl;
4694 struct objc_property32 op;
4695 const char *r;
4696 uint32_t offset, xoffset, left, j;
4697 SectionRef S, xS;
4698 const char *name;
4699
4700 r = get_pointer_32(p, offset, left, S, info);
4701 if (r == nullptr)
4702 return;
4703 memset(&opl, '\0', sizeof(struct objc_property_list32));
4704 if (left < sizeof(struct objc_property_list32)) {
4705 memcpy(&opl, r, left);
4706 outs() << " (objc_property_list entends past the end of the section)\n";
4707 } else
4708 memcpy(&opl, r, sizeof(struct objc_property_list32));
4709 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4710 swapStruct(opl);
4711 outs() << " entsize " << opl.entsize << "\n";
4712 outs() << " count " << opl.count << "\n";
4713
4714 p += sizeof(struct objc_property_list32);
4715 offset += sizeof(struct objc_property_list32);
4716 for (j = 0; j < opl.count; j++) {
4717 r = get_pointer_32(p, offset, left, S, info);
4718 if (r == nullptr)
4719 return;
4720 memset(&op, '\0', sizeof(struct objc_property32));
4721 if (left < sizeof(struct objc_property32)) {
4722 memcpy(&op, r, left);
4723 outs() << " (objc_property entends past the end of the section)\n";
4724 } else
4725 memcpy(&op, r, sizeof(struct objc_property32));
4726 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4727 swapStruct(op);
4728
4729 outs() << "\t\t\t name " << format("0x%" PRIx32"x", op.name);
4730 name = get_pointer_32(op.name, xoffset, left, xS, info);
4731 if (name != nullptr)
4732 outs() << format(" %.*s", left, name);
4733 outs() << "\n";
4734
4735 outs() << "\t\t\tattributes " << format("0x%" PRIx32"x", op.attributes);
4736 name = get_pointer_32(op.attributes, xoffset, left, xS, info);
4737 if (name != nullptr)
4738 outs() << format(" %.*s", left, name);
4739 outs() << "\n";
4740
4741 p += sizeof(struct objc_property32);
4742 offset += sizeof(struct objc_property32);
4743 }
4744}
4745
4746static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
4747 bool &is_meta_class) {
4748 struct class_ro64_t cro;
4749 const char *r;
4750 uint32_t offset, xoffset, left;
4751 SectionRef S, xS;
4752 const char *name, *sym_name;
4753 uint64_t n_value;
4754
4755 r = get_pointer_64(p, offset, left, S, info);
4756 if (r == nullptr || left < sizeof(struct class_ro64_t))
4757 return false;
4758 memcpy(&cro, r, sizeof(struct class_ro64_t));
4759 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4760 swapStruct(cro);
4761 outs() << " flags " << format("0x%" PRIx32"x", cro.flags);
4762 if (cro.flags & RO_META(1 << 0))
4763 outs() << " RO_META";
4764 if (cro.flags & RO_ROOT(1 << 1))
4765 outs() << " RO_ROOT";
4766 if (cro.flags & RO_HAS_CXX_STRUCTORS(1 << 2))
4767 outs() << " RO_HAS_CXX_STRUCTORS";
4768 outs() << "\n";
4769 outs() << " instanceStart " << cro.instanceStart << "\n";
4770 outs() << " instanceSize " << cro.instanceSize << "\n";
4771 outs() << " reserved " << format("0x%" PRIx32"x", cro.reserved)
4772 << "\n";
4773 outs() << " ivarLayout " << format("0x%" PRIx64"l" "x", cro.ivarLayout)
4774 << "\n";
4775 print_layout_map64(cro.ivarLayout, info);
4776
4777 outs() << " name ";
4778 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name)__builtin_offsetof(struct class_ro64_t, name), S,
4779 info, n_value, cro.name);
4780 if (n_value != 0) {
4781 if (info->verbose && sym_name != nullptr)
4782 outs() << sym_name;
4783 else
4784 outs() << format("0x%" PRIx64"l" "x", n_value);
4785 if (cro.name != 0)
4786 outs() << " + " << format("0x%" PRIx64"l" "x", cro.name);
4787 } else
4788 outs() << format("0x%" PRIx64"l" "x", cro.name);
4789 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
4790 if (name != nullptr)
4791 outs() << format(" %.*s", left, name);
4792 outs() << "\n";
4793
4794 outs() << " baseMethods ";
4795 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods)__builtin_offsetof(struct class_ro64_t, baseMethods),
4796 S, info, n_value, cro.baseMethods);
4797 if (n_value != 0) {
4798 if (info->verbose && sym_name != nullptr)
4799 outs() << sym_name;
4800 else
4801 outs() << format("0x%" PRIx64"l" "x", n_value);
4802 if (cro.baseMethods != 0)
4803 outs() << " + " << format("0x%" PRIx64"l" "x", cro.baseMethods);
4804 } else
4805 outs() << format("0x%" PRIx64"l" "x", cro.baseMethods);
4806 outs() << " (struct method_list_t *)\n";
4807 if (cro.baseMethods + n_value != 0)
4808 print_method_list64_t(cro.baseMethods + n_value, info, "");
4809
4810 outs() << " baseProtocols ";
4811 sym_name =
4812 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols)__builtin_offsetof(struct class_ro64_t, baseProtocols), S,
4813 info, n_value, cro.baseProtocols);
4814 if (n_value != 0) {
4815 if (info->verbose && sym_name != nullptr)
4816 outs() << sym_name;
4817 else
4818 outs() << format("0x%" PRIx64"l" "x", n_value);
4819 if (cro.baseProtocols != 0)
4820 outs() << " + " << format("0x%" PRIx64"l" "x", cro.baseProtocols);
4821 } else
4822 outs() << format("0x%" PRIx64"l" "x", cro.baseProtocols);
4823 outs() << "\n";
4824 if (cro.baseProtocols + n_value != 0)
4825 print_protocol_list64_t(cro.baseProtocols + n_value, info);
4826
4827 outs() << " ivars ";
4828 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars)__builtin_offsetof(struct class_ro64_t, ivars), S,
4829 info, n_value, cro.ivars);
4830 if (n_value != 0) {
4831 if (info->verbose && sym_name != nullptr)
4832 outs() << sym_name;
4833 else
4834 outs() << format("0x%" PRIx64"l" "x", n_value);
4835 if (cro.ivars != 0)
4836 outs() << " + " << format("0x%" PRIx64"l" "x", cro.ivars);
4837 } else
4838 outs() << format("0x%" PRIx64"l" "x", cro.ivars);
4839 outs() << "\n";
4840 if (cro.ivars + n_value != 0)
4841 print_ivar_list64_t(cro.ivars + n_value, info);
4842
4843 outs() << " weakIvarLayout ";
4844 sym_name =
4845 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout)__builtin_offsetof(struct class_ro64_t, weakIvarLayout), S,
4846 info, n_value, cro.weakIvarLayout);
4847 if (n_value != 0) {
4848 if (info->verbose && sym_name != nullptr)
4849 outs() << sym_name;
4850 else
4851 outs() << format("0x%" PRIx64"l" "x", n_value);
4852 if (cro.weakIvarLayout != 0)
4853 outs() << " + " << format("0x%" PRIx64"l" "x", cro.weakIvarLayout);
4854 } else
4855 outs() << format("0x%" PRIx64"l" "x", cro.weakIvarLayout);
4856 outs() << "\n";
4857 print_layout_map64(cro.weakIvarLayout + n_value, info);
4858
4859 outs() << " baseProperties ";
4860 sym_name =
4861 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties)__builtin_offsetof(struct class_ro64_t, baseProperties), S,
4862 info, n_value, cro.baseProperties);
4863 if (n_value != 0) {
4864 if (info->verbose && sym_name != nullptr)
4865 outs() << sym_name;
4866 else
4867 outs() << format("0x%" PRIx64"l" "x", n_value);
4868 if (cro.baseProperties != 0)
4869 outs() << " + " << format("0x%" PRIx64"l" "x", cro.baseProperties);
4870 } else
4871 outs() << format("0x%" PRIx64"l" "x", cro.baseProperties);
4872 outs() << "\n";
4873 if (cro.baseProperties + n_value != 0)
4874 print_objc_property_list64(cro.baseProperties + n_value, info);
4875
4876 is_meta_class = (cro.flags & RO_META(1 << 0)) != 0;
4877 return true;
4878}
4879
4880static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
4881 bool &is_meta_class) {
4882 struct class_ro32_t cro;
4883 const char *r;
4884 uint32_t offset, xoffset, left;
4885 SectionRef S, xS;
4886 const char *name;
4887
4888 r = get_pointer_32(p, offset, left, S, info);
4889 if (r == nullptr)
4890 return false;
4891 memset(&cro, '\0', sizeof(struct class_ro32_t));
4892 if (left < sizeof(struct class_ro32_t)) {
4893 memcpy(&cro, r, left);
4894 outs() << " (class_ro_t entends past the end of the section)\n";
4895 } else
4896 memcpy(&cro, r, sizeof(struct class_ro32_t));
4897 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4898 swapStruct(cro);
4899 outs() << " flags " << format("0x%" PRIx32"x", cro.flags);
4900 if (cro.flags & RO_META(1 << 0))
4901 outs() << " RO_META";
4902 if (cro.flags & RO_ROOT(1 << 1))
4903 outs() << " RO_ROOT";
4904 if (cro.flags & RO_HAS_CXX_STRUCTORS(1 << 2))
4905 outs() << " RO_HAS_CXX_STRUCTORS";
4906 outs() << "\n";
4907 outs() << " instanceStart " << cro.instanceStart << "\n";
4908 outs() << " instanceSize " << cro.instanceSize << "\n";
4909 outs() << " ivarLayout " << format("0x%" PRIx32"x", cro.ivarLayout)
4910 << "\n";
4911 print_layout_map32(cro.ivarLayout, info);
4912
4913 outs() << " name " << format("0x%" PRIx32"x", cro.name);
4914 name = get_pointer_32(cro.name, xoffset, left, xS, info);
4915 if (name != nullptr)
4916 outs() << format(" %.*s", left, name);
4917 outs() << "\n";
4918
4919 outs() << " baseMethods "
4920 << format("0x%" PRIx32"x", cro.baseMethods)
4921 << " (struct method_list_t *)\n";
4922 if (cro.baseMethods != 0)
4923 print_method_list32_t(cro.baseMethods, info, "");
4924
4925 outs() << " baseProtocols "
4926 << format("0x%" PRIx32"x", cro.baseProtocols) << "\n";
4927 if (cro.baseProtocols != 0)
4928 print_protocol_list32_t(cro.baseProtocols, info);
4929 outs() << " ivars " << format("0x%" PRIx32"x", cro.ivars)
4930 << "\n";
4931 if (cro.ivars != 0)
4932 print_ivar_list32_t(cro.ivars, info);
4933 outs() << " weakIvarLayout "
4934 << format("0x%" PRIx32"x", cro.weakIvarLayout) << "\n";
4935 print_layout_map32(cro.weakIvarLayout, info);
4936 outs() << " baseProperties "
4937 << format("0x%" PRIx32"x", cro.baseProperties) << "\n";
4938 if (cro.baseProperties != 0)
4939 print_objc_property_list32(cro.baseProperties, info);
4940 is_meta_class = (cro.flags & RO_META(1 << 0)) != 0;
4941 return true;
4942}
4943
4944static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
4945 struct class64_t c;
4946 const char *r;
4947 uint32_t offset, left;
4948 SectionRef S;
4949 const char *name;
4950 uint64_t isa_n_value, n_value;
4951
4952 r = get_pointer_64(p, offset, left, S, info);
4953 if (r == nullptr || left < sizeof(struct class64_t))
4954 return;
4955 memcpy(&c, r, sizeof(struct class64_t));
4956 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4957 swapStruct(c);
4958
4959 outs() << " isa " << format("0x%" PRIx64"l" "x", c.isa);
4960 name = get_symbol_64(offset + offsetof(struct class64_t, isa)__builtin_offsetof(struct class64_t, isa), S, info,
4961 isa_n_value, c.isa);
4962 if (name != nullptr)
4963 outs() << " " << name;
4964 outs() << "\n";
4965
4966 outs() << " superclass " << format("0x%" PRIx64"l" "x", c.superclass);
4967 name = get_symbol_64(offset + offsetof(struct class64_t, superclass)__builtin_offsetof(struct class64_t, superclass), S, info,
4968 n_value, c.superclass);
4969 if (name != nullptr)
4970 outs() << " " << name;
4971 else {
4972 name = get_dyld_bind_info_symbolname(S.getAddress() +
4973 offset + offsetof(struct class64_t, superclass)__builtin_offsetof(struct class64_t, superclass), info);
4974 if (name != nullptr)
4975 outs() << " " << name;
4976 }
4977 outs() << "\n";
4978
4979 outs() << " cache " << format("0x%" PRIx64"l" "x", c.cache);
4980 name = get_symbol_64(offset + offsetof(struct class64_t, cache)__builtin_offsetof(struct class64_t, cache), S, info,
4981 n_value, c.cache);
4982 if (name != nullptr)
4983 outs() << " " << name;
4984 outs() << "\n";
4985
4986 outs() << " vtable " << format("0x%" PRIx64"l" "x", c.vtable);
4987 name = get_symbol_64(offset + offsetof(struct class64_t, vtable)__builtin_offsetof(struct class64_t, vtable), S, info,
4988 n_value, c.vtable);
4989 if (name != nullptr)
4990 outs() << " " << name;
4991 outs() << "\n";
4992
4993 name = get_symbol_64(offset + offsetof(struct class64_t, data)__builtin_offsetof(struct class64_t, data), S, info,
4994 n_value, c.data);
4995 outs() << " data ";
4996 if (n_value != 0) {
4997 if (info->verbose && name != nullptr)
4998 outs() << name;
4999 else
5000 outs() << format("0x%" PRIx64"l" "x", n_value);
5001 if (c.data != 0)
5002 outs() << " + " << format("0x%" PRIx64"l" "x", c.data);
5003 } else
5004 outs() << format("0x%" PRIx64"l" "x", c.data);
5005 outs() << " (struct class_ro_t *)";
5006
5007 // This is a Swift class if some of the low bits of the pointer are set.
5008 if ((c.data + n_value) & 0x7)
5009 outs() << " Swift class";
5010 outs() << "\n";
5011 bool is_meta_class;
5012 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5013 return;
5014
5015 if (!is_meta_class &&
5016 c.isa + isa_n_value != p &&
5017 c.isa + isa_n_value != 0 &&
5018 info->depth < 100) {
5019 info->depth++;
5020 outs() << "Meta Class\n";
5021 print_class64_t(c.isa + isa_n_value, info);
5022 }
5023}
5024
5025static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5026 struct class32_t c;
5027 const char *r;
5028 uint32_t offset, left;
5029 SectionRef S;
5030 const char *name;
5031
5032 r = get_pointer_32(p, offset, left, S, info);
5033 if (r == nullptr)
5034 return;
5035 memset(&c, '\0', sizeof(struct class32_t));
5036 if (left < sizeof(struct class32_t)) {
5037 memcpy(&c, r, left);
5038 outs() << " (class_t entends past the end of the section)\n";
5039 } else
5040 memcpy(&c, r, sizeof(struct class32_t));
5041 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5042 swapStruct(c);
5043
5044 outs() << " isa " << format("0x%" PRIx32"x", c.isa);
5045 name =
5046 get_symbol_32(offset + offsetof(struct class32_t, isa)__builtin_offsetof(struct class32_t, isa), S, info, c.isa);
5047 if (name != nullptr)
5048 outs() << " " << name;
5049 outs() << "\n";
5050
5051 outs() << " superclass " << format("0x%" PRIx32"x", c.superclass);
5052 name = get_symbol_32(offset + offsetof(struct class32_t, superclass)__builtin_offsetof(struct class32_t, superclass), S, info,
5053 c.superclass);
5054 if (name != nullptr)
5055 outs() << " " << name;
5056 outs() << "\n";
5057
5058 outs() << " cache " << format("0x%" PRIx32"x", c.cache);
5059 name = get_symbol_32(offset + offsetof(struct class32_t, cache)__builtin_offsetof(struct class32_t, cache), S, info,
5060 c.cache);
5061 if (name != nullptr)
5062 outs() << " " << name;
5063 outs() << "\n";
5064
5065 outs() << " vtable " << format("0x%" PRIx32"x", c.vtable);
5066 name = get_symbol_32(offset + offsetof(struct class32_t, vtable)__builtin_offsetof(struct class32_t, vtable), S, info,
5067 c.vtable);
5068 if (name != nullptr)
5069 outs() << " " << name;
5070 outs() << "\n";
5071
5072 name =
5073 get_symbol_32(offset + offsetof(struct class32_t, data)__builtin_offsetof(struct class32_t, data), S, info, c.data);
5074 outs() << " data " << format("0x%" PRIx32"x", c.data)
5075 << " (struct class_ro_t *)";
5076
5077 // This is a Swift class if some of the low bits of the pointer are set.
5078 if (c.data & 0x3)
5079 outs() << " Swift class";
5080 outs() << "\n";
5081 bool is_meta_class;
5082 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5083 return;
5084
5085 if (!is_meta_class) {
5086 outs() << "Meta Class\n";
5087 print_class32_t(c.isa, info);
5088 }
5089}
5090
5091static void print_objc_class_t(struct objc_class_t *objc_class,
5092 struct DisassembleInfo *info) {
5093 uint32_t offset, left, xleft;
5094 const char *name, *p, *ivar_list;
5095 SectionRef S;
5096 int32_t i;
5097 struct objc_ivar_list_t objc_ivar_list;
5098 struct objc_ivar_t ivar;
5099
5100 outs() << "\t\t isa " << format("0x%08" PRIx32"x", objc_class->isa);
5101 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)((objc_class)->info & (0x2))) {
5102 name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5103 if (name != nullptr)
5104 outs() << format(" %.*s", left, name);
5105 else
5106 outs() << " (not in an __OBJC section)";
5107 }
5108 outs() << "\n";
5109
5110 outs() << "\t super_class "
5111 << format("0x%08" PRIx32"x", objc_class->super_class);
5112 if (info->verbose) {
5113 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5114 if (name != nullptr)
5115 outs() << format(" %.*s", left, name);
5116 else
5117 outs() << " (not in an __OBJC section)";
5118 }
5119 outs() << "\n";
5120
5121 outs() << "\t\t name " << format("0x%08" PRIx32"x", objc_class->name);
5122 if (info->verbose) {
5123 name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5124 if (name != nullptr)
5125 outs() << format(" %.*s", left, name);
5126 else
5127 outs() << " (not in an __OBJC section)";
5128 }
5129 outs() << "\n";
5130
5131 outs() << "\t\t version " << format("0x%08" PRIx32"x", objc_class->version)
5132 << "\n";
5133
5134 outs() << "\t\t info " << format("0x%08" PRIx32"x", objc_class->info);
5135 if (info->verbose) {
5136 if (CLS_GETINFO(objc_class, CLS_CLASS)((objc_class)->info & (0x1)))
5137 outs() << " CLS_CLASS";
5138 else if (CLS_GETINFO(objc_class, CLS_META)((objc_class)->info & (0x2)))
5139 outs() << " CLS_META";
5140 }
5141 outs() << "\n";
5142
5143 outs() << "\t instance_size "
5144 << format("0x%08" PRIx32"x", objc_class->instance_size) << "\n";
5145
5146 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5147 outs() << "\t\t ivars " << format("0x%08" PRIx32"x", objc_class->ivars);
5148 if (p != nullptr) {
5149 if (left > sizeof(struct objc_ivar_list_t)) {
5150 outs() << "\n";
5151 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5152 } else {
5153 outs() << " (entends past the end of the section)\n";
5154 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5155 memcpy(&objc_ivar_list, p, left);
5156 }
5157 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5158 swapStruct(objc_ivar_list);
5159 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n";
5160 ivar_list = p + sizeof(struct objc_ivar_list_t);
5161 for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5162 if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5163 outs() << "\t\t remaining ivar's extend past the of the section\n";
5164 break;
5165 }
5166 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5167 sizeof(struct objc_ivar_t));
5168 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5169 swapStruct(ivar);
5170
5171 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32"x", ivar.ivar_name);
5172 if (info->verbose) {
5173 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5174 if (name != nullptr)
5175 outs() << format(" %.*s", xleft, name);
5176 else
5177 outs() << " (not in an __OBJC section)";
5178 }
5179 outs() << "\n";
5180
5181 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32"x", ivar.ivar_type);
5182 if (info->verbose) {
5183 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5184 if (name != nullptr)
5185 outs() << format(" %.*s", xleft, name);
5186 else
5187 outs() << " (not in an __OBJC section)";
5188 }
5189 outs() << "\n";
5190
5191 outs() << "\t\t ivar_offset "
5192 << format("0x%08" PRIx32"x", ivar.ivar_offset) << "\n";
5193 }
5194 } else {
5195 outs() << " (not in an __OBJC section)\n";
5196 }
5197
5198 outs() << "\t\t methods " << format("0x%08" PRIx32"x", objc_class->methodLists);
5199 if (print_method_list(objc_class->methodLists, info))
5200 outs() << " (not in an __OBJC section)\n";
5201
5202 outs() << "\t\t cache " << format("0x%08" PRIx32"x", objc_class->cache)
5203 << "\n";
5204
5205 outs() << "\t\tprotocols " << format("0x%08" PRIx32"x", objc_class->protocols);
5206 if (print_protocol_list(objc_class->protocols, 16, info))
5207 outs() << " (not in an __OBJC section)\n";
5208}
5209
5210static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5211 struct DisassembleInfo *info) {
5212 uint32_t offset, left;
5213 const char *name;
5214 SectionRef S;
5215
5216 outs() << "\t category name "
5217 << format("0x%08" PRIx32"x", objc_category->category_name);
5218 if (info->verbose) {
5219 name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5220 true);
5221 if (name != nullptr)
5222 outs() << format(" %.*s", left, name);
5223 else
5224 outs() << " (not in an __OBJC section)";
5225 }
5226 outs() << "\n";
5227
5228 outs() << "\t\t class name "
5229 << format("0x%08" PRIx32"x", objc_category->class_name);
5230 if (info->verbose) {
5231 name =
5232 get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5233 if (name != nullptr)
5234 outs() << format(" %.*s", left, name);
5235 else
5236 outs() << " (not in an __OBJC section)";
5237 }
5238 outs() << "\n";
5239
5240 outs() << "\t instance methods "
5241 << format("0x%08" PRIx32"x", objc_category->instance_methods);
5242 if (print_method_list(objc_category->instance_methods, info))
5243 outs() << " (not in an __OBJC section)\n";
5244
5245 outs() << "\t class methods "
5246 << format("0x%08" PRIx32"x", objc_category->class_methods);
5247 if (print_method_list(objc_category->class_methods, info))
5248 outs() << " (not in an __OBJC section)\n";
5249}
5250
5251static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5252 struct category64_t c;
5253 const char *r;
5254 uint32_t offset, xoffset, left;
5255 SectionRef S, xS;
5256 const char *name, *sym_name;
5257 uint64_t n_value;
5258
5259 r = get_pointer_64(p, offset, left, S, info);
5260 if (r == nullptr)
5261 return;
5262 memset(&c, '\0', sizeof(struct category64_t));
5263 if (left < sizeof(struct category64_t)) {
5264 memcpy(&c, r, left);
5265 outs() << " (category_t entends past the end of the section)\n";
5266 } else
5267 memcpy(&c, r, sizeof(struct category64_t));
5268 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5269 swapStruct(c);
5270
5271 outs() << " name ";
5272 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name)__builtin_offsetof(struct category64_t, name), S,
5273 info, n_value, c.name);
5274 if (n_value != 0) {
5275 if (info->verbose && sym_name != nullptr)
5276 outs() << sym_name;
5277 else
5278 outs() << format("0x%" PRIx64"l" "x", n_value);
5279 if (c.name != 0)
5280 outs() << " + " << format("0x%" PRIx64"l" "x", c.name);
5281 } else
5282 outs() << format("0x%" PRIx64"l" "x", c.name);
5283 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
5284 if (name != nullptr)
5285 outs() << format(" %.*s", left, name);
5286 outs() << "\n";
5287
5288 outs() << " cls ";
5289 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls)__builtin_offsetof(struct category64_t, cls), S, info,
5290 n_value, c.cls);
5291 if (n_value != 0) {
5292 if (info->verbose && sym_name != nullptr)
5293 outs() << sym_name;
5294 else
5295 outs() << format("0x%" PRIx64"l" "x", n_value);
5296 if (c.cls != 0)
5297 outs() << " + " << format("0x%" PRIx64"l" "x", c.cls);
5298 } else
5299 outs() << format("0x%" PRIx64"l" "x", c.cls);
5300 outs() << "\n";
5301 if (c.cls + n_value != 0)
5302 print_class64_t(c.cls + n_value, info);
5303
5304 outs() << " instanceMethods ";
5305 sym_name =
5306 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods)__builtin_offsetof(struct category64_t, instanceMethods), S,
5307 info, n_value, c.instanceMethods);
5308 if (n_value != 0) {
5309 if (info->verbose && sym_name != nullptr)
5310 outs() << sym_name;
5311 else
5312 outs() << format("0x%" PRIx64"l" "x", n_value);
5313 if (c.instanceMethods != 0)
5314 outs() << " + " << format("0x%" PRIx64"l" "x", c.instanceMethods);
5315 } else
5316 outs() << format("0x%" PRIx64"l" "x", c.instanceMethods);
5317 outs() << "\n";
5318 if (c.instanceMethods + n_value != 0)
5319 print_method_list64_t(c.instanceMethods + n_value, info, "");
5320
5321 outs() << " classMethods ";
5322 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods)__builtin_offsetof(struct category64_t, classMethods),
5323 S, info, n_value, c.classMethods);
5324 if (n_value != 0) {
5325 if (info->verbose && sym_name != nullptr)
5326 outs() << sym_name;
5327 else
5328 outs() << format("0x%" PRIx64"l" "x", n_value);
5329 if (c.classMethods != 0)
5330 outs() << " + " << format("0x%" PRIx64"l" "x", c.classMethods);
5331 } else
5332 outs() << format("0x%" PRIx64"l" "x", c.classMethods);
5333 outs() << "\n";
5334 if (c.classMethods + n_value != 0)
5335 print_method_list64_t(c.classMethods + n_value, info, "");
5336
5337 outs() << " protocols ";
5338 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols)__builtin_offsetof(struct category64_t, protocols), S,
5339 info, n_value, c.protocols);
5340 if (n_value != 0) {
5341 if (info->verbose && sym_name != nullptr)
5342 outs() << sym_name;
5343 else
5344 outs() << format("0x%" PRIx64"l" "x", n_value);
5345 if (c.protocols != 0)
5346 outs() << " + " << format("0x%" PRIx64"l" "x", c.protocols);
5347 } else
5348 outs() << format("0x%" PRIx64"l" "x", c.protocols);
5349 outs() << "\n";
5350 if (c.protocols + n_value != 0)
5351 print_protocol_list64_t(c.protocols + n_value, info);
5352
5353 outs() << "instanceProperties ";
5354 sym_name =
5355 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties)__builtin_offsetof(struct category64_t, instanceProperties),
5356 S, info, n_value, c.instanceProperties);
5357 if (n_value != 0) {
5358 if (info->verbose && sym_name != nullptr)
5359 outs() << sym_name;
5360 else
5361 outs() << format("0x%" PRIx64"l" "x", n_value);
5362 if (c.instanceProperties != 0)
5363 outs() << " + " << format("0x%" PRIx64"l" "x", c.instanceProperties);
5364 } else
5365 outs() << format("0x%" PRIx64"l" "x", c.instanceProperties);
5366 outs() << "\n";
5367 if (c.instanceProperties + n_value != 0)
5368 print_objc_property_list64(c.instanceProperties + n_value, info);
5369}
5370
5371static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
5372 struct category32_t c;
5373 const char *r;
5374 uint32_t offset, left;
5375 SectionRef S, xS;
5376 const char *name;
5377
5378 r = get_pointer_32(p, offset, left, S, info);
5379 if (r == nullptr)
5380 return;
5381 memset(&c, '\0', sizeof(struct category32_t));
5382 if (left < sizeof(struct category32_t)) {
5383 memcpy(&c, r, left);
5384 outs() << " (category_t entends past the end of the section)\n";
5385 } else
5386 memcpy(&c, r, sizeof(struct category32_t));
5387 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5388 swapStruct(c);
5389
5390 outs() << " name " << format("0x%" PRIx32"x", c.name);
5391 name = get_symbol_32(offset + offsetof(struct category32_t, name)__builtin_offsetof(struct category32_t, name), S, info,
5392 c.name);
5393 if (name)
5394 outs() << " " << name;
5395 outs() << "\n";
5396
5397 outs() << " cls " << format("0x%" PRIx32"x", c.cls) << "\n";
5398 if (c.cls != 0)
5399 print_class32_t(c.cls, info);
5400 outs() << " instanceMethods " << format("0x%" PRIx32"x", c.instanceMethods)
5401 << "\n";
5402 if (c.instanceMethods != 0)
5403 print_method_list32_t(c.instanceMethods, info, "");
5404 outs() << " classMethods " << format("0x%" PRIx32"x", c.classMethods)
5405 << "\n";
5406 if (c.classMethods != 0)
5407 print_method_list32_t(c.classMethods, info, "");
5408 outs() << " protocols " << format("0x%" PRIx32"x", c.protocols) << "\n";
5409 if (c.protocols != 0)
5410 print_protocol_list32_t(c.protocols, info);
5411 outs() << "instanceProperties " << format("0x%" PRIx32"x", c.instanceProperties)
5412 << "\n";
5413 if (c.instanceProperties != 0)
5414 print_objc_property_list32(c.instanceProperties, info);
5415}
5416
5417static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
5418 uint32_t i, left, offset, xoffset;
5419 uint64_t p, n_value;
5420 struct message_ref64 mr;
5421 const char *name, *sym_name;
5422 const char *r;
5423 SectionRef xS;
5424
5425 if (S == SectionRef())
5426 return;
5427
5428 StringRef SectName;
5429 S.getName(SectName);
5430 DataRefImpl Ref = S.getRawDataRefImpl();
5431 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5432 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5433 offset = 0;
5434 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5435 p = S.getAddress() + i;
5436 r = get_pointer_64(p, offset, left, S, info);
5437 if (r == nullptr)
5438 return;
5439 memset(&mr, '\0', sizeof(struct message_ref64));
5440 if (left < sizeof(struct message_ref64)) {
5441 memcpy(&mr, r, left);
5442 outs() << " (message_ref entends past the end of the section)\n";
5443 } else
5444 memcpy(&mr, r, sizeof(struct message_ref64));
5445 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5446 swapStruct(mr);
5447
5448 outs() << " imp ";
5449 name = get_symbol_64(offset + offsetof(struct message_ref64, imp)__builtin_offsetof(struct message_ref64, imp), S, info,
5450 n_value, mr.imp);
5451 if (n_value != 0) {
5452 outs() << format("0x%" PRIx64"l" "x", n_value) << " ";
5453 if (mr.imp != 0)
5454 outs() << "+ " << format("0x%" PRIx64"l" "x", mr.imp) << " ";
5455 } else
5456 outs() << format("0x%" PRIx64"l" "x", mr.imp) << " ";
5457 if (name != nullptr)
5458 outs() << " " << name;
5459 outs() << "\n";
5460
5461 outs() << " sel ";
5462 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel)__builtin_offsetof(struct message_ref64, sel), S,
5463 info, n_value, mr.sel);
5464 if (n_value != 0) {
5465 if (info->verbose && sym_name != nullptr)
5466 outs() << sym_name;
5467 else
5468 outs() << format("0x%" PRIx64"l" "x", n_value);
5469 if (mr.sel != 0)
5470 outs() << " + " << format("0x%" PRIx64"l" "x", mr.sel);
5471 } else
5472 outs() << format("0x%" PRIx64"l" "x", mr.sel);
5473 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
5474 if (name != nullptr)
5475 outs() << format(" %.*s", left, name);
5476 outs() << "\n";
5477
5478 offset += sizeof(struct message_ref64);
5479 }
5480}
5481
5482static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
5483 uint32_t i, left, offset, xoffset, p;
5484 struct message_ref32 mr;
5485 const char *name, *r;
5486 SectionRef xS;
5487
5488 if (S == SectionRef())
5489 return;
5490
5491 StringRef SectName;
5492 S.getName(SectName);
5493 DataRefImpl Ref = S.getRawDataRefImpl();
5494 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5495 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5496 offset = 0;
5497 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5498 p = S.getAddress() + i;
5499 r = get_pointer_32(p, offset, left, S, info);
5500 if (r == nullptr)
5501 return;
5502 memset(&mr, '\0', sizeof(struct message_ref32));
5503 if (left < sizeof(struct message_ref32)) {
5504 memcpy(&mr, r, left);
5505 outs() << " (message_ref entends past the end of the section)\n";
5506 } else
5507 memcpy(&mr, r, sizeof(struct message_ref32));
5508 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5509 swapStruct(mr);
5510
5511 outs() << " imp " << format("0x%" PRIx32"x", mr.imp);
5512 name = get_symbol_32(offset + offsetof(struct message_ref32, imp)__builtin_offsetof(struct message_ref32, imp), S, info,
5513 mr.imp);
5514 if (name != nullptr)
5515 outs() << " " << name;
5516 outs() << "\n";
5517
5518 outs() << " sel " << format("0x%" PRIx32"x", mr.sel);
5519 name = get_pointer_32(mr.sel, xoffset, left, xS, info);
5520 if (name != nullptr)
5521 outs() << " " << name;
5522 outs() << "\n";
5523
5524 offset += sizeof(struct message_ref32);
5525 }
5526}
5527
5528static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
5529 uint32_t left, offset, swift_version;
5530 uint64_t p;
5531 struct objc_image_info64 o;
5532 const char *r;
5533
5534 if (S == SectionRef())
5535 return;
5536
5537 StringRef SectName;
5538 S.getName(SectName);
5539 DataRefImpl Ref = S.getRawDataRefImpl();
5540 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5541 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5542 p = S.getAddress();
5543 r = get_pointer_64(p, offset, left, S, info);
5544 if (r == nullptr)
5545 return;
5546 memset(&o, '\0', sizeof(struct objc_image_info64));
5547 if (left < sizeof(struct objc_image_info64)) {
5548 memcpy(&o, r, left);
5549 outs() << " (objc_image_info entends past the end of the section)\n";
5550 } else
5551 memcpy(&o, r, sizeof(struct objc_image_info64));
5552 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5553 swapStruct(o);
5554 outs() << " version " << o.version << "\n";
5555 outs() << " flags " << format("0x%" PRIx32"x", o.flags);
5556 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT(1 << 0))
5557 outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5558 if (o.flags & OBJC_IMAGE_SUPPORTS_GC(1 << 1))
5559 outs() << " OBJC_IMAGE_SUPPORTS_GC";
5560 swift_version = (o.flags >> 8) & 0xff;
5561 if (swift_version != 0) {
5562 if (swift_version == 1)
5563 outs() << " Swift 1.0";
5564 else if (swift_version == 2)
5565 outs() << " Swift 1.1";
5566 else
5567 outs() << " unknown future Swift version (" << swift_version << ")";
5568 }
5569 outs() << "\n";
5570}
5571
5572static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
5573 uint32_t left, offset, swift_version, p;
5574 struct objc_image_info32 o;
5575 const char *r;
5576
5577 if (S == SectionRef())
5578 return;
5579
5580 StringRef SectName;
5581 S.getName(SectName);
5582 DataRefImpl Ref = S.getRawDataRefImpl();
5583 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5584 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5585 p = S.getAddress();
5586 r = get_pointer_32(p, offset, left, S, info);
5587 if (r == nullptr)
5588 return;
5589 memset(&o, '\0', sizeof(struct objc_image_info32));
5590 if (left < sizeof(struct objc_image_info32)) {
5591 memcpy(&o, r, left);
5592 outs() << " (objc_image_info entends past the end of the section)\n";
5593 } else
5594 memcpy(&o, r, sizeof(struct objc_image_info32));
5595 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5596 swapStruct(o);
5597 outs() << " version " << o.version << "\n";
5598 outs() << " flags " << format("0x%" PRIx32"x", o.flags);
5599 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT(1 << 0))
5600 outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5601 if (o.flags & OBJC_IMAGE_SUPPORTS_GC(1 << 1))
5602 outs() << " OBJC_IMAGE_SUPPORTS_GC";
5603 swift_version = (o.flags >> 8) & 0xff;
5604 if (swift_version != 0) {
5605 if (swift_version == 1)
5606 outs() << " Swift 1.0";
5607 else if (swift_version == 2)
5608 outs() << " Swift 1.1";
5609 else
5610 outs() << " unknown future Swift version (" << swift_version << ")";
5611 }
5612 outs() << "\n";
5613}
5614
5615static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
5616 uint32_t left, offset, p;
5617 struct imageInfo_t o;
5618 const char *r;
5619
5620 StringRef SectName;
5621 S.getName(SectName);
5622 DataRefImpl Ref = S.getRawDataRefImpl();
5623 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5624 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5625 p = S.getAddress();
5626 r = get_pointer_32(p, offset, left, S, info);
5627 if (r == nullptr)
5628 return;
5629 memset(&o, '\0', sizeof(struct imageInfo_t));
5630 if (left < sizeof(struct imageInfo_t)) {
5631 memcpy(&o, r, left);
5632 outs() << " (imageInfo entends past the end of the section)\n";
5633 } else
5634 memcpy(&o, r, sizeof(struct imageInfo_t));
5635 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5636 swapStruct(o);
5637 outs() << " version " << o.version << "\n";
5638 outs() << " flags " << format("0x%" PRIx32"x", o.flags);
5639 if (o.flags & 0x1)
5640 outs() << " F&C";
5641 if (o.flags & 0x2)
5642 outs() << " GC";
5643 if (o.flags & 0x4)
5644 outs() << " GC-only";
5645 else
5646 outs() << " RR";
5647 outs() << "\n";
5648}
5649
5650static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
5651 SymbolAddressMap AddrMap;
5652 if (verbose)
5653 CreateSymbolAddressMap(O, &AddrMap);
5654
5655 std::vector<SectionRef> Sections;
5656 for (const SectionRef &Section : O->sections()) {
5657 StringRef SectName;
5658 Section.getName(SectName);
5659 Sections.push_back(Section);
5660 }
5661
5662 struct DisassembleInfo info;
5663 // Set up the block of info used by the Symbolizer call backs.
5664 info.verbose = verbose;
5665 info.O = O;
5666 info.AddrMap = &AddrMap;
5667 info.Sections = &Sections;
5668 info.class_name = nullptr;
5669 info.selector_name = nullptr;
5670 info.method = nullptr;
5671 info.demangled_name = nullptr;
5672 info.bindtable = nullptr;
5673 info.adrp_addr = 0;
5674 info.adrp_inst = 0;
5675
5676 info.depth = 0;
5677 SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5678 if (CL == SectionRef())
5679 CL = get_section(O, "__DATA", "__objc_classlist");
5680 if (CL == SectionRef())
5681 CL = get_section(O, "__DATA_CONST", "__objc_classlist");
5682 if (CL == SectionRef())
5683 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
5684 info.S = CL;
5685 walk_pointer_list_64("class", CL, O, &info, print_class64_t);
5686
5687 SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5688 if (CR == SectionRef())
5689 CR = get_section(O, "__DATA", "__objc_classrefs");
5690 if (CR == SectionRef())
5691 CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
5692 if (CR == SectionRef())
5693 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
5694 info.S = CR;
5695 walk_pointer_list_64("class refs", CR, O, &info, nullptr);
5696
5697 SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5698 if (SR == SectionRef())
5699 SR = get_section(O, "__DATA", "__objc_superrefs");
5700 if (SR == SectionRef())
5701 SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
5702 if (SR == SectionRef())
5703 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
5704 info.S = SR;
5705 walk_pointer_list_64("super refs", SR, O, &info, nullptr);
5706
5707 SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5708 if (CA == SectionRef())
5709 CA = get_section(O, "__DATA", "__objc_catlist");
5710 if (CA == SectionRef())
5711 CA = get_section(O, "__DATA_CONST", "__objc_catlist");
5712 if (CA == SectionRef())
5713 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
5714 info.S = CA;
5715 walk_pointer_list_64("category", CA, O, &info, print_category64_t);
5716
5717 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5718 if (PL == SectionRef())
5719 PL = get_section(O, "__DATA", "__objc_protolist");
5720 if (PL == SectionRef())
5721 PL = get_section(O, "__DATA_CONST", "__objc_protolist");
5722 if (PL == SectionRef())
5723 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
5724 info.S = PL;
5725 walk_pointer_list_64("protocol", PL, O, &info, nullptr);
5726
5727 SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5728 if (MR == SectionRef())
5729 MR = get_section(O, "__DATA", "__objc_msgrefs");
5730 if (MR == SectionRef())
5731 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
5732 if (MR == SectionRef())
5733 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
5734 info.S = MR;
5735 print_message_refs64(MR, &info);
5736
5737 SectionRef II = get_section(O, "__OBJC2", "__image_info");
5738 if (II == SectionRef())
5739 II = get_section(O, "__DATA", "__objc_imageinfo");
5740 if (II == SectionRef())
5741 II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
5742 if (II == SectionRef())
5743 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
5744 info.S = II;
5745 print_image_info64(II, &info);
5746}
5747
5748static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5749 SymbolAddressMap AddrMap;
5750 if (verbose)
5751 CreateSymbolAddressMap(O, &AddrMap);
5752
5753 std::vector<SectionRef> Sections;
5754 for (const SectionRef &Section : O->sections()) {
5755 StringRef SectName;
5756 Section.getName(SectName);
5757 Sections.push_back(Section);
5758 }
5759
5760 struct DisassembleInfo info;
5761 // Set up the block of info used by the Symbolizer call backs.
5762 info.verbose = verbose;
5763 info.O = O;
5764 info.AddrMap = &AddrMap;
5765 info.Sections = &Sections;
5766 info.class_name = nullptr;
5767 info.selector_name = nullptr;
5768 info.method = nullptr;
5769 info.demangled_name = nullptr;
5770 info.bindtable = nullptr;
5771 info.adrp_addr = 0;
5772 info.adrp_inst = 0;
5773
5774 SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5775 if (CL == SectionRef())
5776 CL = get_section(O, "__DATA", "__objc_classlist");
5777 if (CL == SectionRef())
5778 CL = get_section(O, "__DATA_CONST", "__objc_classlist");
5779 if (CL == SectionRef())
5780 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
5781 info.S = CL;
5782 walk_pointer_list_32("class", CL, O, &info, print_class32_t);
5783
5784 SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5785 if (CR == SectionRef())
5786 CR = get_section(O, "__DATA", "__objc_classrefs");
5787 if (CR == SectionRef())
5788 CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
5789 if (CR == SectionRef())
5790 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
5791 info.S = CR;
5792 walk_pointer_list_32("class refs", CR, O, &info, nullptr);
5793
5794 SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5795 if (SR == SectionRef())
5796 SR = get_section(O, "__DATA", "__objc_superrefs");
5797 if (SR == SectionRef())
5798 SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
5799 if (SR == SectionRef())
5800 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
5801 info.S = SR;
5802 walk_pointer_list_32("super refs", SR, O, &info, nullptr);
5803
5804 SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5805 if (CA == SectionRef())
5806 CA = get_section(O, "__DATA", "__objc_catlist");
5807 if (CA == SectionRef())
5808 CA = get_section(O, "__DATA_CONST", "__objc_catlist");
5809 if (CA == SectionRef())
5810 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
5811 info.S = CA;
5812 walk_pointer_list_32("category", CA, O, &info, print_category32_t);
5813
5814 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5815 if (PL == SectionRef())
5816 PL = get_section(O, "__DATA", "__objc_protolist");
5817 if (PL == SectionRef())
5818 PL = get_section(O, "__DATA_CONST", "__objc_protolist");
5819 if (PL == SectionRef())
5820 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
5821 info.S = PL;
5822 walk_pointer_list_32("protocol", PL, O, &info, nullptr);
5823
5824 SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5825 if (MR == SectionRef())
5826 MR = get_section(O, "__DATA", "__objc_msgrefs");
5827 if (MR == SectionRef())
5828 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
5829 if (MR == SectionRef())
5830 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
5831 info.S = MR;
5832 print_message_refs32(MR, &info);
5833
5834 SectionRef II = get_section(O, "__OBJC2", "__image_info");
5835 if (II == SectionRef())
5836 II = get_section(O, "__DATA", "__objc_imageinfo");
5837 if (II == SectionRef())
5838 II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
5839 if (II == SectionRef())
5840 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
5841 info.S = II;
5842 print_image_info32(II, &info);
5843}
5844
5845static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5846 uint32_t i, j, p, offset, xoffset, left, defs_left, def;
5847 const char *r, *name, *defs;
5848 struct objc_module_t module;
5849 SectionRef S, xS;
77
Calling defaulted default constructor for 'SectionRef'
79
Returning from default constructor for 'SectionRef'
5850 struct objc_symtab_t symtab;
5851 struct objc_class_t objc_class;
5852 struct objc_category_t objc_category;
5853
5854 outs() << "Objective-C segment\n";
5855 S = get_section(O, "__OBJC", "__module_info");
5856 if (S == SectionRef())
80
Taking false branch
5857 return false;
5858
5859 SymbolAddressMap AddrMap;
5860 if (verbose)
81
Taking false branch
5861 CreateSymbolAddressMap(O, &AddrMap);
5862
5863 std::vector<SectionRef> Sections;
5864 for (const SectionRef &Section : O->sections()) {
5865 StringRef SectName;
5866 Section.getName(SectName);
5867 Sections.push_back(Section);
5868 }
5869
5870 struct DisassembleInfo info;
5871 // Set up the block of info used by the Symbolizer call backs.
5872 info.verbose = verbose;
5873 info.O = O;
5874 info.AddrMap = &AddrMap;
5875 info.Sections = &Sections;
5876 info.class_name = nullptr;
5877 info.selector_name = nullptr;
5878 info.method = nullptr;
5879 info.demangled_name = nullptr;
5880 info.bindtable = nullptr;
5881 info.adrp_addr = 0;
5882 info.adrp_inst = 0;
5883
5884 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
82
Calling 'SectionRef::getSize'
5885 p = S.getAddress() + i;
5886 r = get_pointer_32(p, offset, left, S, &info, true);
5887 if (r == nullptr)
5888 return true;
5889 memset(&module, '\0', sizeof(struct objc_module_t));
5890 if (left < sizeof(struct objc_module_t)) {
5891 memcpy(&module, r, left);
5892 outs() << " (module extends past end of __module_info section)\n";
5893 } else
5894 memcpy(&module, r, sizeof(struct objc_module_t));
5895 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5896 swapStruct(module);
5897
5898 outs() << "Module " << format("0x%" PRIx32"x", p) << "\n";
5899 outs() << " version " << module.version << "\n";
5900 outs() << " size " << module.size << "\n";
5901 outs() << " name ";
5902 name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
5903 if (name != nullptr)
5904 outs() << format("%.*s", left, name);
5905 else
5906 outs() << format("0x%08" PRIx32"x", module.name)
5907 << "(not in an __OBJC section)";
5908 outs() << "\n";
5909
5910 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
5911 if (module.symtab == 0 || r == nullptr) {
5912 outs() << " symtab " << format("0x%08" PRIx32"x", module.symtab)
5913 << " (not in an __OBJC section)\n";
5914 continue;
5915 }
5916 outs() << " symtab " << format("0x%08" PRIx32"x", module.symtab) << "\n";
5917 memset(&symtab, '\0', sizeof(struct objc_symtab_t));
5918 defs_left = 0;
5919 defs = nullptr;
5920 if (left < sizeof(struct objc_symtab_t)) {
5921 memcpy(&symtab, r, left);
5922 outs() << "\tsymtab extends past end of an __OBJC section)\n";
5923 } else {
5924 memcpy(&symtab, r, sizeof(struct objc_symtab_t));
5925 if (left > sizeof(struct objc_symtab_t)) {
5926 defs_left = left - sizeof(struct objc_symtab_t);
5927 defs = r + sizeof(struct objc_symtab_t);
5928 }
5929 }
5930 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5931 swapStruct(symtab);
5932
5933 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
5934 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
5935 outs() << "\trefs " << format("0x%08" PRIx32"x", symtab.refs);
5936 if (r == nullptr)
5937 outs() << " (not in an __OBJC section)";
5938 outs() << "\n";
5939 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
5940 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
5941 if (symtab.cls_def_cnt > 0)
5942 outs() << "\tClass Definitions\n";
5943 for (j = 0; j < symtab.cls_def_cnt; j++) {
5944 if ((j + 1) * sizeof(uint32_t) > defs_left) {
5945 outs() << "\t(remaining class defs entries entends past the end of the "
5946 << "section)\n";
5947 break;
5948 }
5949 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
5950 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5951 sys::swapByteOrder(def);
5952
5953 r = get_pointer_32(def, xoffset, left, xS, &info, true);
5954 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32"x", def);
5955 if (r != nullptr) {
5956 if (left > sizeof(struct objc_class_t)) {
5957 outs() << "\n";
5958 memcpy(&objc_class, r, sizeof(struct objc_class_t));
5959 } else {
5960 outs() << " (entends past the end of the section)\n";
5961 memset(&objc_class, '\0', sizeof(struct objc_class_t));
5962 memcpy(&objc_class, r, left);
5963 }
5964 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5965 swapStruct(objc_class);
5966 print_objc_class_t(&objc_class, &info);
5967 } else {
5968 outs() << "(not in an __OBJC section)\n";
5969 }
5970
5971 if (CLS_GETINFO(&objc_class, CLS_CLASS)((&objc_class)->info & (0x1))) {
5972 outs() << "\tMeta Class";
5973 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
5974 if (r != nullptr) {
5975 if (left > sizeof(struct objc_class_t)) {
5976 outs() << "\n";
5977 memcpy(&objc_class, r, sizeof(struct objc_class_t));
5978 } else {
5979 outs() << " (entends past the end of the section)\n";
5980 memset(&objc_class, '\0', sizeof(struct objc_class_t));
5981 memcpy(&objc_class, r, left);
5982 }
5983 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5984 swapStruct(objc_class);
5985 print_objc_class_t(&objc_class, &info);
5986 } else {
5987 outs() << "(not in an __OBJC section)\n";
5988 }
5989 }
5990 }
5991 if (symtab.cat_def_cnt > 0)
5992 outs() << "\tCategory Definitions\n";
5993 for (j = 0; j < symtab.cat_def_cnt; j++) {
5994 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
5995 outs() << "\t(remaining category defs entries entends past the end of "
5996 << "the section)\n";
5997 break;
5998 }
5999 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6000 sizeof(uint32_t));
6001 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6002 sys::swapByteOrder(def);
6003
6004 r = get_pointer_32(def, xoffset, left, xS, &info, true);
6005 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6006 << format("0x%08" PRIx32"x", def);
6007 if (r != nullptr) {
6008 if (left > sizeof(struct objc_category_t)) {
6009 outs() << "\n";
6010 memcpy(&objc_category, r, sizeof(struct objc_category_t));
6011 } else {
6012 outs() << " (entends past the end of the section)\n";
6013 memset(&objc_category, '\0', sizeof(struct objc_category_t));
6014 memcpy(&objc_category, r, left);
6015 }
6016 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6017 swapStruct(objc_category);
6018 print_objc_objc_category_t(&objc_category, &info);
6019 } else {
6020 outs() << "(not in an __OBJC section)\n";
6021 }
6022 }
6023 }
6024 const SectionRef II = get_section(O, "__OBJC", "__image_info");
6025 if (II != SectionRef())
6026 print_image_info(II, &info);
6027
6028 return true;
6029}
6030
6031static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6032 uint32_t size, uint32_t addr) {
6033 SymbolAddressMap AddrMap;
6034 CreateSymbolAddressMap(O, &AddrMap);
6035
6036 std::vector<SectionRef> Sections;
6037 for (const SectionRef &Section : O->sections()) {
6038 StringRef SectName;
6039 Section.getName(SectName);
6040 Sections.push_back(Section);
6041 }
6042
6043 struct DisassembleInfo info;
6044 // Set up the block of info used by the Symbolizer call backs.
6045 info.verbose = true;
6046 info.O = O;
6047 info.AddrMap = &AddrMap;
6048 info.Sections = &Sections;
6049 info.class_name = nullptr;
6050 info.selector_name = nullptr;
6051 info.method = nullptr;
6052 info.demangled_name = nullptr;
6053 info.bindtable = nullptr;
6054 info.adrp_addr = 0;
6055 info.adrp_inst = 0;
6056
6057 const char *p;
6058 struct objc_protocol_t protocol;
6059 uint32_t left, paddr;
6060 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6061 memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6062 left = size - (p - sect);
6063 if (left < sizeof(struct objc_protocol_t)) {
6064 outs() << "Protocol extends past end of __protocol section\n";
6065 memcpy(&protocol, p, left);
6066 } else
6067 memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6068 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6069 swapStruct(protocol);
6070 paddr = addr + (p - sect);
6071 outs() << "Protocol " << format("0x%" PRIx32"x", paddr);
6072 if (print_protocol(paddr, 0, &info))
6073 outs() << "(not in an __OBJC section)\n";
6074 }
6075}
6076
6077#ifdef HAVE_LIBXAR
6078inline void swapStruct(struct xar_header &xar) {
6079 sys::swapByteOrder(xar.magic);
6080 sys::swapByteOrder(xar.size);
6081 sys::swapByteOrder(xar.version);
6082 sys::swapByteOrder(xar.toc_length_compressed);
6083 sys::swapByteOrder(xar.toc_length_uncompressed);
6084 sys::swapByteOrder(xar.cksum_alg);
6085}
6086
6087static void PrintModeVerbose(uint32_t mode) {
6088 switch(mode & S_IFMT){
6089 case S_IFDIR:
6090 outs() << "d";
6091 break;
6092 case S_IFCHR:
6093 outs() << "c";
6094 break;
6095 case S_IFBLK:
6096 outs() << "b";
6097 break;
6098 case S_IFREG:
6099 outs() << "-";
6100 break;
6101 case S_IFLNK:
6102 outs() << "l";
6103 break;
6104 case S_IFSOCK:
6105 outs() << "s";
6106 break;
6107 default:
6108 outs() << "?";
6109 break;
6110 }
6111
6112 /* owner permissions */
6113 if(mode & S_IREAD)
6114 outs() << "r";
6115 else
6116 outs() << "-";
6117 if(mode & S_IWRITE)
6118 outs() << "w";
6119 else
6120 outs() << "-";
6121 if(mode & S_ISUID)
6122 outs() << "s";
6123 else if(mode & S_IEXEC)
6124 outs() << "x";
6125 else
6126 outs() << "-";
6127
6128 /* group permissions */
6129 if(mode & (S_IREAD >> 3))
6130 outs() << "r";
6131 else
6132 outs() << "-";
6133 if(mode & (S_IWRITE >> 3))
6134 outs() << "w";
6135 else
6136 outs() << "-";
6137 if(mode & S_ISGID)
6138 outs() << "s";
6139 else if(mode & (S_IEXEC >> 3))
6140 outs() << "x";
6141 else
6142 outs() << "-";
6143
6144 /* other permissions */
6145 if(mode & (S_IREAD >> 6))
6146 outs() << "r";
6147 else
6148 outs() << "-";
6149 if(mode & (S_IWRITE >> 6))
6150 outs() << "w";
6151 else
6152 outs() << "-";
6153 if(mode & S_ISVTX)
6154 outs() << "t";
6155 else if(mode & (S_IEXEC >> 6))
6156 outs() << "x";
6157 else
6158 outs() << "-";
6159}
6160
6161static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
6162 xar_file_t xf;
6163 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
6164 char *endp;
6165 uint32_t mode_value;
6166
6167 ScopedXarIter xi;
6168 if (!xi) {
6169 errs() << "Can't obtain an xar iterator for xar archive "
6170 << XarFilename << "\n";
6171 return;
6172 }
6173
6174 // Go through the xar's files.
6175 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
6176 ScopedXarIter xp;
6177 if(!xp){
6178 errs() << "Can't obtain an xar iterator for xar archive "
6179 << XarFilename << "\n";
6180 return;
6181 }
6182 type = nullptr;
6183 mode = nullptr;
6184 user = nullptr;
6185 group = nullptr;
6186 size = nullptr;
6187 mtime = nullptr;
6188 name = nullptr;
6189 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6190 const char *val = nullptr;
6191 xar_prop_get(xf, key, &val);
6192#if 0 // Useful for debugging.
6193 outs() << "key: " << key << " value: " << val << "\n";
6194#endif
6195 if(strcmp(key, "type") == 0)
6196 type = val;
6197 if(strcmp(key, "mode") == 0)
6198 mode = val;
6199 if(strcmp(key, "user") == 0)
6200 user = val;
6201 if(strcmp(key, "group") == 0)
6202 group = val;
6203 if(strcmp(key, "data/size") == 0)
6204 size = val;
6205 if(strcmp(key, "mtime") == 0)
6206 mtime = val;
6207 if(strcmp(key, "name") == 0)
6208 name = val;
6209 }
6210 if(mode != nullptr){
6211 mode_value = strtoul(mode, &endp, 8);
6212 if(*endp != '\0')
6213 outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
6214 if(strcmp(type, "file") == 0)
6215 mode_value |= S_IFREG;
6216 PrintModeVerbose(mode_value);
6217 outs() << " ";
6218 }
6219 if(user != nullptr)
6220 outs() << format("%10s/", user);
6221 if(group != nullptr)
6222 outs() << format("%-10s ", group);
6223 if(size != nullptr)
6224 outs() << format("%7s ", size);
6225 if(mtime != nullptr){
6226 for(m = mtime; *m != 'T' && *m != '\0'; m++)
6227 outs() << *m;
6228 if(*m == 'T')
6229 m++;
6230 outs() << " ";
6231 for( ; *m != 'Z' && *m != '\0'; m++)
6232 outs() << *m;
6233 outs() << " ";
6234 }
6235 if(name != nullptr)
6236 outs() << name;
6237 outs() << "\n";
6238 }
6239}
6240
6241static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
6242 uint32_t size, bool verbose,
6243 bool PrintXarHeader, bool PrintXarFileHeaders,
6244 std::string XarMemberName) {
6245 if(size < sizeof(struct xar_header)) {
6246 outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
6247 "of struct xar_header)\n";
6248 return;
6249 }
6250 struct xar_header XarHeader;
6251 memcpy(&XarHeader, sect, sizeof(struct xar_header));
6252 if (sys::IsLittleEndianHost)
6253 swapStruct(XarHeader);
6254 if (PrintXarHeader) {
6255 if (!XarMemberName.empty())
6256 outs() << "In xar member " << XarMemberName << ": ";
6257 else
6258 outs() << "For (__LLVM,__bundle) section: ";
6259 outs() << "xar header\n";
6260 if (XarHeader.magic == XAR_HEADER_MAGIC)
6261 outs() << " magic XAR_HEADER_MAGIC\n";
6262 else
6263 outs() << " magic "
6264 << format_hex(XarHeader.magic, 10, true)
6265 << " (not XAR_HEADER_MAGIC)\n";
6266 outs() << " size " << XarHeader.size << "\n";
6267 outs() << " version " << XarHeader.version << "\n";
6268 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed
6269 << "\n";
6270 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
6271 << "\n";
6272 outs() << " cksum_alg ";
6273 switch (XarHeader.cksum_alg) {
6274 case XAR_CKSUM_NONE:
6275 outs() << "XAR_CKSUM_NONE\n";
6276 break;
6277 case XAR_CKSUM_SHA1:
6278 outs() << "XAR_CKSUM_SHA1\n";
6279 break;
6280 case XAR_CKSUM_MD5:
6281 outs() << "XAR_CKSUM_MD5\n";
6282 break;
6283#ifdef XAR_CKSUM_SHA256
6284 case XAR_CKSUM_SHA256:
6285 outs() << "XAR_CKSUM_SHA256\n";
6286 break;
6287#endif
6288#ifdef XAR_CKSUM_SHA512
6289 case XAR_CKSUM_SHA512:
6290 outs() << "XAR_CKSUM_SHA512\n";
6291 break;
6292#endif
6293 default:
6294 outs() << XarHeader.cksum_alg << "\n";
6295 }
6296 }
6297
6298 SmallString<128> XarFilename;
6299 int FD;
6300 std::error_code XarEC =
6301 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
6302 if (XarEC) {
6303 errs() << XarEC.message() << "\n";
6304 return;
6305 }
6306 ToolOutputFile XarFile(XarFilename, FD);
6307 raw_fd_ostream &XarOut = XarFile.os();
6308 StringRef XarContents(sect, size);
6309 XarOut << XarContents;
6310 XarOut.close();
6311 if (XarOut.has_error())
6312 return;
6313
6314 ScopedXarFile xar(XarFilename.c_str(), READ);
6315 if (!xar) {
6316 errs() << "Can't create temporary xar archive " << XarFilename << "\n";
6317 return;
6318 }
6319
6320 SmallString<128> TocFilename;
6321 std::error_code TocEC =
6322 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
6323 if (TocEC) {
6324 errs() << TocEC.message() << "\n";
6325 return;
6326 }
6327 xar_serialize(xar, TocFilename.c_str());
6328
6329 if (PrintXarFileHeaders) {
6330 if (!XarMemberName.empty())
6331 outs() << "In xar member " << XarMemberName << ": ";
6332 else
6333 outs() << "For (__LLVM,__bundle) section: ";
6334 outs() << "xar archive files:\n";
6335 PrintXarFilesSummary(XarFilename.c_str(), xar);
6336 }
6337
6338 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
6339 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
6340 if (std::error_code EC = FileOrErr.getError()) {
6341 errs() << EC.message() << "\n";
6342 return;
6343 }
6344 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
6345
6346 if (!XarMemberName.empty())
6347 outs() << "In xar member " << XarMemberName << ": ";
6348 else
6349 outs() << "For (__LLVM,__bundle) section: ";
6350 outs() << "xar table of contents:\n";
6351 outs() << Buffer->getBuffer() << "\n";
6352
6353 // TODO: Go through the xar's files.
6354 ScopedXarIter xi;
6355 if(!xi){
6356 errs() << "Can't obtain an xar iterator for xar archive "
6357 << XarFilename.c_str() << "\n";
6358 return;
6359 }
6360 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
6361 const char *key;
6362 const char *member_name, *member_type, *member_size_string;
6363 size_t member_size;
6364
6365 ScopedXarIter xp;
6366 if(!xp){
6367 errs() << "Can't obtain an xar iterator for xar archive "
6368 << XarFilename.c_str() << "\n";
6369 return;
6370 }
6371 member_name = NULL__null;
6372 member_type = NULL__null;
6373 member_size_string = NULL__null;
6374 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6375 const char *val = nullptr;
6376 xar_prop_get(xf, key, &val);
6377#if 0 // Useful for debugging.
6378 outs() << "key: " << key << " value: " << val << "\n";
6379#endif
6380 if (strcmp(key, "name") == 0)
6381 member_name = val;
6382 if (strcmp(key, "type") == 0)
6383 member_type = val;
6384 if (strcmp(key, "data/size") == 0)
6385 member_size_string = val;
6386 }
6387 /*
6388 * If we find a file with a name, date/size and type properties
6389 * and with the type being "file" see if that is a xar file.
6390 */
6391 if (member_name != NULL__null && member_type != NULL__null &&
6392 strcmp(member_type, "file") == 0 &&
6393 member_size_string != NULL__null){
6394 // Extract the file into a buffer.
6395 char *endptr;
6396 member_size = strtoul(member_size_string, &endptr, 10);
6397 if (*endptr == '\0' && member_size != 0) {
6398 char *buffer;
6399 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
6400#if 0 // Useful for debugging.
6401 outs() << "xar member: " << member_name << " extracted\n";
6402#endif
6403 // Set the XarMemberName we want to see printed in the header.
6404 std::string OldXarMemberName;
6405 // If XarMemberName is already set this is nested. So
6406 // save the old name and create the nested name.
6407 if (!XarMemberName.empty()) {
6408 OldXarMemberName = XarMemberName;
6409 XarMemberName =
6410 (Twine("[") + XarMemberName + "]" + member_name).str();
6411 } else {
6412 OldXarMemberName = "";
6413 XarMemberName = member_name;
6414 }
6415 // See if this is could be a xar file (nested).
6416 if (member_size >= sizeof(struct xar_header)) {
6417#if 0 // Useful for debugging.
6418 outs() << "could be a xar file: " << member_name << "\n";
6419#endif
6420 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
6421 if (sys::IsLittleEndianHost)
6422 swapStruct(XarHeader);
6423 if (XarHeader.magic == XAR_HEADER_MAGIC)
6424 DumpBitcodeSection(O, buffer, member_size, verbose,
6425 PrintXarHeader, PrintXarFileHeaders,
6426 XarMemberName);
6427 }
6428 XarMemberName = OldXarMemberName;
6429 delete buffer;
6430 }
6431 }
6432 }
6433 }
6434}
6435#endif // defined(HAVE_LIBXAR)
6436
6437static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6438 if (O->is64Bit())
72
Assuming the condition is false
73
Taking false branch
6439 printObjc2_64bit_MetaData(O, verbose);
6440 else {
6441 MachO::mach_header H;
6442 H = O->getHeader();
6443 if (H.cputype == MachO::CPU_TYPE_ARM)
74
Assuming the condition is false
75
Taking false branch
6444 printObjc2_32bit_MetaData(O, verbose);
6445 else {
6446 // This is the 32-bit non-arm cputype case. Which is normally
6447 // the first Objective-C ABI. But it may be the case of a
6448 // binary for the iOS simulator which is the second Objective-C
6449 // ABI. In that case printObjc1_32bit_MetaData() will determine that
6450 // and return false.
6451 if (!printObjc1_32bit_MetaData(O, verbose))
76
Calling 'printObjc1_32bit_MetaData'
6452 printObjc2_32bit_MetaData(O, verbose);
6453 }
6454 }
6455}
6456
6457// GuessLiteralPointer returns a string which for the item in the Mach-O file
6458// for the address passed in as ReferenceValue for printing as a comment with
6459// the instruction and also returns the corresponding type of that item
6460// indirectly through ReferenceType.
6461//
6462// If ReferenceValue is an address of literal cstring then a pointer to the
6463// cstring is returned and ReferenceType is set to
6464// LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6465//
6466// If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6467// Class ref that name is returned and the ReferenceType is set accordingly.
6468//
6469// Lastly, literals which are Symbol address in a literal pool are looked for
6470// and if found the symbol name is returned and ReferenceType is set to
6471// LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6472//
6473// If there is no item in the Mach-O file for the address passed in as
6474// ReferenceValue nullptr is returned and ReferenceType is unchanged.
6475static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6476 uint64_t ReferencePC,
6477 uint64_t *ReferenceType,
6478 struct DisassembleInfo *info) {
6479 // First see if there is an external relocation entry at the ReferencePC.
6480 if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6481 uint64_t sect_addr = info->S.getAddress();
6482 uint64_t sect_offset = ReferencePC - sect_addr;
6483 bool reloc_found = false;
6484 DataRefImpl Rel;
6485 MachO::any_relocation_info RE;
6486 bool isExtern = false;
6487 SymbolRef Symbol;
6488 for (const RelocationRef &Reloc : info->S.relocations()) {
6489 uint64_t RelocOffset = Reloc.getOffset();
6490 if (RelocOffset == sect_offset) {
6491 Rel = Reloc.getRawDataRefImpl();
6492 RE = info->O->getRelocation(Rel);
6493 if (info->O->isRelocationScattered(RE))
6494 continue;
6495 isExtern = info->O->getPlainRelocationExternal(RE);
6496 if (isExtern) {
6497 symbol_iterator RelocSym = Reloc.getSymbol();
6498 Symbol = *RelocSym;
6499 }
6500 reloc_found = true;
6501 break;
6502 }
6503 }
6504 // If there is an external relocation entry for a symbol in a section
6505 // then used that symbol's value for the value of the reference.
6506 if (reloc_found && isExtern) {
6507 if (info->O->getAnyRelocationPCRel(RE)) {
6508 unsigned Type = info->O->getAnyRelocationType(RE);
6509 if (Type == MachO::X86_64_RELOC_SIGNED) {
6510 ReferenceValue = Symbol.getValue();
6511 }
6512 }
6513 }
6514 }
6515
6516 // Look for literals such as Objective-C CFStrings refs, Selector refs,
6517 // Message refs and Class refs.
6518 bool classref, selref, msgref, cfstring;
6519 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6520 selref, msgref, cfstring);
6521 if (classref && pointer_value == 0) {
6522 // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6523 // And the pointer_value in that section is typically zero as it will be
6524 // set by dyld as part of the "bind information".
6525 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6526 if (name != nullptr) {
6527 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref8;
6528 const char *class_name = strrchr(name, '$');
6529 if (class_name != nullptr && class_name[1] == '_' &&
6530 class_name[2] != '\0') {
6531 info->class_name = class_name + 2;
6532 return name;
6533 }
6534 }
6535 }
6536
6537 if (classref) {
6538 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref8;
6539 const char *name =
6540 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6541 if (name != nullptr)
6542 info->class_name = name;
6543 else
6544 name = "bad class ref";
6545 return name;
6546 }
6547
6548 if (cfstring) {
6549 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref4;
6550 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6551 return name;
6552 }
6553
6554 if (selref && pointer_value == 0)
6555 pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6556
6557 if (pointer_value != 0)
6558 ReferenceValue = pointer_value;
6559
6560 const char *name = GuessCstringPointer(ReferenceValue, info);
6561 if (name) {
6562 if (pointer_value != 0 && selref) {
6563 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref7;
6564 info->selector_name = name;
6565 } else if (pointer_value != 0 && msgref) {
6566 info->class_name = nullptr;
6567 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref6;
6568 info->selector_name = name;
6569 } else
6570 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr3;
6571 return name;
6572 }
6573
6574 // Lastly look for an indirect symbol with this ReferenceValue which is in
6575 // a literal pool. If found return that symbol name.
6576 name = GuessIndirectSymbol(ReferenceValue, info);
6577 if (name) {
6578 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr2;
6579 return name;
6580 }
6581
6582 return nullptr;
6583}
6584
6585// SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6586// the Symbolizer. It looks up the ReferenceValue using the info passed via the
6587// pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6588// is created and returns the symbol name that matches the ReferenceValue or
6589// nullptr if none. The ReferenceType is passed in for the IN type of
6590// reference the instruction is making from the values in defined in the header
6591// "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific
6592// Out type and the ReferenceName will also be set which is added as a comment
6593// to the disassembled instruction.
6594//
6595// If the symbol name is a C++ mangled name then the demangled name is
6596// returned through ReferenceName and ReferenceType is set to
6597// LLVMDisassembler_ReferenceType_DeMangled_Name .
6598//
6599// When this is called to get a symbol name for a branch target then the
6600// ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6601// SymbolValue will be looked for in the indirect symbol table to determine if
6602// it is an address for a symbol stub. If so then the symbol name for that
6603// stub is returned indirectly through ReferenceName and then ReferenceType is
6604// set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6605//
6606// When this is called with an value loaded via a PC relative load then
6607// ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6608// SymbolValue is checked to be an address of literal pointer, symbol pointer,
6609// or an Objective-C meta data reference. If so the output ReferenceType is
6610// set to correspond to that as well as setting the ReferenceName.
6611static const char *SymbolizerSymbolLookUp(void *DisInfo,
6612 uint64_t ReferenceValue,
6613 uint64_t *ReferenceType,
6614 uint64_t ReferencePC,
6615 const char **ReferenceName) {
6616 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6617 // If no verbose symbolic information is wanted then just return nullptr.
6618 if (!info->verbose) {
6619 *ReferenceName = nullptr;
6620 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6621 return nullptr;
6622 }
6623
6624 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6625
6626 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch1) {
6627 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6628 if (*ReferenceName != nullptr) {
6629 method_reference(info, ReferenceType, ReferenceName);
6630 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message5)
6631 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub1;
6632 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6633 if (info->demangled_name != nullptr)
6634 free(info->demangled_name);
6635 int status;
6636 info->demangled_name =
6637 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
6638 if (info->demangled_name != nullptr) {
6639 *ReferenceName = info->demangled_name;
6640 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name9;
6641 } else
6642 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6643 } else
6644 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6645 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load2) {
6646 *ReferenceName =
6647 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6648 if (*ReferenceName)
6649 method_reference(info, ReferenceType, ReferenceName);
6650 else
6651 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6652 // If this is arm64 and the reference is an adrp instruction save the
6653 // instruction, passed in ReferenceValue and the address of the instruction
6654 // for use later if we see and add immediate instruction.
6655 } else if (info->O->getArch() == Triple::aarch64 &&
6656 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP0x100000001) {
6657 info->adrp_inst = ReferenceValue;
6658 info->adrp_addr = ReferencePC;
6659 SymbolName = nullptr;
6660 *ReferenceName = nullptr;
6661 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6662 // If this is arm64 and reference is an add immediate instruction and we
6663 // have
6664 // seen an adrp instruction just before it and the adrp's Xd register
6665 // matches
6666 // this add's Xn register reconstruct the value being referenced and look to
6667 // see if it is a literal pointer. Note the add immediate instruction is
6668 // passed in ReferenceValue.
6669 } else if (info->O->getArch() == Triple::aarch64 &&
6670 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri0x100000002 &&
6671 ReferencePC - 4 == info->adrp_addr &&
6672 (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6673 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6674 uint32_t addxri_inst;
6675 uint64_t adrp_imm, addxri_imm;
6676
6677 adrp_imm =
6678 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6679 if (info->adrp_inst & 0x0200000)
6680 adrp_imm |= 0xfffffffffc000000LL;
6681
6682 addxri_inst = ReferenceValue;
6683 addxri_imm = (addxri_inst >> 10) & 0xfff;
6684 if (((addxri_inst >> 22) & 0x3) == 1)
6685 addxri_imm <<= 12;
6686
6687 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6688 (adrp_imm << 12) + addxri_imm;
6689
6690 *ReferenceName =
6691 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6692 if (*ReferenceName == nullptr)
6693 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6694 // If this is arm64 and the reference is a load register instruction and we
6695 // have seen an adrp instruction just before it and the adrp's Xd register
6696 // matches this add's Xn register reconstruct the value being referenced and
6697 // look to see if it is a literal pointer. Note the load register
6698 // instruction is passed in ReferenceValue.
6699 } else if (info->O->getArch() == Triple::aarch64 &&
6700 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui0x100000003 &&
6701 ReferencePC - 4 == info->adrp_addr &&
6702 (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6703 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6704 uint32_t ldrxui_inst;
6705 uint64_t adrp_imm, ldrxui_imm;
6706
6707 adrp_imm =
6708 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6709 if (info->adrp_inst & 0x0200000)
6710 adrp_imm |= 0xfffffffffc000000LL;
6711
6712 ldrxui_inst = ReferenceValue;
6713 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
6714
6715 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6716 (adrp_imm << 12) + (ldrxui_imm << 3);
6717
6718 *ReferenceName =
6719 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6720 if (*ReferenceName == nullptr)
6721 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6722 }
6723 // If this arm64 and is an load register (PC-relative) instruction the
6724 // ReferenceValue is the PC plus the immediate value.
6725 else if (info->O->getArch() == Triple::aarch64 &&
6726 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl0x100000004 ||
6727 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR0x100000005)) {
6728 *ReferenceName =
6729 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6730 if (*ReferenceName == nullptr)
6731 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6732 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6733 if (info->demangled_name != nullptr)
6734 free(info->demangled_name);
6735 int status;
6736 info->demangled_name =
6737 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
6738 if (info->demangled_name != nullptr) {
6739 *ReferenceName = info->demangled_name;
6740 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name9;
6741 }
6742 }
6743 else {
6744 *ReferenceName = nullptr;
6745 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6746 }
6747
6748 return SymbolName;
6749}
6750
6751/// \brief Emits the comments that are stored in the CommentStream.
6752/// Each comment in the CommentStream must end with a newline.
6753static void emitComments(raw_svector_ostream &CommentStream,
6754 SmallString<128> &CommentsToEmit,
6755 formatted_raw_ostream &FormattedOS,
6756 const MCAsmInfo &MAI) {
6757 // Flush the stream before taking its content.
6758 StringRef Comments = CommentsToEmit.str();
6759 // Get the default information for printing a comment.
6760 StringRef CommentBegin = MAI.getCommentString();
6761 unsigned CommentColumn = MAI.getCommentColumn();
6762 bool IsFirst = true;
6763 while (!Comments.empty()) {
6764 if (!IsFirst)
6765 FormattedOS << '\n';
6766 // Emit a line of comments.
6767 FormattedOS.PadToColumn(CommentColumn);
6768 size_t Position = Comments.find('\n');
6769 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
6770 // Move after the newline character.
6771 Comments = Comments.substr(Position + 1);
6772 IsFirst = false;
6773 }
6774 FormattedOS.flush();
6775
6776 // Tell the comment stream that the vector changed underneath it.
6777 CommentsToEmit.clear();
6778}
6779
6780static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
6781 StringRef DisSegName, StringRef DisSectName) {
6782 const char *McpuDefault = nullptr;
6783 const Target *ThumbTarget = nullptr;
6784 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
6785 if (!TheTarget) {
6786 // GetTarget prints out stuff.
6787 return;
6788 }
6789 std::string MachOMCPU;
6790 if (MCPU.empty() && McpuDefault)
6791 MachOMCPU = McpuDefault;
6792 else
6793 MachOMCPU = MCPU;
6794
6795 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
6796 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
6797 if (ThumbTarget)
6798 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
6799
6800 // Package up features to be passed to target/subtarget
6801 std::string FeaturesStr;
6802 if (MAttrs.size()) {
6803 SubtargetFeatures Features;
6804 for (unsigned i = 0; i != MAttrs.size(); ++i)
6805 Features.AddFeature(MAttrs[i]);
6806 FeaturesStr = Features.getString();
6807 }
6808
6809 // Set up disassembler.
6810 std::unique_ptr<const MCRegisterInfo> MRI(
6811 TheTarget->createMCRegInfo(TripleName));
6812 std::unique_ptr<const MCAsmInfo> AsmInfo(
6813 TheTarget->createMCAsmInfo(*MRI, TripleName));
6814 std::unique_ptr<const MCSubtargetInfo> STI(
6815 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
6816 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
6817 std::unique_ptr<MCDisassembler> DisAsm(
6818 TheTarget->createMCDisassembler(*STI, Ctx));
6819 std::unique_ptr<MCSymbolizer> Symbolizer;
6820 struct DisassembleInfo SymbolizerInfo;
6821 std::unique_ptr<MCRelocationInfo> RelInfo(
6822 TheTarget->createMCRelocationInfo(TripleName, Ctx));
6823 if (RelInfo) {
6824 Symbolizer.reset(TheTarget->createMCSymbolizer(
6825 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6826 &SymbolizerInfo, &Ctx, std::move(RelInfo)));
6827 DisAsm->setSymbolizer(std::move(Symbolizer));
6828 }
6829 int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
6830 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
6831 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
6832 // Set the display preference for hex vs. decimal immediates.
6833 IP->setPrintImmHex(PrintImmHex);
6834 // Comment stream and backing vector.
6835 SmallString<128> CommentsToEmit;
6836 raw_svector_ostream CommentStream(CommentsToEmit);
6837 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
6838 // if it is done then arm64 comments for string literals don't get printed
6839 // and some constant get printed instead and not setting it causes intel
6840 // (32-bit and 64-bit) comments printed with different spacing before the
6841 // comment causing different diffs with the 'C' disassembler library API.
6842 // IP->setCommentStream(CommentStream);
6843
6844 if (!AsmInfo || !STI || !DisAsm || !IP) {
6845 errs() << "error: couldn't initialize disassembler for target "
6846 << TripleName << '\n';
6847 return;
6848 }
6849
6850 // Set up separate thumb disassembler if needed.
6851 std::unique_ptr<const MCRegisterInfo> ThumbMRI;
6852 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
6853 std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
6854 std::unique_ptr<MCDisassembler> ThumbDisAsm;
6855 std::unique_ptr<MCInstPrinter> ThumbIP;
6856 std::unique_ptr<MCContext> ThumbCtx;
6857 std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
6858 struct DisassembleInfo ThumbSymbolizerInfo;
6859 std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
6860 if (ThumbTarget) {
6861 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
6862 ThumbAsmInfo.reset(
6863 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName));
6864 ThumbSTI.reset(
6865 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
6866 FeaturesStr));
6867 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
6868 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
6869 MCContext *PtrThumbCtx = ThumbCtx.get();
6870 ThumbRelInfo.reset(
6871 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
6872 if (ThumbRelInfo) {
6873 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
6874 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6875 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
6876 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
6877 }
6878 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
6879 ThumbIP.reset(ThumbTarget->createMCInstPrinter(
6880 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
6881 *ThumbInstrInfo, *ThumbMRI));
6882 // Set the display preference for hex vs. decimal immediates.
6883 ThumbIP->setPrintImmHex(PrintImmHex);
6884 }
6885
6886 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) {
6887 errs() << "error: couldn't initialize disassembler for target "
6888 << ThumbTripleName << '\n';
6889 return;
6890 }
6891
6892 MachO::mach_header Header = MachOOF->getHeader();
6893
6894 // FIXME: Using the -cfg command line option, this code used to be able to
6895 // annotate relocations with the referenced symbol's name, and if this was
6896 // inside a __[cf]string section, the data it points to. This is now replaced
6897 // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
6898 std::vector<SectionRef> Sections;
6899 std::vector<SymbolRef> Symbols;
6900 SmallVector<uint64_t, 8> FoundFns;
6901 uint64_t BaseSegmentAddress;
6902
6903 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
6904 BaseSegmentAddress);
6905
6906 // Sort the symbols by address, just in case they didn't come in that way.
6907 std::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
6908
6909 // Build a data in code table that is sorted on by the address of each entry.
6910 uint64_t BaseAddress = 0;
6911 if (Header.filetype == MachO::MH_OBJECT)
6912 BaseAddress = Sections[0].getAddress();
6913 else
6914 BaseAddress = BaseSegmentAddress;
6915 DiceTable Dices;
6916 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
6917 DI != DE; ++DI) {
6918 uint32_t Offset;
6919 DI->getOffset(Offset);
6920 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
6921 }
6922 array_pod_sort(Dices.begin(), Dices.end());
6923
6924#ifndef NDEBUG
6925 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
6926#else
6927 raw_ostream &DebugOut = nulls();
6928#endif
6929
6930 std::unique_ptr<DIContext> diContext;
6931 ObjectFile *DbgObj = MachOOF;
6932 // Try to find debug info and set up the DIContext for it.
6933 if (UseDbg) {
6934 // A separate DSym file path was specified, parse it as a macho file,
6935 // get the sections and supply it to the section name parsing machinery.
6936 if (!DSYMFile.empty()) {
6937 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
6938 MemoryBuffer::getFileOrSTDIN(DSYMFile);
6939 if (std::error_code EC = BufOrErr.getError()) {
6940 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
6941 return;
6942 }
6943 DbgObj =
6944 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef())
6945 .get()
6946 .release();
6947 }
6948
6949 // Setup the DIContext
6950 diContext = DWARFContext::create(*DbgObj);
6951 }
6952
6953 if (FilterSections.size() == 0)
6954 outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
6955
6956 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
6957 StringRef SectName;
6958 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName)
6959 continue;
6960
6961 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
6962
6963 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
6964 if (SegmentName != DisSegName)
6965 continue;
6966
6967 StringRef BytesStr;
6968 Sections[SectIdx].getContents(BytesStr);
6969 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
6970 BytesStr.size());
6971 uint64_t SectAddress = Sections[SectIdx].getAddress();
6972
6973 bool symbolTableWorked = false;
6974
6975 // Create a map of symbol addresses to symbol names for use by
6976 // the SymbolizerSymbolLookUp() routine.
6977 SymbolAddressMap AddrMap;
6978 bool DisSymNameFound = false;
6979 for (const SymbolRef &Symbol : MachOOF->symbols()) {
6980 Expected<SymbolRef::Type> STOrErr = Symbol.getType();
6981 if (!STOrErr)
6982 report_error(MachOOF->getFileName(), STOrErr.takeError());
6983 SymbolRef::Type ST = *STOrErr;
6984 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
6985 ST == SymbolRef::ST_Other) {
6986 uint64_t Address = Symbol.getValue();
6987 Expected<StringRef> SymNameOrErr = Symbol.getName();
6988 if (!SymNameOrErr)
6989 report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
6990 StringRef SymName = *SymNameOrErr;
6991 AddrMap[Address] = SymName;
6992 if (!DisSymName.empty() && DisSymName == SymName)
6993 DisSymNameFound = true;
6994 }
6995 }
6996 if (!DisSymName.empty() && !DisSymNameFound) {
6997 outs() << "Can't find -dis-symname: " << DisSymName << "\n";
6998 return;
6999 }
7000 // Set up the block of info used by the Symbolizer call backs.
7001 SymbolizerInfo.verbose = !NoSymbolicOperands;
7002 SymbolizerInfo.O = MachOOF;
7003 SymbolizerInfo.S = Sections[SectIdx];
7004 SymbolizerInfo.AddrMap = &AddrMap;
7005 SymbolizerInfo.Sections = &Sections;
7006 SymbolizerInfo.class_name = nullptr;
7007 SymbolizerInfo.selector_name = nullptr;
7008 SymbolizerInfo.method = nullptr;
7009 SymbolizerInfo.demangled_name = nullptr;
7010 SymbolizerInfo.bindtable = nullptr;
7011 SymbolizerInfo.adrp_addr = 0;
7012 SymbolizerInfo.adrp_inst = 0;
7013 // Same for the ThumbSymbolizer
7014 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
7015 ThumbSymbolizerInfo.O = MachOOF;
7016 ThumbSymbolizerInfo.S = Sections[SectIdx];
7017 ThumbSymbolizerInfo.AddrMap = &AddrMap;
7018 ThumbSymbolizerInfo.Sections = &Sections;
7019 ThumbSymbolizerInfo.class_name = nullptr;
7020 ThumbSymbolizerInfo.selector_name = nullptr;
7021 ThumbSymbolizerInfo.method = nullptr;
7022 ThumbSymbolizerInfo.demangled_name = nullptr;
7023 ThumbSymbolizerInfo.bindtable = nullptr;
7024 ThumbSymbolizerInfo.adrp_addr = 0;
7025 ThumbSymbolizerInfo.adrp_inst = 0;
7026
7027 unsigned int Arch = MachOOF->getArch();
7028
7029 // Skip all symbols if this is a stubs file.
7030 if (Bytes.size() == 0)
7031 return;
7032
7033 // If the section has symbols but no symbol at the start of the section
7034 // these are used to make sure the bytes before the first symbol are
7035 // disassembled.
7036 bool FirstSymbol = true;
7037 bool FirstSymbolAtSectionStart = true;
7038
7039 // Disassemble symbol by symbol.
7040 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7041 Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
7042 if (!SymNameOrErr)
7043 report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
7044 StringRef SymName = *SymNameOrErr;
7045
7046 Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
7047 if (!STOrErr)
7048 report_error(MachOOF->getFileName(), STOrErr.takeError());
7049 SymbolRef::Type ST = *STOrErr;
7050 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7051 continue;
7052
7053 // Make sure the symbol is defined in this section.
7054 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7055 if (!containsSym) {
7056 if (!DisSymName.empty() && DisSymName == SymName) {
7057 outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7058 return;
7059 }
7060 continue;
7061 }
7062 // The __mh_execute_header is special and we need to deal with that fact
7063 // this symbol is before the start of the (__TEXT,__text) section and at the
7064 // address of the start of the __TEXT segment. This is because this symbol
7065 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7066 // start of the section in a standard MH_EXECUTE filetype.
7067 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7068 outs() << "-dis-symname: __mh_execute_header not in any section\n";
7069 return;
7070 }
7071 // When this code is trying to disassemble a symbol at a time and in the
7072 // case there is only the __mh_execute_header symbol left as in a stripped
7073 // executable, we need to deal with this by ignoring this symbol so the
7074 // whole section is disassembled and this symbol is then not displayed.
7075 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7076 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7077 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7078 continue;
7079
7080 // If we are only disassembling one symbol see if this is that symbol.
7081 if (!DisSymName.empty() && DisSymName != SymName)
7082 continue;
7083
7084 // Start at the address of the symbol relative to the section's address.
7085 uint64_t SectSize = Sections[SectIdx].getSize();
7086 uint64_t Start = Symbols[SymIdx].getValue();
7087 uint64_t SectionAddress = Sections[SectIdx].getAddress();
7088 Start -= SectionAddress;
7089
7090 if (Start > SectSize) {
7091 outs() << "section data ends, " << SymName
7092 << " lies outside valid range\n";
7093 return;
7094 }
7095
7096 // Stop disassembling either at the beginning of the next symbol or at
7097 // the end of the section.
7098 bool containsNextSym = false;
7099 uint64_t NextSym = 0;
7100 uint64_t NextSymIdx = SymIdx + 1;
7101 while (Symbols.size() > NextSymIdx) {
7102 Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
7103 if (!STOrErr)
7104 report_error(MachOOF->getFileName(), STOrErr.takeError());
7105 SymbolRef::Type NextSymType = *STOrErr;
7106 if (NextSymType == SymbolRef::ST_Function) {
7107 containsNextSym =
7108 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7109 NextSym = Symbols[NextSymIdx].getValue();
7110 NextSym -= SectionAddress;
7111 break;
7112 }
7113 ++NextSymIdx;
7114 }
7115
7116 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7117 uint64_t Size;
7118
7119 symbolTableWorked = true;
7120
7121 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7122 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb;
7123
7124 // We only need the dedicated Thumb target if there's a real choice
7125 // (i.e. we're not targeting M-class) and the function is Thumb.
7126 bool UseThumbTarget = IsThumb && ThumbTarget;
7127
7128 // If we are not specifying a symbol to start disassembly with and this
7129 // is the first symbol in the section but not at the start of the section
7130 // then move the disassembly index to the start of the section and
7131 // don't print the symbol name just yet. This is so the bytes before the
7132 // first symbol are disassembled.
7133 uint64_t SymbolStart = Start;
7134 if (DisSymName.empty() && FirstSymbol && Start != 0) {
7135 FirstSymbolAtSectionStart = false;
7136 Start = 0;
7137 }
7138 else
7139 outs() << SymName << ":\n";
7140
7141 DILineInfo lastLine;
7142 for (uint64_t Index = Start; Index < End; Index += Size) {
7143 MCInst Inst;
7144
7145 // If this is the first symbol in the section and it was not at the
7146 // start of the section, see if we are at its Index now and if so print
7147 // the symbol name.
7148 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7149 outs() << SymName << ":\n";
7150
7151 uint64_t PC = SectAddress + Index;
7152 if (!NoLeadingAddr) {
7153 if (FullLeadingAddr) {
7154 if (MachOOF->is64Bit())
7155 outs() << format("%016" PRIx64"l" "x", PC);
7156 else
7157 outs() << format("%08" PRIx64"l" "x", PC);
7158 } else {
7159 outs() << format("%8" PRIx64"l" "x" ":", PC);
7160 }
7161 }
7162 if (!NoShowRawInsn || Arch == Triple::arm)
7163 outs() << "\t";
7164
7165 // Check the data in code table here to see if this is data not an
7166 // instruction to be disassembled.
7167 DiceTable Dice;
7168 Dice.push_back(std::make_pair(PC, DiceRef()));
7169 dice_table_iterator DTI =
7170 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
7171 compareDiceTableEntries);
7172 if (DTI != Dices.end()) {
7173 uint16_t Length;
7174 DTI->second.getLength(Length);
7175 uint16_t Kind;
7176 DTI->second.getKind(Kind);
7177 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind);
7178 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
7179 (PC == (DTI->first + Length - 1)) && (Length & 1))
7180 Size++;
7181 continue;
7182 }
7183
7184 SmallVector<char, 64> AnnotationsBytes;
7185 raw_svector_ostream Annotations(AnnotationsBytes);
7186
7187 bool gotInst;
7188 if (UseThumbTarget)
7189 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7190 PC, DebugOut, Annotations);
7191 else
7192 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7193 DebugOut, Annotations);
7194 if (gotInst) {
7195 if (!NoShowRawInsn || Arch == Triple::arm) {
7196 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
7197 }
7198 formatted_raw_ostream FormattedOS(outs());
7199 StringRef AnnotationsStr = Annotations.str();
7200 if (UseThumbTarget)
7201 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
7202 else
7203 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
7204 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7205
7206 // Print debug info.
7207 if (diContext) {
7208 DILineInfo dli = diContext->getLineInfoForAddress(PC);
7209 // Print valid line info if it changed.
7210 if (dli != lastLine && dli.Line != 0)
7211 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7212 << dli.Column;
7213 lastLine = dli;
7214 }
7215 outs() << "\n";
7216 } else {
7217 unsigned int Arch = MachOOF->getArch();
7218 if (Arch == Triple::x86_64 || Arch == Triple::x86) {
7219 outs() << format("\t.byte 0x%02x #bad opcode\n",
7220 *(Bytes.data() + Index) & 0xff);
7221 Size = 1; // skip exactly one illegible byte and move on.
7222 } else if (Arch == Triple::aarch64 ||
7223 (Arch == Triple::arm && !IsThumb)) {
7224 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7225 (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7226 (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7227 (*(Bytes.data() + Index + 3) & 0xff) << 24;
7228 outs() << format("\t.long\t0x%08x\n", opcode);
7229 Size = 4;
7230 } else if (Arch == Triple::arm) {
7231 assert(IsThumb && "ARM mode should have been dealt with above")(static_cast <bool> (IsThumb && "ARM mode should have been dealt with above"
) ? void (0) : __assert_fail ("IsThumb && \"ARM mode should have been dealt with above\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-objdump/MachODump.cpp"
, 7231, __extension__ __PRETTY_FUNCTION__))
;
7232 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7233 (*(Bytes.data() + Index + 1) & 0xff) << 8;
7234 outs() << format("\t.short\t0x%04x\n", opcode);
7235 Size = 2;
7236 } else{
7237 errs() << "llvm-objdump: warning: invalid instruction encoding\n";
7238 if (Size == 0)
7239 Size = 1; // skip illegible bytes
7240 }
7241 }
7242 }
7243 // Now that we are done disassembled the first symbol set the bool that
7244 // were doing this to false.
7245 FirstSymbol = false;
7246 }
7247 if (!symbolTableWorked) {
7248 // Reading the symbol table didn't work, disassemble the whole section.
7249 uint64_t SectAddress = Sections[SectIdx].getAddress();
7250 uint64_t SectSize = Sections[SectIdx].getSize();
7251 uint64_t InstSize;
7252 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7253 MCInst Inst;
7254
7255 uint64_t PC = SectAddress + Index;
7256 SmallVector<char, 64> AnnotationsBytes;
7257 raw_svector_ostream Annotations(AnnotationsBytes);
7258 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7259 DebugOut, Annotations)) {
7260 if (!NoLeadingAddr) {
7261 if (FullLeadingAddr) {
7262 if (MachOOF->is64Bit())
7263 outs() << format("%016" PRIx64"l" "x", PC);
7264 else
7265 outs() << format("%08" PRIx64"l" "x", PC);
7266 } else {
7267 outs() << format("%8" PRIx64"l" "x" ":", PC);
7268 }
7269 }
7270 if (!NoShowRawInsn || Arch == Triple::arm) {
7271 outs() << "\t";
7272 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
7273 }
7274 StringRef AnnotationsStr = Annotations.str();
7275 IP->printInst(&Inst, outs(), AnnotationsStr, *STI);
7276 outs() << "\n";
7277 } else {
7278 unsigned int Arch = MachOOF->getArch();
7279 if (Arch == Triple::x86_64 || Arch == Triple::x86) {
7280 outs() << format("\t.byte 0x%02x #bad opcode\n",
7281 *(Bytes.data() + Index) & 0xff);
7282 InstSize = 1; // skip exactly one illegible byte and move on.
7283 } else {
7284 errs() << "llvm-objdump: warning: invalid instruction encoding\n";
7285 if (InstSize == 0)
7286 InstSize = 1; // skip illegible bytes
7287 }
7288 }
7289 }
7290 }
7291 // The TripleName's need to be reset if we are called again for a different
7292 // archtecture.
7293 TripleName = "";
7294 ThumbTripleName = "";
7295
7296 if (SymbolizerInfo.method != nullptr)
7297 free(SymbolizerInfo.method);
7298 if (SymbolizerInfo.demangled_name != nullptr)
7299 free(SymbolizerInfo.demangled_name);
7300 if (ThumbSymbolizerInfo.method != nullptr)
7301 free(ThumbSymbolizerInfo.method);
7302 if (ThumbSymbolizerInfo.demangled_name != nullptr)
7303 free(ThumbSymbolizerInfo.demangled_name);
7304 }
7305}
7306
7307//===----------------------------------------------------------------------===//
7308// __compact_unwind section dumping
7309//===----------------------------------------------------------------------===//
7310
7311namespace {
7312
7313template <typename T> static uint64_t readNext(const char *&Buf) {
7314 using llvm::support::little;
7315 using llvm::support::unaligned;
7316
7317 uint64_t Val = support::endian::read<T, little, unaligned>(Buf);
7318 Buf += sizeof(T);
7319 return Val;
7320}
7321
7322struct CompactUnwindEntry {
7323 uint32_t OffsetInSection;
7324
7325 uint64_t FunctionAddr;
7326 uint32_t Length;
7327 uint32_t CompactEncoding;
7328 uint64_t PersonalityAddr;
7329 uint64_t LSDAAddr;
7330
7331 RelocationRef FunctionReloc;
7332 RelocationRef PersonalityReloc;
7333 RelocationRef LSDAReloc;
7334
7335 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
7336 : OffsetInSection(Offset) {
7337 if (Is64)
7338 read<uint64_t>(Contents.data() + Offset);
7339 else
7340 read<uint32_t>(Contents.data() + Offset);
7341 }
7342
7343private:
7344 template <typename UIntPtr> void read(const char *Buf) {
7345 FunctionAddr = readNext<UIntPtr>(Buf);
7346 Length = readNext<uint32_t>(Buf);
7347 CompactEncoding = readNext<uint32_t>(Buf);
7348 PersonalityAddr = readNext<UIntPtr>(Buf);
7349 LSDAAddr = readNext<UIntPtr>(Buf);
7350 }
7351};
7352}
7353
7354/// Given a relocation from __compact_unwind, consisting of the RelocationRef
7355/// and data being relocated, determine the best base Name and Addend to use for
7356/// display purposes.
7357///
7358/// 1. An Extern relocation will directly reference a symbol (and the data is
7359/// then already an addend), so use that.
7360/// 2. Otherwise the data is an offset in the object file's layout; try to find
7361// a symbol before it in the same section, and use the offset from there.
7362/// 3. Finally, if all that fails, fall back to an offset from the start of the
7363/// referenced section.
7364static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
7365 std::map<uint64_t, SymbolRef> &Symbols,
7366 const RelocationRef &Reloc, uint64_t Addr,
7367 StringRef &Name, uint64_t &Addend) {
7368 if (Reloc.getSymbol() != Obj->symbol_end()) {
7369 Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
7370 if (!NameOrErr)
7371 report_error(Obj->getFileName(), NameOrErr.takeError());
7372 Name = *NameOrErr;
7373 Addend = Addr;
7374 return;
7375 }
7376
7377 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
7378 SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
7379
7380 uint64_t SectionAddr = RelocSection.getAddress();
7381
7382 auto Sym = Symbols.upper_bound(Addr);
7383 if (Sym == Symbols.begin()) {
7384 // The first symbol in the object is after this reference, the best we can
7385 // do is section-relative notation.
7386 RelocSection.getName(Name);
7387 Addend = Addr - SectionAddr;
7388 return;
7389 }
7390
7391 // Go back one so that SymbolAddress <= Addr.
7392 --Sym;
7393
7394 auto SectOrErr = Sym->second.getSection();
7395 if (!SectOrErr)
7396 report_error(Obj->getFileName(), SectOrErr.takeError());
7397 section_iterator SymSection = *SectOrErr;
7398 if (RelocSection == *SymSection) {
7399 // There's a valid symbol in the same section before this reference.
7400 Expected<StringRef> NameOrErr = Sym->second.getName();
7401 if (!NameOrErr)
7402 report_error(Obj->getFileName(), NameOrErr.takeError());
7403 Name = *NameOrErr;
7404 Addend = Addr - Sym->first;
7405 return;
7406 }
7407
7408 // There is a symbol before this reference, but it's in a different
7409 // section. Probably not helpful to mention it, so use the section name.
7410 RelocSection.getName(Name);
7411 Addend = Addr - SectionAddr;
7412}
7413
7414static void printUnwindRelocDest(const MachOObjectFile *Obj,
7415 std::map<uint64_t, SymbolRef> &Symbols,
7416 const RelocationRef &Reloc, uint64_t Addr) {
7417 StringRef Name;
7418 uint64_t Addend;
7419
7420 if (!Reloc.getObject())
7421 return;
7422
7423 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7424
7425 outs() << Name;
7426 if (Addend)
7427 outs() << " + " << format("0x%" PRIx64"l" "x", Addend);
7428}
7429
7430static void
7431printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7432 std::map<uint64_t, SymbolRef> &Symbols,
7433 const SectionRef &CompactUnwind) {
7434
7435 if (!Obj->isLittleEndian()) {
7436 outs() << "Skipping big-endian __compact_unwind section\n";
7437 return;
7438 }
7439
7440 bool Is64 = Obj->is64Bit();
7441 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7442 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7443
7444 StringRef Contents;
7445 CompactUnwind.getContents(Contents);
7446
7447 SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7448
7449 // First populate the initial raw offsets, encodings and so on from the entry.
7450 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7451 CompactUnwindEntry Entry(Contents.data(), Offset, Is64);
7452 CompactUnwinds.push_back(Entry);
7453 }
7454
7455 // Next we need to look at the relocations to find out what objects are
7456 // actually being referred to.
7457 for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7458 uint64_t RelocAddress = Reloc.getOffset();
7459
7460 uint32_t EntryIdx = RelocAddress / EntrySize;
7461 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7462 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7463
7464 if (OffsetInEntry == 0)
7465 Entry.FunctionReloc = Reloc;
7466 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7467 Entry.PersonalityReloc = Reloc;
7468 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7469 Entry.LSDAReloc = Reloc;