Bug Summary

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

Annotated Source Code

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