Bug Summary

File:include/llvm/Object/ObjectFile.h
Warning:line 401, column 10
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MachODump.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-8/lib/clang/8.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/llvm-objdump -I /build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-objdump -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/include -I /build/llvm-toolchain-snapshot-8~svn345461/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/8.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-8/lib/clang/8.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/llvm-objdump -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-10-27-211344-32123-1 -x c++ /build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-objdump/MachODump.cpp -faddrsig

/build/llvm-toolchain-snapshot-8~svn345461/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 ArchiveMemberOffsets("archive-member-offsets",
80 cl::desc("Print the offset to each archive member for "
81 "Mach-O archives (requires -macho and "
82 "-archive-headers)"));
83
84cl::opt<bool>
85 llvm::IndirectSymbols("indirect-symbols",
86 cl::desc("Print indirect symbol table for Mach-O "
87 "objects (requires -macho)"));
88
89cl::opt<bool>
90 llvm::DataInCode("data-in-code",
91 cl::desc("Print the data in code table for Mach-O objects "
92 "(requires -macho)"));
93
94cl::opt<bool>
95 llvm::LinkOptHints("link-opt-hints",
96 cl::desc("Print the linker optimization hints for "
97 "Mach-O objects (requires -macho)"));
98
99cl::opt<bool>
100 llvm::InfoPlist("info-plist",
101 cl::desc("Print the info plist section as strings for "
102 "Mach-O objects (requires -macho)"));
103
104cl::opt<bool>
105 llvm::DylibsUsed("dylibs-used",
106 cl::desc("Print the shared libraries used for linked "
107 "Mach-O files (requires -macho)"));
108
109cl::opt<bool>
110 llvm::DylibId("dylib-id",
111 cl::desc("Print the shared library's id for the dylib Mach-O "
112 "file (requires -macho)"));
113
114cl::opt<bool>
115 llvm::NonVerbose("non-verbose",
116 cl::desc("Print the info for Mach-O objects in "
117 "non-verbose or numeric form (requires -macho)"));
118
119cl::opt<bool>
120 llvm::ObjcMetaData("objc-meta-data",
121 cl::desc("Print the Objective-C runtime meta data for "
122 "Mach-O files (requires -macho)"));
123
124cl::opt<std::string> llvm::DisSymName(
125 "dis-symname",
126 cl::desc("disassemble just this symbol's instructions (requires -macho)"));
127
128static cl::opt<bool> NoSymbolicOperands(
129 "no-symbolic-operands",
130 cl::desc("do not symbolic operands when disassembling (requires -macho)"));
131
132static cl::list<std::string>
133 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
134 cl::ZeroOrMore);
135
136bool ArchAll = false;
137
138static std::string ThumbTripleName;
139
140static const Target *GetTarget(const MachOObjectFile *MachOObj,
141 const char **McpuDefault,
142 const Target **ThumbTarget) {
143 // Figure out the target triple.
144 llvm::Triple TT(TripleName);
145 if (TripleName.empty()) {
146 TT = MachOObj->getArchTriple(McpuDefault);
147 TripleName = TT.str();
148 }
149
150 if (TT.getArch() == Triple::arm) {
151 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
152 // that support ARM are also capable of Thumb mode.
153 llvm::Triple ThumbTriple = TT;
154 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
155 ThumbTriple.setArchName(ThumbName);
156 ThumbTripleName = ThumbTriple.str();
157 }
158
159 // Get the target specific parser.
160 std::string Error;
161 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
162 if (TheTarget && ThumbTripleName.empty())
163 return TheTarget;
164
165 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
166 if (*ThumbTarget)
167 return TheTarget;
168
169 errs() << "llvm-objdump: error: unable to get target for '";
170 if (!TheTarget)
171 errs() << TripleName;
172 else
173 errs() << ThumbTripleName;
174 errs() << "', see --version and --triple.\n";
175 return nullptr;
176}
177
178struct SymbolSorter {
179 bool operator()(const SymbolRef &A, const SymbolRef &B) {
180 Expected<SymbolRef::Type> ATypeOrErr = A.getType();
181 if (!ATypeOrErr)
182 report_error(A.getObject()->getFileName(), ATypeOrErr.takeError());
183 SymbolRef::Type AType = *ATypeOrErr;
184 Expected<SymbolRef::Type> BTypeOrErr = B.getType();
185 if (!BTypeOrErr)
186 report_error(B.getObject()->getFileName(), BTypeOrErr.takeError());
187 SymbolRef::Type BType = *BTypeOrErr;
188 uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
189 uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
190 return AAddr < BAddr;
191 }
192};
193
194// Types for the storted data in code table that is built before disassembly
195// and the predicate function to sort them.
196typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
197typedef std::vector<DiceTableEntry> DiceTable;
198typedef DiceTable::iterator dice_table_iterator;
199
200#ifdef HAVE_LIBXAR
201namespace {
202struct ScopedXarFile {
203 xar_t xar;
204 ScopedXarFile(const char *filename, int32_t flags)
205 : xar(xar_open(filename, flags)) {}
206 ~ScopedXarFile() {
207 if (xar)
208 xar_close(xar);
209 }
210 ScopedXarFile(const ScopedXarFile &) = delete;
211 ScopedXarFile &operator=(const ScopedXarFile &) = delete;
212 operator xar_t() { return xar; }
213};
214
215struct ScopedXarIter {
216 xar_iter_t iter;
217 ScopedXarIter() : iter(xar_iter_new()) {}
218 ~ScopedXarIter() {
219 if (iter)
220 xar_iter_free(iter);
221 }
222 ScopedXarIter(const ScopedXarIter &) = delete;
223 ScopedXarIter &operator=(const ScopedXarIter &) = delete;
224 operator xar_iter_t() { return iter; }
225};
226} // namespace
227#endif // defined(HAVE_LIBXAR)
228
229// This is used to search for a data in code table entry for the PC being
230// disassembled. The j parameter has the PC in j.first. A single data in code
231// table entry can cover many bytes for each of its Kind's. So if the offset,
232// aka the i.first value, of the data in code table entry plus its Length
233// covers the PC being searched for this will return true. If not it will
234// return false.
235static bool compareDiceTableEntries(const DiceTableEntry &i,
236 const DiceTableEntry &j) {
237 uint16_t Length;
238 i.second.getLength(Length);
239
240 return j.first >= i.first && j.first < i.first + Length;
241}
242
243static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
244 unsigned short Kind) {
245 uint32_t Value, Size = 1;
246
247 switch (Kind) {
248 default:
249 case MachO::DICE_KIND_DATA:
250 if (Length >= 4) {
251 if (!NoShowRawInsn)
252 dumpBytes(makeArrayRef(bytes, 4), outs());
253 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
254 outs() << "\t.long " << Value;
255 Size = 4;
256 } else if (Length >= 2) {
257 if (!NoShowRawInsn)
258 dumpBytes(makeArrayRef(bytes, 2), outs());
259 Value = bytes[1] << 8 | bytes[0];
260 outs() << "\t.short " << Value;
261 Size = 2;
262 } else {
263 if (!NoShowRawInsn)
264 dumpBytes(makeArrayRef(bytes, 2), outs());
265 Value = bytes[0];
266 outs() << "\t.byte " << Value;
267 Size = 1;
268 }
269 if (Kind == MachO::DICE_KIND_DATA)
270 outs() << "\t@ KIND_DATA\n";
271 else
272 outs() << "\t@ data in code kind = " << Kind << "\n";
273 break;
274 case MachO::DICE_KIND_JUMP_TABLE8:
275 if (!NoShowRawInsn)
276 dumpBytes(makeArrayRef(bytes, 1), outs());
277 Value = bytes[0];
278 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
279 Size = 1;
280 break;
281 case MachO::DICE_KIND_JUMP_TABLE16:
282 if (!NoShowRawInsn)
283 dumpBytes(makeArrayRef(bytes, 2), outs());
284 Value = bytes[1] << 8 | bytes[0];
285 outs() << "\t.short " << format("%5u", Value & 0xffff)
286 << "\t@ KIND_JUMP_TABLE16\n";
287 Size = 2;
288 break;
289 case MachO::DICE_KIND_JUMP_TABLE32:
290 case MachO::DICE_KIND_ABS_JUMP_TABLE32:
291 if (!NoShowRawInsn)
292 dumpBytes(makeArrayRef(bytes, 4), outs());
293 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
294 outs() << "\t.long " << Value;
295 if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
296 outs() << "\t@ KIND_JUMP_TABLE32\n";
297 else
298 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
299 Size = 4;
300 break;
301 }
302 return Size;
303}
304
305static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
306 std::vector<SectionRef> &Sections,
307 std::vector<SymbolRef> &Symbols,
308 SmallVectorImpl<uint64_t> &FoundFns,
309 uint64_t &BaseSegmentAddress) {
310 for (const SymbolRef &Symbol : MachOObj->symbols()) {
311 Expected<StringRef> SymName = Symbol.getName();
312 if (!SymName)
313 report_error(MachOObj->getFileName(), SymName.takeError());
314 if (!SymName->startswith("ltmp"))
315 Symbols.push_back(Symbol);
316 }
317
318 for (const SectionRef &Section : MachOObj->sections()) {
319 StringRef SectName;
320 Section.getName(SectName);
321 Sections.push_back(Section);
322 }
323
324 bool BaseSegmentAddressSet = false;
325 for (const auto &Command : MachOObj->load_commands()) {
326 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
327 // We found a function starts segment, parse the addresses for later
328 // consumption.
329 MachO::linkedit_data_command LLC =
330 MachOObj->getLinkeditDataLoadCommand(Command);
331
332 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
333 } else if (Command.C.cmd == MachO::LC_SEGMENT) {
334 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
335 StringRef SegName = SLC.segname;
336 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
337 BaseSegmentAddressSet = true;
338 BaseSegmentAddress = SLC.vmaddr;
339 }
340 }
341 }
342}
343
344static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
345 uint32_t n, uint32_t count,
346 uint32_t stride, uint64_t addr) {
347 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
348 uint32_t nindirectsyms = Dysymtab.nindirectsyms;
349 if (n > nindirectsyms)
350 outs() << " (entries start past the end of the indirect symbol "
351 "table) (reserved1 field greater than the table size)";
352 else if (n + count > nindirectsyms)
353 outs() << " (entries extends past the end of the indirect symbol "
354 "table)";
355 outs() << "\n";
356 uint32_t cputype = O->getHeader().cputype;
357 if (cputype & MachO::CPU_ARCH_ABI64)
358 outs() << "address index";
359 else
360 outs() << "address index";
361 if (verbose)
362 outs() << " name\n";
363 else
364 outs() << "\n";
365 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
366 if (cputype & MachO::CPU_ARCH_ABI64)
367 outs() << format("0x%016" PRIx64"l" "x", addr + j * stride) << " ";
368 else
369 outs() << format("0x%08" PRIx32"x", (uint32_t)addr + j * stride) << " ";
370 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
371 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
372 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
373 outs() << "LOCAL\n";
374 continue;
375 }
376 if (indirect_symbol ==
377 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
378 outs() << "LOCAL ABSOLUTE\n";
379 continue;
380 }
381 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
382 outs() << "ABSOLUTE\n";
383 continue;
384 }
385 outs() << format("%5u ", indirect_symbol);
386 if (verbose) {
387 MachO::symtab_command Symtab = O->getSymtabLoadCommand();
388 if (indirect_symbol < Symtab.nsyms) {
389 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
390 SymbolRef Symbol = *Sym;
391 Expected<StringRef> SymName = Symbol.getName();
392 if (!SymName)
393 report_error(O->getFileName(), SymName.takeError());
394 outs() << *SymName;
395 } else {
396 outs() << "?";
397 }
398 }
399 outs() << "\n";
400 }
401}
402
403static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
404 for (const auto &Load : O->load_commands()) {
405 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
406 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
407 for (unsigned J = 0; J < Seg.nsects; ++J) {
408 MachO::section_64 Sec = O->getSection64(Load, J);
409 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
410 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
411 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
412 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
413 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
414 section_type == MachO::S_SYMBOL_STUBS) {
415 uint32_t stride;
416 if (section_type == MachO::S_SYMBOL_STUBS)
417 stride = Sec.reserved2;
418 else
419 stride = 8;
420 if (stride == 0) {
421 outs() << "Can't print indirect symbols for (" << Sec.segname << ","
422 << Sec.sectname << ") "
423 << "(size of stubs in reserved2 field is zero)\n";
424 continue;
425 }
426 uint32_t count = Sec.size / stride;
427 outs() << "Indirect symbols for (" << Sec.segname << ","
428 << Sec.sectname << ") " << count << " entries";
429 uint32_t n = Sec.reserved1;
430 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
431 }
432 }
433 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
434 MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
435 for (unsigned J = 0; J < Seg.nsects; ++J) {
436 MachO::section Sec = O->getSection(Load, J);
437 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
438 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
439 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
440 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
441 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
442 section_type == MachO::S_SYMBOL_STUBS) {
443 uint32_t stride;
444 if (section_type == MachO::S_SYMBOL_STUBS)
445 stride = Sec.reserved2;
446 else
447 stride = 4;
448 if (stride == 0) {
449 outs() << "Can't print indirect symbols for (" << Sec.segname << ","
450 << Sec.sectname << ") "
451 << "(size of stubs in reserved2 field is zero)\n";
452 continue;
453 }
454 uint32_t count = Sec.size / stride;
455 outs() << "Indirect symbols for (" << Sec.segname << ","
456 << Sec.sectname << ") " << count << " entries";
457 uint32_t n = Sec.reserved1;
458 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
459 }
460 }
461 }
462 }
463}
464
465static void PrintRType(const uint64_t cputype, const unsigned r_type) {
466 static char const *generic_r_types[] = {
467 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ",
468 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ",
469 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
470 };
471 static char const *x86_64_r_types[] = {
472 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ",
473 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ",
474 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
475 };
476 static char const *arm_r_types[] = {
477 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
478 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ",
479 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
480 };
481 static char const *arm64_r_types[] = {
482 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ",
483 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF",
484 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
485 };
486
487 if (r_type > 0xf){
488 outs() << format("%-7u", r_type) << " ";
489 return;
490 }
491 switch (cputype) {
492 case MachO::CPU_TYPE_I386:
493 outs() << generic_r_types[r_type];
494 break;
495 case MachO::CPU_TYPE_X86_64:
496 outs() << x86_64_r_types[r_type];
497 break;
498 case MachO::CPU_TYPE_ARM:
499 outs() << arm_r_types[r_type];
500 break;
501 case MachO::CPU_TYPE_ARM64:
502 outs() << arm64_r_types[r_type];
503 break;
504 default:
505 outs() << format("%-7u ", r_type);
506 }
507}
508
509static void PrintRLength(const uint64_t cputype, const unsigned r_type,
510 const unsigned r_length, const bool previous_arm_half){
511 if (cputype == MachO::CPU_TYPE_ARM &&
512 (r_type == llvm::MachO::ARM_RELOC_HALF ||
513 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF ||
514 previous_arm_half == true)) {
515 if ((r_length & 0x1) == 0)
516 outs() << "lo/";
517 else
518 outs() << "hi/";
519 if ((r_length & 0x1) == 0)
520 outs() << "arm ";
521 else
522 outs() << "thm ";
523 } else {
524 switch (r_length) {
525 case 0:
526 outs() << "byte ";
527 break;
528 case 1:
529 outs() << "word ";
530 break;
531 case 2:
532 outs() << "long ";
533 break;
534 case 3:
535 if (cputype == MachO::CPU_TYPE_X86_64)
536 outs() << "quad ";
537 else
538 outs() << format("?(%2d) ", r_length);
539 break;
540 default:
541 outs() << format("?(%2d) ", r_length);
542 }
543 }
544}
545
546static void PrintRelocationEntries(const MachOObjectFile *O,
547 const relocation_iterator Begin,
548 const relocation_iterator End,
549 const uint64_t cputype,
550 const bool verbose) {
551 const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
552 bool previous_arm_half = false;
553 bool previous_sectdiff = false;
554 uint32_t sectdiff_r_type = 0;
555
556 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
557 const DataRefImpl Rel = Reloc->getRawDataRefImpl();
558 const MachO::any_relocation_info RE = O->getRelocation(Rel);
559 const unsigned r_type = O->getAnyRelocationType(RE);
560 const bool r_scattered = O->isRelocationScattered(RE);
561 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
562 const unsigned r_length = O->getAnyRelocationLength(RE);
563 const unsigned r_address = O->getAnyRelocationAddress(RE);
564 const bool r_extern = (r_scattered ? false :
565 O->getPlainRelocationExternal(RE));
566 const uint32_t r_value = (r_scattered ?
567 O->getScatteredRelocationValue(RE) : 0);
568 const unsigned r_symbolnum = (r_scattered ? 0 :
569 O->getPlainRelocationSymbolNum(RE));
570
571 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
572 if (verbose) {
573 // scattered: address
574 if ((cputype == MachO::CPU_TYPE_I386 &&
575 r_type == llvm::MachO::GENERIC_RELOC_PAIR) ||
576 (cputype == MachO::CPU_TYPE_ARM &&
577 r_type == llvm::MachO::ARM_RELOC_PAIR))
578 outs() << " ";
579 else
580 outs() << format("%08x ", (unsigned int)r_address);
581
582 // scattered: pcrel
583 if (r_pcrel)
584 outs() << "True ";
585 else
586 outs() << "False ";
587
588 // scattered: length
589 PrintRLength(cputype, r_type, r_length, previous_arm_half);
590
591 // scattered: extern & type
592 outs() << "n/a ";
593 PrintRType(cputype, r_type);
594
595 // scattered: scattered & value
596 outs() << format("True 0x%08x", (unsigned int)r_value);
597 if (previous_sectdiff == false) {
598 if ((cputype == MachO::CPU_TYPE_ARM &&
599 r_type == llvm::MachO::ARM_RELOC_PAIR))
600 outs() << format(" half = 0x%04x ", (unsigned int)r_address);
601 }
602 else if (cputype == MachO::CPU_TYPE_ARM &&
603 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)
604 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
605 if ((cputype == MachO::CPU_TYPE_I386 &&
606 (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF ||
607 r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
608 (cputype == MachO::CPU_TYPE_ARM &&
609 (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF ||
610 sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF ||
611 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) {
612 previous_sectdiff = true;
613 sectdiff_r_type = r_type;
614 }
615 else {
616 previous_sectdiff = false;
617 sectdiff_r_type = 0;
618 }
619 if (cputype == MachO::CPU_TYPE_ARM &&
620 (r_type == llvm::MachO::ARM_RELOC_HALF ||
621 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
622 previous_arm_half = true;
623 else
624 previous_arm_half = false;
625 outs() << "\n";
626 }
627 else {
628 // scattered: address pcrel length extern type scattered value
629 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n",
630 (unsigned int)r_address, r_pcrel, r_length, r_type,
631 (unsigned int)r_value);
632 }
633 }
634 else {
635 if (verbose) {
636 // plain: address
637 if (cputype == MachO::CPU_TYPE_ARM &&
638 r_type == llvm::MachO::ARM_RELOC_PAIR)
639 outs() << " ";
640 else
641 outs() << format("%08x ", (unsigned int)r_address);
642
643 // plain: pcrel
644 if (r_pcrel)
645 outs() << "True ";
646 else
647 outs() << "False ";
648
649 // plain: length
650 PrintRLength(cputype, r_type, r_length, previous_arm_half);
651
652 if (r_extern) {
653 // plain: extern & type & scattered
654 outs() << "True ";
655 PrintRType(cputype, r_type);
656 outs() << "False ";
657
658 // plain: symbolnum/value
659 if (r_symbolnum > Symtab.nsyms)
660 outs() << format("?(%d)\n", r_symbolnum);
661 else {
662 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
663 Expected<StringRef> SymNameNext = Symbol.getName();
664 const char *name = NULL__null;
665 if (SymNameNext)
666 name = SymNameNext->data();
667 if (name == NULL__null)
668 outs() << format("?(%d)\n", r_symbolnum);
669 else
670 outs() << name << "\n";
671 }
672 }
673 else {
674 // plain: extern & type & scattered
675 outs() << "False ";
676 PrintRType(cputype, r_type);
677 outs() << "False ";
678
679 // plain: symbolnum/value
680 if (cputype == MachO::CPU_TYPE_ARM &&
681 r_type == llvm::MachO::ARM_RELOC_PAIR)
682 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
683 else if (cputype == MachO::CPU_TYPE_ARM64 &&
684 r_type == llvm::MachO::ARM64_RELOC_ADDEND)
685 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
686 else {
687 outs() << format("%d ", r_symbolnum);
688 if (r_symbolnum == llvm::MachO::R_ABS)
689 outs() << "R_ABS\n";
690 else {
691 // in this case, r_symbolnum is actually a 1-based section number
692 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
693 if (r_symbolnum > 0 && r_symbolnum <= nsects) {
694 llvm::object::DataRefImpl DRI;
695 DRI.d.a = r_symbolnum-1;
696 StringRef SegName = O->getSectionFinalSegmentName(DRI);
697 StringRef SectName;
698 if (O->getSectionName(DRI, SectName))
699 outs() << "(?,?)\n";
700 else
701 outs() << "(" << SegName << "," << SectName << ")\n";
702 }
703 else {
704 outs() << "(?,?)\n";
705 }
706 }
707 }
708 }
709 if (cputype == MachO::CPU_TYPE_ARM &&
710 (r_type == llvm::MachO::ARM_RELOC_HALF ||
711 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
712 previous_arm_half = true;
713 else
714 previous_arm_half = false;
715 }
716 else {
717 // plain: address pcrel length extern type scattered symbolnum/section
718 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n",
719 (unsigned int)r_address, r_pcrel, r_length, r_extern,
720 r_type, r_symbolnum);
721 }
722 }
723 }
724}
725
726static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
727 const uint64_t cputype = O->getHeader().cputype;
728 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
729 if (Dysymtab.nextrel != 0) {
730 outs() << "External relocation information " << Dysymtab.nextrel
731 << " entries";
732 outs() << "\naddress pcrel length extern type scattered "
733 "symbolnum/value\n";
734 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
735 verbose);
736 }
737 if (Dysymtab.nlocrel != 0) {
738 outs() << format("Local relocation information %u entries",
739 Dysymtab.nlocrel);
740 outs() << "\naddress pcrel length extern type scattered "
741 "symbolnum/value\n";
742 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
743 verbose);
744 }
745 for (const auto &Load : O->load_commands()) {
746 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
747 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
748 for (unsigned J = 0; J < Seg.nsects; ++J) {
749 const MachO::section_64 Sec = O->getSection64(Load, J);
750 if (Sec.nreloc != 0) {
751 DataRefImpl DRI;
752 DRI.d.a = J;
753 const StringRef SegName = O->getSectionFinalSegmentName(DRI);
754 StringRef SectName;
755 if (O->getSectionName(DRI, SectName))
756 outs() << "Relocation information (" << SegName << ",?) "
757 << format("%u entries", Sec.nreloc);
758 else
759 outs() << "Relocation information (" << SegName << ","
760 << SectName << format(") %u entries", Sec.nreloc);
761 outs() << "\naddress pcrel length extern type scattered "
762 "symbolnum/value\n";
763 PrintRelocationEntries(O, O->section_rel_begin(DRI),
764 O->section_rel_end(DRI), cputype, verbose);
765 }
766 }
767 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
768 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
769 for (unsigned J = 0; J < Seg.nsects; ++J) {
770 const MachO::section Sec = O->getSection(Load, J);
771 if (Sec.nreloc != 0) {
772 DataRefImpl DRI;
773 DRI.d.a = J;
774 const StringRef SegName = O->getSectionFinalSegmentName(DRI);
775 StringRef SectName;
776 if (O->getSectionName(DRI, SectName))
777 outs() << "Relocation information (" << SegName << ",?) "
778 << format("%u entries", Sec.nreloc);
779 else
780 outs() << "Relocation information (" << SegName << ","
781 << SectName << format(") %u entries", Sec.nreloc);
782 outs() << "\naddress pcrel length extern type scattered "
783 "symbolnum/value\n";
784 PrintRelocationEntries(O, O->section_rel_begin(DRI),
785 O->section_rel_end(DRI), cputype, verbose);
786 }
787 }
788 }
789 }
790}
791
792static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
793 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
794 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
795 outs() << "Data in code table (" << nentries << " entries)\n";
796 outs() << "offset length kind\n";
797 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
798 ++DI) {
799 uint32_t Offset;
800 DI->getOffset(Offset);
801 outs() << format("0x%08" PRIx32"x", Offset) << " ";
802 uint16_t Length;
803 DI->getLength(Length);
804 outs() << format("%6u", Length) << " ";
805 uint16_t Kind;
806 DI->getKind(Kind);
807 if (verbose) {
808 switch (Kind) {
809 case MachO::DICE_KIND_DATA:
810 outs() << "DATA";
811 break;
812 case MachO::DICE_KIND_JUMP_TABLE8:
813 outs() << "JUMP_TABLE8";
814 break;
815 case MachO::DICE_KIND_JUMP_TABLE16:
816 outs() << "JUMP_TABLE16";
817 break;
818 case MachO::DICE_KIND_JUMP_TABLE32:
819 outs() << "JUMP_TABLE32";
820 break;
821 case MachO::DICE_KIND_ABS_JUMP_TABLE32:
822 outs() << "ABS_JUMP_TABLE32";
823 break;
824 default:
825 outs() << format("0x%04" PRIx32"x", Kind);
826 break;
827 }
828 } else
829 outs() << format("0x%04" PRIx32"x", Kind);
830 outs() << "\n";
831 }
832}
833
834static void PrintLinkOptHints(MachOObjectFile *O) {
835 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
836 const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
837 uint32_t nloh = LohLC.datasize;
838 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
839 for (uint32_t i = 0; i < nloh;) {
840 unsigned n;
841 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
842 i += n;
843 outs() << " identifier " << identifier << " ";
844 if (i >= nloh)
845 return;
846 switch (identifier) {
847 case 1:
848 outs() << "AdrpAdrp\n";
849 break;
850 case 2:
851 outs() << "AdrpLdr\n";
852 break;
853 case 3:
854 outs() << "AdrpAddLdr\n";
855 break;
856 case 4:
857 outs() << "AdrpLdrGotLdr\n";
858 break;
859 case 5:
860 outs() << "AdrpAddStr\n";
861 break;
862 case 6:
863 outs() << "AdrpLdrGotStr\n";
864 break;
865 case 7:
866 outs() << "AdrpAdd\n";
867 break;
868 case 8:
869 outs() << "AdrpLdrGot\n";
870 break;
871 default:
872 outs() << "Unknown identifier value\n";
873 break;
874 }
875 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
876 i += n;
877 outs() << " narguments " << narguments << "\n";
878 if (i >= nloh)
879 return;
880
881 for (uint32_t j = 0; j < narguments; j++) {
882 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
883 i += n;
884 outs() << "\tvalue " << format("0x%" PRIx64"l" "x", value) << "\n";
885 if (i >= nloh)
886 return;
887 }
888 }
889}
890
891static void PrintDylibs(MachOObjectFile *O, bool JustId) {
892 unsigned Index = 0;
893 for (const auto &Load : O->load_commands()) {
894 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
895 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
896 Load.C.cmd == MachO::LC_LOAD_DYLIB ||
897 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
898 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
899 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
900 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
901 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
902 if (dl.dylib.name < dl.cmdsize) {
903 const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
904 if (JustId)
905 outs() << p << "\n";
906 else {
907 outs() << "\t" << p;
908 outs() << " (compatibility version "
909 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
910 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
911 << (dl.dylib.compatibility_version & 0xff) << ",";
912 outs() << " current version "
913 << ((dl.dylib.current_version >> 16) & 0xffff) << "."
914 << ((dl.dylib.current_version >> 8) & 0xff) << "."
915 << (dl.dylib.current_version & 0xff) << ")\n";
916 }
917 } else {
918 outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
919 if (Load.C.cmd == MachO::LC_ID_DYLIB)
920 outs() << "LC_ID_DYLIB ";
921 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
922 outs() << "LC_LOAD_DYLIB ";
923 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
924 outs() << "LC_LOAD_WEAK_DYLIB ";
925 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
926 outs() << "LC_LAZY_LOAD_DYLIB ";
927 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
928 outs() << "LC_REEXPORT_DYLIB ";
929 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
930 outs() << "LC_LOAD_UPWARD_DYLIB ";
931 else
932 outs() << "LC_??? ";
933 outs() << "command " << Index++ << "\n";
934 }
935 }
936 }
937}
938
939typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
940
941static void CreateSymbolAddressMap(MachOObjectFile *O,
942 SymbolAddressMap *AddrMap) {
943 // Create a map of symbol addresses to symbol names.
944 for (const SymbolRef &Symbol : O->symbols()) {
945 Expected<SymbolRef::Type> STOrErr = Symbol.getType();
946 if (!STOrErr)
947 report_error(O->getFileName(), STOrErr.takeError());
948 SymbolRef::Type ST = *STOrErr;
949 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
950 ST == SymbolRef::ST_Other) {
951 uint64_t Address = Symbol.getValue();
952 Expected<StringRef> SymNameOrErr = Symbol.getName();
953 if (!SymNameOrErr)
954 report_error(O->getFileName(), SymNameOrErr.takeError());
955 StringRef SymName = *SymNameOrErr;
956 if (!SymName.startswith(".objc"))
957 (*AddrMap)[Address] = SymName;
958 }
959 }
960}
961
962// GuessSymbolName is passed the address of what might be a symbol and a
963// pointer to the SymbolAddressMap. It returns the name of a symbol
964// with that address or nullptr if no symbol is found with that address.
965static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
966 const char *SymbolName = nullptr;
967 // A DenseMap can't lookup up some values.
968 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
969 StringRef name = AddrMap->lookup(value);
970 if (!name.empty())
971 SymbolName = name.data();
972 }
973 return SymbolName;
974}
975
976static void DumpCstringChar(const char c) {
977 char p[2];
978 p[0] = c;
979 p[1] = '\0';
980 outs().write_escaped(p);
981}
982
983static void DumpCstringSection(MachOObjectFile *O, const char *sect,
984 uint32_t sect_size, uint64_t sect_addr,
985 bool print_addresses) {
986 for (uint32_t i = 0; i < sect_size; i++) {
987 if (print_addresses) {
988 if (O->is64Bit())
989 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
990 else
991 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
992 }
993 for (; i < sect_size && sect[i] != '\0'; i++)
994 DumpCstringChar(sect[i]);
995 if (i < sect_size && sect[i] == '\0')
996 outs() << "\n";
997 }
998}
999
1000static void DumpLiteral4(uint32_t l, float f) {
1001 outs() << format("0x%08" PRIx32"x", l);
1002 if ((l & 0x7f800000) != 0x7f800000)
1003 outs() << format(" (%.16e)\n", f);
1004 else {
1005 if (l == 0x7f800000)
1006 outs() << " (+Infinity)\n";
1007 else if (l == 0xff800000)
1008 outs() << " (-Infinity)\n";
1009 else if ((l & 0x00400000) == 0x00400000)
1010 outs() << " (non-signaling Not-a-Number)\n";
1011 else
1012 outs() << " (signaling Not-a-Number)\n";
1013 }
1014}
1015
1016static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
1017 uint32_t sect_size, uint64_t sect_addr,
1018 bool print_addresses) {
1019 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
1020 if (print_addresses) {
1021 if (O->is64Bit())
1022 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
1023 else
1024 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
1025 }
1026 float f;
1027 memcpy(&f, sect + i, sizeof(float));
1028 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1029 sys::swapByteOrder(f);
1030 uint32_t l;
1031 memcpy(&l, sect + i, sizeof(uint32_t));
1032 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1033 sys::swapByteOrder(l);
1034 DumpLiteral4(l, f);
1035 }
1036}
1037
1038static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
1039 double d) {
1040 outs() << format("0x%08" PRIx32"x", l0) << " " << format("0x%08" PRIx32"x", l1);
1041 uint32_t Hi, Lo;
1042 Hi = (O->isLittleEndian()) ? l1 : l0;
1043 Lo = (O->isLittleEndian()) ? l0 : l1;
1044
1045 // Hi is the high word, so this is equivalent to if(isfinite(d))
1046 if ((Hi & 0x7ff00000) != 0x7ff00000)
1047 outs() << format(" (%.16e)\n", d);
1048 else {
1049 if (Hi == 0x7ff00000 && Lo == 0)
1050 outs() << " (+Infinity)\n";
1051 else if (Hi == 0xfff00000 && Lo == 0)
1052 outs() << " (-Infinity)\n";
1053 else if ((Hi & 0x00080000) == 0x00080000)
1054 outs() << " (non-signaling Not-a-Number)\n";
1055 else
1056 outs() << " (signaling Not-a-Number)\n";
1057 }
1058}
1059
1060static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
1061 uint32_t sect_size, uint64_t sect_addr,
1062 bool print_addresses) {
1063 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
1064 if (print_addresses) {
1065 if (O->is64Bit())
1066 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
1067 else
1068 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
1069 }
1070 double d;
1071 memcpy(&d, sect + i, sizeof(double));
1072 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1073 sys::swapByteOrder(d);
1074 uint32_t l0, l1;
1075 memcpy(&l0, sect + i, sizeof(uint32_t));
1076 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1077 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1078 sys::swapByteOrder(l0);
1079 sys::swapByteOrder(l1);
1080 }
1081 DumpLiteral8(O, l0, l1, d);
1082 }
1083}
1084
1085static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
1086 outs() << format("0x%08" PRIx32"x", l0) << " ";
1087 outs() << format("0x%08" PRIx32"x", l1) << " ";
1088 outs() << format("0x%08" PRIx32"x", l2) << " ";
1089 outs() << format("0x%08" PRIx32"x", l3) << "\n";
1090}
1091
1092static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
1093 uint32_t sect_size, uint64_t sect_addr,
1094 bool print_addresses) {
1095 for (uint32_t i = 0; i < sect_size; i += 16) {
1096 if (print_addresses) {
1097 if (O->is64Bit())
1098 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
1099 else
1100 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
1101 }
1102 uint32_t l0, l1, l2, l3;
1103 memcpy(&l0, sect + i, sizeof(uint32_t));
1104 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1105 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
1106 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
1107 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1108 sys::swapByteOrder(l0);
1109 sys::swapByteOrder(l1);
1110 sys::swapByteOrder(l2);
1111 sys::swapByteOrder(l3);
1112 }
1113 DumpLiteral16(l0, l1, l2, l3);
1114 }
1115}
1116
1117static void DumpLiteralPointerSection(MachOObjectFile *O,
1118 const SectionRef &Section,
1119 const char *sect, uint32_t sect_size,
1120 uint64_t sect_addr,
1121 bool print_addresses) {
1122 // Collect the literal sections in this Mach-O file.
1123 std::vector<SectionRef> LiteralSections;
1124 for (const SectionRef &Section : O->sections()) {
1125 DataRefImpl Ref = Section.getRawDataRefImpl();
1126 uint32_t section_type;
1127 if (O->is64Bit()) {
1128 const MachO::section_64 Sec = O->getSection64(Ref);
1129 section_type = Sec.flags & MachO::SECTION_TYPE;
1130 } else {
1131 const MachO::section Sec = O->getSection(Ref);
1132 section_type = Sec.flags & MachO::SECTION_TYPE;
1133 }
1134 if (section_type == MachO::S_CSTRING_LITERALS ||
1135 section_type == MachO::S_4BYTE_LITERALS ||
1136 section_type == MachO::S_8BYTE_LITERALS ||
1137 section_type == MachO::S_16BYTE_LITERALS)
1138 LiteralSections.push_back(Section);
1139 }
1140
1141 // Set the size of the literal pointer.
1142 uint32_t lp_size = O->is64Bit() ? 8 : 4;
1143
1144 // Collect the external relocation symbols for the literal pointers.
1145 std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1146 for (const RelocationRef &Reloc : Section.relocations()) {
1147 DataRefImpl Rel;
1148 MachO::any_relocation_info RE;
1149 bool isExtern = false;
1150 Rel = Reloc.getRawDataRefImpl();
1151 RE = O->getRelocation(Rel);
1152 isExtern = O->getPlainRelocationExternal(RE);
1153 if (isExtern) {
1154 uint64_t RelocOffset = Reloc.getOffset();
1155 symbol_iterator RelocSym = Reloc.getSymbol();
1156 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1157 }
1158 }
1159 array_pod_sort(Relocs.begin(), Relocs.end());
1160
1161 // Dump each literal pointer.
1162 for (uint32_t i = 0; i < sect_size; i += lp_size) {
1163 if (print_addresses) {
1164 if (O->is64Bit())
1165 outs() << format("%016" PRIx64"l" "x", sect_addr + i) << " ";
1166 else
1167 outs() << format("%08" PRIx64"l" "x", sect_addr + i) << " ";
1168 }
1169 uint64_t lp;
1170 if (O->is64Bit()) {
1171 memcpy(&lp, sect + i, sizeof(uint64_t));
1172 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1173 sys::swapByteOrder(lp);
1174 } else {
1175 uint32_t li;
1176 memcpy(&li, sect + i, sizeof(uint32_t));
1177 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1178 sys::swapByteOrder(li);
1179 lp = li;
1180 }
1181
1182 // First look for an external relocation entry for this literal pointer.
1183 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1184 return P.first == i;
1185 });
1186 if (Reloc != Relocs.end()) {
1187 symbol_iterator RelocSym = Reloc->second;
1188 Expected<StringRef> SymName = RelocSym->getName();
1189 if (!SymName)
1190 report_error(O->getFileName(), SymName.takeError());
1191 outs() << "external relocation entry for symbol:" << *SymName << "\n";
1192 continue;
1193 }
1194
1195 // For local references see what the section the literal pointer points to.
1196 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
1197 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
1198 });
1199 if (Sect == LiteralSections.end()) {
1200 outs() << format("0x%" PRIx64"l" "x", lp) << " (not in a literal section)\n";
1201 continue;
1202 }
1203
1204 uint64_t SectAddress = Sect->getAddress();
1205 uint64_t SectSize = Sect->getSize();
1206
1207 StringRef SectName;
1208 Sect->getName(SectName);
1209 DataRefImpl Ref = Sect->getRawDataRefImpl();
1210 StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
1211 outs() << SegmentName << ":" << SectName << ":";
1212
1213 uint32_t section_type;
1214 if (O->is64Bit()) {
1215 const MachO::section_64 Sec = O->getSection64(Ref);
1216 section_type = Sec.flags & MachO::SECTION_TYPE;
1217 } else {
1218 const MachO::section Sec = O->getSection(Ref);
1219 section_type = Sec.flags & MachO::SECTION_TYPE;
1220 }
1221
1222 StringRef BytesStr;
1223 Sect->getContents(BytesStr);
1224 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
1225
1226 switch (section_type) {
1227 case MachO::S_CSTRING_LITERALS:
1228 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
1229 i++) {
1230 DumpCstringChar(Contents[i]);
1231 }
1232 outs() << "\n";
1233 break;
1234 case MachO::S_4BYTE_LITERALS:
1235 float f;
1236 memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
1237 uint32_t l;
1238 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
1239 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1240 sys::swapByteOrder(f);
1241 sys::swapByteOrder(l);
1242 }
1243 DumpLiteral4(l, f);
1244 break;
1245 case MachO::S_8BYTE_LITERALS: {
1246 double d;
1247 memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
1248 uint32_t l0, l1;
1249 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1250 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1251 sizeof(uint32_t));
1252 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1253 sys::swapByteOrder(f);
1254 sys::swapByteOrder(l0);
1255 sys::swapByteOrder(l1);
1256 }
1257 DumpLiteral8(O, l0, l1, d);
1258 break;
1259 }
1260 case MachO::S_16BYTE_LITERALS: {
1261 uint32_t l0, l1, l2, l3;
1262 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1263 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1264 sizeof(uint32_t));
1265 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
1266 sizeof(uint32_t));
1267 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
1268 sizeof(uint32_t));
1269 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1270 sys::swapByteOrder(l0);
1271 sys::swapByteOrder(l1);
1272 sys::swapByteOrder(l2);
1273 sys::swapByteOrder(l3);
1274 }
1275 DumpLiteral16(l0, l1, l2, l3);
1276 break;
1277 }
1278 }
1279 }
1280}
1281
1282static void DumpInitTermPointerSection(MachOObjectFile *O,
1283 const SectionRef &Section,
1284 const char *sect,
1285 uint32_t sect_size, uint64_t sect_addr,
1286 SymbolAddressMap *AddrMap,
1287 bool verbose) {
1288 uint32_t stride;
1289 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
1290
1291 // Collect the external relocation symbols for the pointers.
1292 std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1293 for (const RelocationRef &Reloc : Section.relocations()) {
1294 DataRefImpl Rel;
1295 MachO::any_relocation_info RE;
1296 bool isExtern = false;
1297 Rel = Reloc.getRawDataRefImpl();
1298 RE = O->getRelocation(Rel);
1299 isExtern = O->getPlainRelocationExternal(RE);
1300 if (isExtern) {
1301 uint64_t RelocOffset = Reloc.getOffset();
1302 symbol_iterator RelocSym = Reloc.getSymbol();
1303 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1304 }
1305 }
1306 array_pod_sort(Relocs.begin(), Relocs.end());
1307
1308 for (uint32_t i = 0; i < sect_size; i += stride) {
1309 const char *SymbolName = nullptr;
1310 uint64_t p;
1311 if (O->is64Bit()) {
1312 outs() << format("0x%016" PRIx64"l" "x", sect_addr + i * stride) << " ";
1313 uint64_t pointer_value;
1314 memcpy(&pointer_value, sect + i, stride);
1315 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1316 sys::swapByteOrder(pointer_value);
1317 outs() << format("0x%016" PRIx64"l" "x", pointer_value);
1318 p = pointer_value;
1319 } else {
1320 outs() << format("0x%08" PRIx64"l" "x", sect_addr + i * stride) << " ";
1321 uint32_t pointer_value;
1322 memcpy(&pointer_value, sect + i, stride);
1323 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1324 sys::swapByteOrder(pointer_value);
1325 outs() << format("0x%08" PRIx32"x", pointer_value);
1326 p = pointer_value;
1327 }
1328 if (verbose) {
1329 // First look for an external relocation entry for this pointer.
1330 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1331 return P.first == i;
1332 });
1333 if (Reloc != Relocs.end()) {
1334 symbol_iterator RelocSym = Reloc->second;
1335 Expected<StringRef> SymName = RelocSym->getName();
1336 if (!SymName)
1337 report_error(O->getFileName(), SymName.takeError());
1338 outs() << " " << *SymName;
1339 } else {
1340 SymbolName = GuessSymbolName(p, AddrMap);
1341 if (SymbolName)
1342 outs() << " " << SymbolName;
1343 }
1344 }
1345 outs() << "\n";
1346 }
1347}
1348
1349static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1350 uint32_t size, uint64_t addr) {
1351 uint32_t cputype = O->getHeader().cputype;
1352 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1353 uint32_t j;
1354 for (uint32_t i = 0; i < size; i += j, addr += j) {
1355 if (O->is64Bit())
1356 outs() << format("%016" PRIx64"l" "x", addr) << "\t";
1357 else
1358 outs() << format("%08" PRIx64"l" "x", addr) << "\t";
1359 for (j = 0; j < 16 && i + j < size; j++) {
1360 uint8_t byte_word = *(sect + i + j);
1361 outs() << format("%02" PRIx32"x", (uint32_t)byte_word) << " ";
1362 }
1363 outs() << "\n";
1364 }
1365 } else {
1366 uint32_t j;
1367 for (uint32_t i = 0; i < size; i += j, addr += j) {
1368 if (O->is64Bit())
1369 outs() << format("%016" PRIx64"l" "x", addr) << "\t";
1370 else
1371 outs() << format("%08" PRIx64"l" "x", addr) << "\t";
1372 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1373 j += sizeof(int32_t)) {
1374 if (i + j + sizeof(int32_t) <= size) {
1375 uint32_t long_word;
1376 memcpy(&long_word, sect + i + j, sizeof(int32_t));
1377 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1378 sys::swapByteOrder(long_word);
1379 outs() << format("%08" PRIx32"x", long_word) << " ";
1380 } else {
1381 for (uint32_t k = 0; i + j + k < size; k++) {
1382 uint8_t byte_word = *(sect + i + j + k);
1383 outs() << format("%02" PRIx32"x", (uint32_t)byte_word) << " ";
1384 }
1385 }
1386 }
1387 outs() << "\n";
1388 }
1389 }
1390}
1391
1392static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1393 StringRef DisSegName, StringRef DisSectName);
1394static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1395 uint32_t size, uint32_t addr);
1396#ifdef HAVE_LIBXAR
1397static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
1398 uint32_t size, bool verbose,
1399 bool PrintXarHeader, bool PrintXarFileHeaders,
1400 std::string XarMemberName);
1401#endif // defined(HAVE_LIBXAR)
1402
1403static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1404 bool verbose) {
1405 SymbolAddressMap AddrMap;
1406 if (verbose)
1407 CreateSymbolAddressMap(O, &AddrMap);
1408
1409 for (unsigned i = 0; i < FilterSections.size(); ++i) {
1410 StringRef DumpSection = FilterSections[i];
1411 std::pair<StringRef, StringRef> DumpSegSectName;
1412 DumpSegSectName = DumpSection.split(',');
1413 StringRef DumpSegName, DumpSectName;
1414 if (DumpSegSectName.second.size()) {
1415 DumpSegName = DumpSegSectName.first;
1416 DumpSectName = DumpSegSectName.second;
1417 } else {
1418 DumpSegName = "";
1419 DumpSectName = DumpSegSectName.first;
1420 }
1421 for (const SectionRef &Section : O->sections()) {
1422 StringRef SectName;
1423 Section.getName(SectName);
1424 DataRefImpl Ref = Section.getRawDataRefImpl();
1425 StringRef SegName = O->getSectionFinalSegmentName(Ref);
1426 if ((DumpSegName.empty() || SegName == DumpSegName) &&
1427 (SectName == DumpSectName)) {
1428
1429 uint32_t section_flags;
1430 if (O->is64Bit()) {
1431 const MachO::section_64 Sec = O->getSection64(Ref);
1432 section_flags = Sec.flags;
1433
1434 } else {
1435 const MachO::section Sec = O->getSection(Ref);
1436 section_flags = Sec.flags;
1437 }
1438 uint32_t section_type = section_flags & MachO::SECTION_TYPE;
1439
1440 StringRef BytesStr;
1441 Section.getContents(BytesStr);
1442 const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1443 uint32_t sect_size = BytesStr.size();
1444 uint64_t sect_addr = Section.getAddress();
1445
1446 outs() << "Contents of (" << SegName << "," << SectName
1447 << ") section\n";
1448
1449 if (verbose) {
1450 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
1451 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
1452 DisassembleMachO(Filename, O, SegName, SectName);
1453 continue;
1454 }
1455 if (SegName == "__TEXT" && SectName == "__info_plist") {
1456 outs() << sect;
1457 continue;
1458 }
1459 if (SegName == "__OBJC" && SectName == "__protocol") {
1460 DumpProtocolSection(O, sect, sect_size, sect_addr);
1461 continue;
1462 }
1463#ifdef HAVE_LIBXAR
1464 if (SegName == "__LLVM" && SectName == "__bundle") {
1465 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
1466 ArchiveHeaders, "");
1467 continue;
1468 }
1469#endif // defined(HAVE_LIBXAR)
1470 switch (section_type) {
1471 case MachO::S_REGULAR:
1472 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1473 break;
1474 case MachO::S_ZEROFILL:
1475 outs() << "zerofill section and has no contents in the file\n";
1476 break;
1477 case MachO::S_CSTRING_LITERALS:
1478 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1479 break;
1480 case MachO::S_4BYTE_LITERALS:
1481 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1482 break;
1483 case MachO::S_8BYTE_LITERALS:
1484 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1485 break;
1486 case MachO::S_16BYTE_LITERALS:
1487 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1488 break;
1489 case MachO::S_LITERAL_POINTERS:
1490 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
1491 !NoLeadingAddr);
1492 break;
1493 case MachO::S_MOD_INIT_FUNC_POINTERS:
1494 case MachO::S_MOD_TERM_FUNC_POINTERS:
1495 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
1496 &AddrMap, verbose);
1497 break;
1498 default:
1499 outs() << "Unknown section type ("
1500 << format("0x%08" PRIx32"x", section_type) << ")\n";
1501 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1502 break;
1503 }
1504 } else {
1505 if (section_type == MachO::S_ZEROFILL)
1506 outs() << "zerofill section and has no contents in the file\n";
1507 else
1508 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1509 }
1510 }
1511 }
1512 }
1513}
1514
1515static void DumpInfoPlistSectionContents(StringRef Filename,
1516 MachOObjectFile *O) {
1517 for (const SectionRef &Section : O->sections()) {
1518 StringRef SectName;
1519 Section.getName(SectName);
1520 DataRefImpl Ref = Section.getRawDataRefImpl();
1521 StringRef SegName = O->getSectionFinalSegmentName(Ref);
1522 if (SegName == "__TEXT" && SectName == "__info_plist") {
1523 if (!NoLeadingHeaders)
1524 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
1525 StringRef BytesStr;
1526 Section.getContents(BytesStr);
1527 const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1528 outs() << format("%.*s", BytesStr.size(), sect) << "\n";
1529 return;
1530 }
1531 }
1532}
1533
1534// checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
1535// and if it is and there is a list of architecture flags is specified then
1536// check to make sure this Mach-O file is one of those architectures or all
1537// architectures were specified. If not then an error is generated and this
1538// routine returns false. Else it returns true.
1539static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
1540 auto *MachO = dyn_cast<MachOObjectFile>(O);
1541
1542 if (!MachO || ArchAll || ArchFlags.empty())
1543 return true;
1544
1545 MachO::mach_header H;
1546 MachO::mach_header_64 H_64;
1547 Triple T;
1548 const char *McpuDefault, *ArchFlag;
1549 if (MachO->is64Bit()) {
1550 H_64 = MachO->MachOObjectFile::getHeader64();
1551 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
1552 &McpuDefault, &ArchFlag);
1553 } else {
1554 H = MachO->MachOObjectFile::getHeader();
1555 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
1556 &McpuDefault, &ArchFlag);
1557 }
1558 const std::string ArchFlagName(ArchFlag);
1559 if (none_of(ArchFlags, [&](const std::string &Name) {
1560 return Name == ArchFlagName;
1561 })) {
1562 errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n";
1563 return false;
1564 }
1565 return true;
1566}
1567
1568static void printObjcMetaData(MachOObjectFile *O, bool verbose);
1569
1570// ProcessMachO() is passed a single opened Mach-O file, which may be an
1571// archive member and or in a slice of a universal file. It prints the
1572// the file name and header info and then processes it according to the
1573// command line options.
1574static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
1575 StringRef ArchiveMemberName = StringRef(),
1576 StringRef ArchitectureName = StringRef()) {
1577 // If we are doing some processing here on the Mach-O file print the header
1578 // info. And don't print it otherwise like in the case of printing the
1579 // UniversalHeaders or ArchiveHeaders.
1580 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
10
Assuming the condition is false
11
Assuming the condition is false
12
Assuming the condition is false
13
Assuming the condition is false
14
Assuming the condition is false
26
Taking false branch
1581 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
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
1582 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData ||
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
1583 (FilterSections.size() != 0)) {
25
Assuming the condition is false
1584 if (!NoLeadingHeaders) {
1585 outs() << Name;
1586 if (!ArchiveMemberName.empty())
1587 outs() << '(' << ArchiveMemberName << ')';
1588 if (!ArchitectureName.empty())
1589 outs() << " (architecture " << ArchitectureName << ")";
1590 outs() << ":\n";
1591 }
1592 }
1593 // To use the report_error() form with an ArchiveName and FileName set
1594 // these up based on what is passed for Name and ArchiveMemberName.
1595 StringRef ArchiveName;
1596 StringRef FileName;
1597 if (!ArchiveMemberName.empty()) {
27
Assuming the condition is false
28
Taking false branch
1598 ArchiveName = Name;
1599 FileName = ArchiveMemberName;
1600 } else {
1601 ArchiveName = StringRef();
1602 FileName = Name;
1603 }
1604
1605 // If we need the symbol table to do the operation then check it here to
1606 // produce a good error message as to where the Mach-O file comes from in
1607 // the error message.
1608 if (Disassemble || IndirectSymbols || FilterSections.size() != 0 ||
29
Assuming the condition is false
30
Assuming the condition is false
31
Assuming the condition is false
33
Taking false branch
1609 UnwindInfo)
32
Assuming the condition is false
1610 if (Error Err = MachOOF->checkSymbolTable())
1611 report_error(ArchiveName, FileName, std::move(Err), ArchitectureName);
1612
1613 if (Disassemble) {
34
Assuming the condition is false
35
Taking false branch
1614 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE &&
1615 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64)
1616 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text");
1617 else
1618 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
1619 }
1620 if (IndirectSymbols)
36
Assuming the condition is false
37
Taking false branch
1621 PrintIndirectSymbols(MachOOF, !NonVerbose);
1622 if (DataInCode)
38
Assuming the condition is false
39
Taking false branch
1623 PrintDataInCodeTable(MachOOF, !NonVerbose);
1624 if (LinkOptHints)
40
Assuming the condition is false
41
Taking false branch
1625 PrintLinkOptHints(MachOOF);
1626 if (Relocations)
42
Assuming the condition is false
43
Taking false branch
1627 PrintRelocations(MachOOF, !NonVerbose);
1628 if (SectionHeaders)
44
Assuming the condition is false
45
Taking false branch
1629 PrintSectionHeaders(MachOOF);
1630 if (SectionContents)
46
Assuming the condition is false
47
Taking false branch
1631 PrintSectionContents(MachOOF);
1632 if (FilterSections.size() != 0)
48
Assuming the condition is false
49
Taking false branch
1633 DumpSectionContents(FileName, MachOOF, !NonVerbose);
1634 if (InfoPlist)
50
Assuming the condition is false
51
Taking false branch
1635 DumpInfoPlistSectionContents(FileName, MachOOF);
1636 if (DylibsUsed)
52
Assuming the condition is false
53
Taking false branch
1637 PrintDylibs(MachOOF, false);
1638 if (DylibId)
54
Assuming the condition is false
55
Taking false branch
1639 PrintDylibs(MachOOF, true);
1640 if (SymbolTable)
56
Assuming the condition is false
57
Taking false branch
1641 PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName);
1642 if (UnwindInfo)
58
Assuming the condition is false
59
Taking false branch
1643 printMachOUnwindInfo(MachOOF);
1644 if (PrivateHeaders) {
60
Assuming the condition is false
61
Taking false branch
1645 printMachOFileHeader(MachOOF);
1646 printMachOLoadCommands(MachOOF);
1647 }
1648 if (FirstPrivateHeader)
62
Assuming the condition is false
63
Taking false branch
1649 printMachOFileHeader(MachOOF);
1650 if (ObjcMetaData)
64
Assuming the condition is true
65
Taking true branch
1651 printObjcMetaData(MachOOF, !NonVerbose);
66
Assuming the condition is false
67
Calling 'printObjcMetaData'
1652 if (ExportsTrie)
1653 printExportsTrie(MachOOF);
1654 if (Rebase)
1655 printRebaseTable(MachOOF);
1656 if (Bind)
1657 printBindTable(MachOOF);
1658 if (LazyBind)
1659 printLazyBindTable(MachOOF);
1660 if (WeakBind)
1661 printWeakBindTable(MachOOF);
1662
1663 if (DwarfDumpType != DIDT_Null) {
1664 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
1665 // Dump the complete DWARF structure.
1666 DIDumpOptions DumpOpts;
1667 DumpOpts.DumpType = DwarfDumpType;
1668 DICtx->dump(outs(), DumpOpts);
1669 }
1670}
1671
1672// printUnknownCPUType() helps print_fat_headers for unknown CPU's.
1673static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
1674 outs() << " cputype (" << cputype << ")\n";
1675 outs() << " cpusubtype (" << cpusubtype << ")\n";
1676}
1677
1678// printCPUType() helps print_fat_headers by printing the cputype and
1679// pusubtype (symbolically for the one's it knows about).
1680static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
1681 switch (cputype) {
1682 case MachO::CPU_TYPE_I386:
1683 switch (cpusubtype) {
1684 case MachO::CPU_SUBTYPE_I386_ALL:
1685 outs() << " cputype CPU_TYPE_I386\n";
1686 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n";
1687 break;
1688 default:
1689 printUnknownCPUType(cputype, cpusubtype);
1690 break;
1691 }
1692 break;
1693 case MachO::CPU_TYPE_X86_64:
1694 switch (cpusubtype) {
1695 case MachO::CPU_SUBTYPE_X86_64_ALL:
1696 outs() << " cputype CPU_TYPE_X86_64\n";
1697 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
1698 break;
1699 case MachO::CPU_SUBTYPE_X86_64_H:
1700 outs() << " cputype CPU_TYPE_X86_64\n";
1701 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n";
1702 break;
1703 default:
1704 printUnknownCPUType(cputype, cpusubtype);
1705 break;
1706 }
1707 break;
1708 case MachO::CPU_TYPE_ARM:
1709 switch (cpusubtype) {
1710 case MachO::CPU_SUBTYPE_ARM_ALL:
1711 outs() << " cputype CPU_TYPE_ARM\n";
1712 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n";
1713 break;
1714 case MachO::CPU_SUBTYPE_ARM_V4T:
1715 outs() << " cputype CPU_TYPE_ARM\n";
1716 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n";
1717 break;
1718 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1719 outs() << " cputype CPU_TYPE_ARM\n";
1720 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
1721 break;
1722 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1723 outs() << " cputype CPU_TYPE_ARM\n";
1724 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
1725 break;
1726 case MachO::CPU_SUBTYPE_ARM_V6:
1727 outs() << " cputype CPU_TYPE_ARM\n";
1728 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n";
1729 break;
1730 case MachO::CPU_SUBTYPE_ARM_V6M:
1731 outs() << " cputype CPU_TYPE_ARM\n";
1732 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n";
1733 break;
1734 case MachO::CPU_SUBTYPE_ARM_V7:
1735 outs() << " cputype CPU_TYPE_ARM\n";
1736 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n";
1737 break;
1738 case MachO::CPU_SUBTYPE_ARM_V7EM:
1739 outs() << " cputype CPU_TYPE_ARM\n";
1740 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
1741 break;
1742 case MachO::CPU_SUBTYPE_ARM_V7K:
1743 outs() << " cputype CPU_TYPE_ARM\n";
1744 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n";
1745 break;
1746 case MachO::CPU_SUBTYPE_ARM_V7M:
1747 outs() << " cputype CPU_TYPE_ARM\n";
1748 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n";
1749 break;
1750 case MachO::CPU_SUBTYPE_ARM_V7S:
1751 outs() << " cputype CPU_TYPE_ARM\n";
1752 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n";
1753 break;
1754 default:
1755 printUnknownCPUType(cputype, cpusubtype);
1756 break;
1757 }
1758 break;
1759 case MachO::CPU_TYPE_ARM64:
1760 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
1761 case MachO::CPU_SUBTYPE_ARM64_ALL:
1762 outs() << " cputype CPU_TYPE_ARM64\n";
1763 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
1764 break;
1765 default:
1766 printUnknownCPUType(cputype, cpusubtype);
1767 break;
1768 }
1769 break;
1770 default:
1771 printUnknownCPUType(cputype, cpusubtype);
1772 break;
1773 }
1774}
1775
1776static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
1777 bool verbose) {
1778 outs() << "Fat headers\n";
1779 if (verbose) {
1780 if (UB->getMagic() == MachO::FAT_MAGIC)
1781 outs() << "fat_magic FAT_MAGIC\n";
1782 else // UB->getMagic() == MachO::FAT_MAGIC_64
1783 outs() << "fat_magic FAT_MAGIC_64\n";
1784 } else
1785 outs() << "fat_magic " << format("0x%" PRIx32"x", MachO::FAT_MAGIC) << "\n";
1786
1787 uint32_t nfat_arch = UB->getNumberOfObjects();
1788 StringRef Buf = UB->getData();
1789 uint64_t size = Buf.size();
1790 uint64_t big_size = sizeof(struct MachO::fat_header) +
1791 nfat_arch * sizeof(struct MachO::fat_arch);
1792 outs() << "nfat_arch " << UB->getNumberOfObjects();
1793 if (nfat_arch == 0)
1794 outs() << " (malformed, contains zero architecture types)\n";
1795 else if (big_size > size)
1796 outs() << " (malformed, architectures past end of file)\n";
1797 else
1798 outs() << "\n";
1799
1800 for (uint32_t i = 0; i < nfat_arch; ++i) {
1801 MachOUniversalBinary::ObjectForArch OFA(UB, i);
1802 uint32_t cputype = OFA.getCPUType();
1803 uint32_t cpusubtype = OFA.getCPUSubType();
1804 outs() << "architecture ";
1805 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
1806 MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
1807 uint32_t other_cputype = other_OFA.getCPUType();
1808 uint32_t other_cpusubtype = other_OFA.getCPUSubType();
1809 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
1810 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
1811 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
1812 outs() << "(illegal duplicate architecture) ";
1813 break;
1814 }
1815 }
1816 if (verbose) {
1817 outs() << OFA.getArchFlagName() << "\n";
1818 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
1819 } else {
1820 outs() << i << "\n";
1821 outs() << " cputype " << cputype << "\n";
1822 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
1823 << "\n";
1824 }
1825 if (verbose &&
1826 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
1827 outs() << " capabilities CPU_SUBTYPE_LIB64\n";
1828 else
1829 outs() << " capabilities "
1830 << format("0x%" PRIx32"x",
1831 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
1832 outs() << " offset " << OFA.getOffset();
1833 if (OFA.getOffset() > size)
1834 outs() << " (past end of file)";
1835 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0)
1836 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
1837 outs() << "\n";
1838 outs() << " size " << OFA.getSize();
1839 big_size = OFA.getOffset() + OFA.getSize();
1840 if (big_size > size)
1841 outs() << " (past end of file)";
1842 outs() << "\n";
1843 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
1844 << ")\n";
1845 }
1846}
1847
1848static void printArchiveChild(StringRef Filename, const Archive::Child &C,
1849 bool verbose, bool print_offset,
1850 StringRef ArchitectureName = StringRef()) {
1851 if (print_offset)
1852 outs() << C.getChildOffset() << "\t";
1853 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
1854 if (!ModeOrErr)
1855 report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName);
1856 sys::fs::perms Mode = ModeOrErr.get();
1857 if (verbose) {
1858 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
1859 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
1860 outs() << "-";
1861 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
1862 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
1863 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
1864 outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
1865 outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
1866 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
1867 outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
1868 outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
1869 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
1870 } else {
1871 outs() << format("0%o ", Mode);
1872 }
1873
1874 Expected<unsigned> UIDOrErr = C.getUID();
1875 if (!UIDOrErr)
1876 report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName);
1877 unsigned UID = UIDOrErr.get();
1878 outs() << format("%3d/", UID);
1879 Expected<unsigned> GIDOrErr = C.getGID();
1880 if (!GIDOrErr)
1881 report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName);
1882 unsigned GID = GIDOrErr.get();
1883 outs() << format("%-3d ", GID);
1884 Expected<uint64_t> Size = C.getRawSize();
1885 if (!Size)
1886 report_error(Filename, C, Size.takeError(), ArchitectureName);
1887 outs() << format("%5" PRId64"l" "d", Size.get()) << " ";
1888
1889 StringRef RawLastModified = C.getRawLastModified();
1890 if (verbose) {
1891 unsigned Seconds;
1892 if (RawLastModified.getAsInteger(10, Seconds))
1893 outs() << "(date: \"" << RawLastModified
1894 << "\" contains non-decimal chars) ";
1895 else {
1896 // Since cime(3) returns a 26 character string of the form:
1897 // "Sun Sep 16 01:03:52 1973\n\0"
1898 // just print 24 characters.
1899 time_t t = Seconds;
1900 outs() << format("%.24s ", ctime(&t));
1901 }
1902 } else {
1903 outs() << RawLastModified << " ";
1904 }
1905
1906 if (verbose) {
1907 Expected<StringRef> NameOrErr = C.getName();
1908 if (!NameOrErr) {
1909 consumeError(NameOrErr.takeError());
1910 Expected<StringRef> NameOrErr = C.getRawName();
1911 if (!NameOrErr)
1912 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
1913 StringRef RawName = NameOrErr.get();
1914 outs() << RawName << "\n";
1915 } else {
1916 StringRef Name = NameOrErr.get();
1917 outs() << Name << "\n";
1918 }
1919 } else {
1920 Expected<StringRef> NameOrErr = C.getRawName();
1921 if (!NameOrErr)
1922 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
1923 StringRef RawName = NameOrErr.get();
1924 outs() << RawName << "\n";
1925 }
1926}
1927
1928static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
1929 bool print_offset,
1930 StringRef ArchitectureName = StringRef()) {
1931 Error Err = Error::success();
1932 ;
1933 for (const auto &C : A->children(Err, false))
1934 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName);
1935
1936 if (Err)
1937 report_error(StringRef(), Filename, std::move(Err), ArchitectureName);
1938}
1939
1940static bool ValidateArchFlags() {
1941 // Check for -arch all and verifiy the -arch flags are valid.
1942 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
1943 if (ArchFlags[i] == "all") {
1944 ArchAll = true;
1945 } else {
1946 if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
1947 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] +
1948 "'for the -arch option\n";
1949 return false;
1950 }
1951 }
1952 }
1953 return true;
1954}
1955
1956// ParseInputMachO() parses the named Mach-O file in Filename and handles the
1957// -arch flags selecting just those slices as specified by them and also parses
1958// archive files. Then for each individual Mach-O file ProcessMachO() is
1959// called to process the file based on the command line options.
1960void llvm::ParseInputMachO(StringRef Filename) {
1961 if (!ValidateArchFlags())
1
Taking false branch
1962 return;
1963
1964 // Attempt to open the binary.
1965 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
1966 if (!BinaryOrErr) {
2
Taking false branch
1967 if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
1968 report_error(Filename, std::move(E));
1969 else
1970 outs() << Filename << ": is not an object file\n";
1971 return;
1972 }
1973 Binary &Bin = *BinaryOrErr.get().getBinary();
1974
1975 if (Archive *A = dyn_cast<Archive>(&Bin)) {
3
Taking true branch
1976 outs() << "Archive : " << Filename << "\n";
1977 if (ArchiveHeaders)
4
Assuming the condition is false
5
Taking false branch
1978 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets);
1979
1980 Error Err = Error::success();
1981 for (auto &C : A->children(Err)) {
1982 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
1983 if (!ChildOrErr) {
6
Taking false branch
1984 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1985 report_error(Filename, C, std::move(E));
1986 continue;
1987 }
1988 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
7
Taking true branch
1989 if (!checkMachOAndArchFlags(O, Filename))
8
Taking false branch
1990 return;
1991 ProcessMachO(Filename, O, O->getFileName());
9
Calling 'ProcessMachO'
1992 }
1993 }
1994 if (Err)
1995 report_error(Filename, std::move(Err));
1996 return;
1997 }
1998 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
1999 ParseInputMachO(UB);
2000 return;
2001 }
2002 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
2003 if (!checkMachOAndArchFlags(O, Filename))
2004 return;
2005 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O))
2006 ProcessMachO(Filename, MachOOF);
2007 else
2008 errs() << "llvm-objdump: '" << Filename << "': "
2009 << "Object is not a Mach-O file type.\n";
2010 return;
2011 }
2012 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-8~svn345461/tools/llvm-objdump/MachODump.cpp"
, 2012)
;
2013}
2014
2015void llvm::ParseInputMachO(MachOUniversalBinary *UB) {
2016 if (!ValidateArchFlags())
2017 return;
2018
2019 auto Filename = UB->getFileName();
2020
2021 if (UniversalHeaders)
2022 printMachOUniversalHeaders(UB, !NonVerbose);
2023
2024 // If we have a list of architecture flags specified dump only those.
2025 if (!ArchAll && ArchFlags.size() != 0) {
2026 // Look for a slice in the universal binary that matches each ArchFlag.
2027 bool ArchFound;
2028 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2029 ArchFound = false;
2030 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2031 E = UB->end_objects();
2032 I != E; ++I) {
2033 if (ArchFlags[i] == I->getArchFlagName()) {
2034 ArchFound = true;
2035 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
2036 I->getAsObjectFile();
2037 std::string ArchitectureName = "";
2038 if (ArchFlags.size() > 1)
2039 ArchitectureName = I->getArchFlagName();
2040 if (ObjOrErr) {
2041 ObjectFile &O = *ObjOrErr.get();
2042 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2043 ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2044 } else if (auto E = isNotObjectErrorInvalidFileType(
2045 ObjOrErr.takeError())) {
2046 report_error(Filename, StringRef(), std::move(E),
2047 ArchitectureName);
2048 continue;
2049 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2050 I->getAsArchive()) {
2051 std::unique_ptr<Archive> &A = *AOrErr;
2052 outs() << "Archive : " << Filename;
2053 if (!ArchitectureName.empty())
2054 outs() << " (architecture " << ArchitectureName << ")";
2055 outs() << "\n";
2056 if (ArchiveHeaders)
2057 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2058 ArchiveMemberOffsets, ArchitectureName);
2059 Error Err = Error::success();
2060 for (auto &C : A->children(Err)) {
2061 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2062 if (!ChildOrErr) {
2063 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2064 report_error(Filename, C, std::move(E), ArchitectureName);
2065 continue;
2066 }
2067 if (MachOObjectFile *O =
2068 dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2069 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
2070 }
2071 if (Err)
2072 report_error(Filename, std::move(Err));
2073 } else {
2074 consumeError(AOrErr.takeError());
2075 error("Mach-O universal file: " + Filename + " for " +
2076 "architecture " + StringRef(I->getArchFlagName()) +
2077 " is not a Mach-O file or an archive file");
2078 }
2079 }
2080 }
2081 if (!ArchFound) {
2082 errs() << "llvm-objdump: file: " + Filename + " does not contain "
2083 << "architecture: " + ArchFlags[i] + "\n";
2084 return;
2085 }
2086 }
2087 return;
2088 }
2089 // No architecture flags were specified so if this contains a slice that
2090 // matches the host architecture dump only that.
2091 if (!ArchAll) {
2092 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2093 E = UB->end_objects();
2094 I != E; ++I) {
2095 if (MachOObjectFile::getHostArch().getArchName() ==
2096 I->getArchFlagName()) {
2097 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2098 std::string ArchiveName;
2099 ArchiveName.clear();
2100 if (ObjOrErr) {
2101 ObjectFile &O = *ObjOrErr.get();
2102 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2103 ProcessMachO(Filename, MachOOF);
2104 } else if (auto E = isNotObjectErrorInvalidFileType(
2105 ObjOrErr.takeError())) {
2106 report_error(Filename, std::move(E));
2107 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2108 I->getAsArchive()) {
2109 std::unique_ptr<Archive> &A = *AOrErr;
2110 outs() << "Archive : " << Filename << "\n";
2111 if (ArchiveHeaders)
2112 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2113 ArchiveMemberOffsets);
2114 Error Err = Error::success();
2115 for (auto &C : A->children(Err)) {
2116 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2117 if (!ChildOrErr) {
2118 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2119 report_error(Filename, C, std::move(E));
2120 continue;
2121 }
2122 if (MachOObjectFile *O =
2123 dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2124 ProcessMachO(Filename, O, O->getFileName());
2125 }
2126 if (Err)
2127 report_error(Filename, std::move(Err));
2128 } else {
2129 consumeError(AOrErr.takeError());
2130 error("Mach-O universal file: " + Filename + " for architecture " +
2131 StringRef(I->getArchFlagName()) +
2132 " is not a Mach-O file or an archive file");
2133 }
2134 return;
2135 }
2136 }
2137 }
2138 // Either all architectures have been specified or none have been specified
2139 // and this does not contain the host architecture so dump all the slices.
2140 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2141 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2142 E = UB->end_objects();
2143 I != E; ++I) {
2144 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2145 std::string ArchitectureName = "";
2146 if (moreThanOneArch)
2147 ArchitectureName = I->getArchFlagName();
2148 if (ObjOrErr) {
2149 ObjectFile &Obj = *ObjOrErr.get();
2150 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
2151 ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2152 } else if (auto E = isNotObjectErrorInvalidFileType(
2153 ObjOrErr.takeError())) {
2154 report_error(StringRef(), Filename, std::move(E), ArchitectureName);
2155 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2156 I->getAsArchive()) {
2157 std::unique_ptr<Archive> &A = *AOrErr;
2158 outs() << "Archive : " << Filename;
2159 if (!ArchitectureName.empty())
2160 outs() << " (architecture " << ArchitectureName << ")";
2161 outs() << "\n";
2162 if (ArchiveHeaders)
2163 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2164 ArchiveMemberOffsets, ArchitectureName);
2165 Error Err = Error::success();
2166 for (auto &C : A->children(Err)) {
2167 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2168 if (!ChildOrErr) {
2169 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2170 report_error(Filename, C, std::move(E), ArchitectureName);
2171 continue;
2172 }
2173 if (MachOObjectFile *O =
2174 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2175 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
2176 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
2177 ArchitectureName);
2178 }
2179 }
2180 if (Err)
2181 report_error(Filename, std::move(Err));
2182 } else {
2183 consumeError(AOrErr.takeError());
2184 error("Mach-O universal file: " + Filename + " for architecture " +
2185 StringRef(I->getArchFlagName()) +
2186 " is not a Mach-O file or an archive file");
2187 }
2188 }
2189}
2190
2191// The block of info used by the Symbolizer call backs.
2192struct DisassembleInfo {
2193 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
2194 std::vector<SectionRef> *Sections, bool verbose)
2195 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
2196 bool verbose;
2197 MachOObjectFile *O;
2198 SectionRef S;
2199 SymbolAddressMap *AddrMap;
2200 std::vector<SectionRef> *Sections;
2201 const char *class_name = nullptr;
2202 const char *selector_name = nullptr;
2203 std::unique_ptr<char[]> method = nullptr;
2204 char *demangled_name = nullptr;
2205 uint64_t adrp_addr = 0;
2206 uint32_t adrp_inst = 0;
2207 std::unique_ptr<SymbolAddressMap> bindtable;
2208 uint32_t depth = 0;
2209};
2210
2211// SymbolizerGetOpInfo() is the operand information call back function.
2212// This is called to get the symbolic information for operand(s) of an
2213// instruction when it is being done. This routine does this from
2214// the relocation information, symbol table, etc. That block of information
2215// is a pointer to the struct DisassembleInfo that was passed when the
2216// disassembler context was created and passed to back to here when
2217// called back by the disassembler for instruction operands that could have
2218// relocation information. The address of the instruction containing operand is
2219// at the Pc parameter. The immediate value the operand has is passed in
2220// op_info->Value and is at Offset past the start of the instruction and has a
2221// byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
2222// LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
2223// names and addends of the symbolic expression to add for the operand. The
2224// value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
2225// information is returned then this function returns 1 else it returns 0.
2226static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
2227 uint64_t Size, int TagType, void *TagBuf) {
2228 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
2229 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
2230 uint64_t value = op_info->Value;
2231
2232 // Make sure all fields returned are zero if we don't set them.
2233 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
2234 op_info->Value = value;
2235
2236 // If the TagType is not the value 1 which it code knows about or if no
2237 // verbose symbolic information is wanted then just return 0, indicating no
2238 // information is being returned.
2239 if (TagType != 1 || !info->verbose)
2240 return 0;
2241
2242 unsigned int Arch = info->O->getArch();
2243 if (Arch == Triple::x86) {
2244 if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
2245 return 0;
2246 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2247 // TODO:
2248 // Search the external relocation entries of a fully linked image
2249 // (if any) for an entry that matches this segment offset.
2250 // uint32_t seg_offset = (Pc + Offset);
2251 return 0;
2252 }
2253 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2254 // for an entry for this section offset.
2255 uint32_t sect_addr = info->S.getAddress();
2256 uint32_t sect_offset = (Pc + Offset) - sect_addr;
2257 bool reloc_found = false;
2258 DataRefImpl Rel;
2259 MachO::any_relocation_info RE;
2260 bool isExtern = false;
2261 SymbolRef Symbol;
2262 bool r_scattered = false;
2263 uint32_t r_value, pair_r_value, r_type;
2264 for (const RelocationRef &Reloc : info->S.relocations()) {
2265 uint64_t RelocOffset = Reloc.getOffset();
2266 if (RelocOffset == sect_offset) {
2267 Rel = Reloc.getRawDataRefImpl();
2268 RE = info->O->getRelocation(Rel);
2269 r_type = info->O->getAnyRelocationType(RE);
2270 r_scattered = info->O->isRelocationScattered(RE);
2271 if (r_scattered) {
2272 r_value = info->O->getScatteredRelocationValue(RE);
2273 if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2274 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
2275 DataRefImpl RelNext = Rel;
2276 info->O->moveRelocationNext(RelNext);
2277 MachO::any_relocation_info RENext;
2278 RENext = info->O->getRelocation(RelNext);
2279 if (info->O->isRelocationScattered(RENext))
2280 pair_r_value = info->O->getScatteredRelocationValue(RENext);
2281 else
2282 return 0;
2283 }
2284 } else {
2285 isExtern = info->O->getPlainRelocationExternal(RE);
2286 if (isExtern) {
2287 symbol_iterator RelocSym = Reloc.getSymbol();
2288 Symbol = *RelocSym;
2289 }
2290 }
2291 reloc_found = true;
2292 break;
2293 }
2294 }
2295 if (reloc_found && isExtern) {
2296 Expected<StringRef> SymName = Symbol.getName();
2297 if (!SymName)
2298 report_error(info->O->getFileName(), SymName.takeError());
2299 const char *name = SymName->data();
2300 op_info->AddSymbol.Present = 1;
2301 op_info->AddSymbol.Name = name;
2302 // For i386 extern relocation entries the value in the instruction is
2303 // the offset from the symbol, and value is already set in op_info->Value.
2304 return 1;
2305 }
2306 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2307 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
2308 const char *add = GuessSymbolName(r_value, info->AddrMap);
2309 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2310 uint32_t offset = value - (r_value - pair_r_value);
2311 op_info->AddSymbol.Present = 1;
2312 if (add != nullptr)
2313 op_info->AddSymbol.Name = add;
2314 else
2315 op_info->AddSymbol.Value = r_value;
2316 op_info->SubtractSymbol.Present = 1;
2317 if (sub != nullptr)
2318 op_info->SubtractSymbol.Name = sub;
2319 else
2320 op_info->SubtractSymbol.Value = pair_r_value;
2321 op_info->Value = offset;
2322 return 1;
2323 }
2324 return 0;
2325 }
2326 if (Arch == Triple::x86_64) {
2327 if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
2328 return 0;
2329 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external
2330 // relocation entries of a linked image (if any) for an entry that matches
2331 // this segment offset.
2332 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2333 uint64_t seg_offset = Pc + Offset;
2334 bool reloc_found = false;
2335 DataRefImpl Rel;
2336 MachO::any_relocation_info RE;
2337 bool isExtern = false;
2338 SymbolRef Symbol;
2339 for (const RelocationRef &Reloc : info->O->external_relocations()) {
2340 uint64_t RelocOffset = Reloc.getOffset();
2341 if (RelocOffset == seg_offset) {
2342 Rel = Reloc.getRawDataRefImpl();
2343 RE = info->O->getRelocation(Rel);
2344 // external relocation entries should always be external.
2345 isExtern = info->O->getPlainRelocationExternal(RE);
2346 if (isExtern) {
2347 symbol_iterator RelocSym = Reloc.getSymbol();
2348 Symbol = *RelocSym;
2349 }
2350 reloc_found = true;
2351 break;
2352 }
2353 }
2354 if (reloc_found && isExtern) {
2355 // The Value passed in will be adjusted by the Pc if the instruction
2356 // adds the Pc. But for x86_64 external relocation entries the Value
2357 // is the offset from the external symbol.
2358 if (info->O->getAnyRelocationPCRel(RE))
2359 op_info->Value -= Pc + Offset + Size;
2360 Expected<StringRef> SymName = Symbol.getName();
2361 if (!SymName)
2362 report_error(info->O->getFileName(), SymName.takeError());
2363 const char *name = SymName->data();
2364 op_info->AddSymbol.Present = 1;
2365 op_info->AddSymbol.Name = name;
2366 return 1;
2367 }
2368 return 0;
2369 }
2370 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2371 // for an entry for this section offset.
2372 uint64_t sect_addr = info->S.getAddress();
2373 uint64_t sect_offset = (Pc + Offset) - sect_addr;
2374 bool reloc_found = false;
2375 DataRefImpl Rel;
2376 MachO::any_relocation_info RE;
2377 bool isExtern = false;
2378 SymbolRef Symbol;
2379 for (const RelocationRef &Reloc : info->S.relocations()) {
2380 uint64_t RelocOffset = Reloc.getOffset();
2381 if (RelocOffset == sect_offset) {
2382 Rel = Reloc.getRawDataRefImpl();
2383 RE = info->O->getRelocation(Rel);
2384 // NOTE: Scattered relocations don't exist on x86_64.
2385 isExtern = info->O->getPlainRelocationExternal(RE);
2386 if (isExtern) {
2387 symbol_iterator RelocSym = Reloc.getSymbol();
2388 Symbol = *RelocSym;
2389 }
2390 reloc_found = true;
2391 break;
2392 }
2393 }
2394 if (reloc_found && isExtern) {
2395 // The Value passed in will be adjusted by the Pc if the instruction
2396 // adds the Pc. But for x86_64 external relocation entries the Value
2397 // is the offset from the external symbol.
2398 if (info->O->getAnyRelocationPCRel(RE))
2399 op_info->Value -= Pc + Offset + Size;
2400 Expected<StringRef> SymName = Symbol.getName();
2401 if (!SymName)
2402 report_error(info->O->getFileName(), SymName.takeError());
2403 const char *name = SymName->data();
2404 unsigned Type = info->O->getAnyRelocationType(RE);
2405 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
2406 DataRefImpl RelNext = Rel;
2407 info->O->moveRelocationNext(RelNext);
2408 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2409 unsigned TypeNext = info->O->getAnyRelocationType(RENext);
2410 bool isExternNext = info->O->getPlainRelocationExternal(RENext);
2411 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
2412 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
2413 op_info->SubtractSymbol.Present = 1;
2414 op_info->SubtractSymbol.Name = name;
2415 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
2416 Symbol = *RelocSymNext;
2417 Expected<StringRef> SymNameNext = Symbol.getName();
2418 if (!SymNameNext)
2419 report_error(info->O->getFileName(), SymNameNext.takeError());
2420 name = SymNameNext->data();
2421 }
2422 }
2423 // TODO: add the VariantKinds to op_info->VariantKind for relocation types
2424 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
2425 op_info->AddSymbol.Present = 1;
2426 op_info->AddSymbol.Name = name;
2427 return 1;
2428 }
2429 return 0;
2430 }
2431 if (Arch == Triple::arm) {
2432 if (Offset != 0 || (Size != 4 && Size != 2))
2433 return 0;
2434 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2435 // TODO:
2436 // Search the external relocation entries of a fully linked image
2437 // (if any) for an entry that matches this segment offset.
2438 // uint32_t seg_offset = (Pc + Offset);
2439 return 0;
2440 }
2441 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2442 // for an entry for this section offset.
2443 uint32_t sect_addr = info->S.getAddress();
2444 uint32_t sect_offset = (Pc + Offset) - sect_addr;
2445 DataRefImpl Rel;
2446 MachO::any_relocation_info RE;
2447 bool isExtern = false;
2448 SymbolRef Symbol;
2449 bool r_scattered = false;
2450 uint32_t r_value, pair_r_value, r_type, r_length, other_half;
2451 auto Reloc =
2452 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
2453 uint64_t RelocOffset = Reloc.getOffset();
2454 return RelocOffset == sect_offset;
2455 });
2456
2457 if (Reloc == info->S.relocations().end())
2458 return 0;
2459
2460 Rel = Reloc->getRawDataRefImpl();
2461 RE = info->O->getRelocation(Rel);
2462 r_length = info->O->getAnyRelocationLength(RE);
2463 r_scattered = info->O->isRelocationScattered(RE);
2464 if (r_scattered) {
2465 r_value = info->O->getScatteredRelocationValue(RE);
2466 r_type = info->O->getScatteredRelocationType(RE);
2467 } else {
2468 r_type = info->O->getAnyRelocationType(RE);
2469 isExtern = info->O->getPlainRelocationExternal(RE);
2470 if (isExtern) {
2471 symbol_iterator RelocSym = Reloc->getSymbol();
2472 Symbol = *RelocSym;
2473 }
2474 }
2475 if (r_type == MachO::ARM_RELOC_HALF ||
2476 r_type == MachO::ARM_RELOC_SECTDIFF ||
2477 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
2478 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2479 DataRefImpl RelNext = Rel;
2480 info->O->moveRelocationNext(RelNext);
2481 MachO::any_relocation_info RENext;
2482 RENext = info->O->getRelocation(RelNext);
2483 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
2484 if (info->O->isRelocationScattered(RENext))
2485 pair_r_value = info->O->getScatteredRelocationValue(RENext);
2486 }
2487
2488 if (isExtern) {
2489 Expected<StringRef> SymName = Symbol.getName();
2490 if (!SymName)
2491 report_error(info->O->getFileName(), SymName.takeError());
2492 const char *name = SymName->data();
2493 op_info->AddSymbol.Present = 1;
2494 op_info->AddSymbol.Name = name;
2495 switch (r_type) {
2496 case MachO::ARM_RELOC_HALF:
2497 if ((r_length & 0x1) == 1) {
2498 op_info->Value = value << 16 | other_half;
2499 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI161;
2500 } else {
2501 op_info->Value = other_half << 16 | value;
2502 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO162;
2503 }
2504 break;
2505 default:
2506 break;
2507 }
2508 return 1;
2509 }
2510 // If we have a branch that is not an external relocation entry then
2511 // return 0 so the code in tryAddingSymbolicOperand() can use the
2512 // SymbolLookUp call back with the branch target address to look up the
2513 // symbol and possibility add an annotation for a symbol stub.
2514 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
2515 r_type == MachO::ARM_THUMB_RELOC_BR22))
2516 return 0;
2517
2518 uint32_t offset = 0;
2519 if (r_type == MachO::ARM_RELOC_HALF ||
2520 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2521 if ((r_length & 0x1) == 1)
2522 value = value << 16 | other_half;
2523 else
2524 value = other_half << 16 | value;
2525 }
2526 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
2527 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
2528 offset = value - r_value;
2529 value = r_value;
2530 }
2531
2532 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2533 if ((r_length & 0x1) == 1)
2534 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI161;
2535 else
2536 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO162;
2537 const char *add = GuessSymbolName(r_value, info->AddrMap);
2538 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2539 int32_t offset = value - (r_value - pair_r_value);
2540 op_info->AddSymbol.Present = 1;
2541 if (add != nullptr)
2542 op_info->AddSymbol.Name = add;
2543 else
2544 op_info->AddSymbol.Value = r_value;
2545 op_info->SubtractSymbol.Present = 1;
2546 if (sub != nullptr)
2547 op_info->SubtractSymbol.Name = sub;
2548 else
2549 op_info->SubtractSymbol.Value = pair_r_value;
2550 op_info->Value = offset;
2551 return 1;
2552 }
2553
2554 op_info->AddSymbol.Present = 1;
2555 op_info->Value = offset;
2556 if (r_type == MachO::ARM_RELOC_HALF) {
2557 if ((r_length & 0x1) == 1)
2558 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI161;
2559 else
2560 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO162;
2561 }
2562 const char *add = GuessSymbolName(value, info->AddrMap);
2563 if (add != nullptr) {
2564 op_info->AddSymbol.Name = add;
2565 return 1;
2566 }
2567 op_info->AddSymbol.Value = value;
2568 return 1;
2569 }
2570 if (Arch == Triple::aarch64) {
2571 if (Offset != 0 || Size != 4)
2572 return 0;
2573 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2574 // TODO:
2575 // Search the external relocation entries of a fully linked image
2576 // (if any) for an entry that matches this segment offset.
2577 // uint64_t seg_offset = (Pc + Offset);
2578 return 0;
2579 }
2580 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2581 // for an entry for this section offset.
2582 uint64_t sect_addr = info->S.getAddress();
2583 uint64_t sect_offset = (Pc + Offset) - sect_addr;
2584 auto Reloc =
2585 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
2586 uint64_t RelocOffset = Reloc.getOffset();
2587 return RelocOffset == sect_offset;
2588 });
2589
2590 if (Reloc == info->S.relocations().end())
2591 return 0;
2592
2593 DataRefImpl Rel = Reloc->getRawDataRefImpl();
2594 MachO::any_relocation_info RE = info->O->getRelocation(Rel);
2595 uint32_t r_type = info->O->getAnyRelocationType(RE);
2596 if (r_type == MachO::ARM64_RELOC_ADDEND) {
2597 DataRefImpl RelNext = Rel;
2598 info->O->moveRelocationNext(RelNext);
2599 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2600 if (value == 0) {
2601 value = info->O->getPlainRelocationSymbolNum(RENext);
2602 op_info->Value = value;
2603 }
2604 }
2605 // NOTE: Scattered relocations don't exist on arm64.
2606 if (!info->O->getPlainRelocationExternal(RE))
2607 return 0;
2608 Expected<StringRef> SymName = Reloc->getSymbol()->getName();
2609 if (!SymName)
2610 report_error(info->O->getFileName(), SymName.takeError());
2611 const char *name = SymName->data();
2612 op_info->AddSymbol.Present = 1;
2613 op_info->AddSymbol.Name = name;
2614
2615 switch (r_type) {
2616 case MachO::ARM64_RELOC_PAGE21:
2617 /* @page */
2618 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE1;
2619 break;
2620 case MachO::ARM64_RELOC_PAGEOFF12:
2621 /* @pageoff */
2622 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF2;
2623 break;
2624 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
2625 /* @gotpage */
2626 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE3;
2627 break;
2628 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
2629 /* @gotpageoff */
2630 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF4;
2631 break;
2632 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
2633 /* @tvlppage is not implemented in llvm-mc */
2634 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP5;
2635 break;
2636 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
2637 /* @tvlppageoff is not implemented in llvm-mc */
2638 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF6;
2639 break;
2640 default:
2641 case MachO::ARM64_RELOC_BRANCH26:
2642 op_info->VariantKind = LLVMDisassembler_VariantKind_None0;
2643 break;
2644 }
2645 return 1;
2646 }
2647 return 0;
2648}
2649
2650// GuessCstringPointer is passed the address of what might be a pointer to a
2651// literal string in a cstring section. If that address is in a cstring section
2652// it returns a pointer to that string. Else it returns nullptr.
2653static const char *GuessCstringPointer(uint64_t ReferenceValue,
2654 struct DisassembleInfo *info) {
2655 for (const auto &Load : info->O->load_commands()) {
2656 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2657 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2658 for (unsigned J = 0; J < Seg.nsects; ++J) {
2659 MachO::section_64 Sec = info->O->getSection64(Load, J);
2660 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2661 if (section_type == MachO::S_CSTRING_LITERALS &&
2662 ReferenceValue >= Sec.addr &&
2663 ReferenceValue < Sec.addr + Sec.size) {
2664 uint64_t sect_offset = ReferenceValue - Sec.addr;
2665 uint64_t object_offset = Sec.offset + sect_offset;
2666 StringRef MachOContents = info->O->getData();
2667 uint64_t object_size = MachOContents.size();
2668 const char *object_addr = (const char *)MachOContents.data();
2669 if (object_offset < object_size) {
2670 const char *name = object_addr + object_offset;
2671 return name;
2672 } else {
2673 return nullptr;
2674 }
2675 }
2676 }
2677 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2678 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2679 for (unsigned J = 0; J < Seg.nsects; ++J) {
2680 MachO::section Sec = info->O->getSection(Load, J);
2681 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2682 if (section_type == MachO::S_CSTRING_LITERALS &&
2683 ReferenceValue >= Sec.addr &&
2684 ReferenceValue < Sec.addr + Sec.size) {
2685 uint64_t sect_offset = ReferenceValue - Sec.addr;
2686 uint64_t object_offset = Sec.offset + sect_offset;
2687 StringRef MachOContents = info->O->getData();
2688 uint64_t object_size = MachOContents.size();
2689 const char *object_addr = (const char *)MachOContents.data();
2690 if (object_offset < object_size) {
2691 const char *name = object_addr + object_offset;
2692 return name;
2693 } else {
2694 return nullptr;
2695 }
2696 }
2697 }
2698 }
2699 }
2700 return nullptr;
2701}
2702
2703// GuessIndirectSymbol returns the name of the indirect symbol for the
2704// ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe
2705// an address of a symbol stub or a lazy or non-lazy pointer to associate the
2706// symbol name being referenced by the stub or pointer.
2707static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
2708 struct DisassembleInfo *info) {
2709 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
2710 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
2711 for (const auto &Load : info->O->load_commands()) {
2712 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2713 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2714 for (unsigned J = 0; J < Seg.nsects; ++J) {
2715 MachO::section_64 Sec = info->O->getSection64(Load, J);
2716 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2717 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2718 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2719 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2720 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2721 section_type == MachO::S_SYMBOL_STUBS) &&
2722 ReferenceValue >= Sec.addr &&
2723 ReferenceValue < Sec.addr + Sec.size) {
2724 uint32_t stride;
2725 if (section_type == MachO::S_SYMBOL_STUBS)
2726 stride = Sec.reserved2;
2727 else
2728 stride = 8;
2729 if (stride == 0)
2730 return nullptr;
2731 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2732 if (index < Dysymtab.nindirectsyms) {
2733 uint32_t indirect_symbol =
2734 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2735 if (indirect_symbol < Symtab.nsyms) {
2736 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2737 SymbolRef Symbol = *Sym;
2738 Expected<StringRef> SymName = Symbol.getName();
2739 if (!SymName)
2740 report_error(info->O->getFileName(), SymName.takeError());
2741 const char *name = SymName->data();
2742 return name;
2743 }
2744 }
2745 }
2746 }
2747 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2748 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2749 for (unsigned J = 0; J < Seg.nsects; ++J) {
2750 MachO::section Sec = info->O->getSection(Load, J);
2751 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2752 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2753 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2754 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2755 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2756 section_type == MachO::S_SYMBOL_STUBS) &&
2757 ReferenceValue >= Sec.addr &&
2758 ReferenceValue < Sec.addr + Sec.size) {
2759 uint32_t stride;
2760 if (section_type == MachO::S_SYMBOL_STUBS)
2761 stride = Sec.reserved2;
2762 else
2763 stride = 4;
2764 if (stride == 0)
2765 return nullptr;
2766 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2767 if (index < Dysymtab.nindirectsyms) {
2768 uint32_t indirect_symbol =
2769 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2770 if (indirect_symbol < Symtab.nsyms) {
2771 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2772 SymbolRef Symbol = *Sym;
2773 Expected<StringRef> SymName = Symbol.getName();
2774 if (!SymName)
2775 report_error(info->O->getFileName(), SymName.takeError());
2776 const char *name = SymName->data();
2777 return name;
2778 }
2779 }
2780 }
2781 }
2782 }
2783 }
2784 return nullptr;
2785}
2786
2787// method_reference() is called passing it the ReferenceName that might be
2788// a reference it to an Objective-C method call. If so then it allocates and
2789// assembles a method call string with the values last seen and saved in
2790// the DisassembleInfo's class_name and selector_name fields. This is saved
2791// into the method field of the info and any previous string is free'ed.
2792// Then the class_name field in the info is set to nullptr. The method call
2793// string is set into ReferenceName and ReferenceType is set to
2794// LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call
2795// then both ReferenceType and ReferenceName are left unchanged.
2796static void method_reference(struct DisassembleInfo *info,
2797 uint64_t *ReferenceType,
2798 const char **ReferenceName) {
2799 unsigned int Arch = info->O->getArch();
2800 if (*ReferenceName != nullptr) {
2801 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
2802 if (info->selector_name != nullptr) {
2803 if (info->class_name != nullptr) {
2804 info->method = llvm::make_unique<char[]>(
2805 5 + strlen(info->class_name) + strlen(info->selector_name));
2806 char *method = info->method.get();
2807 if (method != nullptr) {
2808 strcpy(method, "+[");
2809 strcat(method, info->class_name);
2810 strcat(method, " ");
2811 strcat(method, info->selector_name);
2812 strcat(method, "]");
2813 *ReferenceName = method;
2814 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message5;
2815 }
2816 } else {
2817 info->method =
2818 llvm::make_unique<char[]>(9 + strlen(info->selector_name));
2819 char *method = info->method.get();
2820 if (method != nullptr) {
2821 if (Arch == Triple::x86_64)
2822 strcpy(method, "-[%rdi ");
2823 else if (Arch == Triple::aarch64)
2824 strcpy(method, "-[x0 ");
2825 else
2826 strcpy(method, "-[r? ");
2827 strcat(method, info->selector_name);
2828 strcat(method, "]");
2829 *ReferenceName = method;
2830 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message5;
2831 }
2832 }
2833 info->class_name = nullptr;
2834 }
2835 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
2836 if (info->selector_name != nullptr) {
2837 info->method =
2838 llvm::make_unique<char[]>(17 + strlen(info->selector_name));
2839 char *method = info->method.get();
2840 if (method != nullptr) {
2841 if (Arch == Triple::x86_64)
2842 strcpy(method, "-[[%rdi super] ");
2843 else if (Arch == Triple::aarch64)
2844 strcpy(method, "-[[x0 super] ");
2845 else
2846 strcpy(method, "-[[r? super] ");
2847 strcat(method, info->selector_name);
2848 strcat(method, "]");
2849 *ReferenceName = method;
2850 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message5;
2851 }
2852 info->class_name = nullptr;
2853 }
2854 }
2855 }
2856}
2857
2858// GuessPointerPointer() is passed the address of what might be a pointer to
2859// a reference to an Objective-C class, selector, message ref or cfstring.
2860// If so the value of the pointer is returned and one of the booleans are set
2861// to true. If not zero is returned and all the booleans are set to false.
2862static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
2863 struct DisassembleInfo *info,
2864 bool &classref, bool &selref, bool &msgref,
2865 bool &cfstring) {
2866 classref = false;
2867 selref = false;
2868 msgref = false;
2869 cfstring = false;
2870 for (const auto &Load : info->O->load_commands()) {
2871 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2872 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2873 for (unsigned J = 0; J < Seg.nsects; ++J) {
2874 MachO::section_64 Sec = info->O->getSection64(Load, J);
2875 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
2876 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2877 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
2878 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
2879 strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
2880 ReferenceValue >= Sec.addr &&
2881 ReferenceValue < Sec.addr + Sec.size) {
2882 uint64_t sect_offset = ReferenceValue - Sec.addr;
2883 uint64_t object_offset = Sec.offset + sect_offset;
2884 StringRef MachOContents = info->O->getData();
2885 uint64_t object_size = MachOContents.size();
2886 const char *object_addr = (const char *)MachOContents.data();
2887 if (object_offset < object_size) {
2888 uint64_t pointer_value;
2889 memcpy(&pointer_value, object_addr + object_offset,
2890 sizeof(uint64_t));
2891 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2892 sys::swapByteOrder(pointer_value);
2893 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
2894 selref = true;
2895 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2896 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
2897 classref = true;
2898 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
2899 ReferenceValue + 8 < Sec.addr + Sec.size) {
2900 msgref = true;
2901 memcpy(&pointer_value, object_addr + object_offset + 8,
2902 sizeof(uint64_t));
2903 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2904 sys::swapByteOrder(pointer_value);
2905 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
2906 cfstring = true;
2907 return pointer_value;
2908 } else {
2909 return 0;
2910 }
2911 }
2912 }
2913 }
2914 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
2915 }
2916 return 0;
2917}
2918
2919// get_pointer_64 returns a pointer to the bytes in the object file at the
2920// Address from a section in the Mach-O file. And indirectly returns the
2921// offset into the section, number of bytes left in the section past the offset
2922// and which section is was being referenced. If the Address is not in a
2923// section nullptr is returned.
2924static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
2925 uint32_t &left, SectionRef &S,
2926 DisassembleInfo *info,
2927 bool objc_only = false) {
2928 offset = 0;
2929 left = 0;
2930 S = SectionRef();
2931 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
2932 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
2933 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
2934 if (SectSize == 0)
2935 continue;
2936 if (objc_only) {
2937 StringRef SectName;
2938 ((*(info->Sections))[SectIdx]).getName(SectName);
2939 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
2940 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
2941 if (SegName != "__OBJC" && SectName != "__cstring")
2942 continue;
2943 }
2944 if (Address >= SectAddress && Address < SectAddress + SectSize) {
2945 S = (*(info->Sections))[SectIdx];
2946 offset = Address - SectAddress;
2947 left = SectSize - offset;
2948 StringRef SectContents;
2949 ((*(info->Sections))[SectIdx]).getContents(SectContents);
2950 return SectContents.data() + offset;
2951 }
2952 }
2953 return nullptr;
2954}
2955
2956static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
2957 uint32_t &left, SectionRef &S,
2958 DisassembleInfo *info,
2959 bool objc_only = false) {
2960 return get_pointer_64(Address, offset, left, S, info, objc_only);
2961}
2962
2963// get_symbol_64() returns the name of a symbol (or nullptr) and the address of
2964// the symbol indirectly through n_value. Based on the relocation information
2965// for the specified section offset in the specified section reference.
2966// If no relocation information is found and a non-zero ReferenceValue for the
2967// symbol is passed, look up that address in the info's AddrMap.
2968static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
2969 DisassembleInfo *info, uint64_t &n_value,
2970 uint64_t ReferenceValue = 0) {
2971 n_value = 0;
2972 if (!info->verbose)
2973 return nullptr;
2974
2975 // See if there is an external relocation entry at the sect_offset.
2976 bool reloc_found = false;
2977 DataRefImpl Rel;
2978 MachO::any_relocation_info RE;
2979 bool isExtern = false;
2980 SymbolRef Symbol;
2981 for (const RelocationRef &Reloc : S.relocations()) {
2982 uint64_t RelocOffset = Reloc.getOffset();
2983 if (RelocOffset == sect_offset) {
2984 Rel = Reloc.getRawDataRefImpl();
2985 RE = info->O->getRelocation(Rel);
2986 if (info->O->isRelocationScattered(RE))
2987 continue;
2988 isExtern = info->O->getPlainRelocationExternal(RE);
2989 if (isExtern) {
2990 symbol_iterator RelocSym = Reloc.getSymbol();
2991 Symbol = *RelocSym;
2992 }
2993 reloc_found = true;
2994 break;
2995 }
2996 }
2997 // If there is an external relocation entry for a symbol in this section
2998 // at this section_offset then use that symbol's value for the n_value
2999 // and return its name.
3000 const char *SymbolName = nullptr;
3001 if (reloc_found && isExtern) {
3002 n_value = Symbol.getValue();
3003 Expected<StringRef> NameOrError = Symbol.getName();
3004 if (!NameOrError)
3005 report_error(info->O->getFileName(), NameOrError.takeError());
3006 StringRef Name = *NameOrError;
3007 if (!Name.empty()) {
3008 SymbolName = Name.data();
3009 return SymbolName;
3010 }
3011 }
3012
3013 // TODO: For fully linked images, look through the external relocation
3014 // entries off the dynamic symtab command. For these the r_offset is from the
3015 // start of the first writeable segment in the Mach-O file. So the offset
3016 // to this section from that segment is passed to this routine by the caller,
3017 // as the database_offset. Which is the difference of the section's starting
3018 // address and the first writable segment.
3019 //
3020 // NOTE: need add passing the database_offset to this routine.
3021
3022 // We did not find an external relocation entry so look up the ReferenceValue
3023 // as an address of a symbol and if found return that symbol's name.
3024 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
3025
3026 return SymbolName;
3027}
3028
3029static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
3030 DisassembleInfo *info,
3031 uint32_t ReferenceValue) {
3032 uint64_t n_value64;
3033 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
3034}
3035
3036// These are structs in the Objective-C meta data and read to produce the
3037// comments for disassembly. While these are part of the ABI they are no
3038// public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h
3039// .
3040
3041// The cfstring object in a 64-bit Mach-O file.
3042struct cfstring64_t {
3043 uint64_t isa; // class64_t * (64-bit pointer)
3044 uint64_t flags; // flag bits
3045 uint64_t characters; // char * (64-bit pointer)
3046 uint64_t length; // number of non-NULL characters in above
3047};
3048
3049// The class object in a 64-bit Mach-O file.
3050struct class64_t {
3051 uint64_t isa; // class64_t * (64-bit pointer)
3052 uint64_t superclass; // class64_t * (64-bit pointer)
3053 uint64_t cache; // Cache (64-bit pointer)
3054 uint64_t vtable; // IMP * (64-bit pointer)
3055 uint64_t data; // class_ro64_t * (64-bit pointer)
3056};
3057
3058struct class32_t {
3059 uint32_t isa; /* class32_t * (32-bit pointer) */
3060 uint32_t superclass; /* class32_t * (32-bit pointer) */
3061 uint32_t cache; /* Cache (32-bit pointer) */
3062 uint32_t vtable; /* IMP * (32-bit pointer) */
3063 uint32_t data; /* class_ro32_t * (32-bit pointer) */
3064};
3065
3066struct class_ro64_t {
3067 uint32_t flags;
3068 uint32_t instanceStart;
3069 uint32_t instanceSize;
3070 uint32_t reserved;
3071 uint64_t ivarLayout; // const uint8_t * (64-bit pointer)
3072 uint64_t name; // const char * (64-bit pointer)
3073 uint64_t baseMethods; // const method_list_t * (64-bit pointer)
3074 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer)
3075 uint64_t ivars; // const ivar_list_t * (64-bit pointer)
3076 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
3077 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
3078};
3079
3080struct class_ro32_t {
3081 uint32_t flags;
3082 uint32_t instanceStart;
3083 uint32_t instanceSize;
3084 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */
3085 uint32_t name; /* const char * (32-bit pointer) */
3086 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */
3087 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */
3088 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */
3089 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
3090 uint32_t baseProperties; /* const struct objc_property_list *
3091 (32-bit pointer) */
3092};
3093
3094/* Values for class_ro{64,32}_t->flags */
3095#define RO_META(1 << 0) (1 << 0)
3096#define RO_ROOT(1 << 1) (1 << 1)
3097#define RO_HAS_CXX_STRUCTORS(1 << 2) (1 << 2)
3098
3099struct method_list64_t {
3100 uint32_t entsize;
3101 uint32_t count;
3102 /* struct method64_t first; These structures follow inline */
3103};
3104
3105struct method_list32_t {
3106 uint32_t entsize;
3107 uint32_t count;
3108 /* struct method32_t first; These structures follow inline */
3109};
3110
3111struct method64_t {
3112 uint64_t name; /* SEL (64-bit pointer) */
3113 uint64_t types; /* const char * (64-bit pointer) */
3114 uint64_t imp; /* IMP (64-bit pointer) */
3115};
3116
3117struct method32_t {
3118 uint32_t name; /* SEL (32-bit pointer) */
3119 uint32_t types; /* const char * (32-bit pointer) */
3120 uint32_t imp; /* IMP (32-bit pointer) */
3121};
3122
3123struct protocol_list64_t {
3124 uint64_t count; /* uintptr_t (a 64-bit value) */
3125 /* struct protocol64_t * list[0]; These pointers follow inline */
3126};
3127
3128struct protocol_list32_t {
3129 uint32_t count; /* uintptr_t (a 32-bit value) */
3130 /* struct protocol32_t * list[0]; These pointers follow inline */
3131};
3132
3133struct protocol64_t {
3134 uint64_t isa; /* id * (64-bit pointer) */
3135 uint64_t name; /* const char * (64-bit pointer) */
3136 uint64_t protocols; /* struct protocol_list64_t *
3137 (64-bit pointer) */
3138 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */
3139 uint64_t classMethods; /* method_list_t * (64-bit pointer) */
3140 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3141 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */
3142 uint64_t instanceProperties; /* struct objc_property_list *
3143 (64-bit pointer) */
3144};
3145
3146struct protocol32_t {
3147 uint32_t isa; /* id * (32-bit pointer) */
3148 uint32_t name; /* const char * (32-bit pointer) */
3149 uint32_t protocols; /* struct protocol_list_t *
3150 (32-bit pointer) */
3151 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */
3152 uint32_t classMethods; /* method_list_t * (32-bit pointer) */
3153 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3154 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */
3155 uint32_t instanceProperties; /* struct objc_property_list *
3156 (32-bit pointer) */
3157};
3158
3159struct ivar_list64_t {
3160 uint32_t entsize;
3161 uint32_t count;
3162 /* struct ivar64_t first; These structures follow inline */
3163};
3164
3165struct ivar_list32_t {
3166 uint32_t entsize;
3167 uint32_t count;
3168 /* struct ivar32_t first; These structures follow inline */
3169};
3170
3171struct ivar64_t {
3172 uint64_t offset; /* uintptr_t * (64-bit pointer) */
3173 uint64_t name; /* const char * (64-bit pointer) */
3174 uint64_t type; /* const char * (64-bit pointer) */
3175 uint32_t alignment;
3176 uint32_t size;
3177};
3178
3179struct ivar32_t {
3180 uint32_t offset; /* uintptr_t * (32-bit pointer) */
3181 uint32_t name; /* const char * (32-bit pointer) */
3182 uint32_t type; /* const char * (32-bit pointer) */
3183 uint32_t alignment;
3184 uint32_t size;
3185};
3186
3187struct objc_property_list64 {
3188 uint32_t entsize;
3189 uint32_t count;
3190 /* struct objc_property64 first; These structures follow inline */
3191};
3192
3193struct objc_property_list32 {
3194 uint32_t entsize;
3195 uint32_t count;
3196 /* struct objc_property32 first; These structures follow inline */
3197};
3198
3199struct objc_property64 {
3200 uint64_t name; /* const char * (64-bit pointer) */
3201 uint64_t attributes; /* const char * (64-bit pointer) */
3202};
3203
3204struct objc_property32 {
3205 uint32_t name; /* const char * (32-bit pointer) */
3206 uint32_t attributes; /* const char * (32-bit pointer) */
3207};
3208
3209struct category64_t {
3210 uint64_t name; /* const char * (64-bit pointer) */
3211 uint64_t cls; /* struct class_t * (64-bit pointer) */
3212 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */
3213 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */
3214 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */
3215 uint64_t instanceProperties; /* struct objc_property_list *
3216 (64-bit pointer) */
3217};
3218
3219struct category32_t {
3220 uint32_t name; /* const char * (32-bit pointer) */
3221 uint32_t cls; /* struct class_t * (32-bit pointer) */
3222 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */
3223 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */
3224 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */
3225 uint32_t instanceProperties; /* struct objc_property_list *
3226 (32-bit pointer) */
3227};
3228
3229struct objc_image_info64 {
3230 uint32_t version;
3231 uint32_t flags;
3232};
3233struct objc_image_info32 {
3234 uint32_t version;
3235 uint32_t flags;
3236};
3237struct imageInfo_t {
3238 uint32_t version;
3239 uint32_t flags;
3240};
3241/* masks for objc_image_info.flags */
3242#define OBJC_IMAGE_IS_REPLACEMENT(1 << 0) (1 << 0)
3243#define OBJC_IMAGE_SUPPORTS_GC(1 << 1) (1 << 1)
3244#define OBJC_IMAGE_IS_SIMULATED(1 << 5) (1 << 5)
3245#define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES(1 << 6) (1 << 6)
3246
3247struct message_ref64 {
3248 uint64_t imp; /* IMP (64-bit pointer) */
3249 uint64_t sel; /* SEL (64-bit pointer) */
3250};
3251
3252struct message_ref32 {
3253 uint32_t imp; /* IMP (32-bit pointer) */
3254 uint32_t sel; /* SEL (32-bit pointer) */
3255};
3256
3257// Objective-C 1 (32-bit only) meta data structs.
3258
3259struct objc_module_t {
3260 uint32_t version;
3261 uint32_t size;
3262 uint32_t name; /* char * (32-bit pointer) */
3263 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3264};
3265
3266struct objc_symtab_t {
3267 uint32_t sel_ref_cnt;
3268 uint32_t refs; /* SEL * (32-bit pointer) */
3269 uint16_t cls_def_cnt;
3270 uint16_t cat_def_cnt;
3271 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */
3272};
3273
3274struct objc_class_t {
3275 uint32_t isa; /* struct objc_class * (32-bit pointer) */
3276 uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3277 uint32_t name; /* const char * (32-bit pointer) */
3278 int32_t version;
3279 int32_t info;
3280 int32_t instance_size;
3281 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */
3282 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3283 uint32_t cache; /* struct objc_cache * (32-bit pointer) */
3284 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */
3285};
3286
3287#define CLS_GETINFO(cls, infomask)((cls)->info & (infomask)) ((cls)->info & (infomask))
3288// class is not a metaclass
3289#define CLS_CLASS0x1 0x1
3290// class is a metaclass
3291#define CLS_META0x2 0x2
3292
3293struct objc_category_t {
3294 uint32_t category_name; /* char * (32-bit pointer) */
3295 uint32_t class_name; /* char * (32-bit pointer) */
3296 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3297 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */
3298 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */
3299};
3300
3301struct objc_ivar_t {
3302 uint32_t ivar_name; /* char * (32-bit pointer) */
3303 uint32_t ivar_type; /* char * (32-bit pointer) */
3304 int32_t ivar_offset;
3305};
3306
3307struct objc_ivar_list_t {
3308 int32_t ivar_count;
3309 // struct objc_ivar_t ivar_list[1]; /* variable length structure */
3310};
3311
3312struct objc_method_list_t {
3313 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3314 int32_t method_count;
3315 // struct objc_method_t method_list[1]; /* variable length structure */
3316};
3317
3318struct objc_method_t {
3319 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */
3320 uint32_t method_types; /* char * (32-bit pointer) */
3321 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3322 (32-bit pointer) */
3323};
3324
3325struct objc_protocol_list_t {
3326 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3327 int32_t count;
3328 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t *
3329 // (32-bit pointer) */
3330};
3331
3332struct objc_protocol_t {
3333 uint32_t isa; /* struct objc_class * (32-bit pointer) */
3334 uint32_t protocol_name; /* char * (32-bit pointer) */
3335 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */
3336 uint32_t instance_methods; /* struct objc_method_description_list *
3337 (32-bit pointer) */
3338 uint32_t class_methods; /* struct objc_method_description_list *
3339 (32-bit pointer) */
3340};
3341
3342struct objc_method_description_list_t {
3343 int32_t count;
3344 // struct objc_method_description_t list[1];
3345};
3346
3347struct objc_method_description_t {
3348 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */
3349 uint32_t types; /* char * (32-bit pointer) */
3350};
3351
3352inline void swapStruct(struct cfstring64_t &cfs) {
3353 sys::swapByteOrder(cfs.isa);
3354 sys::swapByteOrder(cfs.flags);
3355 sys::swapByteOrder(cfs.characters);
3356 sys::swapByteOrder(cfs.length);
3357}
3358
3359inline void swapStruct(struct class64_t &c) {
3360 sys::swapByteOrder(c.isa);
3361 sys::swapByteOrder(c.superclass);
3362 sys::swapByteOrder(c.cache);
3363 sys::swapByteOrder(c.vtable);
3364 sys::swapByteOrder(c.data);
3365}
3366
3367inline void swapStruct(struct class32_t &c) {
3368 sys::swapByteOrder(c.isa);
3369 sys::swapByteOrder(c.superclass);
3370 sys::swapByteOrder(c.cache);
3371 sys::swapByteOrder(c.vtable);
3372 sys::swapByteOrder(c.data);
3373}
3374
3375inline void swapStruct(struct class_ro64_t &cro) {
3376 sys::swapByteOrder(cro.flags);
3377 sys::swapByteOrder(cro.instanceStart);
3378 sys::swapByteOrder(cro.instanceSize);
3379 sys::swapByteOrder(cro.reserved);
3380 sys::swapByteOrder(cro.ivarLayout);
3381 sys::swapByteOrder(cro.name);
3382 sys::swapByteOrder(cro.baseMethods);
3383 sys::swapByteOrder(cro.baseProtocols);
3384 sys::swapByteOrder(cro.ivars);
3385 sys::swapByteOrder(cro.weakIvarLayout);
3386 sys::swapByteOrder(cro.baseProperties);
3387}
3388
3389inline void swapStruct(struct class_ro32_t &cro) {
3390 sys::swapByteOrder(cro.flags);
3391 sys::swapByteOrder(cro.instanceStart);
3392 sys::swapByteOrder(cro.instanceSize);
3393 sys::swapByteOrder(cro.ivarLayout);
3394 sys::swapByteOrder(cro.name);
3395 sys::swapByteOrder(cro.baseMethods);
3396 sys::swapByteOrder(cro.baseProtocols);
3397 sys::swapByteOrder(cro.ivars);
3398 sys::swapByteOrder(cro.weakIvarLayout);
3399 sys::swapByteOrder(cro.baseProperties);
3400}
3401
3402inline void swapStruct(struct method_list64_t &ml) {
3403 sys::swapByteOrder(ml.entsize);
3404 sys::swapByteOrder(ml.count);
3405}
3406
3407inline void swapStruct(struct method_list32_t &ml) {
3408 sys::swapByteOrder(ml.entsize);
3409 sys::swapByteOrder(ml.count);
3410}
3411
3412inline void swapStruct(struct method64_t &m) {
3413 sys::swapByteOrder(m.name);
3414 sys::swapByteOrder(m.types);
3415 sys::swapByteOrder(m.imp);
3416}
3417
3418inline void swapStruct(struct method32_t &m) {
3419 sys::swapByteOrder(m.name);
3420 sys::swapByteOrder(m.types);
3421 sys::swapByteOrder(m.imp);
3422}
3423
3424inline void swapStruct(struct protocol_list64_t &pl) {
3425 sys::swapByteOrder(pl.count);
3426}
3427
3428inline void swapStruct(struct protocol_list32_t &pl) {
3429 sys::swapByteOrder(pl.count);
3430}
3431
3432inline void swapStruct(struct protocol64_t &p) {
3433 sys::swapByteOrder(p.isa);
3434 sys::swapByteOrder(p.name);
3435 sys::swapByteOrder(p.protocols);
3436 sys::swapByteOrder(p.instanceMethods);
3437 sys::swapByteOrder(p.classMethods);
3438 sys::swapByteOrder(p.optionalInstanceMethods);
3439 sys::swapByteOrder(p.optionalClassMethods);
3440 sys::swapByteOrder(p.instanceProperties);
3441}
3442
3443inline void swapStruct(struct protocol32_t &p) {
3444 sys::swapByteOrder(p.isa);
3445 sys::swapByteOrder(p.name);
3446 sys::swapByteOrder(p.protocols);
3447 sys::swapByteOrder(p.instanceMethods);
3448 sys::swapByteOrder(p.classMethods);
3449 sys::swapByteOrder(p.optionalInstanceMethods);
3450 sys::swapByteOrder(p.optionalClassMethods);
3451 sys::swapByteOrder(p.instanceProperties);
3452}
3453
3454inline void swapStruct(struct ivar_list64_t &il) {
3455 sys::swapByteOrder(il.entsize);
3456 sys::swapByteOrder(il.count);
3457}
3458
3459inline void swapStruct(struct ivar_list32_t &il) {
3460 sys::swapByteOrder(il.entsize);
3461 sys::swapByteOrder(il.count);
3462}
3463
3464inline void swapStruct(struct ivar64_t &i) {
3465 sys::swapByteOrder(i.offset);
3466 sys::swapByteOrder(i.name);
3467 sys::swapByteOrder(i.type);
3468 sys::swapByteOrder(i.alignment);
3469 sys::swapByteOrder(i.size);
3470}
3471
3472inline void swapStruct(struct ivar32_t &i) {
3473 sys::swapByteOrder(i.offset);
3474 sys::swapByteOrder(i.name);
3475 sys::swapByteOrder(i.type);
3476 sys::swapByteOrder(i.alignment);
3477 sys::swapByteOrder(i.size);
3478}
3479
3480inline void swapStruct(struct objc_property_list64 &pl) {
3481 sys::swapByteOrder(pl.entsize);
3482 sys::swapByteOrder(pl.count);
3483}
3484
3485inline void swapStruct(struct objc_property_list32 &pl) {
3486 sys::swapByteOrder(pl.entsize);
3487 sys::swapByteOrder(pl.count);
3488}
3489
3490inline void swapStruct(struct objc_property64 &op) {
3491 sys::swapByteOrder(op.name);
3492 sys::swapByteOrder(op.attributes);
3493}
3494
3495inline void swapStruct(struct objc_property32 &op) {
3496 sys::swapByteOrder(op.name);
3497 sys::swapByteOrder(op.attributes);
3498}
3499
3500inline void swapStruct(struct category64_t &c) {
3501 sys::swapByteOrder(c.name);
3502 sys::swapByteOrder(c.cls);
3503 sys::swapByteOrder(c.instanceMethods);
3504 sys::swapByteOrder(c.classMethods);
3505 sys::swapByteOrder(c.protocols);
3506 sys::swapByteOrder(c.instanceProperties);
3507}
3508
3509inline void swapStruct(struct category32_t &c) {
3510 sys::swapByteOrder(c.name);
3511 sys::swapByteOrder(c.cls);
3512 sys::swapByteOrder(c.instanceMethods);
3513 sys::swapByteOrder(c.classMethods);
3514 sys::swapByteOrder(c.protocols);
3515 sys::swapByteOrder(c.instanceProperties);
3516}
3517
3518inline void swapStruct(struct objc_image_info64 &o) {
3519 sys::swapByteOrder(o.version);
3520 sys::swapByteOrder(o.flags);
3521}
3522
3523inline void swapStruct(struct objc_image_info32 &o) {
3524 sys::swapByteOrder(o.version);
3525 sys::swapByteOrder(o.flags);
3526}
3527
3528inline void swapStruct(struct imageInfo_t &o) {
3529 sys::swapByteOrder(o.version);
3530 sys::swapByteOrder(o.flags);
3531}
3532
3533inline void swapStruct(struct message_ref64 &mr) {
3534 sys::swapByteOrder(mr.imp);
3535 sys::swapByteOrder(mr.sel);
3536}
3537
3538inline void swapStruct(struct message_ref32 &mr) {
3539 sys::swapByteOrder(mr.imp);
3540 sys::swapByteOrder(mr.sel);
3541}
3542
3543inline void swapStruct(struct objc_module_t &module) {
3544 sys::swapByteOrder(module.version);
3545 sys::swapByteOrder(module.size);
3546 sys::swapByteOrder(module.name);
3547 sys::swapByteOrder(module.symtab);
3548}
3549
3550inline void swapStruct(struct objc_symtab_t &symtab) {
3551 sys::swapByteOrder(symtab.sel_ref_cnt);
3552 sys::swapByteOrder(symtab.refs);
3553 sys::swapByteOrder(symtab.cls_def_cnt);
3554 sys::swapByteOrder(symtab.cat_def_cnt);
3555}
3556
3557inline void swapStruct(struct objc_class_t &objc_class) {
3558 sys::swapByteOrder(objc_class.isa);
3559 sys::swapByteOrder(objc_class.super_class);
3560 sys::swapByteOrder(objc_class.name);
3561 sys::swapByteOrder(objc_class.version);
3562 sys::swapByteOrder(objc_class.info);
3563 sys::swapByteOrder(objc_class.instance_size);
3564 sys::swapByteOrder(objc_class.ivars);
3565 sys::swapByteOrder(objc_class.methodLists);
3566 sys::swapByteOrder(objc_class.cache);
3567 sys::swapByteOrder(objc_class.protocols);
3568}
3569
3570inline void swapStruct(struct objc_category_t &objc_category) {
3571 sys::swapByteOrder(objc_category.category_name);
3572 sys::swapByteOrder(objc_category.class_name);
3573 sys::swapByteOrder(objc_category.instance_methods);
3574 sys::swapByteOrder(objc_category.class_methods);
3575 sys::swapByteOrder(objc_category.protocols);
3576}
3577
3578inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
3579 sys::swapByteOrder(objc_ivar_list.ivar_count);
3580}
3581
3582inline void swapStruct(struct objc_ivar_t &objc_ivar) {
3583 sys::swapByteOrder(objc_ivar.ivar_name);
3584 sys::swapByteOrder(objc_ivar.ivar_type);
3585 sys::swapByteOrder(objc_ivar.ivar_offset);
3586}
3587
3588inline void swapStruct(struct objc_method_list_t &method_list) {
3589 sys::swapByteOrder(method_list.obsolete);
3590 sys::swapByteOrder(method_list.method_count);
3591}
3592
3593inline void swapStruct(struct objc_method_t &method) {
3594 sys::swapByteOrder(method.method_name);
3595 sys::swapByteOrder(method.method_types);
3596 sys::swapByteOrder(method.method_imp);
3597}
3598
3599inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
3600 sys::swapByteOrder(protocol_list.next);
3601 sys::swapByteOrder(protocol_list.count);
3602}
3603
3604inline void swapStruct(struct objc_protocol_t &protocol) {
3605 sys::swapByteOrder(protocol.isa);
3606 sys::swapByteOrder(protocol.protocol_name);
3607 sys::swapByteOrder(protocol.protocol_list);
3608 sys::swapByteOrder(protocol.instance_methods);
3609 sys::swapByteOrder(protocol.class_methods);
3610}
3611
3612inline void swapStruct(struct objc_method_description_list_t &mdl) {
3613 sys::swapByteOrder(mdl.count);
3614}
3615
3616inline void swapStruct(struct objc_method_description_t &md) {
3617 sys::swapByteOrder(md.name);
3618 sys::swapByteOrder(md.types);
3619}
3620
3621static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
3622 struct DisassembleInfo *info);
3623
3624// get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
3625// to an Objective-C class and returns the class name. It is also passed the
3626// address of the pointer, so when the pointer is zero as it can be in an .o
3627// file, that is used to look for an external relocation entry with a symbol
3628// name.
3629static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
3630 uint64_t ReferenceValue,
3631 struct DisassembleInfo *info) {
3632 const char *r;
3633 uint32_t offset, left;
3634 SectionRef S;
3635
3636 // The pointer_value can be 0 in an object file and have a relocation
3637 // entry for the class symbol at the ReferenceValue (the address of the
3638 // pointer).
3639 if (pointer_value == 0) {
3640 r = get_pointer_64(ReferenceValue, offset, left, S, info);
3641 if (r == nullptr || left < sizeof(uint64_t))
3642 return nullptr;
3643 uint64_t n_value;
3644 const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3645 if (symbol_name == nullptr)
3646 return nullptr;
3647 const char *class_name = strrchr(symbol_name, '$');
3648 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
3649 return class_name + 2;
3650 else
3651 return nullptr;
3652 }
3653
3654 // The case were the pointer_value is non-zero and points to a class defined
3655 // in this Mach-O file.
3656 r = get_pointer_64(pointer_value, offset, left, S, info);
3657 if (r == nullptr || left < sizeof(struct class64_t))
3658 return nullptr;
3659 struct class64_t c;
3660 memcpy(&c, r, sizeof(struct class64_t));
3661 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3662 swapStruct(c);
3663 if (c.data == 0)
3664 return nullptr;
3665 r = get_pointer_64(c.data, offset, left, S, info);
3666 if (r == nullptr || left < sizeof(struct class_ro64_t))
3667 return nullptr;
3668 struct class_ro64_t cro;
3669 memcpy(&cro, r, sizeof(struct class_ro64_t));
3670 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3671 swapStruct(cro);
3672 if (cro.name == 0)
3673 return nullptr;
3674 const char *name = get_pointer_64(cro.name, offset, left, S, info);
3675 return name;
3676}
3677
3678// get_objc2_64bit_cfstring_name is used for disassembly and is passed a
3679// pointer to a cfstring and returns its name or nullptr.
3680static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
3681 struct DisassembleInfo *info) {
3682 const char *r, *name;
3683 uint32_t offset, left;
3684 SectionRef S;
3685 struct cfstring64_t cfs;
3686 uint64_t cfs_characters;
3687
3688 r = get_pointer_64(ReferenceValue, offset, left, S, info);
3689 if (r == nullptr || left < sizeof(struct cfstring64_t))
3690 return nullptr;
3691 memcpy(&cfs, r, sizeof(struct cfstring64_t));
3692 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3693 swapStruct(cfs);
3694 if (cfs.characters == 0) {
3695 uint64_t n_value;
3696 const char *symbol_name = get_symbol_64(
3697 offset + offsetof(struct cfstring64_t, characters)__builtin_offsetof(struct cfstring64_t, characters), S, info, n_value);
3698 if (symbol_name == nullptr)
3699 return nullptr;
3700 cfs_characters = n_value;
3701 } else
3702 cfs_characters = cfs.characters;
3703 name = get_pointer_64(cfs_characters, offset, left, S, info);
3704
3705 return name;
3706}
3707
3708// get_objc2_64bit_selref() is used for disassembly and is passed a the address
3709// of a pointer to an Objective-C selector reference when the pointer value is
3710// zero as in a .o file and is likely to have a external relocation entry with
3711// who's symbol's n_value is the real pointer to the selector name. If that is
3712// the case the real pointer to the selector name is returned else 0 is
3713// returned
3714static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
3715 struct DisassembleInfo *info) {
3716 uint32_t offset, left;
3717 SectionRef S;
3718
3719 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
3720 if (r == nullptr || left < sizeof(uint64_t))
3721 return 0;
3722 uint64_t n_value;
3723 const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3724 if (symbol_name == nullptr)
3725 return 0;
3726 return n_value;
3727}
3728
3729static const SectionRef get_section(MachOObjectFile *O, const char *segname,
3730 const char *sectname) {
3731 for (const SectionRef &Section : O->sections()) {
3732 StringRef SectName;
3733 Section.getName(SectName);
3734 DataRefImpl Ref = Section.getRawDataRefImpl();
3735 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3736 if (SegName == segname && SectName == sectname)
3737 return Section;
3738 }
3739 return SectionRef();
3740}
3741
3742static void
3743walk_pointer_list_64(const char *listname, const SectionRef S,
3744 MachOObjectFile *O, struct DisassembleInfo *info,
3745 void (*func)(uint64_t, struct DisassembleInfo *info)) {
3746 if (S == SectionRef())
77
Taking false branch
3747 return;
3748
3749 StringRef SectName;
3750 S.getName(SectName);
78
Calling 'SectionRef::getName'
3751 DataRefImpl Ref = S.getRawDataRefImpl();
3752 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3753 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3754
3755 StringRef BytesStr;
3756 S.getContents(BytesStr);
3757 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3758
3759 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
3760 uint32_t left = S.getSize() - i;
3761 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
3762 uint64_t p = 0;
3763 memcpy(&p, Contents + i, size);
3764 if (i + sizeof(uint64_t) > S.getSize())
3765 outs() << listname << " list pointer extends past end of (" << SegName
3766 << "," << SectName << ") section\n";
3767 outs() << format("%016" PRIx64"l" "x", S.getAddress() + i) << " ";
3768
3769 if (O->isLittleEndian() != sys::IsLittleEndianHost)
3770 sys::swapByteOrder(p);
3771
3772 uint64_t n_value = 0;
3773 const char *name = get_symbol_64(i, S, info, n_value, p);
3774 if (name == nullptr)
3775 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
3776
3777 if (n_value != 0) {
3778 outs() << format("0x%" PRIx64"l" "x", n_value);
3779 if (p != 0)
3780 outs() << " + " << format("0x%" PRIx64"l" "x", p);
3781 } else
3782 outs() << format("0x%" PRIx64"l" "x", p);
3783 if (name != nullptr)
3784 outs() << " " << name;
3785 outs() << "\n";
3786
3787 p += n_value;
3788 if (func)
3789 func(p, info);
3790 }
3791}
3792
3793static void
3794walk_pointer_list_32(const char *listname, const SectionRef S,
3795 MachOObjectFile *O, struct DisassembleInfo *info,
3796 void (*func)(uint32_t, struct DisassembleInfo *info)) {
3797 if (S == SectionRef())
3798 return;
3799
3800 StringRef SectName;
3801 S.getName(SectName);
3802 DataRefImpl Ref = S.getRawDataRefImpl();
3803 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3804 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3805
3806 StringRef BytesStr;
3807 S.getContents(BytesStr);
3808 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3809
3810 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
3811 uint32_t left = S.getSize() - i;
3812 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
3813 uint32_t p = 0;
3814 memcpy(&p, Contents + i, size);
3815 if (i + sizeof(uint32_t) > S.getSize())
3816 outs() << listname << " list pointer extends past end of (" << SegName
3817 << "," << SectName << ") section\n";
3818 uint32_t Address = S.getAddress() + i;
3819 outs() << format("%08" PRIx32"x", Address) << " ";
3820
3821 if (O->isLittleEndian() != sys::IsLittleEndianHost)
3822 sys::swapByteOrder(p);
3823 outs() << format("0x%" PRIx32"x", p);
3824
3825 const char *name = get_symbol_32(i, S, info, p);
3826 if (name != nullptr)
3827 outs() << " " << name;
3828 outs() << "\n";
3829
3830 if (func)
3831 func(p, info);
3832 }
3833}
3834
3835static void print_layout_map(const char *layout_map, uint32_t left) {
3836 if (layout_map == nullptr)
3837 return;
3838 outs() << " layout map: ";
3839 do {
3840 outs() << format("0x%02" PRIx32"x", (*layout_map) & 0xff) << " ";
3841 left--;
3842 layout_map++;
3843 } while (*layout_map != '\0' && left != 0);
3844 outs() << "\n";
3845}
3846
3847static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
3848 uint32_t offset, left;
3849 SectionRef S;
3850 const char *layout_map;
3851
3852 if (p == 0)
3853 return;
3854 layout_map = get_pointer_64(p, offset, left, S, info);
3855 print_layout_map(layout_map, left);
3856}
3857
3858static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
3859 uint32_t offset, left;
3860 SectionRef S;
3861 const char *layout_map;
3862
3863 if (p == 0)
3864 return;
3865 layout_map = get_pointer_32(p, offset, left, S, info);
3866 print_layout_map(layout_map, left);
3867}
3868
3869static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
3870 const char *indent) {
3871 struct method_list64_t ml;
3872 struct method64_t m;
3873 const char *r;
3874 uint32_t offset, xoffset, left, i;
3875 SectionRef S, xS;
3876 const char *name, *sym_name;
3877 uint64_t n_value;
3878
3879 r = get_pointer_64(p, offset, left, S, info);
3880 if (r == nullptr)
3881 return;
3882 memset(&ml, '\0', sizeof(struct method_list64_t));
3883 if (left < sizeof(struct method_list64_t)) {
3884 memcpy(&ml, r, left);
3885 outs() << " (method_list_t entends past the end of the section)\n";
3886 } else
3887 memcpy(&ml, r, sizeof(struct method_list64_t));
3888 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3889 swapStruct(ml);
3890 outs() << indent << "\t\t entsize " << ml.entsize << "\n";
3891 outs() << indent << "\t\t count " << ml.count << "\n";
3892
3893 p += sizeof(struct method_list64_t);
3894 offset += sizeof(struct method_list64_t);
3895 for (i = 0; i < ml.count; i++) {
3896 r = get_pointer_64(p, offset, left, S, info);
3897 if (r == nullptr)
3898 return;
3899 memset(&m, '\0', sizeof(struct method64_t));
3900 if (left < sizeof(struct method64_t)) {
3901 memcpy(&m, r, left);
3902 outs() << indent << " (method_t extends past the end of the section)\n";
3903 } else
3904 memcpy(&m, r, sizeof(struct method64_t));
3905 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3906 swapStruct(m);
3907
3908 outs() << indent << "\t\t name ";
3909 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name)__builtin_offsetof(struct method64_t, name), S,
3910 info, n_value, m.name);
3911 if (n_value != 0) {
3912 if (info->verbose && sym_name != nullptr)
3913 outs() << sym_name;
3914 else
3915 outs() << format("0x%" PRIx64"l" "x", n_value);
3916 if (m.name != 0)
3917 outs() << " + " << format("0x%" PRIx64"l" "x", m.name);
3918 } else
3919 outs() << format("0x%" PRIx64"l" "x", m.name);
3920 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
3921 if (name != nullptr)
3922 outs() << format(" %.*s", left, name);
3923 outs() << "\n";
3924
3925 outs() << indent << "\t\t types ";
3926 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types)__builtin_offsetof(struct method64_t, types), S,
3927 info, n_value, m.types);
3928 if (n_value != 0) {
3929 if (info->verbose && sym_name != nullptr)
3930 outs() << sym_name;
3931 else
3932 outs() << format("0x%" PRIx64"l" "x", n_value);
3933 if (m.types != 0)
3934 outs() << " + " << format("0x%" PRIx64"l" "x", m.types);
3935 } else
3936 outs() << format("0x%" PRIx64"l" "x", m.types);
3937 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
3938 if (name != nullptr)
3939 outs() << format(" %.*s", left, name);
3940 outs() << "\n";
3941
3942 outs() << indent << "\t\t imp ";
3943 name = get_symbol_64(offset + offsetof(struct method64_t, imp)__builtin_offsetof(struct method64_t, imp), S, info,
3944 n_value, m.imp);
3945 if (info->verbose && name == nullptr) {
3946 if (n_value != 0) {
3947 outs() << format("0x%" PRIx64"l" "x", n_value) << " ";
3948 if (m.imp != 0)
3949 outs() << "+ " << format("0x%" PRIx64"l" "x", m.imp) << " ";
3950 } else
3951 outs() << format("0x%" PRIx64"l" "x", m.imp) << " ";
3952 }
3953 if (name != nullptr)
3954 outs() << name;
3955 outs() << "\n";
3956
3957 p += sizeof(struct method64_t);
3958 offset += sizeof(struct method64_t);
3959 }
3960}
3961
3962static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
3963 const char *indent) {
3964 struct method_list32_t ml;
3965 struct method32_t m;
3966 const char *r, *name;
3967 uint32_t offset, xoffset, left, i;
3968 SectionRef S, xS;
3969
3970 r = get_pointer_32(p, offset, left, S, info);
3971 if (r == nullptr)
3972 return;
3973 memset(&ml, '\0', sizeof(struct method_list32_t));
3974 if (left < sizeof(struct method_list32_t)) {
3975 memcpy(&ml, r, left);
3976 outs() << " (method_list_t entends past the end of the section)\n";
3977 } else
3978 memcpy(&ml, r, sizeof(struct method_list32_t));
3979 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3980 swapStruct(ml);
3981 outs() << indent << "\t\t entsize " << ml.entsize << "\n";
3982 outs() << indent << "\t\t count " << ml.count << "\n";
3983
3984 p += sizeof(struct method_list32_t);
3985 offset += sizeof(struct method_list32_t);
3986 for (i = 0; i < ml.count; i++) {
3987 r = get_pointer_32(p, offset, left, S, info);
3988 if (r == nullptr)
3989 return;
3990 memset(&m, '\0', sizeof(struct method32_t));
3991 if (left < sizeof(struct method32_t)) {
3992 memcpy(&ml, r, left);
3993 outs() << indent << " (method_t entends past the end of the section)\n";
3994 } else
3995 memcpy(&m, r, sizeof(struct method32_t));
3996 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3997 swapStruct(m);
3998
3999 outs() << indent << "\t\t name " << format("0x%" PRIx32"x", m.name);
4000 name = get_pointer_32(m.name, xoffset, left, xS, info);
4001 if (name != nullptr)
4002 outs() << format(" %.*s", left, name);
4003 outs() << "\n";
4004
4005 outs() << indent << "\t\t types " << format("0x%" PRIx32"x", m.types);
4006 name = get_pointer_32(m.types, xoffset, left, xS, info);
4007 if (name != nullptr)
4008 outs() << format(" %.*s", left, name);
4009 outs() << "\n";
4010
4011 outs() << indent << "\t\t imp " << format("0x%" PRIx32"x", m.imp);
4012 name = get_symbol_32(offset + offsetof(struct method32_t, imp)__builtin_offsetof(struct method32_t, imp), S, info,
4013 m.imp);
4014 if (name != nullptr)
4015 outs() << " " << name;
4016 outs() << "\n";
4017
4018 p += sizeof(struct method32_t);
4019 offset += sizeof(struct method32_t);
4020 }
4021}
4022
4023static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
4024 uint32_t offset, left, xleft;
4025 SectionRef S;
4026 struct objc_method_list_t method_list;
4027 struct objc_method_t method;
4028 const char *r, *methods, *name, *SymbolName;
4029 int32_t i;
4030
4031 r = get_pointer_32(p, offset, left, S, info, true);
4032 if (r == nullptr)
4033 return true;
4034
4035 outs() << "\n";
4036 if (left > sizeof(struct objc_method_list_t)) {
4037 memcpy(&method_list, r, sizeof(struct objc_method_list_t));
4038 } else {
4039 outs() << "\t\t objc_method_list extends past end of the section\n";
4040 memset(&method_list, '\0', sizeof(struct objc_method_list_t));
4041 memcpy(&method_list, r, left);
4042 }
4043 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4044 swapStruct(method_list);
4045
4046 outs() << "\t\t obsolete "
4047 << format("0x%08" PRIx32"x", method_list.obsolete) << "\n";
4048 outs() << "\t\t method_count " << method_list.method_count << "\n";
4049
4050 methods = r + sizeof(struct objc_method_list_t);
4051 for (i = 0; i < method_list.method_count; i++) {
4052 if ((i + 1) * sizeof(struct objc_method_t) > left) {
4053 outs() << "\t\t remaining method's extend past the of the section\n";
4054 break;
4055 }
4056 memcpy(&method, methods + i * sizeof(struct objc_method_t),
4057 sizeof(struct objc_method_t));
4058 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4059 swapStruct(method);
4060
4061 outs() << "\t\t method_name "
4062 << format("0x%08" PRIx32"x", method.method_name);
4063 if (info->verbose) {
4064 name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4065 if (name != nullptr)
4066 outs() << format(" %.*s", xleft, name);
4067 else
4068 outs() << " (not in an __OBJC section)";
4069 }
4070 outs() << "\n";
4071
4072 outs() << "\t\t method_types "
4073 << format("0x%08" PRIx32"x", method.method_types);
4074 if (info->verbose) {
4075 name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4076 if (name != nullptr)
4077 outs() << format(" %.*s", xleft, name);
4078 else
4079 outs() << " (not in an __OBJC section)";
4080 }
4081 outs() << "\n";
4082
4083 outs() << "\t\t method_imp "
4084 << format("0x%08" PRIx32"x", method.method_imp) << " ";
4085 if (info->verbose) {
4086 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4087 if (SymbolName != nullptr)
4088 outs() << SymbolName;
4089 }
4090 outs() << "\n";
4091 }
4092 return false;
4093}
4094
4095static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4096 struct protocol_list64_t pl;
4097 uint64_t q, n_value;
4098 struct protocol64_t pc;
4099 const char *r;
4100 uint32_t offset, xoffset, left, i;
4101 SectionRef S, xS;
4102 const char *name, *sym_name;
4103
4104 r = get_pointer_64(p, offset, left, S, info);
4105 if (r == nullptr)
4106 return;
4107 memset(&pl, '\0', sizeof(struct protocol_list64_t));
4108 if (left < sizeof(struct protocol_list64_t)) {
4109 memcpy(&pl, r, left);
4110 outs() << " (protocol_list_t entends past the end of the section)\n";
4111 } else
4112 memcpy(&pl, r, sizeof(struct protocol_list64_t));
4113 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4114 swapStruct(pl);
4115 outs() << " count " << pl.count << "\n";
4116
4117 p += sizeof(struct protocol_list64_t);
4118 offset += sizeof(struct protocol_list64_t);
4119 for (i = 0; i < pl.count; i++) {
4120 r = get_pointer_64(p, offset, left, S, info);
4121 if (r == nullptr)
4122 return;
4123 q = 0;
4124 if (left < sizeof(uint64_t)) {
4125 memcpy(&q, r, left);
4126 outs() << " (protocol_t * entends past the end of the section)\n";
4127 } else
4128 memcpy(&q, r, sizeof(uint64_t));
4129 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4130 sys::swapByteOrder(q);
4131
4132 outs() << "\t\t list[" << i << "] ";
4133 sym_name = get_symbol_64(offset, S, info, n_value, q);
4134 if (n_value != 0) {
4135 if (info->verbose && sym_name != nullptr)
4136 outs() << sym_name;
4137 else
4138 outs() << format("0x%" PRIx64"l" "x", n_value);
4139 if (q != 0)
4140 outs() << " + " << format("0x%" PRIx64"l" "x", q);
4141 } else
4142 outs() << format("0x%" PRIx64"l" "x", q);
4143 outs() << " (struct protocol_t *)\n";
4144
4145 r = get_pointer_64(q + n_value, offset, left, S, info);
4146 if (r == nullptr)
4147 return;
4148 memset(&pc, '\0', sizeof(struct protocol64_t));
4149 if (left < sizeof(struct protocol64_t)) {
4150 memcpy(&pc, r, left);
4151 outs() << " (protocol_t entends past the end of the section)\n";
4152 } else
4153 memcpy(&pc, r, sizeof(struct protocol64_t));
4154 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4155 swapStruct(pc);
4156
4157 outs() << "\t\t\t isa " << format("0x%" PRIx64"l" "x", pc.isa) << "\n";
4158
4159 outs() << "\t\t\t name ";
4160 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name)__builtin_offsetof(struct protocol64_t, name), S,
4161 info, n_value, pc.name);
4162 if (n_value != 0) {
4163 if (info->verbose && sym_name != nullptr)
4164 outs() << sym_name;
4165 else
4166 outs() << format("0x%" PRIx64"l" "x", n_value);
4167 if (pc.name != 0)
4168 outs() << " + " << format("0x%" PRIx64"l" "x", pc.name);
4169 } else
4170 outs() << format("0x%" PRIx64"l" "x", pc.name);
4171 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4172 if (name != nullptr)
4173 outs() << format(" %.*s", left, name);
4174 outs() << "\n";
4175
4176 outs() << "\t\t\tprotocols " << format("0x%" PRIx64"l" "x", pc.protocols) << "\n";
4177
4178 outs() << "\t\t instanceMethods ";
4179 sym_name =
4180 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods)__builtin_offsetof(struct protocol64_t, instanceMethods),
4181 S, info, n_value, pc.instanceMethods);
4182 if (n_value != 0) {
4183 if (info->verbose && sym_name != nullptr)
4184 outs() << sym_name;
4185 else
4186 outs() << format("0x%" PRIx64"l" "x", n_value);
4187 if (pc.instanceMethods != 0)
4188 outs() << " + " << format("0x%" PRIx64"l" "x", pc.instanceMethods);
4189 } else
4190 outs() << format("0x%" PRIx64"l" "x", pc.instanceMethods);
4191 outs() << " (struct method_list_t *)\n";
4192 if (pc.instanceMethods + n_value != 0)
4193 print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4194
4195 outs() << "\t\t classMethods ";
4196 sym_name =
4197 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods)__builtin_offsetof(struct protocol64_t, classMethods), S,
4198 info, n_value, pc.classMethods);
4199 if (n_value != 0) {
4200 if (info->verbose && sym_name != nullptr)
4201 outs() << sym_name;
4202 else
4203 outs() << format("0x%" PRIx64"l" "x", n_value);
4204 if (pc.classMethods != 0)
4205 outs() << " + " << format("0x%" PRIx64"l" "x", pc.classMethods);
4206 } else
4207 outs() << format("0x%" PRIx64"l" "x", pc.classMethods);
4208 outs() << " (struct method_list_t *)\n";
4209 if (pc.classMethods + n_value != 0)
4210 print_method_list64_t(pc.classMethods + n_value, info, "\t");
4211
4212 outs() << "\t optionalInstanceMethods "
4213 << format("0x%" PRIx64"l" "x", pc.optionalInstanceMethods) << "\n";
4214 outs() << "\t optionalClassMethods "
4215 << format("0x%" PRIx64"l" "x", pc.optionalClassMethods) << "\n";
4216 outs() << "\t instanceProperties "
4217 << format("0x%" PRIx64"l" "x", pc.instanceProperties) << "\n";
4218
4219 p += sizeof(uint64_t);
4220 offset += sizeof(uint64_t);
4221 }
4222}
4223
4224static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4225 struct protocol_list32_t pl;
4226 uint32_t q;
4227 struct protocol32_t pc;
4228 const char *r;
4229 uint32_t offset, xoffset, left, i;
4230 SectionRef S, xS;
4231 const char *name;
4232
4233 r = get_pointer_32(p, offset, left, S, info);
4234 if (r == nullptr)
4235 return;
4236 memset(&pl, '\0', sizeof(struct protocol_list32_t));
4237 if (left < sizeof(struct protocol_list32_t)) {
4238 memcpy(&pl, r, left);
4239 outs() << " (protocol_list_t entends past the end of the section)\n";
4240 } else
4241 memcpy(&pl, r, sizeof(struct protocol_list32_t));
4242 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4243 swapStruct(pl);
4244 outs() << " count " << pl.count << "\n";
4245
4246 p += sizeof(struct protocol_list32_t);
4247 offset += sizeof(struct protocol_list32_t);
4248 for (i = 0; i < pl.count; i++) {
4249 r = get_pointer_32(p, offset, left, S, info);
4250 if (r == nullptr)
4251 return;
4252 q = 0;
4253 if (left < sizeof(uint32_t)) {
4254 memcpy(&q, r, left);
4255 outs() << " (protocol_t * entends past the end of the section)\n";
4256 } else
4257 memcpy(&q, r, sizeof(uint32_t));
4258 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4259 sys::swapByteOrder(q);
4260 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32"x", q)
4261 << " (struct protocol_t *)\n";
4262 r = get_pointer_32(q, offset, left, S, info);
4263 if (r == nullptr)
4264 return;
4265 memset(&pc, '\0', sizeof(struct protocol32_t));
4266 if (left < sizeof(struct protocol32_t)) {
4267 memcpy(&pc, r, left);
4268 outs() << " (protocol_t entends past the end of the section)\n";
4269 } else
4270 memcpy(&pc, r, sizeof(struct protocol32_t));
4271 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4272 swapStruct(pc);
4273 outs() << "\t\t\t isa " << format("0x%" PRIx32"x", pc.isa) << "\n";
4274 outs() << "\t\t\t name " << format("0x%" PRIx32"x", pc.name);
4275 name = get_pointer_32(pc.name, xoffset, left, xS, info);
4276 if (name != nullptr)
4277 outs() << format(" %.*s", left, name);
4278 outs() << "\n";
4279 outs() << "\t\t\tprotocols " << format("0x%" PRIx32"x", pc.protocols) << "\n";
4280 outs() << "\t\t instanceMethods "
4281 << format("0x%" PRIx32"x", pc.instanceMethods)
4282 << " (struct method_list_t *)\n";
4283 if (pc.instanceMethods != 0)
4284 print_method_list32_t(pc.instanceMethods, info, "\t");
4285 outs() << "\t\t classMethods " << format("0x%" PRIx32"x", pc.classMethods)
4286 << " (struct method_list_t *)\n";
4287 if (pc.classMethods != 0)
4288 print_method_list32_t(pc.classMethods, info, "\t");
4289 outs() << "\t optionalInstanceMethods "
4290 << format("0x%" PRIx32"x", pc.optionalInstanceMethods) << "\n";
4291 outs() << "\t optionalClassMethods "
4292 << format("0x%" PRIx32"x", pc.optionalClassMethods) << "\n";
4293 outs() << "\t instanceProperties "
4294 << format("0x%" PRIx32"x", pc.instanceProperties) << "\n";
4295 p += sizeof(uint32_t);
4296 offset += sizeof(uint32_t);
4297 }
4298}
4299
4300static void print_indent(uint32_t indent) {
4301 for (uint32_t i = 0; i < indent;) {
4302 if (indent - i >= 8) {
4303 outs() << "\t";
4304 i += 8;
4305 } else {
4306 for (uint32_t j = i; j < indent; j++)
4307 outs() << " ";
4308 return;
4309 }
4310 }
4311}
4312
4313static bool print_method_description_list(uint32_t p, uint32_t indent,
4314 struct DisassembleInfo *info) {
4315 uint32_t offset, left, xleft;
4316 SectionRef S;
4317 struct objc_method_description_list_t mdl;
4318 struct objc_method_description_t md;
4319 const char *r, *list, *name;
4320 int32_t i;
4321
4322 r = get_pointer_32(p, offset, left, S, info, true);
4323 if (r == nullptr)
4324 return true;
4325
4326 outs() << "\n";
4327 if (left > sizeof(struct objc_method_description_list_t)) {
4328 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
4329 } else {
4330 print_indent(indent);
4331 outs() << " objc_method_description_list extends past end of the section\n";
4332 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
4333 memcpy(&mdl, r, left);
4334 }
4335 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4336 swapStruct(mdl);
4337
4338 print_indent(indent);
4339 outs() << " count " << mdl.count << "\n";
4340
4341 list = r + sizeof(struct objc_method_description_list_t);
4342 for (i = 0; i < mdl.count; i++) {
4343 if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
4344 print_indent(indent);
4345 outs() << " remaining list entries extend past the of the section\n";
4346 break;
4347 }
4348 print_indent(indent);
4349 outs() << " list[" << i << "]\n";
4350 memcpy(&md, list + i * sizeof(struct objc_method_description_t),
4351 sizeof(struct objc_method_description_t));
4352 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4353 swapStruct(md);
4354
4355 print_indent(indent);
4356 outs() << " name " << format("0x%08" PRIx32"x", md.name);
4357 if (info->verbose) {
4358 name = get_pointer_32(md.name, offset, xleft, S, info, true);
4359 if (name != nullptr)
4360 outs() << format(" %.*s", xleft, name);
4361 else
4362 outs() << " (not in an __OBJC section)";
4363 }
4364 outs() << "\n";
4365
4366 print_indent(indent);
4367 outs() << " types " << format("0x%08" PRIx32"x", md.types);
4368 if (info->verbose) {
4369 name = get_pointer_32(md.types, offset, xleft, S, info, true);
4370 if (name != nullptr)
4371 outs() << format(" %.*s", xleft, name);
4372 else
4373 outs() << " (not in an __OBJC section)";
4374 }
4375 outs() << "\n";
4376 }
4377 return false;
4378}
4379
4380static bool print_protocol_list(uint32_t p, uint32_t indent,
4381 struct DisassembleInfo *info);
4382
4383static bool print_protocol(uint32_t p, uint32_t indent,
4384 struct DisassembleInfo *info) {
4385 uint32_t offset, left;
4386 SectionRef S;
4387 struct objc_protocol_t protocol;
4388 const char *r, *name;
4389
4390 r = get_pointer_32(p, offset, left, S, info, true);
4391 if (r == nullptr)
4392 return true;
4393
4394 outs() << "\n";
4395 if (left >= sizeof(struct objc_protocol_t)) {
4396 memcpy(&protocol, r, sizeof(struct objc_protocol_t));
4397 } else {
4398 print_indent(indent);
4399 outs() << " Protocol extends past end of the section\n";
4400 memset(&protocol, '\0', sizeof(struct objc_protocol_t));
4401 memcpy(&protocol, r, left);
4402 }
4403 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4404 swapStruct(protocol);
4405
4406 print_indent(indent);
4407 outs() << " isa " << format("0x%08" PRIx32"x", protocol.isa)
4408 << "\n";
4409
4410 print_indent(indent);
4411 outs() << " protocol_name "
4412 << format("0x%08" PRIx32"x", protocol.protocol_name);
4413 if (info->verbose) {
4414 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
4415 if (name != nullptr)
4416 outs() << format(" %.*s", left, name);
4417 else
4418 outs() << " (not in an __OBJC section)";
4419 }
4420 outs() << "\n";
4421
4422 print_indent(indent);
4423 outs() << " protocol_list "
4424 << format("0x%08" PRIx32"x", protocol.protocol_list);
4425 if (print_protocol_list(protocol.protocol_list, indent + 4, info))
4426 outs() << " (not in an __OBJC section)\n";
4427
4428 print_indent(indent);
4429 outs() << " instance_methods "
4430 << format("0x%08" PRIx32"x", protocol.instance_methods);
4431 if (print_method_description_list(protocol.instance_methods, indent, info))
4432 outs() << " (not in an __OBJC section)\n";
4433
4434 print_indent(indent);
4435 outs() << " class_methods "
4436 << format("0x%08" PRIx32"x", protocol.class_methods);
4437 if (print_method_description_list(protocol.class_methods, indent, info))
4438 outs() << " (not in an __OBJC section)\n";
4439
4440 return false;
4441}
4442
4443static bool print_protocol_list(uint32_t p, uint32_t indent,
4444 struct DisassembleInfo *info) {
4445 uint32_t offset, left, l;
4446 SectionRef S;
4447 struct objc_protocol_list_t protocol_list;
4448 const char *r, *list;
4449 int32_t i;
4450
4451 r = get_pointer_32(p, offset, left, S, info, true);
4452 if (r == nullptr)
4453 return true;
4454
4455 outs() << "\n";
4456 if (left > sizeof(struct objc_protocol_list_t)) {
4457 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
4458 } else {
4459 outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
4460 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
4461 memcpy(&protocol_list, r, left);
4462 }
4463 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4464 swapStruct(protocol_list);
4465
4466 print_indent(indent);
4467 outs() << " next " << format("0x%08" PRIx32"x", protocol_list.next)
4468 << "\n";
4469 print_indent(indent);
4470 outs() << " count " << protocol_list.count << "\n";
4471
4472 list = r + sizeof(struct objc_protocol_list_t);
4473 for (i = 0; i < protocol_list.count; i++) {
4474 if ((i + 1) * sizeof(uint32_t) > left) {
4475 outs() << "\t\t remaining list entries extend past the of the section\n";
4476 break;
4477 }
4478 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
4479 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4480 sys::swapByteOrder(l);
4481
4482 print_indent(indent);
4483 outs() << " list[" << i << "] " << format("0x%08" PRIx32"x", l);
4484 if (print_protocol(l, indent, info))
4485 outs() << "(not in an __OBJC section)\n";
4486 }
4487 return false;
4488}
4489
4490static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
4491 struct ivar_list64_t il;
4492 struct ivar64_t i;
4493 const char *r;
4494 uint32_t offset, xoffset, left, j;
4495 SectionRef S, xS;
4496 const char *name, *sym_name, *ivar_offset_p;
4497 uint64_t ivar_offset, n_value;
4498
4499 r = get_pointer_64(p, offset, left, S, info);
4500 if (r == nullptr)
4501 return;
4502 memset(&il, '\0', sizeof(struct ivar_list64_t));
4503 if (left < sizeof(struct ivar_list64_t)) {
4504 memcpy(&il, r, left);
4505 outs() << " (ivar_list_t entends past the end of the section)\n";
4506 } else
4507 memcpy(&il, r, sizeof(struct ivar_list64_t));
4508 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4509 swapStruct(il);
4510 outs() << " entsize " << il.entsize << "\n";
4511 outs() << " count " << il.count << "\n";
4512
4513 p += sizeof(struct ivar_list64_t);
4514 offset += sizeof(struct ivar_list64_t);
4515 for (j = 0; j < il.count; j++) {
4516 r = get_pointer_64(p, offset, left, S, info);
4517 if (r == nullptr)
4518 return;
4519 memset(&i, '\0', sizeof(struct ivar64_t));
4520 if (left < sizeof(struct ivar64_t)) {
4521 memcpy(&i, r, left);
4522 outs() << " (ivar_t entends past the end of the section)\n";
4523 } else
4524 memcpy(&i, r, sizeof(struct ivar64_t));
4525 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4526 swapStruct(i);
4527
4528 outs() << "\t\t\t offset ";
4529 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset)__builtin_offsetof(struct ivar64_t, offset), S,
4530 info, n_value, i.offset);
4531 if (n_value != 0) {
4532 if (info->verbose && sym_name != nullptr)
4533 outs() << sym_name;
4534 else
4535 outs() << format("0x%" PRIx64"l" "x", n_value);
4536 if (i.offset != 0)
4537 outs() << " + " << format("0x%" PRIx64"l" "x", i.offset);
4538 } else
4539 outs() << format("0x%" PRIx64"l" "x", i.offset);
4540 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
4541 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4542 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4543 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4544 sys::swapByteOrder(ivar_offset);
4545 outs() << " " << ivar_offset << "\n";
4546 } else
4547 outs() << "\n";
4548
4549 outs() << "\t\t\t name ";
4550 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name)__builtin_offsetof(struct ivar64_t, name), S, info,
4551 n_value, i.name);
4552 if (n_value != 0) {
4553 if (info->verbose && sym_name != nullptr)
4554 outs() << sym_name;
4555 else
4556 outs() << format("0x%" PRIx64"l" "x", n_value);
4557 if (i.name != 0)
4558 outs() << " + " << format("0x%" PRIx64"l" "x", i.name);
4559 } else
4560 outs() << format("0x%" PRIx64"l" "x", i.name);
4561 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
4562 if (name != nullptr)
4563 outs() << format(" %.*s", left, name);
4564 outs() << "\n";
4565
4566 outs() << "\t\t\t type ";
4567 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type)__builtin_offsetof(struct ivar64_t, type), S, info,
4568 n_value, i.name);
4569 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
4570 if (n_value != 0) {
4571 if (info->verbose && sym_name != nullptr)
4572 outs() << sym_name;
4573 else
4574 outs() << format("0x%" PRIx64"l" "x", n_value);
4575 if (i.type != 0)
4576 outs() << " + " << format("0x%" PRIx64"l" "x", i.type);
4577 } else
4578 outs() << format("0x%" PRIx64"l" "x", i.type);
4579 if (name != nullptr)
4580 outs() << format(" %.*s", left, name);
4581 outs() << "\n";
4582
4583 outs() << "\t\t\talignment " << i.alignment << "\n";
4584 outs() << "\t\t\t size " << i.size << "\n";
4585
4586 p += sizeof(struct ivar64_t);
4587 offset += sizeof(struct ivar64_t);
4588 }
4589}
4590
4591static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
4592 struct ivar_list32_t il;
4593 struct ivar32_t i;
4594 const char *r;
4595 uint32_t offset, xoffset, left, j;
4596 SectionRef S, xS;
4597 const char *name, *ivar_offset_p;
4598 uint32_t ivar_offset;
4599
4600 r = get_pointer_32(p, offset, left, S, info);
4601 if (r == nullptr)
4602 return;
4603 memset(&il, '\0', sizeof(struct ivar_list32_t));
4604 if (left < sizeof(struct ivar_list32_t)) {
4605 memcpy(&il, r, left);
4606 outs() << " (ivar_list_t entends past the end of the section)\n";
4607 } else
4608 memcpy(&il, r, sizeof(struct ivar_list32_t));
4609 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4610 swapStruct(il);
4611 outs() << " entsize " << il.entsize << "\n";
4612 outs() << " count " << il.count << "\n";
4613
4614 p += sizeof(struct ivar_list32_t);
4615 offset += sizeof(struct ivar_list32_t);
4616 for (j = 0; j < il.count; j++) {
4617 r = get_pointer_32(p, offset, left, S, info);
4618 if (r == nullptr)
4619 return;
4620 memset(&i, '\0', sizeof(struct ivar32_t));
4621 if (left < sizeof(struct ivar32_t)) {
4622 memcpy(&i, r, left);
4623 outs() << " (ivar_t entends past the end of the section)\n";
4624 } else
4625 memcpy(&i, r, sizeof(struct ivar32_t));
4626 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4627 swapStruct(i);
4628
4629 outs() << "\t\t\t offset " << format("0x%" PRIx32"x", i.offset);
4630 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
4631 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4632 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4633 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4634 sys::swapByteOrder(ivar_offset);
4635 outs() << " " << ivar_offset << "\n";
4636 } else
4637 outs() << "\n";
4638
4639 outs() << "\t\t\t name " << format("0x%" PRIx32"x", i.name);
4640 name = get_pointer_32(i.name, xoffset, left, xS, info);
4641 if (name != nullptr)
4642 outs() << format(" %.*s", left, name);
4643 outs() << "\n";
4644
4645 outs() << "\t\t\t type " << format("0x%" PRIx32"x", i.type);
4646 name = get_pointer_32(i.type, xoffset, left, xS, info);
4647 if (name != nullptr)
4648 outs() << format(" %.*s", left, name);
4649 outs() << "\n";
4650
4651 outs() << "\t\t\talignment " << i.alignment << "\n";
4652 outs() << "\t\t\t size " << i.size << "\n";
4653
4654 p += sizeof(struct ivar32_t);
4655 offset += sizeof(struct ivar32_t);
4656 }
4657}
4658
4659static void print_objc_property_list64(uint64_t p,
4660 struct DisassembleInfo *info) {
4661 struct objc_property_list64 opl;
4662 struct objc_property64 op;
4663 const char *r;
4664 uint32_t offset, xoffset, left, j;
4665 SectionRef S, xS;
4666 const char *name, *sym_name;
4667 uint64_t n_value;
4668
4669 r = get_pointer_64(p, offset, left, S, info);
4670 if (r == nullptr)
4671 return;
4672 memset(&opl, '\0', sizeof(struct objc_property_list64));
4673 if (left < sizeof(struct objc_property_list64)) {
4674 memcpy(&opl, r, left);
4675 outs() << " (objc_property_list entends past the end of the section)\n";
4676 } else
4677 memcpy(&opl, r, sizeof(struct objc_property_list64));
4678 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4679 swapStruct(opl);
4680 outs() << " entsize " << opl.entsize << "\n";
4681 outs() << " count " << opl.count << "\n";
4682
4683 p += sizeof(struct objc_property_list64);
4684 offset += sizeof(struct objc_property_list64);
4685 for (j = 0; j < opl.count; j++) {
4686 r = get_pointer_64(p, offset, left, S, info);
4687 if (r == nullptr)
4688 return;
4689 memset(&op, '\0', sizeof(struct objc_property64));
4690 if (left < sizeof(struct objc_property64)) {
4691 memcpy(&op, r, left);
4692 outs() << " (objc_property entends past the end of the section)\n";
4693 } else
4694 memcpy(&op, r, sizeof(struct objc_property64));
4695 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4696 swapStruct(op);
4697
4698 outs() << "\t\t\t name ";
4699 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name)__builtin_offsetof(struct objc_property64, name), S,
4700 info, n_value, op.name);
4701 if (n_value != 0) {
4702 if (info->verbose && sym_name != nullptr)
4703 outs() << sym_name;
4704 else
4705 outs() << format("0x%" PRIx64"l" "x", n_value);
4706 if (op.name != 0)
4707 outs() << " + " << format("0x%" PRIx64"l" "x", op.name);
4708 } else
4709 outs() << format("0x%" PRIx64"l" "x", op.name);
4710 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
4711 if (name != nullptr)
4712 outs() << format(" %.*s", left, name);
4713 outs() << "\n";
4714
4715 outs() << "\t\t\tattributes ";
4716 sym_name =
4717 get_symbol_64(offset + offsetof(struct objc_property64, attributes)__builtin_offsetof(struct objc_property64, attributes), S,
4718 info, n_value, op.attributes);
4719 if (n_value != 0) {
4720 if (info->verbose && sym_name != nullptr)
4721 outs() << sym_name;
4722 else
4723 outs() << format("0x%" PRIx64"l" "x", n_value);
4724 if (op.attributes != 0)
4725 outs() << " + " << format("0x%" PRIx64"l" "x", op.attributes);
4726 } else
4727 outs() << format("0x%" PRIx64"l" "x", op.attributes);
4728 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
4729 if (name != nullptr)
4730 outs() << format(" %.*s", left, name);
4731 outs() << "\n";
4732
4733 p += sizeof(struct objc_property64);
4734 offset += sizeof(struct objc_property64);
4735 }
4736}
4737
4738static void print_objc_property_list32(uint32_t p,
4739 struct DisassembleInfo *info) {
4740 struct objc_property_list32 opl;
4741 struct objc_property32 op;
4742 const char *r;
4743 uint32_t offset, xoffset, left, j;
4744 SectionRef S, xS;
4745 const char *name;
4746
4747 r = get_pointer_32(p, offset, left, S, info);
4748 if (r == nullptr)
4749 return;
4750 memset(&opl, '\0', sizeof(struct objc_property_list32));
4751 if (left < sizeof(struct objc_property_list32)) {
4752 memcpy(&opl, r, left);
4753 outs() << " (objc_property_list entends past the end of the section)\n";
4754 } else
4755 memcpy(&opl, r, sizeof(struct objc_property_list32));
4756 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4757 swapStruct(opl);
4758 outs() << " entsize " << opl.entsize << "\n";
4759 outs() << " count " << opl.count << "\n";
4760
4761 p += sizeof(struct objc_property_list32);
4762 offset += sizeof(struct objc_property_list32);
4763 for (j = 0; j < opl.count; j++) {
4764 r = get_pointer_32(p, offset, left, S, info);
4765 if (r == nullptr)
4766 return;
4767 memset(&op, '\0', sizeof(struct objc_property32));
4768 if (left < sizeof(struct objc_property32)) {
4769 memcpy(&op, r, left);
4770 outs() << " (objc_property entends past the end of the section)\n";
4771 } else
4772 memcpy(&op, r, sizeof(struct objc_property32));
4773 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4774 swapStruct(op);
4775
4776 outs() << "\t\t\t name " << format("0x%" PRIx32"x", op.name);
4777 name = get_pointer_32(op.name, xoffset, left, xS, info);
4778 if (name != nullptr)
4779 outs() << format(" %.*s", left, name);
4780 outs() << "\n";
4781
4782 outs() << "\t\t\tattributes " << format("0x%" PRIx32"x", op.attributes);
4783 name = get_pointer_32(op.attributes, xoffset, left, xS, info);
4784 if (name != nullptr)
4785 outs() << format(" %.*s", left, name);
4786 outs() << "\n";
4787
4788 p += sizeof(struct objc_property32);
4789 offset += sizeof(struct objc_property32);
4790 }
4791}
4792
4793static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
4794 bool &is_meta_class) {
4795 struct class_ro64_t cro;
4796 const char *r;
4797 uint32_t offset, xoffset, left;
4798 SectionRef S, xS;
4799 const char *name, *sym_name;
4800 uint64_t n_value;
4801
4802 r = get_pointer_64(p, offset, left, S, info);
4803 if (r == nullptr || left < sizeof(struct class_ro64_t))
4804 return false;
4805 memcpy(&cro, r, sizeof(struct class_ro64_t));
4806 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4807 swapStruct(cro);
4808 outs() << " flags " << format("0x%" PRIx32"x", cro.flags);
4809 if (cro.flags & RO_META(1 << 0))
4810 outs() << " RO_META";
4811 if (cro.flags & RO_ROOT(1 << 1))
4812 outs() << " RO_ROOT";
4813 if (cro.flags & RO_HAS_CXX_STRUCTORS(1 << 2))
4814 outs() << " RO_HAS_CXX_STRUCTORS";
4815 outs() << "\n";
4816 outs() << " instanceStart " << cro.instanceStart << "\n";
4817 outs() << " instanceSize " << cro.instanceSize << "\n";
4818 outs() << " reserved " << format("0x%" PRIx32"x", cro.reserved)
4819 << "\n";
4820 outs() << " ivarLayout " << format("0x%" PRIx64"l" "x", cro.ivarLayout)
4821 << "\n";
4822 print_layout_map64(cro.ivarLayout, info);
4823
4824 outs() << " name ";
4825 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name)__builtin_offsetof(struct class_ro64_t, name), S,
4826 info, n_value, cro.name);
4827 if (n_value != 0) {
4828 if (info->verbose && sym_name != nullptr)
4829 outs() << sym_name;
4830 else
4831 outs() << format("0x%" PRIx64"l" "x", n_value);
4832 if (cro.name != 0)
4833 outs() << " + " << format("0x%" PRIx64"l" "x", cro.name);
4834 } else
4835 outs() << format("0x%" PRIx64"l" "x", cro.name);
4836 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
4837 if (name != nullptr)
4838 outs() << format(" %.*s", left, name);
4839 outs() << "\n";
4840
4841 outs() << " baseMethods ";
4842 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods)__builtin_offsetof(struct class_ro64_t, baseMethods),
4843 S, info, n_value, cro.baseMethods);
4844 if (n_value != 0) {
4845 if (info->verbose && sym_name != nullptr)
4846 outs() << sym_name;
4847 else
4848 outs() << format("0x%" PRIx64"l" "x", n_value);
4849 if (cro.baseMethods != 0)
4850 outs() << " + " << format("0x%" PRIx64"l" "x", cro.baseMethods);
4851 } else
4852 outs() << format("0x%" PRIx64"l" "x", cro.baseMethods);
4853 outs() << " (struct method_list_t *)\n";
4854 if (cro.baseMethods + n_value != 0)
4855 print_method_list64_t(cro.baseMethods + n_value, info, "");
4856
4857 outs() << " baseProtocols ";
4858 sym_name =
4859 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols)__builtin_offsetof(struct class_ro64_t, baseProtocols), S,
4860 info, n_value, cro.baseProtocols);
4861 if (n_value != 0) {
4862 if (info->verbose && sym_name != nullptr)
4863 outs() << sym_name;
4864 else
4865 outs() << format("0x%" PRIx64"l" "x", n_value);
4866 if (cro.baseProtocols != 0)
4867 outs() << " + " << format("0x%" PRIx64"l" "x", cro.baseProtocols);
4868 } else
4869 outs() << format("0x%" PRIx64"l" "x", cro.baseProtocols);
4870 outs() << "\n";
4871 if (cro.baseProtocols + n_value != 0)
4872 print_protocol_list64_t(cro.baseProtocols + n_value, info);
4873
4874 outs() << " ivars ";
4875 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars)__builtin_offsetof(struct class_ro64_t, ivars), S,
4876 info, n_value, cro.ivars);
4877 if (n_value != 0) {
4878 if (info->verbose && sym_name != nullptr)
4879 outs() << sym_name;
4880 else
4881 outs() << format("0x%" PRIx64"l" "x", n_value);
4882 if (cro.ivars != 0)
4883 outs() << " + " << format("0x%" PRIx64"l" "x", cro.ivars);
4884 } else
4885 outs() << format("0x%" PRIx64"l" "x", cro.ivars);
4886 outs() << "\n";
4887 if (cro.ivars + n_value != 0)
4888 print_ivar_list64_t(cro.ivars + n_value, info);
4889
4890 outs() << " weakIvarLayout ";
4891 sym_name =
4892 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout)__builtin_offsetof(struct class_ro64_t, weakIvarLayout), S,
4893 info, n_value, cro.weakIvarLayout);
4894 if (n_value != 0) {
4895 if (info->verbose && sym_name != nullptr)
4896 outs() << sym_name;
4897 else
4898 outs() << format("0x%" PRIx64"l" "x", n_value);
4899 if (cro.weakIvarLayout != 0)
4900 outs() << " + " << format("0x%" PRIx64"l" "x", cro.weakIvarLayout);
4901 } else
4902 outs() << format("0x%" PRIx64"l" "x", cro.weakIvarLayout);
4903 outs() << "\n";
4904 print_layout_map64(cro.weakIvarLayout + n_value, info);
4905
4906 outs() << " baseProperties ";
4907 sym_name =
4908 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties)__builtin_offsetof(struct class_ro64_t, baseProperties), S,
4909 info, n_value, cro.baseProperties);
4910 if (n_value != 0) {
4911 if (info->verbose && sym_name != nullptr)
4912 outs() << sym_name;
4913 else
4914 outs() << format("0x%" PRIx64"l" "x", n_value);
4915 if (cro.baseProperties != 0)
4916 outs() << " + " << format("0x%" PRIx64"l" "x", cro.baseProperties);
4917 } else
4918 outs() << format("0x%" PRIx64"l" "x", cro.baseProperties);
4919 outs() << "\n";
4920 if (cro.baseProperties + n_value != 0)
4921 print_objc_property_list64(cro.baseProperties + n_value, info);
4922
4923 is_meta_class = (cro.flags & RO_META(1 << 0)) != 0;
4924 return true;
4925}
4926
4927static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
4928 bool &is_meta_class) {
4929 struct class_ro32_t cro;
4930 const char *r;
4931 uint32_t offset, xoffset, left;
4932 SectionRef S, xS;
4933 const char *name;
4934
4935 r = get_pointer_32(p, offset, left, S, info);
4936 if (r == nullptr)
4937 return false;
4938 memset(&cro, '\0', sizeof(struct class_ro32_t));
4939 if (left < sizeof(struct class_ro32_t)) {
4940 memcpy(&cro, r, left);
4941 outs() << " (class_ro_t entends past the end of the section)\n";
4942 } else
4943 memcpy(&cro, r, sizeof(struct class_ro32_t));
4944 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4945 swapStruct(cro);
4946 outs() << " flags " << format("0x%" PRIx32"x", cro.flags);
4947 if (cro.flags & RO_META(1 << 0))
4948 outs() << " RO_META";
4949 if (cro.flags & RO_ROOT(1 << 1))
4950 outs() << " RO_ROOT";
4951 if (cro.flags & RO_HAS_CXX_STRUCTORS(1 << 2))
4952 outs() << " RO_HAS_CXX_STRUCTORS";
4953 outs() << "\n";
4954 outs() << " instanceStart " << cro.instanceStart << "\n";
4955 outs() << " instanceSize " << cro.instanceSize << "\n";
4956 outs() << " ivarLayout " << format("0x%" PRIx32"x", cro.ivarLayout)
4957 << "\n";
4958 print_layout_map32(cro.ivarLayout, info);
4959
4960 outs() << " name " << format("0x%" PRIx32"x", cro.name);
4961 name = get_pointer_32(cro.name, xoffset, left, xS, info);
4962 if (name != nullptr)
4963 outs() << format(" %.*s", left, name);
4964 outs() << "\n";
4965
4966 outs() << " baseMethods "
4967 << format("0x%" PRIx32"x", cro.baseMethods)
4968 << " (struct method_list_t *)\n";
4969 if (cro.baseMethods != 0)
4970 print_method_list32_t(cro.baseMethods, info, "");
4971
4972 outs() << " baseProtocols "
4973 << format("0x%" PRIx32"x", cro.baseProtocols) << "\n";
4974 if (cro.baseProtocols != 0)
4975 print_protocol_list32_t(cro.baseProtocols, info);
4976 outs() << " ivars " << format("0x%" PRIx32"x", cro.ivars)
4977 << "\n";
4978 if (cro.ivars != 0)
4979 print_ivar_list32_t(cro.ivars, info);
4980 outs() << " weakIvarLayout "
4981 << format("0x%" PRIx32"x", cro.weakIvarLayout) << "\n";
4982 print_layout_map32(cro.weakIvarLayout, info);
4983 outs() << " baseProperties "
4984 << format("0x%" PRIx32"x", cro.baseProperties) << "\n";
4985 if (cro.baseProperties != 0)
4986 print_objc_property_list32(cro.baseProperties, info);
4987 is_meta_class = (cro.flags & RO_META(1 << 0)) != 0;
4988 return true;
4989}
4990
4991static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
4992 struct class64_t c;
4993 const char *r;
4994 uint32_t offset, left;
4995 SectionRef S;
4996 const char *name;
4997 uint64_t isa_n_value, n_value;
4998
4999 r = get_pointer_64(p, offset, left, S, info);
5000 if (r == nullptr || left < sizeof(struct class64_t))
5001 return;
5002 memcpy(&c, r, sizeof(struct class64_t));
5003 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5004 swapStruct(c);
5005
5006 outs() << " isa " << format("0x%" PRIx64"l" "x", c.isa);
5007 name = get_symbol_64(offset + offsetof(struct class64_t, isa)__builtin_offsetof(struct class64_t, isa), S, info,
5008 isa_n_value, c.isa);
5009 if (name != nullptr)
5010 outs() << " " << name;
5011 outs() << "\n";
5012
5013 outs() << " superclass " << format("0x%" PRIx64"l" "x", c.superclass);
5014 name = get_symbol_64(offset + offsetof(struct class64_t, superclass)__builtin_offsetof(struct class64_t, superclass), S, info,
5015 n_value, c.superclass);
5016 if (name != nullptr)
5017 outs() << " " << name;
5018 else {
5019 name = get_dyld_bind_info_symbolname(S.getAddress() +
5020 offset + offsetof(struct class64_t, superclass)__builtin_offsetof(struct class64_t, superclass), info);
5021 if (name != nullptr)
5022 outs() << " " << name;
5023 }
5024 outs() << "\n";
5025
5026 outs() << " cache " << format("0x%" PRIx64"l" "x", c.cache);
5027 name = get_symbol_64(offset + offsetof(struct class64_t, cache)__builtin_offsetof(struct class64_t, cache), S, info,
5028 n_value, c.cache);
5029 if (name != nullptr)
5030 outs() << " " << name;
5031 outs() << "\n";
5032
5033 outs() << " vtable " << format("0x%" PRIx64"l" "x", c.vtable);
5034 name = get_symbol_64(offset + offsetof(struct class64_t, vtable)__builtin_offsetof(struct class64_t, vtable), S, info,
5035 n_value, c.vtable);
5036 if (name != nullptr)
5037 outs() << " " << name;
5038 outs() << "\n";
5039
5040 name = get_symbol_64(offset + offsetof(struct class64_t, data)__builtin_offsetof(struct class64_t, data), S, info,
5041 n_value, c.data);
5042 outs() << " data ";
5043 if (n_value != 0) {
5044 if (info->verbose && name != nullptr)
5045 outs() << name;
5046 else
5047 outs() << format("0x%" PRIx64"l" "x", n_value);
5048 if (c.data != 0)
5049 outs() << " + " << format("0x%" PRIx64"l" "x", c.data);
5050 } else
5051 outs() << format("0x%" PRIx64"l" "x", c.data);
5052 outs() << " (struct class_ro_t *)";
5053
5054 // This is a Swift class if some of the low bits of the pointer are set.
5055 if ((c.data + n_value) & 0x7)
5056 outs() << " Swift class";
5057 outs() << "\n";
5058 bool is_meta_class;
5059 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5060 return;
5061
5062 if (!is_meta_class &&
5063 c.isa + isa_n_value != p &&
5064 c.isa + isa_n_value != 0 &&
5065 info->depth < 100) {
5066 info->depth++;
5067 outs() << "Meta Class\n";
5068 print_class64_t(c.isa + isa_n_value, info);
5069 }
5070}
5071
5072static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5073 struct class32_t c;
5074 const char *r;
5075 uint32_t offset, left;
5076 SectionRef S;
5077 const char *name;
5078
5079 r = get_pointer_32(p, offset, left, S, info);
5080 if (r == nullptr)
5081 return;
5082 memset(&c, '\0', sizeof(struct class32_t));
5083 if (left < sizeof(struct class32_t)) {
5084 memcpy(&c, r, left);
5085 outs() << " (class_t entends past the end of the section)\n";
5086 } else
5087 memcpy(&c, r, sizeof(struct class32_t));
5088 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5089 swapStruct(c);
5090
5091 outs() << " isa " << format("0x%" PRIx32"x", c.isa);
5092 name =
5093 get_symbol_32(offset + offsetof(struct class32_t, isa)__builtin_offsetof(struct class32_t, isa), S, info, c.isa);
5094 if (name != nullptr)
5095 outs() << " " << name;
5096 outs() << "\n";
5097
5098 outs() << " superclass " << format("0x%" PRIx32"x", c.superclass);
5099 name = get_symbol_32(offset + offsetof(struct class32_t, superclass)__builtin_offsetof(struct class32_t, superclass), S, info,
5100 c.superclass);
5101 if (name != nullptr)
5102 outs() << " " << name;
5103 outs() << "\n";
5104
5105 outs() << " cache " << format("0x%" PRIx32"x", c.cache);
5106 name = get_symbol_32(offset + offsetof(struct class32_t, cache)__builtin_offsetof(struct class32_t, cache), S, info,
5107 c.cache);
5108 if (name != nullptr)
5109 outs() << " " << name;
5110 outs() << "\n";
5111
5112 outs() << " vtable " << format("0x%" PRIx32"x", c.vtable);
5113 name = get_symbol_32(offset + offsetof(struct class32_t, vtable)__builtin_offsetof(struct class32_t, vtable), S, info,
5114 c.vtable);
5115 if (name != nullptr)
5116 outs() << " " << name;
5117 outs() << "\n";
5118
5119 name =
5120 get_symbol_32(offset + offsetof(struct class32_t, data)__builtin_offsetof(struct class32_t, data), S, info, c.data);
5121 outs() << " data " << format("0x%" PRIx32"x", c.data)
5122 << " (struct class_ro_t *)";
5123
5124 // This is a Swift class if some of the low bits of the pointer are set.
5125 if (c.data & 0x3)
5126 outs() << " Swift class";
5127 outs() << "\n";
5128 bool is_meta_class;
5129 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5130 return;
5131
5132 if (!is_meta_class) {
5133 outs() << "Meta Class\n";
5134 print_class32_t(c.isa, info);
5135 }
5136}
5137
5138static void print_objc_class_t(struct objc_class_t *objc_class,
5139 struct DisassembleInfo *info) {
5140 uint32_t offset, left, xleft;
5141 const char *name, *p, *ivar_list;
5142 SectionRef S;
5143 int32_t i;
5144 struct objc_ivar_list_t objc_ivar_list;
5145 struct objc_ivar_t ivar;
5146
5147 outs() << "\t\t isa " << format("0x%08" PRIx32"x", objc_class->isa);
5148 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)((objc_class)->info & (0x2))) {
5149 name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5150 if (name != nullptr)
5151 outs() << format(" %.*s", left, name);
5152 else
5153 outs() << " (not in an __OBJC section)";
5154 }
5155 outs() << "\n";
5156
5157 outs() << "\t super_class "
5158 << format("0x%08" PRIx32"x", objc_class->super_class);
5159 if (info->verbose) {
5160 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5161 if (name != nullptr)
5162 outs() << format(" %.*s", left, name);
5163 else
5164 outs() << " (not in an __OBJC section)";
5165 }
5166 outs() << "\n";
5167
5168 outs() << "\t\t name " << format("0x%08" PRIx32"x", objc_class->name);
5169 if (info->verbose) {
5170 name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5171 if (name != nullptr)
5172 outs() << format(" %.*s", left, name);
5173 else
5174 outs() << " (not in an __OBJC section)";
5175 }
5176 outs() << "\n";
5177
5178 outs() << "\t\t version " << format("0x%08" PRIx32"x", objc_class->version)
5179 << "\n";
5180
5181 outs() << "\t\t info " << format("0x%08" PRIx32"x", objc_class->info);
5182 if (info->verbose) {
5183 if (CLS_GETINFO(objc_class, CLS_CLASS)((objc_class)->info & (0x1)))
5184 outs() << " CLS_CLASS";
5185 else if (CLS_GETINFO(objc_class, CLS_META)((objc_class)->info & (0x2)))
5186 outs() << " CLS_META";
5187 }
5188 outs() << "\n";
5189
5190 outs() << "\t instance_size "
5191 << format("0x%08" PRIx32"x", objc_class->instance_size) << "\n";
5192
5193 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5194 outs() << "\t\t ivars " << format("0x%08" PRIx32"x", objc_class->ivars);
5195 if (p != nullptr) {
5196 if (left > sizeof(struct objc_ivar_list_t)) {
5197 outs() << "\n";
5198 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5199 } else {
5200 outs() << " (entends past the end of the section)\n";
5201 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5202 memcpy(&objc_ivar_list, p, left);
5203 }
5204 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5205 swapStruct(objc_ivar_list);
5206 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n";
5207 ivar_list = p + sizeof(struct objc_ivar_list_t);
5208 for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5209 if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5210 outs() << "\t\t remaining ivar's extend past the of the section\n";
5211 break;
5212 }
5213 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5214 sizeof(struct objc_ivar_t));
5215 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5216 swapStruct(ivar);
5217
5218 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32"x", ivar.ivar_name);
5219 if (info->verbose) {
5220 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5221 if (name != nullptr)
5222 outs() << format(" %.*s", xleft, name);
5223 else
5224 outs() << " (not in an __OBJC section)";
5225 }
5226 outs() << "\n";
5227
5228 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32"x", ivar.ivar_type);
5229 if (info->verbose) {
5230 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5231 if (name != nullptr)
5232 outs() << format(" %.*s", xleft, name);
5233 else
5234 outs() << " (not in an __OBJC section)";
5235 }
5236 outs() << "\n";
5237
5238 outs() << "\t\t ivar_offset "
5239 << format("0x%08" PRIx32"x", ivar.ivar_offset) << "\n";
5240 }
5241 } else {
5242 outs() << " (not in an __OBJC section)\n";
5243 }
5244
5245 outs() << "\t\t methods " << format("0x%08" PRIx32"x", objc_class->methodLists);
5246 if (print_method_list(objc_class->methodLists, info))
5247 outs() << " (not in an __OBJC section)\n";
5248
5249 outs() << "\t\t cache " << format("0x%08" PRIx32"x", objc_class->cache)
5250 << "\n";
5251
5252 outs() << "\t\tprotocols " << format("0x%08" PRIx32"x", objc_class->protocols);
5253 if (print_protocol_list(objc_class->protocols, 16, info))
5254 outs() << " (not in an __OBJC section)\n";
5255}
5256
5257static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5258 struct DisassembleInfo *info) {
5259 uint32_t offset, left;
5260 const char *name;
5261 SectionRef S;
5262
5263 outs() << "\t category name "
5264 << format("0x%08" PRIx32"x", objc_category->category_name);
5265 if (info->verbose) {
5266 name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5267 true);
5268 if (name != nullptr)
5269 outs() << format(" %.*s", left, name);
5270 else
5271 outs() << " (not in an __OBJC section)";
5272 }
5273 outs() << "\n";
5274
5275 outs() << "\t\t class name "
5276 << format("0x%08" PRIx32"x", objc_category->class_name);
5277 if (info->verbose) {
5278 name =
5279 get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5280 if (name != nullptr)
5281 outs() << format(" %.*s", left, name);
5282 else
5283 outs() << " (not in an __OBJC section)";
5284 }
5285 outs() << "\n";
5286
5287 outs() << "\t instance methods "
5288 << format("0x%08" PRIx32"x", objc_category->instance_methods);
5289 if (print_method_list(objc_category->instance_methods, info))
5290 outs() << " (not in an __OBJC section)\n";
5291
5292 outs() << "\t class methods "
5293 << format("0x%08" PRIx32"x", objc_category->class_methods);
5294 if (print_method_list(objc_category->class_methods, info))
5295 outs() << " (not in an __OBJC section)\n";
5296}
5297
5298static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5299 struct category64_t c;
5300 const char *r;
5301 uint32_t offset, xoffset, left;
5302 SectionRef S, xS;
5303 const char *name, *sym_name;
5304 uint64_t n_value;
5305
5306 r = get_pointer_64(p, offset, left, S, info);
5307 if (r == nullptr)
5308 return;
5309 memset(&c, '\0', sizeof(struct category64_t));
5310 if (left < sizeof(struct category64_t)) {
5311 memcpy(&c, r, left);
5312 outs() << " (category_t entends past the end of the section)\n";
5313 } else
5314 memcpy(&c, r, sizeof(struct category64_t));
5315 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5316 swapStruct(c);
5317
5318 outs() << " name ";
5319 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name)__builtin_offsetof(struct category64_t, name), S,
5320 info, n_value, c.name);
5321 if (n_value != 0) {
5322 if (info->verbose && sym_name != nullptr)
5323 outs() << sym_name;
5324 else
5325 outs() << format("0x%" PRIx64"l" "x", n_value);
5326 if (c.name != 0)
5327 outs() << " + " << format("0x%" PRIx64"l" "x", c.name);
5328 } else
5329 outs() << format("0x%" PRIx64"l" "x", c.name);
5330 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
5331 if (name != nullptr)
5332 outs() << format(" %.*s", left, name);
5333 outs() << "\n";
5334
5335 outs() << " cls ";
5336 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls)__builtin_offsetof(struct category64_t, cls), S, info,
5337 n_value, c.cls);
5338 if (n_value != 0) {
5339 if (info->verbose && sym_name != nullptr)
5340 outs() << sym_name;
5341 else
5342 outs() << format("0x%" PRIx64"l" "x", n_value);
5343 if (c.cls != 0)
5344 outs() << " + " << format("0x%" PRIx64"l" "x", c.cls);
5345 } else
5346 outs() << format("0x%" PRIx64"l" "x", c.cls);
5347 outs() << "\n";
5348 if (c.cls + n_value != 0)
5349 print_class64_t(c.cls + n_value, info);
5350
5351 outs() << " instanceMethods ";
5352 sym_name =
5353 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods)__builtin_offsetof(struct category64_t, instanceMethods), S,
5354 info, n_value, c.instanceMethods);
5355 if (n_value != 0) {
5356 if (info->verbose && sym_name != nullptr)
5357 outs() << sym_name;
5358 else
5359 outs() << format("0x%" PRIx64"l" "x", n_value);
5360 if (c.instanceMethods != 0)
5361 outs() << " + " << format("0x%" PRIx64"l" "x", c.instanceMethods);
5362 } else
5363 outs() << format("0x%" PRIx64"l" "x", c.instanceMethods);
5364 outs() << "\n";
5365 if (c.instanceMethods + n_value != 0)
5366 print_method_list64_t(c.instanceMethods + n_value, info, "");
5367
5368 outs() << " classMethods ";
5369 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods)__builtin_offsetof(struct category64_t, classMethods),
5370 S, info, n_value, c.classMethods);
5371 if (n_value != 0) {
5372 if (info->verbose && sym_name != nullptr)
5373 outs() << sym_name;
5374 else
5375 outs() << format("0x%" PRIx64"l" "x", n_value);
5376 if (c.classMethods != 0)
5377 outs() << " + " << format("0x%" PRIx64"l" "x", c.classMethods);
5378 } else
5379 outs() << format("0x%" PRIx64"l" "x", c.classMethods);
5380 outs() << "\n";
5381 if (c.classMethods + n_value != 0)
5382 print_method_list64_t(c.classMethods + n_value, info, "");
5383
5384 outs() << " protocols ";
5385 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols)__builtin_offsetof(struct category64_t, protocols), S,
5386 info, n_value, c.protocols);
5387 if (n_value != 0) {
5388 if (info->verbose && sym_name != nullptr)
5389 outs() << sym_name;
5390 else
5391 outs() << format("0x%" PRIx64"l" "x", n_value);
5392 if (c.protocols != 0)
5393 outs() << " + " << format("0x%" PRIx64"l" "x", c.protocols);
5394 } else
5395 outs() << format("0x%" PRIx64"l" "x", c.protocols);
5396 outs() << "\n";
5397 if (c.protocols + n_value != 0)
5398 print_protocol_list64_t(c.protocols + n_value, info);
5399
5400 outs() << "instanceProperties ";
5401 sym_name =
5402 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties)__builtin_offsetof(struct category64_t, instanceProperties),
5403 S, info, n_value, c.instanceProperties);
5404 if (n_value != 0) {
5405 if (info->verbose && sym_name != nullptr)
5406 outs() << sym_name;
5407 else
5408 outs() << format("0x%" PRIx64"l" "x", n_value);
5409 if (c.instanceProperties != 0)
5410 outs() << " + " << format("0x%" PRIx64"l" "x", c.instanceProperties);
5411 } else
5412 outs() << format("0x%" PRIx64"l" "x", c.instanceProperties);
5413 outs() << "\n";
5414 if (c.instanceProperties + n_value != 0)
5415 print_objc_property_list64(c.instanceProperties + n_value, info);
5416}
5417
5418static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
5419 struct category32_t c;
5420 const char *r;
5421 uint32_t offset, left;
5422 SectionRef S, xS;
5423 const char *name;
5424
5425 r = get_pointer_32(p, offset, left, S, info);
5426 if (r == nullptr)
5427 return;
5428 memset(&c, '\0', sizeof(struct category32_t));
5429 if (left < sizeof(struct category32_t)) {
5430 memcpy(&c, r, left);
5431 outs() << " (category_t entends past the end of the section)\n";
5432 } else
5433 memcpy(&c, r, sizeof(struct category32_t));
5434 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5435 swapStruct(c);
5436
5437 outs() << " name " << format("0x%" PRIx32"x", c.name);
5438 name = get_symbol_32(offset + offsetof(struct category32_t, name)__builtin_offsetof(struct category32_t, name), S, info,
5439 c.name);
5440 if (name)
5441 outs() << " " << name;
5442 outs() << "\n";
5443
5444 outs() << " cls " << format("0x%" PRIx32"x", c.cls) << "\n";
5445 if (c.cls != 0)
5446 print_class32_t(c.cls, info);
5447 outs() << " instanceMethods " << format("0x%" PRIx32"x", c.instanceMethods)
5448 << "\n";
5449 if (c.instanceMethods != 0)
5450 print_method_list32_t(c.instanceMethods, info, "");
5451 outs() << " classMethods " << format("0x%" PRIx32"x", c.classMethods)
5452 << "\n";
5453 if (c.classMethods != 0)
5454 print_method_list32_t(c.classMethods, info, "");
5455 outs() << " protocols " << format("0x%" PRIx32"x", c.protocols) << "\n";
5456 if (c.protocols != 0)
5457 print_protocol_list32_t(c.protocols, info);
5458 outs() << "instanceProperties " << format("0x%" PRIx32"x", c.instanceProperties)
5459 << "\n";
5460 if (c.instanceProperties != 0)
5461 print_objc_property_list32(c.instanceProperties, info);
5462}
5463
5464static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
5465 uint32_t i, left, offset, xoffset;
5466 uint64_t p, n_value;
5467 struct message_ref64 mr;
5468 const char *name, *sym_name;
5469 const char *r;
5470 SectionRef xS;
5471
5472 if (S == SectionRef())
5473 return;
5474
5475 StringRef SectName;
5476 S.getName(SectName);
5477 DataRefImpl Ref = S.getRawDataRefImpl();
5478 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5479 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5480 offset = 0;
5481 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5482 p = S.getAddress() + i;
5483 r = get_pointer_64(p, offset, left, S, info);
5484 if (r == nullptr)
5485 return;
5486 memset(&mr, '\0', sizeof(struct message_ref64));
5487 if (left < sizeof(struct message_ref64)) {
5488 memcpy(&mr, r, left);
5489 outs() << " (message_ref entends past the end of the section)\n";
5490 } else
5491 memcpy(&mr, r, sizeof(struct message_ref64));
5492 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5493 swapStruct(mr);
5494
5495 outs() << " imp ";
5496 name = get_symbol_64(offset + offsetof(struct message_ref64, imp)__builtin_offsetof(struct message_ref64, imp), S, info,
5497 n_value, mr.imp);
5498 if (n_value != 0) {
5499 outs() << format("0x%" PRIx64"l" "x", n_value) << " ";
5500 if (mr.imp != 0)
5501 outs() << "+ " << format("0x%" PRIx64"l" "x", mr.imp) << " ";
5502 } else
5503 outs() << format("0x%" PRIx64"l" "x", mr.imp) << " ";
5504 if (name != nullptr)
5505 outs() << " " << name;
5506 outs() << "\n";
5507
5508 outs() << " sel ";
5509 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel)__builtin_offsetof(struct message_ref64, sel), S,
5510 info, n_value, mr.sel);
5511 if (n_value != 0) {
5512 if (info->verbose && sym_name != nullptr)
5513 outs() << sym_name;
5514 else
5515 outs() << format("0x%" PRIx64"l" "x", n_value);
5516 if (mr.sel != 0)
5517 outs() << " + " << format("0x%" PRIx64"l" "x", mr.sel);
5518 } else
5519 outs() << format("0x%" PRIx64"l" "x", mr.sel);
5520 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
5521 if (name != nullptr)
5522 outs() << format(" %.*s", left, name);
5523 outs() << "\n";
5524
5525 offset += sizeof(struct message_ref64);
5526 }
5527}
5528
5529static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
5530 uint32_t i, left, offset, xoffset, p;
5531 struct message_ref32 mr;
5532 const char *name, *r;
5533 SectionRef xS;
5534
5535 if (S == SectionRef())
5536 return;
5537
5538 StringRef SectName;
5539 S.getName(SectName);
5540 DataRefImpl Ref = S.getRawDataRefImpl();
5541 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5542 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5543 offset = 0;
5544 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5545 p = S.getAddress() + i;
5546 r = get_pointer_32(p, offset, left, S, info);
5547 if (r == nullptr)
5548 return;
5549 memset(&mr, '\0', sizeof(struct message_ref32));
5550 if (left < sizeof(struct message_ref32)) {
5551 memcpy(&mr, r, left);
5552 outs() << " (message_ref entends past the end of the section)\n";
5553 } else
5554 memcpy(&mr, r, sizeof(struct message_ref32));
5555 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5556 swapStruct(mr);
5557
5558 outs() << " imp " << format("0x%" PRIx32"x", mr.imp);
5559 name = get_symbol_32(offset + offsetof(struct message_ref32, imp)__builtin_offsetof(struct message_ref32, imp), S, info,
5560 mr.imp);
5561 if (name != nullptr)
5562 outs() << " " << name;
5563 outs() << "\n";
5564
5565 outs() << " sel " << format("0x%" PRIx32"x", mr.sel);
5566 name = get_pointer_32(mr.sel, xoffset, left, xS, info);
5567 if (name != nullptr)
5568 outs() << " " << name;
5569 outs() << "\n";
5570
5571 offset += sizeof(struct message_ref32);
5572 }
5573}
5574
5575static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
5576 uint32_t left, offset, swift_version;
5577 uint64_t p;
5578 struct objc_image_info64 o;
5579 const char *r;
5580
5581 if (S == SectionRef())
5582 return;
5583
5584 StringRef SectName;
5585 S.getName(SectName);
5586 DataRefImpl Ref = S.getRawDataRefImpl();
5587 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5588 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5589 p = S.getAddress();
5590 r = get_pointer_64(p, offset, left, S, info);
5591 if (r == nullptr)
5592 return;
5593 memset(&o, '\0', sizeof(struct objc_image_info64));
5594 if (left < sizeof(struct objc_image_info64)) {
5595 memcpy(&o, r, left);
5596 outs() << " (objc_image_info entends past the end of the section)\n";
5597 } else
5598 memcpy(&o, r, sizeof(struct objc_image_info64));
5599 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5600 swapStruct(o);
5601 outs() << " version " << o.version << "\n";
5602 outs() << " flags " << format("0x%" PRIx32"x", o.flags);
5603 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT(1 << 0))
5604 outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5605 if (o.flags & OBJC_IMAGE_SUPPORTS_GC(1 << 1))
5606 outs() << " OBJC_IMAGE_SUPPORTS_GC";
5607 if (o.flags & OBJC_IMAGE_IS_SIMULATED(1 << 5))
5608 outs() << " OBJC_IMAGE_IS_SIMULATED";
5609 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES(1 << 6))
5610 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
5611 swift_version = (o.flags >> 8) & 0xff;
5612 if (swift_version != 0) {
5613 if (swift_version == 1)
5614 outs() << " Swift 1.0";
5615 else if (swift_version == 2)
5616 outs() << " Swift 1.1";
5617 else if(swift_version == 3)
5618 outs() << " Swift 2.0";
5619 else if(swift_version == 4)
5620 outs() << " Swift 3.0";
5621 else if(swift_version == 5)
5622 outs() << " Swift 4.0";
5623 else if(swift_version == 6)
5624 outs() << " Swift 4.1";
5625 else
5626 outs() << " unknown future Swift version (" << swift_version << ")";
5627 }
5628 outs() << "\n";
5629}
5630
5631static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
5632 uint32_t left, offset, swift_version, p;
5633 struct objc_image_info32 o;
5634 const char *r;
5635
5636 if (S == SectionRef())
5637 return;
5638
5639 StringRef SectName;
5640 S.getName(SectName);
5641 DataRefImpl Ref = S.getRawDataRefImpl();
5642 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5643 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5644 p = S.getAddress();
5645 r = get_pointer_32(p, offset, left, S, info);
5646 if (r == nullptr)
5647 return;
5648 memset(&o, '\0', sizeof(struct objc_image_info32));
5649 if (left < sizeof(struct objc_image_info32)) {
5650 memcpy(&o, r, left);
5651 outs() << " (objc_image_info entends past the end of the section)\n";
5652 } else
5653 memcpy(&o, r, sizeof(struct objc_image_info32));
5654 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5655 swapStruct(o);
5656 outs() << " version " << o.version << "\n";
5657 outs() << " flags " << format("0x%" PRIx32"x", o.flags);
5658 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT(1 << 0))
5659 outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5660 if (o.flags & OBJC_IMAGE_SUPPORTS_GC(1 << 1))
5661 outs() << " OBJC_IMAGE_SUPPORTS_GC";
5662 swift_version = (o.flags >> 8) & 0xff;
5663 if (swift_version != 0) {
5664 if (swift_version == 1)
5665 outs() << " Swift 1.0";
5666 else if (swift_version == 2)
5667 outs() << " Swift 1.1";
5668 else if(swift_version == 3)
5669 outs() << " Swift 2.0";
5670 else if(swift_version == 4)
5671 outs() << " Swift 3.0";
5672 else if(swift_version == 5)
5673 outs() << " Swift 4.0";
5674 else if(swift_version == 6)
5675 outs() << " Swift 4.1";
5676 else
5677 outs() << " unknown future Swift version (" << swift_version << ")";
5678 }
5679 outs() << "\n";
5680}
5681
5682static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
5683 uint32_t left, offset, p;
5684 struct imageInfo_t o;
5685 const char *r;
5686
5687 StringRef SectName;
5688 S.getName(SectName);
5689 DataRefImpl Ref = S.getRawDataRefImpl();
5690 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5691 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5692 p = S.getAddress();
5693 r = get_pointer_32(p, offset, left, S, info);
5694 if (r == nullptr)
5695 return;
5696 memset(&o, '\0', sizeof(struct imageInfo_t));
5697 if (left < sizeof(struct imageInfo_t)) {
5698 memcpy(&o, r, left);
5699 outs() << " (imageInfo entends past the end of the section)\n";
5700 } else
5701 memcpy(&o, r, sizeof(struct imageInfo_t));
5702 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5703 swapStruct(o);
5704 outs() << " version " << o.version << "\n";
5705 outs() << " flags " << format("0x%" PRIx32"x", o.flags);
5706 if (o.flags & 0x1)
5707 outs() << " F&C";
5708 if (o.flags & 0x2)
5709 outs() << " GC";
5710 if (o.flags & 0x4)
5711 outs() << " GC-only";
5712 else
5713 outs() << " RR";
5714 outs() << "\n";
5715}
5716
5717static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
5718 SymbolAddressMap AddrMap;
5719 if (verbose)
71
Taking false branch
5720 CreateSymbolAddressMap(O, &AddrMap);
5721
5722 std::vector<SectionRef> Sections;
5723 for (const SectionRef &Section : O->sections()) {
5724 StringRef SectName;
5725 Section.getName(SectName);
5726 Sections.push_back(Section);
5727 }
5728
5729 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5730
5731 SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5732 if (CL == SectionRef())
72
Taking false branch
5733 CL = get_section(O, "__DATA", "__objc_classlist");
5734 if (CL == SectionRef())
73
Taking false branch
5735 CL = get_section(O, "__DATA_CONST", "__objc_classlist");
5736 if (CL == SectionRef())
74
Taking false branch
5737 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
5738 info.S = CL;
5739 walk_pointer_list_64("class", CL, O, &info, print_class64_t);
75
Null pointer value stored to 'S.OwningObject'
76
Calling 'walk_pointer_list_64'
5740
5741 SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5742 if (CR == SectionRef())
5743 CR = get_section(O, "__DATA", "__objc_classrefs");
5744 if (CR == SectionRef())
5745 CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
5746 if (CR == SectionRef())
5747 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
5748 info.S = CR;
5749 walk_pointer_list_64("class refs", CR, O, &info, nullptr);
5750
5751 SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5752 if (SR == SectionRef())
5753 SR = get_section(O, "__DATA", "__objc_superrefs");
5754 if (SR == SectionRef())
5755 SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
5756 if (SR == SectionRef())
5757 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
5758 info.S = SR;
5759 walk_pointer_list_64("super refs", SR, O, &info, nullptr);
5760
5761 SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5762 if (CA == SectionRef())
5763 CA = get_section(O, "__DATA", "__objc_catlist");
5764 if (CA == SectionRef())
5765 CA = get_section(O, "__DATA_CONST", "__objc_catlist");
5766 if (CA == SectionRef())
5767 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
5768 info.S = CA;
5769 walk_pointer_list_64("category", CA, O, &info, print_category64_t);
5770
5771 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5772 if (PL == SectionRef())
5773 PL = get_section(O, "__DATA", "__objc_protolist");
5774 if (PL == SectionRef())
5775 PL = get_section(O, "__DATA_CONST", "__objc_protolist");
5776 if (PL == SectionRef())
5777 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
5778 info.S = PL;
5779 walk_pointer_list_64("protocol", PL, O, &info, nullptr);
5780
5781 SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5782 if (MR == SectionRef())
5783 MR = get_section(O, "__DATA", "__objc_msgrefs");
5784 if (MR == SectionRef())
5785 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
5786 if (MR == SectionRef())
5787 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
5788 info.S = MR;
5789 print_message_refs64(MR, &info);
5790
5791 SectionRef II = get_section(O, "__OBJC2", "__image_info");
5792 if (II == SectionRef())
5793 II = get_section(O, "__DATA", "__objc_imageinfo");
5794 if (II == SectionRef())
5795 II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
5796 if (II == SectionRef())
5797 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
5798 info.S = II;
5799 print_image_info64(II, &info);
5800}
5801
5802static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5803 SymbolAddressMap AddrMap;
5804 if (verbose)
5805 CreateSymbolAddressMap(O, &AddrMap);
5806
5807 std::vector<SectionRef> Sections;
5808 for (const SectionRef &Section : O->sections()) {
5809 StringRef SectName;
5810 Section.getName(SectName);
5811 Sections.push_back(Section);
5812 }
5813
5814 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5815
5816 SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5817 if (CL == SectionRef())
5818 CL = get_section(O, "__DATA", "__objc_classlist");
5819 if (CL == SectionRef())
5820 CL = get_section(O, "__DATA_CONST", "__objc_classlist");
5821 if (CL == SectionRef())
5822 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
5823 info.S = CL;
5824 walk_pointer_list_32("class", CL, O, &info, print_class32_t);
5825
5826 SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5827 if (CR == SectionRef())
5828 CR = get_section(O, "__DATA", "__objc_classrefs");
5829 if (CR == SectionRef())
5830 CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
5831 if (CR == SectionRef())
5832 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
5833 info.S = CR;
5834 walk_pointer_list_32("class refs", CR, O, &info, nullptr);
5835
5836 SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5837 if (SR == SectionRef())
5838 SR = get_section(O, "__DATA", "__objc_superrefs");
5839 if (SR == SectionRef())
5840 SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
5841 if (SR == SectionRef())
5842 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
5843 info.S = SR;
5844 walk_pointer_list_32("super refs", SR, O, &info, nullptr);
5845
5846 SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5847 if (CA == SectionRef())
5848 CA = get_section(O, "__DATA", "__objc_catlist");
5849 if (CA == SectionRef())
5850 CA = get_section(O, "__DATA_CONST", "__objc_catlist");
5851 if (CA == SectionRef())
5852 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
5853 info.S = CA;
5854 walk_pointer_list_32("category", CA, O, &info, print_category32_t);
5855
5856 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5857 if (PL == SectionRef())
5858 PL = get_section(O, "__DATA", "__objc_protolist");
5859 if (PL == SectionRef())
5860 PL = get_section(O, "__DATA_CONST", "__objc_protolist");
5861 if (PL == SectionRef())
5862 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
5863 info.S = PL;
5864 walk_pointer_list_32("protocol", PL, O, &info, nullptr);
5865
5866 SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5867 if (MR == SectionRef())
5868 MR = get_section(O, "__DATA", "__objc_msgrefs");
5869 if (MR == SectionRef())
5870 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
5871 if (MR == SectionRef())
5872 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
5873 info.S = MR;
5874 print_message_refs32(MR, &info);
5875
5876 SectionRef II = get_section(O, "__OBJC2", "__image_info");
5877 if (II == SectionRef())
5878 II = get_section(O, "__DATA", "__objc_imageinfo");
5879 if (II == SectionRef())
5880 II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
5881 if (II == SectionRef())
5882 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
5883 info.S = II;
5884 print_image_info32(II, &info);
5885}
5886
5887static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5888 uint32_t i, j, p, offset, xoffset, left, defs_left, def;
5889 const char *r, *name, *defs;
5890 struct objc_module_t module;
5891 SectionRef S, xS;
5892 struct objc_symtab_t symtab;
5893 struct objc_class_t objc_class;
5894 struct objc_category_t objc_category;
5895
5896 outs() << "Objective-C segment\n";
5897 S = get_section(O, "__OBJC", "__module_info");
5898 if (S == SectionRef())
5899 return false;
5900
5901 SymbolAddressMap AddrMap;
5902 if (verbose)
5903 CreateSymbolAddressMap(O, &AddrMap);
5904
5905 std::vector<SectionRef> Sections;
5906 for (const SectionRef &Section : O->sections()) {
5907 StringRef SectName;
5908 Section.getName(SectName);
5909 Sections.push_back(Section);
5910 }
5911
5912 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5913
5914 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
5915 p = S.getAddress() + i;
5916 r = get_pointer_32(p, offset, left, S, &info, true);
5917 if (r == nullptr)
5918 return true;
5919 memset(&module, '\0', sizeof(struct objc_module_t));
5920 if (left < sizeof(struct objc_module_t)) {
5921 memcpy(&module, r, left);
5922 outs() << " (module extends past end of __module_info section)\n";
5923 } else
5924 memcpy(&module, r, sizeof(struct objc_module_t));
5925 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5926 swapStruct(module);
5927
5928 outs() << "Module " << format("0x%" PRIx32"x", p) << "\n";
5929 outs() << " version " << module.version << "\n";
5930 outs() << " size " << module.size << "\n";
5931 outs() << " name ";
5932 name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
5933 if (name != nullptr)
5934 outs() << format("%.*s", left, name);
5935 else
5936 outs() << format("0x%08" PRIx32"x", module.name)
5937 << "(not in an __OBJC section)";
5938 outs() << "\n";
5939
5940 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
5941 if (module.symtab == 0 || r == nullptr) {
5942 outs() << " symtab " << format("0x%08" PRIx32"x", module.symtab)
5943 << " (not in an __OBJC section)\n";
5944 continue;
5945 }
5946 outs() << " symtab " << format("0x%08" PRIx32"x", module.symtab) << "\n";
5947 memset(&symtab, '\0', sizeof(struct objc_symtab_t));
5948 defs_left = 0;
5949 defs = nullptr;
5950 if (left < sizeof(struct objc_symtab_t)) {
5951 memcpy(&symtab, r, left);
5952 outs() << "\tsymtab extends past end of an __OBJC section)\n";
5953 } else {
5954 memcpy(&symtab, r, sizeof(struct objc_symtab_t));
5955 if (left > sizeof(struct objc_symtab_t)) {
5956 defs_left = left - sizeof(struct objc_symtab_t);
5957 defs = r + sizeof(struct objc_symtab_t);
5958 }
5959 }
5960 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5961 swapStruct(symtab);
5962
5963 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
5964 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
5965 outs() << "\trefs " << format("0x%08" PRIx32"x", symtab.refs);
5966 if (r == nullptr)
5967 outs() << " (not in an __OBJC section)";
5968 outs() << "\n";
5969 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
5970 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
5971 if (symtab.cls_def_cnt > 0)
5972 outs() << "\tClass Definitions\n";
5973 for (j = 0; j < symtab.cls_def_cnt; j++) {
5974 if ((j + 1) * sizeof(uint32_t) > defs_left) {
5975 outs() << "\t(remaining class defs entries entends past the end of the "
5976 << "section)\n";
5977 break;
5978 }
5979 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
5980 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5981 sys::swapByteOrder(def);
5982
5983 r = get_pointer_32(def, xoffset, left, xS, &info, true);
5984 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32"x", def);
5985 if (r != nullptr) {
5986 if (left > sizeof(struct objc_class_t)) {
5987 outs() << "\n";
5988 memcpy(&objc_class, r, sizeof(struct objc_class_t));
5989 } else {
5990 outs() << " (entends past the end of the section)\n";
5991 memset(&objc_class, '\0', sizeof(struct objc_class_t));
5992 memcpy(&objc_class, r, left);
5993 }
5994 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5995 swapStruct(objc_class);
5996 print_objc_class_t(&objc_class, &info);
5997 } else {
5998 outs() << "(not in an __OBJC section)\n";
5999 }
6000
6001 if (CLS_GETINFO(&objc_class, CLS_CLASS)((&objc_class)->info & (0x1))) {
6002 outs() << "\tMeta Class";
6003 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
6004 if (r != nullptr) {
6005 if (left > sizeof(struct objc_class_t)) {
6006 outs() << "\n";
6007 memcpy(&objc_class, r, sizeof(struct objc_class_t));
6008 } else {
6009 outs() << " (entends past the end of the section)\n";
6010 memset(&objc_class, '\0', sizeof(struct objc_class_t));
6011 memcpy(&objc_class, r, left);
6012 }
6013 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6014 swapStruct(objc_class);
6015 print_objc_class_t(&objc_class, &info);
6016 } else {
6017 outs() << "(not in an __OBJC section)\n";
6018 }
6019 }
6020 }
6021 if (symtab.cat_def_cnt > 0)
6022 outs() << "\tCategory Definitions\n";
6023 for (j = 0; j < symtab.cat_def_cnt; j++) {
6024 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
6025 outs() << "\t(remaining category defs entries entends past the end of "
6026 << "the section)\n";
6027 break;
6028 }
6029 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6030 sizeof(uint32_t));
6031 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6032 sys::swapByteOrder(def);
6033
6034 r = get_pointer_32(def, xoffset, left, xS, &info, true);
6035 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6036 << format("0x%08" PRIx32"x", def);
6037 if (r != nullptr) {
6038 if (left > sizeof(struct objc_category_t)) {
6039 outs() << "\n";
6040 memcpy(&objc_category, r, sizeof(struct objc_category_t));
6041 } else {
6042 outs() << " (entends past the end of the section)\n";
6043 memset(&objc_category, '\0', sizeof(struct objc_category_t));
6044 memcpy(&objc_category, r, left);
6045 }
6046 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6047 swapStruct(objc_category);
6048 print_objc_objc_category_t(&objc_category, &info);
6049 } else {
6050 outs() << "(not in an __OBJC section)\n";
6051 }
6052 }
6053 }
6054 const SectionRef II = get_section(O, "__OBJC", "__image_info");
6055 if (II != SectionRef())
6056 print_image_info(II, &info);
6057
6058 return true;
6059}
6060
6061static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6062 uint32_t size, uint32_t addr) {
6063 SymbolAddressMap AddrMap;
6064 CreateSymbolAddressMap(O, &AddrMap);
6065
6066 std::vector<SectionRef> Sections;
6067 for (const SectionRef &Section : O->sections()) {
6068 StringRef SectName;
6069 Section.getName(SectName);
6070 Sections.push_back(Section);
6071 }
6072
6073 struct DisassembleInfo info(O, &AddrMap, &Sections, true);
6074
6075 const char *p;
6076 struct objc_protocol_t protocol;
6077 uint32_t left, paddr;
6078 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6079 memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6080 left = size - (p - sect);
6081 if (left < sizeof(struct objc_protocol_t)) {
6082 outs() << "Protocol extends past end of __protocol section\n";
6083 memcpy(&protocol, p, left);
6084 } else
6085 memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6086 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6087 swapStruct(protocol);
6088 paddr = addr + (p - sect);
6089 outs() << "Protocol " << format("0x%" PRIx32"x", paddr);
6090 if (print_protocol(paddr, 0, &info))
6091 outs() << "(not in an __OBJC section)\n";
6092 }
6093}
6094
6095#ifdef HAVE_LIBXAR
6096inline void swapStruct(struct xar_header &xar) {
6097 sys::swapByteOrder(xar.magic);
6098 sys::swapByteOrder(xar.size);
6099 sys::swapByteOrder(xar.version);
6100 sys::swapByteOrder(xar.toc_length_compressed);
6101 sys::swapByteOrder(xar.toc_length_uncompressed);
6102 sys::swapByteOrder(xar.cksum_alg);
6103}
6104
6105static void PrintModeVerbose(uint32_t mode) {
6106 switch(mode & S_IFMT){
6107 case S_IFDIR:
6108 outs() << "d";
6109 break;
6110 case S_IFCHR:
6111 outs() << "c";
6112 break;
6113 case S_IFBLK:
6114 outs() << "b";
6115 break;
6116 case S_IFREG:
6117 outs() << "-";
6118 break;
6119 case S_IFLNK:
6120 outs() << "l";
6121 break;
6122 case S_IFSOCK:
6123 outs() << "s";
6124 break;
6125 default:
6126 outs() << "?";
6127 break;
6128 }
6129
6130 /* owner permissions */
6131 if(mode & S_IREAD)
6132 outs() << "r";
6133 else
6134 outs() << "-";
6135 if(mode & S_IWRITE)
6136 outs() << "w";
6137 else
6138 outs() << "-";
6139 if(mode & S_ISUID)
6140 outs() << "s";
6141 else if(mode & S_IEXEC)
6142 outs() << "x";
6143 else
6144 outs() << "-";
6145
6146 /* group permissions */
6147 if(mode & (S_IREAD >> 3))
6148 outs() << "r";
6149 else
6150 outs() << "-";
6151 if(mode & (S_IWRITE >> 3))
6152 outs() << "w";
6153 else
6154 outs() << "-";
6155 if(mode & S_ISGID)
6156 outs() << "s";
6157 else if(mode & (S_IEXEC >> 3))
6158 outs() << "x";
6159 else
6160 outs() << "-";
6161
6162 /* other permissions */
6163 if(mode & (S_IREAD >> 6))
6164 outs() << "r";
6165 else
6166 outs() << "-";
6167 if(mode & (S_IWRITE >> 6))
6168 outs() << "w";
6169 else
6170 outs() << "-";
6171 if(mode & S_ISVTX)
6172 outs() << "t";
6173 else if(mode & (S_IEXEC >> 6))
6174 outs() << "x";
6175 else
6176 outs() << "-";
6177}
6178
6179static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
6180 xar_file_t xf;
6181 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
6182 char *endp;
6183 uint32_t mode_value;
6184
6185 ScopedXarIter xi;
6186 if (!xi) {
6187 errs() << "Can't obtain an xar iterator for xar archive "
6188 << XarFilename << "\n";
6189 return;
6190 }
6191
6192 // Go through the xar's files.
6193 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
6194 ScopedXarIter xp;
6195 if(!xp){
6196 errs() << "Can't obtain an xar iterator for xar archive "
6197 << XarFilename << "\n";
6198 return;
6199 }
6200 type = nullptr;
6201 mode = nullptr;
6202 user = nullptr;
6203 group = nullptr;
6204 size = nullptr;
6205 mtime = nullptr;
6206 name = nullptr;
6207 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6208 const char *val = nullptr;
6209 xar_prop_get(xf, key, &val);
6210#if 0 // Useful for debugging.
6211 outs() << "key: " << key << " value: " << val << "\n";
6212#endif
6213 if(strcmp(key, "type") == 0)
6214 type = val;
6215 if(strcmp(key, "mode") == 0)
6216 mode = val;
6217 if(strcmp(key, "user") == 0)
6218 user = val;
6219 if(strcmp(key, "group") == 0)
6220 group = val;
6221 if(strcmp(key, "data/size") == 0)
6222 size = val;
6223 if(strcmp(key, "mtime") == 0)
6224 mtime = val;
6225 if(strcmp(key, "name") == 0)
6226 name = val;
6227 }
6228 if(mode != nullptr){
6229 mode_value = strtoul(mode, &endp, 8);
6230 if(*endp != '\0')
6231 outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
6232 if(strcmp(type, "file") == 0)
6233 mode_value |= S_IFREG;
6234 PrintModeVerbose(mode_value);
6235 outs() << " ";
6236 }
6237 if(user != nullptr)
6238 outs() << format("%10s/", user);
6239 if(group != nullptr)
6240 outs() << format("%-10s ", group);
6241 if(size != nullptr)
6242 outs() << format("%7s ", size);
6243 if(mtime != nullptr){
6244 for(m = mtime; *m != 'T' && *m != '\0'; m++)
6245 outs() << *m;
6246 if(*m == 'T')
6247 m++;
6248 outs() << " ";
6249 for( ; *m != 'Z' && *m != '\0'; m++)
6250 outs() << *m;
6251 outs() << " ";
6252 }
6253 if(name != nullptr)
6254 outs() << name;
6255 outs() << "\n";
6256 }
6257}
6258
6259static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
6260 uint32_t size, bool verbose,
6261 bool PrintXarHeader, bool PrintXarFileHeaders,
6262 std::string XarMemberName) {
6263 if(size < sizeof(struct xar_header)) {
6264 outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
6265 "of struct xar_header)\n";
6266 return;
6267 }
6268 struct xar_header XarHeader;
6269 memcpy(&XarHeader, sect, sizeof(struct xar_header));
6270 if (sys::IsLittleEndianHost)
6271 swapStruct(XarHeader);
6272 if (PrintXarHeader) {
6273 if (!XarMemberName.empty())
6274 outs() << "In xar member " << XarMemberName << ": ";
6275 else
6276 outs() << "For (__LLVM,__bundle) section: ";
6277 outs() << "xar header\n";
6278 if (XarHeader.magic == XAR_HEADER_MAGIC)
6279 outs() << " magic XAR_HEADER_MAGIC\n";
6280 else
6281 outs() << " magic "
6282 << format_hex(XarHeader.magic, 10, true)
6283 << " (not XAR_HEADER_MAGIC)\n";
6284 outs() << " size " << XarHeader.size << "\n";
6285 outs() << " version " << XarHeader.version << "\n";
6286 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed
6287 << "\n";
6288 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
6289 << "\n";
6290 outs() << " cksum_alg ";
6291 switch (XarHeader.cksum_alg) {
6292 case XAR_CKSUM_NONE:
6293 outs() << "XAR_CKSUM_NONE\n";
6294 break;
6295 case XAR_CKSUM_SHA1:
6296 outs() << "XAR_CKSUM_SHA1\n";
6297 break;
6298 case XAR_CKSUM_MD5:
6299 outs() << "XAR_CKSUM_MD5\n";
6300 break;
6301#ifdef XAR_CKSUM_SHA256
6302 case XAR_CKSUM_SHA256:
6303 outs() << "XAR_CKSUM_SHA256\n";
6304 break;
6305#endif
6306#ifdef XAR_CKSUM_SHA512
6307 case XAR_CKSUM_SHA512:
6308 outs() << "XAR_CKSUM_SHA512\n";
6309 break;
6310#endif
6311 default:
6312 outs() << XarHeader.cksum_alg << "\n";
6313 }
6314 }
6315
6316 SmallString<128> XarFilename;
6317 int FD;
6318 std::error_code XarEC =
6319 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
6320 if (XarEC) {
6321 errs() << XarEC.message() << "\n";
6322 return;
6323 }
6324 ToolOutputFile XarFile(XarFilename, FD);
6325 raw_fd_ostream &XarOut = XarFile.os();
6326 StringRef XarContents(sect, size);
6327 XarOut << XarContents;
6328 XarOut.close();
6329 if (XarOut.has_error())
6330 return;
6331
6332 ScopedXarFile xar(XarFilename.c_str(), READ);
6333 if (!xar) {
6334 errs() << "Can't create temporary xar archive " << XarFilename << "\n";
6335 return;
6336 }
6337
6338 SmallString<128> TocFilename;
6339 std::error_code TocEC =
6340 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
6341 if (TocEC) {
6342 errs() << TocEC.message() << "\n";
6343 return;
6344 }
6345 xar_serialize(xar, TocFilename.c_str());
6346
6347 if (PrintXarFileHeaders) {
6348 if (!XarMemberName.empty())
6349 outs() << "In xar member " << XarMemberName << ": ";
6350 else
6351 outs() << "For (__LLVM,__bundle) section: ";
6352 outs() << "xar archive files:\n";
6353 PrintXarFilesSummary(XarFilename.c_str(), xar);
6354 }
6355
6356 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
6357 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
6358 if (std::error_code EC = FileOrErr.getError()) {
6359 errs() << EC.message() << "\n";
6360 return;
6361 }
6362 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
6363
6364 if (!XarMemberName.empty())
6365 outs() << "In xar member " << XarMemberName << ": ";
6366 else
6367 outs() << "For (__LLVM,__bundle) section: ";
6368 outs() << "xar table of contents:\n";
6369 outs() << Buffer->getBuffer() << "\n";
6370
6371 // TODO: Go through the xar's files.
6372 ScopedXarIter xi;
6373 if(!xi){
6374 errs() << "Can't obtain an xar iterator for xar archive "
6375 << XarFilename.c_str() << "\n";
6376 return;
6377 }
6378 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
6379 const char *key;
6380 const char *member_name, *member_type, *member_size_string;
6381 size_t member_size;
6382
6383 ScopedXarIter xp;
6384 if(!xp){
6385 errs() << "Can't obtain an xar iterator for xar archive "
6386 << XarFilename.c_str() << "\n";
6387 return;
6388 }
6389 member_name = NULL__null;
6390 member_type = NULL__null;
6391 member_size_string = NULL__null;
6392 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6393 const char *val = nullptr;
6394 xar_prop_get(xf, key, &val);
6395#if 0 // Useful for debugging.
6396 outs() << "key: " << key << " value: " << val << "\n";
6397#endif
6398 if (strcmp(key, "name") == 0)
6399 member_name = val;
6400 if (strcmp(key, "type") == 0)
6401 member_type = val;
6402 if (strcmp(key, "data/size") == 0)
6403 member_size_string = val;
6404 }
6405 /*
6406 * If we find a file with a name, date/size and type properties
6407 * and with the type being "file" see if that is a xar file.
6408 */
6409 if (member_name != NULL__null && member_type != NULL__null &&
6410 strcmp(member_type, "file") == 0 &&
6411 member_size_string != NULL__null){
6412 // Extract the file into a buffer.
6413 char *endptr;
6414 member_size = strtoul(member_size_string, &endptr, 10);
6415 if (*endptr == '\0' && member_size != 0) {
6416 char *buffer;
6417 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
6418#if 0 // Useful for debugging.
6419 outs() << "xar member: " << member_name << " extracted\n";
6420#endif
6421 // Set the XarMemberName we want to see printed in the header.
6422 std::string OldXarMemberName;
6423 // If XarMemberName is already set this is nested. So
6424 // save the old name and create the nested name.
6425 if (!XarMemberName.empty()) {
6426 OldXarMemberName = XarMemberName;
6427 XarMemberName =
6428 (Twine("[") + XarMemberName + "]" + member_name).str();
6429 } else {
6430 OldXarMemberName = "";
6431 XarMemberName = member_name;
6432 }
6433 // See if this is could be a xar file (nested).
6434 if (member_size >= sizeof(struct xar_header)) {
6435#if 0 // Useful for debugging.
6436 outs() << "could be a xar file: " << member_name << "\n";
6437#endif
6438 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
6439 if (sys::IsLittleEndianHost)
6440 swapStruct(XarHeader);
6441 if (XarHeader.magic == XAR_HEADER_MAGIC)
6442 DumpBitcodeSection(O, buffer, member_size, verbose,
6443 PrintXarHeader, PrintXarFileHeaders,
6444 XarMemberName);
6445 }
6446 XarMemberName = OldXarMemberName;
6447 delete buffer;
6448 }
6449 }
6450 }
6451 }
6452}
6453#endif // defined(HAVE_LIBXAR)
6454
6455static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6456 if (O->is64Bit())
68
Assuming the condition is true
69
Taking true branch
6457 printObjc2_64bit_MetaData(O, verbose);
70
Calling 'printObjc2_64bit_MetaData'
6458 else {
6459 MachO::mach_header H;
6460 H = O->getHeader();
6461 if (H.cputype == MachO::CPU_TYPE_ARM)
6462 printObjc2_32bit_MetaData(O, verbose);
6463 else {
6464 // This is the 32-bit non-arm cputype case. Which is normally
6465 // the first Objective-C ABI. But it may be the case of a
6466 // binary for the iOS simulator which is the second Objective-C
6467 // ABI. In that case printObjc1_32bit_MetaData() will determine that
6468 // and return false.
6469 if (!printObjc1_32bit_MetaData(O, verbose))
6470 printObjc2_32bit_MetaData(O, verbose);
6471 }
6472 }
6473}
6474
6475// GuessLiteralPointer returns a string which for the item in the Mach-O file
6476// for the address passed in as ReferenceValue for printing as a comment with
6477// the instruction and also returns the corresponding type of that item
6478// indirectly through ReferenceType.
6479//
6480// If ReferenceValue is an address of literal cstring then a pointer to the
6481// cstring is returned and ReferenceType is set to
6482// LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6483//
6484// If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6485// Class ref that name is returned and the ReferenceType is set accordingly.
6486//
6487// Lastly, literals which are Symbol address in a literal pool are looked for
6488// and if found the symbol name is returned and ReferenceType is set to
6489// LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6490//
6491// If there is no item in the Mach-O file for the address passed in as
6492// ReferenceValue nullptr is returned and ReferenceType is unchanged.
6493static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6494 uint64_t ReferencePC,
6495 uint64_t *ReferenceType,
6496 struct DisassembleInfo *info) {
6497 // First see if there is an external relocation entry at the ReferencePC.
6498 if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6499 uint64_t sect_addr = info->S.getAddress();
6500 uint64_t sect_offset = ReferencePC - sect_addr;
6501 bool reloc_found = false;
6502 DataRefImpl Rel;
6503 MachO::any_relocation_info RE;
6504 bool isExtern = false;
6505 SymbolRef Symbol;
6506 for (const RelocationRef &Reloc : info->S.relocations()) {
6507 uint64_t RelocOffset = Reloc.getOffset();
6508 if (RelocOffset == sect_offset) {
6509 Rel = Reloc.getRawDataRefImpl();
6510 RE = info->O->getRelocation(Rel);
6511 if (info->O->isRelocationScattered(RE))
6512 continue;
6513 isExtern = info->O->getPlainRelocationExternal(RE);
6514 if (isExtern) {
6515 symbol_iterator RelocSym = Reloc.getSymbol();
6516 Symbol = *RelocSym;
6517 }
6518 reloc_found = true;
6519 break;
6520 }
6521 }
6522 // If there is an external relocation entry for a symbol in a section
6523 // then used that symbol's value for the value of the reference.
6524 if (reloc_found && isExtern) {
6525 if (info->O->getAnyRelocationPCRel(RE)) {
6526 unsigned Type = info->O->getAnyRelocationType(RE);
6527 if (Type == MachO::X86_64_RELOC_SIGNED) {
6528 ReferenceValue = Symbol.getValue();
6529 }
6530 }
6531 }
6532 }
6533
6534 // Look for literals such as Objective-C CFStrings refs, Selector refs,
6535 // Message refs and Class refs.
6536 bool classref, selref, msgref, cfstring;
6537 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6538 selref, msgref, cfstring);
6539 if (classref && pointer_value == 0) {
6540 // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6541 // And the pointer_value in that section is typically zero as it will be
6542 // set by dyld as part of the "bind information".
6543 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6544 if (name != nullptr) {
6545 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref8;
6546 const char *class_name = strrchr(name, '$');
6547 if (class_name != nullptr && class_name[1] == '_' &&
6548 class_name[2] != '\0') {
6549 info->class_name = class_name + 2;
6550 return name;
6551 }
6552 }
6553 }
6554
6555 if (classref) {
6556 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref8;
6557 const char *name =
6558 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6559 if (name != nullptr)
6560 info->class_name = name;
6561 else
6562 name = "bad class ref";
6563 return name;
6564 }
6565
6566 if (cfstring) {
6567 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref4;
6568 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6569 return name;
6570 }
6571
6572 if (selref && pointer_value == 0)
6573 pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6574
6575 if (pointer_value != 0)
6576 ReferenceValue = pointer_value;
6577
6578 const char *name = GuessCstringPointer(ReferenceValue, info);
6579 if (name) {
6580 if (pointer_value != 0 && selref) {
6581 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref7;
6582 info->selector_name = name;
6583 } else if (pointer_value != 0 && msgref) {
6584 info->class_name = nullptr;
6585 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref6;
6586 info->selector_name = name;
6587 } else
6588 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr3;
6589 return name;
6590 }
6591
6592 // Lastly look for an indirect symbol with this ReferenceValue which is in
6593 // a literal pool. If found return that symbol name.
6594 name = GuessIndirectSymbol(ReferenceValue, info);
6595 if (name) {
6596 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr2;
6597 return name;
6598 }
6599
6600 return nullptr;
6601}
6602
6603// SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6604// the Symbolizer. It looks up the ReferenceValue using the info passed via the
6605// pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6606// is created and returns the symbol name that matches the ReferenceValue or
6607// nullptr if none. The ReferenceType is passed in for the IN type of
6608// reference the instruction is making from the values in defined in the header
6609// "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific
6610// Out type and the ReferenceName will also be set which is added as a comment
6611// to the disassembled instruction.
6612//
6613// If the symbol name is a C++ mangled name then the demangled name is
6614// returned through ReferenceName and ReferenceType is set to
6615// LLVMDisassembler_ReferenceType_DeMangled_Name .
6616//
6617// When this is called to get a symbol name for a branch target then the
6618// ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6619// SymbolValue will be looked for in the indirect symbol table to determine if
6620// it is an address for a symbol stub. If so then the symbol name for that
6621// stub is returned indirectly through ReferenceName and then ReferenceType is
6622// set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6623//
6624// When this is called with an value loaded via a PC relative load then
6625// ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6626// SymbolValue is checked to be an address of literal pointer, symbol pointer,
6627// or an Objective-C meta data reference. If so the output ReferenceType is
6628// set to correspond to that as well as setting the ReferenceName.
6629static const char *SymbolizerSymbolLookUp(void *DisInfo,
6630 uint64_t ReferenceValue,
6631 uint64_t *ReferenceType,
6632 uint64_t ReferencePC,
6633 const char **ReferenceName) {
6634 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6635 // If no verbose symbolic information is wanted then just return nullptr.
6636 if (!info->verbose) {
6637 *ReferenceName = nullptr;
6638 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6639 return nullptr;
6640 }
6641
6642 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6643
6644 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch1) {
6645 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6646 if (*ReferenceName != nullptr) {
6647 method_reference(info, ReferenceType, ReferenceName);
6648 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message5)
6649 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub1;
6650 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6651 if (info->demangled_name != nullptr)
6652 free(info->demangled_name);
6653 int status;
6654 info->demangled_name =
6655 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
6656 if (info->demangled_name != nullptr) {
6657 *ReferenceName = info->demangled_name;
6658 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name9;
6659 } else
6660 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6661 } else
6662 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6663 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load2) {
6664 *ReferenceName =
6665 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6666 if (*ReferenceName)
6667 method_reference(info, ReferenceType, ReferenceName);
6668 else
6669 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6670 // If this is arm64 and the reference is an adrp instruction save the
6671 // instruction, passed in ReferenceValue and the address of the instruction
6672 // for use later if we see and add immediate instruction.
6673 } else if (info->O->getArch() == Triple::aarch64 &&
6674 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP0x100000001) {
6675 info->adrp_inst = ReferenceValue;
6676 info->adrp_addr = ReferencePC;
6677 SymbolName = nullptr;
6678 *ReferenceName = nullptr;
6679 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6680 // If this is arm64 and reference is an add immediate instruction and we
6681 // have
6682 // seen an adrp instruction just before it and the adrp's Xd register
6683 // matches
6684 // this add's Xn register reconstruct the value being referenced and look to
6685 // see if it is a literal pointer. Note the add immediate instruction is
6686 // passed in ReferenceValue.
6687 } else if (info->O->getArch() == Triple::aarch64 &&
6688 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri0x100000002 &&
6689 ReferencePC - 4 == info->adrp_addr &&
6690 (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6691 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6692 uint32_t addxri_inst;
6693 uint64_t adrp_imm, addxri_imm;
6694
6695 adrp_imm =
6696 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6697 if (info->adrp_inst & 0x0200000)
6698 adrp_imm |= 0xfffffffffc000000LL;
6699
6700 addxri_inst = ReferenceValue;
6701 addxri_imm = (addxri_inst >> 10) & 0xfff;
6702 if (((addxri_inst >> 22) & 0x3) == 1)
6703 addxri_imm <<= 12;
6704
6705 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6706 (adrp_imm << 12) + addxri_imm;
6707
6708 *ReferenceName =
6709 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6710 if (*ReferenceName == nullptr)
6711 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6712 // If this is arm64 and the reference is a load register instruction and we
6713 // have seen an adrp instruction just before it and the adrp's Xd register
6714 // matches this add's Xn register reconstruct the value being referenced and
6715 // look to see if it is a literal pointer. Note the load register
6716 // instruction is passed in ReferenceValue.
6717 } else if (info->O->getArch() == Triple::aarch64 &&
6718 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui0x100000003 &&
6719 ReferencePC - 4 == info->adrp_addr &&
6720 (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6721 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6722 uint32_t ldrxui_inst;
6723 uint64_t adrp_imm, ldrxui_imm;
6724
6725 adrp_imm =
6726 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6727 if (info->adrp_inst & 0x0200000)
6728 adrp_imm |= 0xfffffffffc000000LL;
6729
6730 ldrxui_inst = ReferenceValue;
6731 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
6732
6733 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6734 (adrp_imm << 12) + (ldrxui_imm << 3);
6735
6736 *ReferenceName =
6737 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6738 if (*ReferenceName == nullptr)
6739 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6740 }
6741 // If this arm64 and is an load register (PC-relative) instruction the
6742 // ReferenceValue is the PC plus the immediate value.
6743 else if (info->O->getArch() == Triple::aarch64 &&
6744 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl0x100000004 ||
6745 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR0x100000005)) {
6746 *ReferenceName =
6747 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6748 if (*ReferenceName == nullptr)
6749 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6750 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6751 if (info->demangled_name != nullptr)
6752 free(info->demangled_name);
6753 int status;
6754 info->demangled_name =
6755 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
6756 if (info->demangled_name != nullptr) {
6757 *ReferenceName = info->demangled_name;
6758 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name9;
6759 }
6760 }
6761 else {
6762 *ReferenceName = nullptr;
6763 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None0;
6764 }
6765
6766 return SymbolName;
6767}
6768
6769/// Emits the comments that are stored in the CommentStream.
6770/// Each comment in the CommentStream must end with a newline.
6771static void emitComments(raw_svector_ostream &CommentStream,
6772 SmallString<128> &CommentsToEmit,
6773 formatted_raw_ostream &FormattedOS,
6774 const MCAsmInfo &MAI) {
6775 // Flush the stream before taking its content.
6776 StringRef Comments = CommentsToEmit.str();
6777 // Get the default information for printing a comment.
6778 StringRef CommentBegin = MAI.getCommentString();
6779 unsigned CommentColumn = MAI.getCommentColumn();
6780 bool IsFirst = true;
6781 while (!Comments.empty()) {
6782 if (!IsFirst)
6783 FormattedOS << '\n';
6784 // Emit a line of comments.
6785 FormattedOS.PadToColumn(CommentColumn);
6786 size_t Position = Comments.find('\n');
6787 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
6788 // Move after the newline character.
6789 Comments = Comments.substr(Position + 1);
6790 IsFirst = false;
6791 }
6792 FormattedOS.flush();
6793
6794 // Tell the comment stream that the vector changed underneath it.
6795 CommentsToEmit.clear();
6796}
6797
6798static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
6799 StringRef DisSegName, StringRef DisSectName) {
6800 const char *McpuDefault = nullptr;
6801 const Target *ThumbTarget = nullptr;
6802 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
6803 if (!TheTarget) {
6804 // GetTarget prints out stuff.
6805 return;
6806 }
6807 std::string MachOMCPU;
6808 if (MCPU.empty() && McpuDefault)
6809 MachOMCPU = McpuDefault;
6810 else
6811 MachOMCPU = MCPU;
6812
6813 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
6814 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
6815 if (ThumbTarget)
6816 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
6817
6818 // Package up features to be passed to target/subtarget
6819 std::string FeaturesStr;
6820 if (MAttrs.size()) {
6821 SubtargetFeatures Features;
6822 for (unsigned i = 0; i != MAttrs.size(); ++i)
6823 Features.AddFeature(MAttrs[i]);
6824 FeaturesStr = Features.getString();
6825 }
6826
6827 // Set up disassembler.
6828 std::unique_ptr<const MCRegisterInfo> MRI(
6829 TheTarget->createMCRegInfo(TripleName));
6830 std::unique_ptr<const MCAsmInfo> AsmInfo(
6831 TheTarget->createMCAsmInfo(*MRI, TripleName));
6832 std::unique_ptr<const MCSubtargetInfo> STI(
6833 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
6834 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
6835 std::unique_ptr<MCDisassembler> DisAsm(
6836 TheTarget->createMCDisassembler(*STI, Ctx));
6837 std::unique_ptr<MCSymbolizer> Symbolizer;
6838 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
6839 std::unique_ptr<MCRelocationInfo> RelInfo(
6840 TheTarget->createMCRelocationInfo(TripleName, Ctx));
6841 if (RelInfo) {
6842 Symbolizer.reset(TheTarget->createMCSymbolizer(
6843 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6844 &SymbolizerInfo, &Ctx, std::move(RelInfo)));
6845 DisAsm->setSymbolizer(std::move(Symbolizer));
6846 }
6847 int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
6848 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
6849 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
6850 // Set the display preference for hex vs. decimal immediates.
6851 IP->setPrintImmHex(PrintImmHex);
6852 // Comment stream and backing vector.
6853 SmallString<128> CommentsToEmit;
6854 raw_svector_ostream CommentStream(CommentsToEmit);
6855 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
6856 // if it is done then arm64 comments for string literals don't get printed
6857 // and some constant get printed instead and not setting it causes intel
6858 // (32-bit and 64-bit) comments printed with different spacing before the
6859 // comment causing different diffs with the 'C' disassembler library API.
6860 // IP->setCommentStream(CommentStream);
6861
6862 if (!AsmInfo || !STI || !DisAsm || !IP) {
6863 errs() << "error: couldn't initialize disassembler for target "
6864 << TripleName << '\n';
6865 return;
6866 }
6867
6868 // Set up separate thumb disassembler if needed.
6869 std::unique_ptr<const MCRegisterInfo> ThumbMRI;
6870 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
6871 std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
6872 std::unique_ptr<MCDisassembler> ThumbDisAsm;
6873 std::unique_ptr<MCInstPrinter> ThumbIP;
6874 std::unique_ptr<MCContext> ThumbCtx;
6875 std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
6876 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
6877 std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
6878 if (ThumbTarget) {
6879 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
6880 ThumbAsmInfo.reset(
6881 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName));
6882 ThumbSTI.reset(
6883 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
6884 FeaturesStr));
6885 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
6886 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
6887 MCContext *PtrThumbCtx = ThumbCtx.get();
6888 ThumbRelInfo.reset(
6889 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
6890 if (ThumbRelInfo) {
6891 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
6892 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6893 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
6894 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
6895 }
6896 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
6897 ThumbIP.reset(ThumbTarget->createMCInstPrinter(
6898 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
6899 *ThumbInstrInfo, *ThumbMRI));
6900 // Set the display preference for hex vs. decimal immediates.
6901 ThumbIP->setPrintImmHex(PrintImmHex);
6902 }
6903
6904 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) {
6905 errs() << "error: couldn't initialize disassembler for target "
6906 << ThumbTripleName << '\n';
6907 return;
6908 }
6909
6910 MachO::mach_header Header = MachOOF->getHeader();
6911
6912 // FIXME: Using the -cfg command line option, this code used to be able to
6913 // annotate relocations with the referenced symbol's name, and if this was
6914 // inside a __[cf]string section, the data it points to. This is now replaced
6915 // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
6916 std::vector<SectionRef> Sections;
6917 std::vector<SymbolRef> Symbols;
6918 SmallVector<uint64_t, 8> FoundFns;
6919 uint64_t BaseSegmentAddress;
6920
6921 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
6922 BaseSegmentAddress);
6923
6924 // Sort the symbols by address, just in case they didn't come in that way.
6925 llvm::sort(Symbols, SymbolSorter());
6926
6927 // Build a data in code table that is sorted on by the address of each entry.
6928 uint64_t BaseAddress = 0;
6929 if (Header.filetype == MachO::MH_OBJECT)
6930 BaseAddress = Sections[0].getAddress();
6931 else
6932 BaseAddress = BaseSegmentAddress;
6933 DiceTable Dices;
6934 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
6935 DI != DE; ++DI) {
6936 uint32_t Offset;
6937 DI->getOffset(Offset);
6938 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
6939 }
6940 array_pod_sort(Dices.begin(), Dices.end());
6941
6942#ifndef NDEBUG
6943 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
6944#else
6945 raw_ostream &DebugOut = nulls();
6946#endif
6947
6948 std::unique_ptr<DIContext> diContext;
6949 ObjectFile *DbgObj = MachOOF;
6950 std::unique_ptr<MemoryBuffer> DSYMBuf;
6951 // Try to find debug info and set up the DIContext for it.
6952 if (UseDbg) {
6953 // A separate DSym file path was specified, parse it as a macho file,
6954 // get the sections and supply it to the section name parsing machinery.
6955 if (!DSYMFile.empty()) {
6956 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
6957 MemoryBuffer::getFileOrSTDIN(DSYMFile);
6958 if (std::error_code EC = BufOrErr.getError()) {
6959 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
6960 return;
6961 }
6962 Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck =
6963 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef());
6964
6965 if (DbgObjCheck.takeError())
6966 report_error(MachOOF->getFileName(), DbgObjCheck.takeError());
6967 DbgObj = DbgObjCheck.get().release();
6968 // We need to keep the file alive, because we're replacing DbgObj with it.
6969 DSYMBuf = std::move(BufOrErr.get());
6970 }
6971
6972 // Setup the DIContext
6973 diContext = DWARFContext::create(*DbgObj);
6974 }
6975
6976 if (FilterSections.size() == 0)
6977 outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
6978
6979 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
6980 StringRef SectName;
6981 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName)
6982 continue;
6983
6984 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
6985
6986 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
6987 if (SegmentName != DisSegName)
6988 continue;
6989
6990 StringRef BytesStr;
6991 Sections[SectIdx].getContents(BytesStr);
6992 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
6993 BytesStr.size());
6994 uint64_t SectAddress = Sections[SectIdx].getAddress();
6995
6996 bool symbolTableWorked = false;
6997
6998 // Create a map of symbol addresses to symbol names for use by
6999 // the SymbolizerSymbolLookUp() routine.
7000 SymbolAddressMap AddrMap;
7001 bool DisSymNameFound = false;
7002 for (const SymbolRef &Symbol : MachOOF->symbols()) {
7003 Expected<SymbolRef::Type> STOrErr = Symbol.getType();
7004 if (!STOrErr)
7005 report_error(MachOOF->getFileName(), STOrErr.takeError());
7006 SymbolRef::Type ST = *STOrErr;
7007 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
7008 ST == SymbolRef::ST_Other) {
7009 uint64_t Address = Symbol.getValue();
7010 Expected<StringRef> SymNameOrErr = Symbol.getName();
7011 if (!SymNameOrErr)
7012 report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
7013 StringRef SymName = *SymNameOrErr;
7014 AddrMap[Address] = SymName;
7015 if (!DisSymName.empty() && DisSymName == SymName)
7016 DisSymNameFound = true;
7017 }
7018 }
7019 if (!DisSymName.empty() && !DisSymNameFound) {
7020 outs() << "Can't find -dis-symname: " << DisSymName << "\n";
7021 return;
7022 }
7023 // Set up the block of info used by the Symbolizer call backs.
7024 SymbolizerInfo.verbose = !NoSymbolicOperands;
7025 SymbolizerInfo.O = MachOOF;
7026 SymbolizerInfo.S = Sections[SectIdx];
7027 SymbolizerInfo.AddrMap = &AddrMap;
7028 SymbolizerInfo.Sections = &Sections;
7029 // Same for the ThumbSymbolizer
7030 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
7031 ThumbSymbolizerInfo.O = MachOOF;
7032 ThumbSymbolizerInfo.S = Sections[SectIdx];
7033 ThumbSymbolizerInfo.AddrMap = &AddrMap;
7034 ThumbSymbolizerInfo.Sections = &Sections;
7035
7036 unsigned int Arch = MachOOF->getArch();
7037
7038 // Skip all symbols if this is a stubs file.
7039 if (Bytes.size() == 0)
7040 return;
7041
7042 // If the section has symbols but no symbol at the start of the section
7043 // these are used to make sure the bytes before the first symbol are
7044 // disassembled.
7045 bool FirstSymbol = true;
7046 bool FirstSymbolAtSectionStart = true;
7047
7048 // Disassemble symbol by symbol.
7049 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7050 Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
7051 if (!SymNameOrErr)
7052 report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
7053 StringRef SymName = *SymNameOrErr;
7054
7055 Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
7056 if (!STOrErr)
7057 report_error(MachOOF->getFileName(), STOrErr.takeError());
7058 SymbolRef::Type ST = *STOrErr;
7059 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7060 continue;
7061
7062 // Make sure the symbol is defined in this section.
7063 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7064 if (!containsSym) {
7065 if (!DisSymName.empty() && DisSymName == SymName) {
7066 outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7067 return;
7068 }
7069 continue;
7070 }
7071 // The __mh_execute_header is special and we need to deal with that fact
7072 // this symbol is before the start of the (__TEXT,__text) section and at the
7073 // address of the start of the __TEXT segment. This is because this symbol
7074 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7075 // start of the section in a standard MH_EXECUTE filetype.
7076 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7077 outs() << "-dis-symname: __mh_execute_header not in any section\n";
7078 return;
7079 }
7080 // When this code is trying to disassemble a symbol at a time and in the
7081 // case there is only the __mh_execute_header symbol left as in a stripped
7082 // executable, we need to deal with this by ignoring this symbol so the
7083 // whole section is disassembled and this symbol is then not displayed.
7084 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7085 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7086 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7087 continue;
7088
7089 // If we are only disassembling one symbol see if this is that symbol.
7090 if (!DisSymName.empty() && DisSymName != SymName)
7091 continue;
7092
7093 // Start at the address of the symbol relative to the section's address.
7094 uint64_t SectSize = Sections[SectIdx].getSize();
7095 uint64_t Start = Symbols[SymIdx].getValue();
7096 uint64_t SectionAddress = Sections[SectIdx].getAddress();
7097 Start -= SectionAddress;
7098
7099 if (Start > SectSize) {
7100 outs() << "section data ends, " << SymName
7101 << " lies outside valid range\n";
7102 return;
7103 }
7104
7105 // Stop disassembling either at the beginning of the next symbol or at
7106 // the end of the section.
7107 bool containsNextSym = false;
7108 uint64_t NextSym = 0;
7109 uint64_t NextSymIdx = SymIdx + 1;
7110 while (Symbols.size() > NextSymIdx) {
7111 Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
7112 if (!STOrErr)
7113 report_error(MachOOF->getFileName(), STOrErr.takeError());
7114 SymbolRef::Type NextSymType = *STOrErr;
7115 if (NextSymType == SymbolRef::ST_Function) {
7116 containsNextSym =
7117 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7118 NextSym = Symbols[NextSymIdx].getValue();
7119 NextSym -= SectionAddress;
7120 break;
7121 }
7122 ++NextSymIdx;
7123 }
7124
7125 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7126 uint64_t Size;
7127
7128 symbolTableWorked = true;
7129
7130 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7131 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb;
7132
7133 // We only need the dedicated Thumb target if there's a real choice
7134 // (i.e. we're not targeting M-class) and the function is Thumb.
7135 bool UseThumbTarget = IsThumb && ThumbTarget;
7136
7137 // If we are not specifying a symbol to start disassembly with and this
7138 // is the first symbol in the section but not at the start of the section
7139 // then move the disassembly index to the start of the section and
7140 // don't print the symbol name just yet. This is so the bytes before the
7141 // first symbol are disassembled.
7142 uint64_t SymbolStart = Start;
7143 if (DisSymName.empty() && FirstSymbol && Start != 0) {
7144 FirstSymbolAtSectionStart = false;
7145 Start = 0;
7146 }
7147 else
7148 outs() << SymName << ":\n";
7149
7150 DILineInfo lastLine;
7151 for (uint64_t Index = Start; Index < End; Index += Size) {
7152 MCInst Inst;
7153
7154 // If this is the first symbol in the section and it was not at the
7155 // start of the section, see if we are at its Index now and if so print
7156 // the symbol name.
7157 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7158 outs() << SymName << ":\n";
7159
7160 uint64_t PC = SectAddress + Index;
7161 if (!NoLeadingAddr) {
7162 if (FullLeadingAddr) {
7163 if (MachOOF->is64Bit())
7164 outs() << format("%016" PRIx64"l" "x", PC);
7165 else
7166 outs() << format("%08" PRIx64"l" "x", PC);
7167 } else {
7168 outs() << format("%8" PRIx64"l" "x" ":", PC);
7169 }
7170 }
7171 if (!NoShowRawInsn || Arch == Triple::arm)
7172 outs() << "\t";
7173
7174 // Check the data in code table here to see if this is data not an
7175 // instruction to be disassembled.
7176 DiceTable Dice;
7177 Dice.push_back(std::make_pair(PC, DiceRef()));
7178 dice_table_iterator DTI =
7179 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
7180 compareDiceTableEntries);
7181 if (DTI != Dices.end()) {
7182 uint16_t Length;
7183 DTI->second.getLength(Length);
7184 uint16_t Kind;
7185 DTI->second.getKind(Kind);
7186 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind);
7187 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
7188 (PC == (DTI->first + Length - 1)) && (Length & 1))
7189 Size++;
7190 continue;
7191 }
7192
7193 SmallVector<char, 64> AnnotationsBytes;
7194 raw_svector_ostream Annotations(AnnotationsBytes);
7195
7196 bool gotInst;
7197 if (UseThumbTarget)
7198 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7199 PC, DebugOut, Annotations);
7200 else
7201 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7202 DebugOut, Annotations);
7203 if (gotInst) {
7204 if (!NoShowRawInsn || Arch == Triple::arm) {
7205 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
7206 }
7207 formatted_raw_ostream FormattedOS(outs());
7208 StringRef AnnotationsStr = Annotations.str();
7209 if (UseThumbTarget)
7210 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
7211 else
7212 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
7213 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7214
7215 // Print debug info.
7216 if (diContext) {
7217 DILineInfo dli = diContext->getLineInfoForAddress(PC);
7218 // Print valid line info if it changed.
7219 if (dli != lastLine && dli.Line != 0)
7220 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7221 << dli.Column;
7222 lastLine = dli;
7223 }
7224 outs() << "\n";
7225 } else {
7226 unsigned int Arch = MachOOF->getArch();
7227 if (Arch == Triple::x86_64 || Arch == Triple::x86) {
7228 outs() << format("\t.byte 0x%02x #bad opcode\n",
7229 *(Bytes.data() + Index) & 0xff);
7230 Size = 1; // skip exactly one illegible byte and move on.
7231 } else if (Arch == Triple::aarch64 ||
7232 (Arch == Triple::arm && !IsThumb)) {
7233 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7234 (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7235 (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7236 (*(Bytes.data() + Index + 3) & 0xff) << 24;
7237 outs() << format("\t.long\t0x%08x\n", opcode);
7238 Size = 4;
7239 } else if (Arch == Triple::arm) {
7240 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-8~svn345461/tools/llvm-objdump/MachODump.cpp"
, 7240, __PRETTY_FUNCTION__))
;
7241 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7242 (*(Bytes.data() + Index + 1) & 0xff) << 8;
7243 outs() << format("\t.short\t0x%04x\n", opcode);
7244 Size = 2;
7245 } else{
7246 errs() << "llvm-objdump: warning: invalid instruction encoding\n";
7247 if (Size == 0)
7248 Size = 1; // skip illegible bytes
7249 }
7250 }
7251 }
7252 // Now that we are done disassembled the first symbol set the bool that
7253 // were doing this to false.
7254 FirstSymbol = false;
7255 }
7256 if (!symbolTableWorked) {
7257 // Reading the symbol table didn't work, disassemble the whole section.
7258 uint64_t SectAddress = Sections[SectIdx].getAddress();
7259 uint64_t SectSize = Sections[SectIdx].getSize();
7260 uint64_t InstSize;
7261 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7262 MCInst Inst;
7263
7264 uint64_t PC = SectAddress + Index;
7265 SmallVector<char, 64> AnnotationsBytes;
7266 raw_svector_ostream Annotations(AnnotationsBytes);
7267 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7268 DebugOut, Annotations)) {
7269 if (!NoLeadingAddr) {
7270 if (FullLeadingAddr) {
7271 if (MachOOF->is64Bit())
7272 outs() << format("%016" PRIx64"l" "x", PC);
7273 else
7274 outs() << format("%08" PRIx64"l" "x", PC);
7275 } else {
7276 outs() << format("%8" PRIx64"l" "x" ":", PC);
7277 }
7278 }
7279 if (!NoShowRawInsn || Arch == Triple::arm) {
7280 outs() << "\t";
7281 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
7282 }
7283 StringRef AnnotationsStr = Annotations.str();
7284 IP->printInst(&Inst, outs(), AnnotationsStr, *STI);
7285 outs() << "\n";
7286 } else {
7287 unsigned int Arch = MachOOF->getArch();
7288 if (Arch == Triple::x86_64 || Arch == Triple::x86) {
7289 outs() << format("\t.byte 0x%02x #bad opcode\n",
7290 *(Bytes.data() + Index) & 0xff);
7291 InstSize = 1; // skip exactly one illegible byte and move on.
7292 } else {
7293 errs() << "llvm-objdump: warning: invalid instruction encoding\n";
7294 if (InstSize == 0)
7295 InstSize = 1; // skip illegible bytes
7296 }
7297 }
7298 }
7299 }
7300 // The TripleName's need to be reset if we are called again for a different
7301 // archtecture.
7302 TripleName = "";
7303 ThumbTripleName = "";
7304
7305 if (SymbolizerInfo.demangled_name != nullptr)
7306 free(SymbolizerInfo.demangled_name);
7307 if (ThumbSymbolizerInfo.demangled_name != nullptr)
7308 free(ThumbSymbolizerInfo.demangled_name);
7309 }
7310}
7311
7312//===----------------------------------------------------------------------===//
7313// __compact_unwind section dumping
7314//===----------------------------------------------------------------------===//
7315
7316namespace {
7317
7318template <typename T>
7319static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
7320 using llvm::support::little;
7321 using llvm::support::unaligned;
7322
7323 if (Offset + sizeof(T) > Contents.size()) {
7324 outs() << "warning: attempt to read past end of buffer\n";
7325 return T();
7326 }
7327
7328 uint64_t Val =
7329 support::endian::read<T, little, unaligned>(Contents.data() + Offset);
7330 return Val;
7331}
7332
7333template <typename T>
7334static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
7335 T Val = read<T>(Contents, Offset);
7336 Offset += sizeof(T);
7337 return Val;
7338}
7339
7340struct CompactUnwindEntry {
7341 uint32_t OffsetInSection;
7342
7343 uint64_t FunctionAddr;
7344 uint32_t Length;
7345 uint32_t CompactEncoding;
7346 uint64_t PersonalityAddr;
7347 uint64_t LSDAAddr;
7348
7349 RelocationRef FunctionReloc;
7350 RelocationRef PersonalityReloc;
7351 RelocationRef LSDAReloc;
7352
7353 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
7354 : OffsetInSection(Offset) {
7355 if (Is64)
7356 read<uint64_t>(Contents, Offset);
7357 else
7358 read<uint32_t>(Contents, Offset);
7359 }
7360
7361private:
7362 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
7363 FunctionAddr = readNext<UIntPtr>(Contents, Offset);
7364 Length = readNext<uint32_t>(Contents, Offset);
7365 CompactEncoding = readNext<uint32_t>(Contents, Offset);
7366 PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
7367 LSDAAddr = readNext<UIntPtr>(Contents, Offset);
7368 }
7369};
7370}
7371
7372/// Given a relocation from __compact_unwind, consisting of the RelocationRef
7373/// and data being relocated, determine the best base Name and Addend to use for
7374/// display purposes.
7375///
7376/// 1. An Extern relocation will directly reference a symbol (and the data is
7377/// then already an addend), so use that.
7378/// 2. Otherwise the data is an offset in the object file's layout; try to find
7379// a symbol before it in the same section, and use the offset from there.
7380/// 3. Finally, if all that fails, fall back to an offset from the start of the
7381/// referenced section.
7382static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
7383 std::map<uint64_t, SymbolRef> &Symbols,
7384 const RelocationRef &Reloc, uint64_t Addr,
7385 StringRef &Name, uint64_t &Addend) {
7386 if (Reloc.getSymbol() != Obj->symbol_end()) {
7387 Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
7388 if (!NameOrErr)
7389 report_error(Obj->getFileName(), NameOrErr.takeError());
7390 Name = *NameOrErr;
7391 Addend = Addr;
7392 return;
7393 }
7394
7395 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
7396 SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
7397
7398 uint64_t SectionAddr = RelocSection.getAddress();
7399
7400 auto Sym = Symbols.upper_bound(Addr);
7401 if (Sym == Symbols.begin()) {
7402 // The first symbol in the object is after this reference, the best we can
7403 // do is section-relative notation.
7404 RelocSection.getName(Name);
7405 Addend = Addr - SectionAddr;
7406 return;
7407 }
7408
7409 // Go back one so that SymbolAddress <= Addr.
7410 --Sym;
7411
7412 auto SectOrErr = Sym->second.getSection();
7413 if (!SectOrErr)
7414 report_error(Obj->getFileName(), SectOrErr.takeError());
7415 section_iterator SymSection = *SectOrErr;
7416 if (RelocSection == *SymSection) {
7417 // There's a valid symbol in the same section before this reference.
7418 Expected<StringRef> NameOrErr = Sym->second.getName();
7419 if (!NameOrErr)
7420 report_error(Obj->getFileName(), NameOrErr.takeError());
7421 Name = *NameOrErr;
7422 Addend = Addr - Sym->first;
7423 return;
7424 }
7425
7426 // There is a symbol before this reference, but it's in a different
7427 // section. Probably not helpful to mention it, so use the section name.
7428 RelocSection.getName(Name);
7429 Addend = Addr - SectionAddr;
7430}
7431
7432static void printUnwindRelocDest(const MachOObjectFile *Obj,
7433 std::map<uint64_t, SymbolRef> &Symbols,
7434 const RelocationRef &Reloc, uint64_t Addr) {
7435 StringRef Name;
7436 uint64_t Addend;
7437
7438 if (!Reloc.getObject())
7439 return;
7440
7441 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7442
7443 outs() << Name;
7444 if (Addend)
7445 outs() << " + " << format("0x%" PRIx64"l" "x", Addend);
7446}
7447
7448static void
7449printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7450 std::map<uint64_t, SymbolRef> &Symbols,
7451 const SectionRef &CompactUnwind) {
7452
7453 if (!Obj->isLittleEndian()) {
7454 outs() << "Skipping big-endian __compact_unwind section\n";
7455 return;
7456 }
7457
7458 bool Is64 = Obj->is64Bit();
7459 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7460 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7461
7462 StringRef Contents;
7463 CompactUnwind.getContents(Contents);
7464
7465 SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7466
7467 // First populate the initial raw offsets, encodings and so on from the entry.
7468 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7469 CompactUnwindEntry Entry(Contents, Offset, Is64);
7470 CompactUnwinds.push_back(Entry);
7471 }
7472
7473 // Next we need to look at the relocations to find out what objects are
7474 // actually being referred to.
7475 for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7476 uint64_t RelocAddress = Reloc.getOffset();
7477
7478 uint32_t EntryIdx = RelocAddress / EntrySize;
7479 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7480 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7481
7482 if (OffsetInEntry == 0)
7483 Entry.FunctionReloc = Reloc;
7484 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7485 Entry.PersonalityReloc = Reloc;
7486 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7487 Entry.LSDAReloc = Reloc;
7488 else {
7489 outs() << "Invalid relocation in __compact_unwind section\n";
7490 return;
7491 }
7492 }
7493
7494 // Finally, we're ready to print the data we've gathered.
7495 outs() << "Contents of __compact_unwind section:\n";
7496 for (auto &Entry : CompactUnwinds) {
7497 outs() << " Entry at offset "
7498 << format("0x%" PRIx32"x", Entry.OffsetInSection) << ":\n";
7499
7500 // 1. Start of the region this entry applies to.
7501 outs() << " start: " << format("0x%" PRIx64"l" "x",
7502 Entry.FunctionAddr) << ' ';
7503 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
7504 outs() << '\n';
7505
7506 // 2. Length of the region this entry applies to.
7507 outs() << " length: " << format("0x%" PRIx32"x", Entry.Length)
7508 << '\n';
7509 // 3. The 32-bit compact encoding.
7510 outs() << " compact encoding: "
7511 << format("0x%08" PRIx32"x", Entry.CompactEncoding) << '\n';
7512
7513 // 4. The personality function, if present.
7514 if (Entry.PersonalityReloc.getObject()) {
7515 outs() << " personality function: "
7516 << format("0x%" PRIx64"l" "x", Entry.PersonalityAddr) << ' ';
7517 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
7518 Entry.PersonalityAddr);
7519 outs() << '\n';
7520 }
7521
7522 // 5. This entry's language-specific data area.
7523 if (Entry.LSDAReloc.getObject()) {
7524 outs() << " LSDA: " << format("0x%" PRIx64"l" "x",
7525 Entry.LSDAAddr) << ' ';
7526 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
7527 outs() << '\n';
7528 }
7529 }
7530}
7531
7532//===----------------------------------------------------------------------===//
7533// __unwind_info section dumping
7534//===----------------------------------------------------------------------===//
7535
7536static void printRegularSecondLevelUnwindPage(StringRef PageData) {
7537 ptrdiff_t Pos = 0;
7538 uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7539 (void)Kind;
7540 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-8~svn345461/tools/llvm-objdump/MachODump.cpp"
, 7540, __PRETTY_FUNCTION__))
;
7541
7542 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7543 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7544
7545 Pos = EntriesStart;
7546 for (unsigned i = 0; i < NumEntries; ++i) {
7547 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
7548 uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7549
7550 outs() << " [" << i << "]: "
7551 << "function offset=" << format("0x%08" PRIx32"x", FunctionOffset)
7552 << ", "
7553 << "encoding=" << format("0x%08" PRIx32"x", Encoding) << '\n';
7554 }
7555}
7556
7557static void printCompressedSecondLevelUnwindPage(
7558 StringRef PageData, uint32_t FunctionBase,
7559 const SmallVectorImpl<uint32_t> &CommonEncodings) {
7560 ptrdiff_t Pos = 0;
7561 uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7562 (void)Kind;
7563 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-8~svn345461/tools/llvm-objdump/MachODump.cpp"
, 7563, __PRETTY_FUNCTION__))
;
7564
7565 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7566 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7567
7568 uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos);
7569 readNext<uint16_t>(PageData, Pos);
7570 StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos);
7571
7572 Pos = EntriesStart;
7573 for (unsigned i = 0; i < NumEntries; ++i) {
7574 uint32_t Entry = readNext<uint32_t>(PageData, Pos);
7575 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
7576 uint32_t EncodingIdx = Entry >> 24;
7577
7578 uint32_t Encoding;
7579 if (EncodingIdx < CommonEncodings.size())
7580 Encoding = CommonEncodings[EncodingIdx];
7581 else
7582 Encoding = read<uint32_t>(PageEncodings,
7583 sizeof(uint32_t) *
7584 (EncodingIdx - CommonEncodings.size()));
7585
7586 outs() << " [" << i << "]: "
7587 << "function offset=" << format("0x%08" PRIx32"x", FunctionOffset)
7588 << ", "
7589 << "encoding[" << EncodingIdx
7590 << "]=" << format("0x%08" PRIx32"x", Encoding) << '\n';
7591 }
7592}
7593
7594static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
7595 std::map<uint64_t, SymbolRef> &Symbols,
7596 const SectionRef &UnwindInfo) {
7597
7598 if (!Obj->isLittleEndian()) {
7599 outs() << "Skipping big-endian __unwind_info section\n";
7600 return;
7601 }
7602
7603 outs() << "Contents of __unwind_info section:\n";
7604
7605 StringRef Contents;
7606 UnwindInfo.getContents(Contents);
7607 ptrdiff_t Pos = 0;
7608
7609 //===----------------------------------
7610 // Section header
7611 //===----------------------------------
7612
7613 uint32_t Version = readNext<uint32_t>(Contents, Pos);
7614 outs() << " Version: "
7615 << format("0x%" PRIx32"x", Version) << '\n';
7616 if (Version != 1) {
7617 outs() << " Skipping section with unknown version\n";
7618 return;
7619 }
7620
7621 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
7622 outs() << " Common encodings array section offset: "
7623 << format("0x%" PRIx32"x", CommonEncodingsStart) << '\n';
7624 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
7625 outs() << " Number of common encodings in array: "
7626 << format("0x%" PRIx32"x", NumCommonEncodings) << '\n';
7627
7628 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
7629 outs() << " Personality function array section offset: "
7630 << format("0x%" PRIx32"x", PersonalitiesStart) << '\n';
7631 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
7632 outs() << " Number of personality functions in array: "
7633 << format("0x%" PRIx32"x", NumPersonalities) << '\n';
7634
7635 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
7636 outs() << " Index array section offset: "
7637 << format("0x%" PRIx32"x", IndicesStart) << '\n';
7638 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
7639 outs() << " Number of indices in array: "
7640 << format("0x%" PRIx32"x", NumIndices) << '\n';
7641
7642 //===----------------------------------
7643 // A shared list of common encodings
7644 //===----------------------------------
7645
7646 // These occupy indices in the range [0, N] whenever an encoding is referenced
7647 // from a compressed 2nd level index table. In practice the linker only
7648 // creates ~128 of these, so that indices are available to embed encodings in
7649 // the 2nd level index.
7650
7651 SmallVector<uint32_t, 64> CommonEncodings;
7652 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n";
7653 Pos = CommonEncodingsStart;
7654 for (unsigned i = 0; i < NumCommonEncodings; ++i) {
7655 uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
7656 CommonEncodings.push_back(Encoding);
7657
7658 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32"x", Encoding)
7659 << '\n';
7660 }
7661
7662 //===----------------------------------
7663 // Personality functions used in this executable
7664 //===----------------------------------
7665
7666 // There should be only a handful of these (one per source language,
7667 // roughly). Particularly since they only get 2 bits in the compact encoding.
7668
7669 outs() << " Personality functions: (count = " << NumPersonalities << ")\n";
7670 Pos = PersonalitiesStart;
7671 for (unsigned i = 0; i < NumPersonalities; ++i) {
7672 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
7673 outs() << " personality[" << i + 1
7674 << "]: " << format("0x%08" PRIx32"x", PersonalityFn) << '\n';
7675 }
7676
7677 //===----------------------------------
7678 // The level 1 index entries
7679 //===----------------------------------
7680
7681 // These specify an approximate place to start searching for the more detailed
7682 // information, sorted by PC.
7683
7684 struct IndexEntry {
7685 uint32_t FunctionOffset;
7686 uint32_t SecondLevelPageStart;
7687 uint32_t LSDAStart;
7688 };
7689
7690 SmallVector<IndexEntry, 4> IndexEntries;
7691
7692 outs() << " Top level indices: (count = " << NumIndices << ")\n";
7693 Pos = IndicesStart;
7694 for (unsigned i = 0; i < NumIndices; ++i) {
7695 IndexEntry Entry;
7696
7697 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
7698 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
7699 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
7700 IndexEntries.push_back(Entry);
7701
7702 outs() << " [" << i << "]: "
7703 << "function offset=" << format("0x%08" PRIx32"x", Entry.FunctionOffset)
7704 << ", "
7705 << "2nd level page offset="
7706 << format("0x%08" PRIx32"x", Entry.SecondLevelPageStart) << ", "
7707 << "LSDA offset=" << format("0x%08" PRIx32"x", Entry.LSDAStart) << '\n';
7708 }
7709
7710 //===----------------------------------
7711 // Next come the LSDA tables
7712 //===----------------------------------
7713
7714 // The LSDA layout is rather implicit: it's a contiguous array of entries from
7715 // the first top-level index's LSDAOffset to the last (sentinel).
7716
7717 outs() << " LSDA descriptors:\n";
7718 Pos = IndexEntries[0].LSDAStart;
7719 const uint32_t LSDASize = 2 * sizeof(uint32_t);
7720 int NumLSDAs =
7721 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
7722
7723 for (int i = 0; i < NumLSDAs; ++i) {
7724 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
7725 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
7726 outs() << " [" << i << "]: "
7727 << "function offset=" << format("0x%08" PRIx32"x", FunctionOffset)
7728 << ", "
7729 << "LSDA offset=" << format("0x%08" PRIx32"x", LSDAOffset) << '\n';
7730 }
7731
7732 //===----------------------------------
7733 // Finally, the 2nd level indices
7734 //===----------------------------------
7735
7736 // Generally these are 4K in size, and have 2 possible forms:
7737 // + Regular stores up to 511 entries with disparate encodings
7738 // + Compressed stores up to 1021 entries if few enough compact encoding
7739 // values are used.
7740 outs() << " Second level indices:\n";
7741 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
7742 // The final sentinel top-level index has no associated 2nd level page
7743 if (IndexEntries[i].SecondLevelPageStart == 0)
7744 break;
7745
7746 outs() << " Second level index[" << i << "]: "
7747 << "offset in section="
7748 << format("0x%08" PRIx32"x", IndexEntries[i].SecondLevelPageStart)
7749 << ", "
7750 << "base function offset="
7751 << format("0x%08" PRIx32"x", IndexEntries[i].FunctionOffset) << '\n';
7752
7753 Pos = IndexEntries[i].SecondLevelPageStart;
7754 if (Pos + sizeof(uint32_t) > Contents.size()) {
7755 outs() << "warning: invalid offset for second level page: " << Pos << '\n';
7756 continue;
7757 }
7758
7759 uint32_t Kind =
7760 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
7761 if (Kind == 2)
7762 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
7763 else if (Kind == 3)
7764 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
7765 IndexEntries[i].FunctionOffset,
7766 CommonEncodings);
7767 else
7768 outs() << " Skipping 2nd level page with unknown kind " << Kind
7769 << '\n';
7770 }
7771}
7772
7773void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
7774 std::map<uint64_t, SymbolRef> Symbols;
7775 for (const SymbolRef &SymRef : Obj->symbols()) {
7776 // Discard any undefined or absolute symbols. They're not going to take part
7777 // in the convenience lookup for unwind info and just take up resources.
7778 auto SectOrErr = SymRef.getSection();
7779 if (!SectOrErr) {
7780 // TODO: Actually report errors helpfully.
7781 consumeError(SectOrErr.takeError());
7782 continue;
7783 }
7784 section_iterator Section = *SectOrErr;
7785 if (Section == Obj->section_end())
7786 continue;
7787
7788 uint64_t Addr = SymRef.getValue();
7789 Symbols.insert(std::make_pair(Addr, SymRef));
7790 }
7791
7792 for (const SectionRef &Section : Obj->sections()) {
7793 StringRef SectName;
7794 Section.getName(SectName);
7795 if (SectName == "__compact_unwind")
7796 printMachOCompactUnwindSection(Obj, Symbols, Section);
7797 else if (SectName == "__unwind_info")
7798 printMachOUnwindInfoSection(Obj, Symbols, Section);
7799 }
7800}
7801
7802static void PrintMachHeader(uint32_t magic, uint32_t cputype,
7803 uint32_t cpusubtype, uint32_t filetype,
7804 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
7805 bool verbose) {
7806 outs() << "Mach header\n";
7807 outs() << " magic cputype cpusubtype caps filetype ncmds "
7808 "sizeofcmds flags\n";
7809 if (verbose) {
7810 if (magic == MachO::MH_MAGIC)
7811 outs() << " MH_MAGIC";
7812 else if (magic == MachO::MH_MAGIC_64)
7813 outs() << "MH_MAGIC_64";
7814 else
7815 outs() << format(" 0x%08" PRIx32"x", magic);
7816 switch (cputype) {
7817 case MachO::CPU_TYPE_I386:
7818 outs() << " I386";
7819 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7820 case MachO::CPU_SUBTYPE_I386_ALL:
7821 outs() << " ALL";
7822 break;
7823 default:
7824 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7825 break;
7826 }
7827 break;
7828 case MachO::CPU_TYPE_X86_64:
7829 outs() << " X86_64";
7830 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7831 case MachO::CPU_SUBTYPE_X86_64_ALL:
7832 outs() << " ALL";
7833 break;
7834 case MachO::CPU_SUBTYPE_X86_64_H:
7835 outs() << " Haswell";
7836 break;
7837 default:
7838 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7839 break;
7840 }
7841 break;
7842 case MachO::CPU_TYPE_ARM:
7843 outs() << " ARM";
7844 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7845 case MachO::CPU_SUBTYPE_ARM_ALL:
7846 outs() << " ALL";
7847 break;
7848 case MachO::CPU_SUBTYPE_ARM_V4T:
7849 outs() << " V4T";
7850 break;
7851 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
7852 outs() << " V5TEJ";
7853 break;
7854 case MachO::CPU_SUBTYPE_ARM_XSCALE:
7855 outs() << " XSCALE";
7856 break;
7857 case MachO::CPU_SUBTYPE_ARM_V6:
7858 outs() << " V6";
7859 break;
7860 case MachO::CPU_SUBTYPE_ARM_V6M:
7861 outs() << " V6M";
7862 break;
7863 case MachO::CPU_SUBTYPE_ARM_V7:
7864 outs() << " V7";
7865 break;
7866 case MachO::CPU_SUBTYPE_ARM_V7EM:
7867 outs() << " V7EM";
7868 break;
7869 case MachO::CPU_SUBTYPE_ARM_V7K:
7870 outs() << " V7K";
7871 break;
7872 case MachO::CPU_SUBTYPE_ARM_V7M:
7873 outs() << " V7M";
7874 break;
7875 case MachO::CPU_SUBTYPE_ARM_V7S:
7876 outs() << " V7S";
7877 break;
7878 default:
7879 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7880 break;
7881 }
7882 break;
7883 case MachO::CPU_TYPE_ARM64:
7884 outs() << " ARM64";
7885 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7886 case MachO::CPU_SUBTYPE_ARM64_ALL:
7887 outs() << " ALL";
7888 break;
7889 default:
7890 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7891 break;
7892 }
7893 break;
7894 case MachO::CPU_TYPE_POWERPC:
7895 outs() << " PPC";
7896 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7897 case MachO::CPU_SUBTYPE_POWERPC_ALL:
7898 outs() << " ALL";
7899 break;
7900 default:
7901 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7902 break;
7903 }
7904 break;
7905 case MachO::CPU_TYPE_POWERPC64:
7906 outs() << " PPC64";
7907 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7908 case MachO::CPU_SUBTYPE_POWERPC_ALL:
7909 outs() << " ALL";
7910 break;
7911 default:
7912 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7913 break;
7914 }
7915 break;
7916 default:
7917 outs() << format(" %7d", cputype);
7918 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7919 break;
7920 }
7921 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
7922 outs() << " LIB64";
7923 } else {
7924 outs() << format(" 0x%02" PRIx32"x",
7925 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
7926 }
7927 switch (filetype) {
7928 case MachO::MH_OBJECT:
7929 outs() << " OBJECT";
7930 break;
7931 case MachO::MH_EXECUTE:
7932 outs() << " EXECUTE";
7933 break;
7934 case MachO::MH_FVMLIB:
7935 outs() << " FVMLIB";
7936 break;
7937 case MachO::MH_CORE:
7938 outs() << " CORE";
7939 break;
7940 case MachO::MH_PRELOAD:
7941 outs() << " PRELOAD";
7942 break;
7943 case MachO::MH_DYLIB:
7944 outs() << " DYLIB";
7945 break;
7946 case MachO::MH_DYLIB_STUB:
7947 outs() << " DYLIB_STUB";
7948 break;
7949 case MachO::MH_DYLINKER:
7950 outs() << " DYLINKER";
7951 break;
7952 case MachO::MH_BUNDLE:
7953 outs() << " BUNDLE";
7954 break;
7955 case MachO::MH_DSYM:
7956 outs() << " DSYM";
7957 break;
7958 case MachO::MH_KEXT_BUNDLE:
7959 outs() << " KEXTBUNDLE";
7960 break;
7961 default:
7962 outs() << format(" %10u", filetype);
7963 break;
7964 }
7965 outs() << format(" %5u", ncmds);
7966 outs() << format(" %10u", sizeofcmds);
7967 uint32_t f = flags;
7968 if (f & MachO::MH_NOUNDEFS) {
7969 outs() << " NOUNDEFS";
7970 f &= ~MachO::MH_NOUNDEFS;
7971 }
7972 if (f & MachO::MH_INCRLINK) {
7973 outs() << " INCRLINK";
7974 f &= ~MachO::MH_INCRLINK;
7975 }
7976 if (f & MachO::MH_DYLDLINK) {
7977 outs() << " DYLDLINK";
7978 f &= ~MachO::MH_DYLDLINK;
7979 }
7980 if (f & MachO::MH_BINDATLOAD) {
7981 outs() << " BINDATLOAD";
7982 f &= ~MachO::MH_BINDATLOAD;
7983 }
7984 if (f & MachO::MH_PREBOUND) {
7985 outs() << " PREBOUND";
7986 f &= ~MachO::MH_PREBOUND;
7987 }
7988 if (f & MachO::MH_SPLIT_SEGS) {
7989 outs() << " SPLIT_SEGS";
7990 f &= ~MachO::MH_SPLIT_SEGS;
7991 }
7992 if (f & MachO::MH_LAZY_INIT) {
7993 outs() << " LAZY_INIT";
7994 f &= ~MachO::MH_LAZY_INIT;
7995 }
7996 if (f & MachO::MH_TWOLEVEL) {
7997 outs() << " TWOLEVEL";
7998 f &= ~MachO::MH_TWOLEVEL;
7999 }
8000 if (f & MachO::MH_FORCE_FLAT) {
8001 outs() << " FORCE_FLAT";
8002 f &= ~MachO::MH_FORCE_FLAT;
8003 }
8004 if (f & MachO::MH_NOMULTIDEFS) {
8005 outs() << " NOMULTIDEFS";
8006 f &= ~MachO::MH_NOMULTIDEFS;
8007 }
8008 if (f & MachO::MH_NOFIXPREBINDING) {
8009 outs() << " NOFIXPREBINDING";
8010 f &= ~MachO::MH_NOFIXPREBINDING;
8011 }
8012 if (f & MachO::MH_PREBINDABLE) {
8013 outs() << " PREBINDABLE";
8014 f &= ~MachO::MH_PREBINDABLE;
8015 }
8016 if (f & MachO::MH_ALLMODSBOUND) {
8017 outs() << " ALLMODSBOUND";
8018 f &= ~MachO::MH_ALLMODSBOUND;
8019 }
8020 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
8021 outs() << " SUBSECTIONS_VIA_SYMBOLS";
8022 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
8023 }
8024 if (f & MachO::MH_CANONICAL) {
8025 outs() << " CANONICAL";
8026 f &= ~MachO::MH_CANONICAL;
8027 }
8028 if (f & MachO::MH_WEAK_DEFINES) {
8029 outs() << " WEAK_DEFINES";
8030 f &= ~MachO::MH_WEAK_DEFINES;
8031 }
8032 if (f & MachO::MH_BINDS_TO_WEAK) {
8033 outs() << " BINDS_TO_WEAK";
8034 f &= ~MachO::MH_BINDS_TO_WEAK;
8035 }
8036 if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
8037 outs() << " ALLOW_STACK_EXECUTION";
8038 f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
8039 }
8040 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
8041 outs() << " DEAD_STRIPPABLE_DYLIB";
8042 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
8043 }
8044 if (f & MachO::MH_PIE) {
8045 outs() << " PIE";
8046 f &= ~MachO::MH_PIE;
8047 }
8048 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
8049 outs() << " NO_REEXPORTED_DYLIBS";
8050 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
8051 }
8052 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
8053 outs() << " MH_HAS_TLV_DESCRIPTORS";
8054 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
8055 }
8056 if (f & MachO::MH_NO_HEAP_EXECUTION) {
8057 outs() << " MH_NO_HEAP_EXECUTION";
8058 f &= ~MachO::MH_NO_HEAP_EXECUTION;
8059 }
8060 if (f & MachO::MH_APP_EXTENSION_SAFE) {
8061 outs() << " APP_EXTENSION_SAFE";
8062 f &= ~MachO::MH_APP_EXTENSION_SAFE;
8063 }
8064 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
8065 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
8066 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
8067 }
8068 if (f != 0 || flags == 0)
8069 outs() << format(" 0x%08" PRIx32"x", f);
8070 } else {
8071 outs() << format(" 0x%08" PRIx32"x", magic);
8072 outs() << format(" %7d", cputype);
8073 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8074 outs() << format(" 0x%02" PRIx32"x",
8075 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8076 outs() << format(" %10u", filetype);
8077 outs() << format(" %5u", ncmds);
8078 outs() << format(" %10u", sizeofcmds);
8079 outs() << format(" 0x%08" PRIx32"x", flags);
8080 }
8081 outs() << "\n";
8082}
8083
8084static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
8085 StringRef SegName, uint64_t vmaddr,
8086 uint64_t vmsize, uint64_t fileoff,
8087 uint64_t filesize, uint32_t maxprot,
8088 uint32_t initprot, uint32_t nsects,
8089 uint32_t flags, uint32_t object_size,
8090 bool verbose) {
8091 uint64_t expected_cmdsize;
8092 if (cmd == MachO::LC_SEGMENT) {
8093 outs() << " cmd LC_SEGMENT\n";
8094 expected_cmdsize = nsects;
8095 expected_cmdsize *= sizeof(struct MachO::section);
8096 expected_cmdsize += sizeof(struct MachO::segment_command);
8097 } else {
8098 outs() << " cmd LC_SEGMENT_64\n";
8099 expected_cmdsize = nsects;
8100 expected_cmdsize *= sizeof(struct MachO::section_64);
8101 expected_cmdsize += sizeof(struct MachO::segment_command_64);
8102 }
8103 outs() << " cmdsize " << cmdsize;
8104 if (cmdsize != expected_cmdsize)
8105 outs() << " Inconsistent size\n";
8106 else
8107 outs() << "\n";
8108 outs() << " segname " << SegName << "\n";
8109 if (cmd == MachO::LC_SEGMENT_64) {
8110 outs() << " vmaddr " << format("0x%016" PRIx64"l" "x", vmaddr) << "\n";
8111 outs() << " vmsize " << format("0x%016" PRIx64"l" "x", vmsize) << "\n";
8112 } else {
8113 outs() << " vmaddr " << format("0x%08" PRIx64"l" "x", vmaddr) << "\n";
8114 outs() << " vmsize " << format("0x%08" PRIx64"l" "x", vmsize) << "\n";
8115 }
8116 outs() << " fileoff " << fileoff;
8117 if (fileoff > object_size)
8118 outs() << " (past end of file)\n";
8119 else
8120 outs() << "\n";
8121 outs() << " filesize " << filesize;
8122 if (fileoff + filesize > object_size)
8123 outs() << " (past end of file)\n";
8124 else
8125 outs() << "\n";
8126 if (verbose) {
8127 if ((maxprot &
8128 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8129 MachO::VM_PROT_EXECUTE)) != 0)
8130 outs() << " maxprot ?" << format("0x%08" PRIx32"x", maxprot) << "\n";
8131 else {
8132 outs() << " maxprot ";
8133 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
8134 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8135 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8136 }
8137 if ((initprot &
8138 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8139 MachO::VM_PROT_EXECUTE)) != 0)
8140 outs() << " initprot ?" << format("0x%08" PRIx32"x", initprot) << "\n";
8141 else {
8142 outs() << " initprot ";
8143 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
8144 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8145 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8146 }
8147 } else {
8148 outs() << " maxprot " << format("0x%08" PRIx32"x", maxprot) << "\n";
8149 outs() << " initprot " << format("0x%08" PRIx32"x", initprot) << "\n";
8150 }
8151 outs() << " nsects " << nsects << "\n";
8152 if (verbose) {
8153 outs() << " flags";
8154 if (flags == 0)
8155 outs() << " (none)\n";
8156 else {
8157 if (flags & MachO::SG_HIGHVM) {
8158 outs() << " HIGHVM";
8159 flags &= ~MachO::SG_HIGHVM;
8160 }
8161 if (flags & MachO::SG_FVMLIB) {
8162 outs() << " FVMLIB";
8163 flags &= ~MachO::SG_FVMLIB;
8164 }
8165 if (flags & MachO::SG_NORELOC) {
8166 outs() << " NORELOC";
8167 flags &= ~MachO::SG_NORELOC;
8168 }
8169 if (flags & MachO::SG_PROTECTED_VERSION_1) {
8170 outs() << " PROTECTED_VERSION_1";
8171 flags &= ~MachO::SG_PROTECTED_VERSION_1;
8172 }
8173 if (flags)
8174 outs() << format(" 0x%08" PRIx32"x", flags) << " (unknown flags)\n";
8175 else
8176 outs() << "\n";
8177 }
8178 } else {
8179 outs() << " flags " << format("0x%" PRIx32"x", flags) << "\n";
8180 }
8181}
8182
8183static void PrintSection(const char *sectname, const char *segname,
8184 uint64_t addr, uint64_t size, uint32_t offset,
8185 uint32_t align, uint32_t reloff, uint32_t nreloc,
8186 uint32_t flags, uint32_t reserved1, uint32_t reserved2,
8187 uint32_t cmd, const char *sg_segname,
8188 uint32_t filetype, uint32_t object_size,
8189 bool verbose) {
8190 outs() << "Section\n";
8191 outs() << " sectname " << format("%.16s\n", sectname);
8192 outs() << " segname " << format("%.16s", segname);
8193 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
8194 outs() << " (does not match segment)\n";
8195 else
8196 outs() << "\n";
8197 if (cmd == MachO::LC_SEGMENT_64) {
8198 outs() << " addr " << format("0x%016" PRIx64"l" "x", addr) << "\n";
8199 outs() << " size " << format("0x%016" PRIx64"l" "x", size);
8200 } else {
8201 outs() << " addr " << format("0x%08" PRIx64"l" "x", addr) << "\n";
8202 outs() << " size " << format("0x%08" PRIx64"l" "x", size);
8203 }
8204 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
8205 outs() << " (past end of file)\n";
8206 else
8207 outs() << "\n";
8208 outs() << " offset " << offset;
8209 if (offset > object_size)
8210 outs() << " (past end of file)\n";
8211 else
8212 outs() << "\n";
8213 uint32_t align_shifted = 1 << align;
8214 outs() << " align 2^" << align << " (" << align_shifted << ")\n";
8215 outs() << " reloff " << reloff;
8216 if (reloff > object_size)
8217 outs() << " (past end of file)\n";
8218 else
8219 outs() << "\n";
8220 outs() << " nreloc " << nreloc;
8221 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
8222 outs() << " (past end of file)\n";
8223 else
8224 outs() << "\n";
8225 uint32_t section_type = flags & MachO::SECTION_TYPE;
8226 if (verbose) {
8227 outs() << " type";
8228 if (section_type == MachO::S_REGULAR)
8229 outs() << " S_REGULAR\n";
8230 else if (section_type == MachO::S_ZEROFILL)
8231 outs() << " S_ZEROFILL\n";
8232 else if (section_type == MachO::S_CSTRING_LITERALS)
8233 outs() << " S_CSTRING_LITERALS\n";
8234 else if (section_type == MachO::S_4BYTE_LITERALS)
8235 outs() << " S_4BYTE_LITERALS\n";
8236 else if (section_type == MachO::S_8BYTE_LITERALS)
8237 outs() << " S_8BYTE_LITERALS\n";
8238 else if (section_type == MachO::S_16BYTE_LITERALS)
8239 outs() << " S_16BYTE_LITERALS\n";
8240 else if (section_type == MachO::S_LITERAL_POINTERS)
8241 outs() << " S_LITERAL_POINTERS\n";
8242 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
8243 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
8244 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
8245 outs() << " S_LAZY_SYMBOL_POINTERS\n";
8246 else if (section_type == MachO::S_SYMBOL_STUBS)
8247 outs() << " S_SYMBOL_STUBS\n";
8248 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
8249 outs() << " S_MOD_INIT_FUNC_POINTERS\n";
8250 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
8251 outs() << " S_MOD_TERM_FUNC_POINTERS\n";
8252 else if (section_type == MachO::S_COALESCED)
8253 outs() << " S_COALESCED\n";
8254 else if (section_type == MachO::S_INTERPOSING)
8255 outs() << " S_INTERPOSING\n";
8256 else if (section_type == MachO::S_DTRACE_DOF)
8257 outs() << " S_DTRACE_DOF\n";
8258 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
8259 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
8260 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
8261 outs() << " S_THREAD_LOCAL_REGULAR\n";
8262 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
8263 outs() << " S_THREAD_LOCAL_ZEROFILL\n";
8264 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
8265 outs() << " S_THREAD_LOCAL_VARIABLES\n";
8266 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8267 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
8268 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
8269 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
8270 else
8271 outs() << format("0x%08" PRIx32"x", section_type) << "\n";
8272 outs() << "attributes";
8273 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
8274 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
8275 outs() << " PURE_INSTRUCTIONS";
8276 if (section_attributes & MachO::S_ATTR_NO_TOC)
8277 outs() << " NO_TOC";
8278 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
8279 outs() << " STRIP_STATIC_SYMS";
8280 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
8281 outs() << " NO_DEAD_STRIP";
8282 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
8283 outs() << " LIVE_SUPPORT";
8284 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
8285 outs() << " SELF_MODIFYING_CODE";
8286 if (section_attributes & MachO::S_ATTR_DEBUG)
8287 outs() << " DEBUG";
8288 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
8289 outs() << " SOME_INSTRUCTIONS";
8290 if (section_attributes & MachO::S_ATTR_EXT_RELOC)
8291 outs() << " EXT_RELOC";
8292 if (section_attributes & MachO::S_ATTR_LOC_RELOC)
8293 outs() << " LOC_RELOC";
8294 if (section_attributes == 0)
8295 outs() << " (none)";
8296 outs() << "\n";
8297 } else
8298 outs() << " flags " << format("0x%08" PRIx32"x", flags) << "\n";
8299 outs() << " reserved1 " << reserved1;
8300 if (section_type == MachO::S_SYMBOL_STUBS ||
8301 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
8302 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
8303 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
8304 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8305 outs() << " (index into indirect symbol table)\n";
8306 else
8307 outs() << "\n";
8308 outs() << " reserved2 " << reserved2;
8309 if (section_type == MachO::S_SYMBOL_STUBS)
8310 outs() << " (size of stubs)\n";
8311 else
8312 outs() << "\n";
8313}
8314
8315static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
8316 uint32_t object_size) {
8317 outs() << " cmd LC_SYMTAB\n";
8318 outs() << " cmdsize " << st.cmdsize;
8319 if (st.cmdsize != sizeof(struct MachO::symtab_command))
8320 outs() << " Incorrect size\n";
8321 else
8322 outs() << "\n";
8323 outs() << " symoff " << st.symoff;
8324 if (st.symoff > object_size)
8325 outs() << " (past end of file)\n";
8326 else
8327 outs() << "\n";
8328 outs() << " nsyms " << st.nsyms;
8329 uint64_t big_size;
8330 if (Is64Bit) {
8331 big_size = st.nsyms;
8332 big_size *= sizeof(struct MachO::nlist_64);
8333 big_size += st.symoff;
8334 if (big_size > object_size)
8335 outs() << " (past end of file)\n";
8336 else
8337 outs() << "\n";
8338 } else {
8339 big_size = st.nsyms;
8340 big_size *= sizeof(struct MachO::nlist);
8341 big_size += st.symoff;
8342 if (big_size > object_size)
8343 outs() << " (past end of file)\n";
8344 else
8345 outs() << "\n";
8346 }
8347 outs() << " stroff " << st.stroff;
8348 if (st.stroff > object_size)
8349 outs() << " (past end of file)\n";
8350 else
8351 outs() << "\n";
8352 outs() << " strsize " << st.strsize;
8353 big_size = st.stroff;
8354 big_size += st.strsize;
8355 if (big_size > object_size)
8356 outs() << " (past end of file)\n";
8357 else
8358 outs() << "\n";
8359}
8360
8361static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
8362 uint32_t nsyms, uint32_t object_size,
8363 bool Is64Bit) {
8364 outs() << " cmd LC_DYSYMTAB\n";
8365 outs() << " cmdsize " << dyst.cmdsize;
8366 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
8367 outs() << " Incorrect size\n";
8368 else
8369 outs() << "\n";
8370 outs() << " ilocalsym " << dyst.ilocalsym;
8371 if (dyst.ilocalsym > nsyms)
8372 outs() << " (greater than the number of symbols)\n";
8373 else
8374 outs() << "\n";
8375 outs() << " nlocalsym " << dyst.nlocalsym;
8376 uint64_t big_size;
8377 big_size = dyst.ilocalsym;
8378 big_size += dyst.nlocalsym;
8379 if (big_size > nsyms)
8380 outs() << " (past the end of the symbol table)\n";
8381 else
8382 outs() << "\n";
8383 outs() << " iextdefsym " << dyst.iextdefsym;
8384 if (dyst.iextdefsym > nsyms)
8385 outs() << " (greater than the number of symbols)\n";
8386 else
8387 outs() << "\n";
8388 outs() << " nextdefsym " << dyst.nextdefsym;
8389 big_size = dyst.iextdefsym;
8390 big_size += dyst.nextdefsym;
8391 if (big_size > nsyms)
8392 outs() << " (past the end of the symbol table)\n";
8393 else
8394 outs() << "\n";
8395 outs() << " iundefsym " << dyst.iundefsym;
8396 if (dyst.iundefsym > nsyms)
8397 outs() << " (greater than the number of symbols)\n";
8398 else
8399 outs() << "\n";
8400 outs() << " nundefsym " << dyst.nundefsym;
8401 big_size = dyst.iundefsym;
8402 big_size += dyst.nundefsym;
8403 if (big_size > nsyms)
8404 outs() << " (past the end of the symbol table)\n";
8405 else
8406 outs() << "\n";
8407 outs() << " tocoff " << dyst.tocoff;
8408 if (dyst.tocoff > object_size)
8409 outs() << " (past end of file)\n";
8410 else
8411 outs() << "\n";
8412 outs() << " ntoc " << dyst.ntoc;
8413 big_size = dyst.ntoc;
8414 big_size *= sizeof(struct MachO::dylib_table_of_contents);
8415 big_size += dyst.tocoff;
8416 if (big_size > object_size)
8417 outs() << " (past end of file)\n";
8418 else
8419 outs() << "\n";
8420 outs() << " modtaboff " << dyst.modtaboff;
8421 if (dyst.modtaboff > object_size)
8422 outs() << " (past end of file)\n";
8423 else
8424 outs() << "\n";
8425 outs() << " nmodtab " << dyst.nmodtab;
8426 uint64_t modtabend;
8427 if (Is64Bit) {
8428 modtabend = dyst.nmodtab;
8429 modtabend *= sizeof(struct MachO::dylib_module_64);
8430 modtabend += dyst.modtaboff;
8431 } else {
8432 modtabend = dyst.nmodtab;
8433 modtabend *= sizeof(struct MachO::dylib_module);
8434 modtabend += dyst.modtaboff;
8435 }
8436 if (modtabend > object_size)
8437 outs() << " (past end of file)\n";
8438 else
8439 outs() << "\n";
8440 outs() << " extrefsymoff " << dyst.extrefsymoff;
8441 if (dyst.extrefsymoff > object_size)
8442 outs() << " (past end of file)\n";
8443 else
8444 outs() << "\n";
8445 outs() << " nextrefsyms " << dyst.nextrefsyms;
8446 big_size = dyst.nextrefsyms;
8447 big_size *= sizeof(struct MachO::dylib_reference);
8448 big_size += dyst.extrefsymoff;
8449 if (big_size > object_size)
8450 outs() << " (past end of file)\n";
8451 else
8452 outs() << "\n";
8453 outs() << " indirectsymoff " << dyst.indirectsymoff;
8454 if (dyst.indirectsymoff > object_size)
8455 outs() << " (past end of file)\n";
8456 else
8457 outs() << "\n";
8458 outs() << " nindirectsyms " << dyst.nindirectsyms;
8459 big_size = dyst.nindirectsyms;
8460 big_size *= sizeof(uint32_t);
8461 big_size += dyst.indirectsymoff;
8462 if (big_size > object_size)
8463 outs() << " (past end of file)\n";
8464 else
8465 outs() << "\n";
8466 outs() << " extreloff " << dyst.extreloff;
8467 if (dyst.extreloff > object_size)
8468 outs() << " (past end of file)\n";
8469 else
8470 outs() << "\n";
8471 outs() << " nextrel " << dyst.nextrel;
8472 big_size = dyst.nextrel;
8473 big_size *= sizeof(struct MachO::relocation_info);
8474 big_size += dyst.extreloff;
8475 if (big_size > object_size)
8476 outs() << " (past end of file)\n";
8477 else
8478 outs() << "\n";
8479 outs() << " locreloff " << dyst.locreloff;
8480 if (dyst.locreloff > object_size)
8481 outs() << " (past end of file)\n";
8482 else
8483 outs() << "\n";
8484 outs() << " nlocrel " << dyst.nlocrel;
8485 big_size = dyst.nlocrel;
8486 big_size *= sizeof(struct MachO::relocation_info);
8487 big_size += dyst.locreloff;
8488 if (big_size > object_size)
8489 outs() << " (past end of file)\n";
8490 else
8491 outs() << "\n";
8492}
8493
8494static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
8495 uint32_t object_size) {
8496 if (dc.cmd == MachO::LC_DYLD_INFO)
8497 outs() << " cmd LC_DYLD_INFO\n";
8498 else
8499 outs() << " cmd LC_DYLD_INFO_ONLY\n";
8500 outs() << " cmdsize " << dc.cmdsize;
8501 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
8502 outs() << " Incorrect size\n";
8503 else
8504 outs() << "\n";
8505 outs() << " rebase_off " << dc.rebase_off;
8506 if (dc.rebase_off > object_size)
8507 outs() << " (past end of file)\n";
8508 else
8509 outs() << "\n";
8510 outs() << " rebase_size " << dc.rebase_size;
8511 uint64_t big_size;
8512 big_size = dc.rebase_off;
8513 big_size += dc.rebase_size;
8514 if (big_size > object_size)
8515 outs() << " (past end of file)\n";
8516 else
8517 outs() << "\n";
8518 outs() << " bind_off " << dc.bind_off;
8519 if (dc.bind_off > object_size)
8520 outs() << " (past end of file)\n";
8521 else
8522 outs() << "\n";
8523 outs() << " bind_size " << dc.bind_size;
8524 big_size = dc.bind_off;
8525 big_size += dc.bind_size;
8526 if (big_size > object_size)
8527 outs() << " (past end of file)\n";
8528 else
8529 outs() << "\n";
8530 outs() << " weak_bind_off " << dc.weak_bind_off;
8531 if (dc.weak_bind_off > object_size)
8532 outs() << " (past end of file)\n";
8533 else
8534 outs() << "\n";
8535 outs() << " weak_bind_size " << dc.weak_bind_size;
8536 big_size = dc.weak_bind_off;
8537 big_size += dc.weak_bind_size;
8538 if (big_size > object_size)
8539 outs() << " (past end of file)\n";
8540 else
8541 outs() << "\n";
8542 outs() << " lazy_bind_off " << dc.lazy_bind_off;
8543 if (dc.lazy_bind_off > object_size)
8544 outs() << " (past end of file)\n";
8545 else
8546 outs() << "\n";
8547 outs() << " lazy_bind_size " << dc.lazy_bind_size;
8548 big_size = dc.lazy_bind_off;
8549 big_size += dc.lazy_bind_size;
8550 if (big_size > object_size)
8551 outs() << " (past end of file)\n";
8552 else
8553 outs() << "\n";
8554 outs() << " export_off " << dc.export_off;
8555 if (dc.export_off > object_size)
8556 outs() << " (past end of file)\n";
8557 else
8558 outs() << "\n";
8559 outs() << " export_size " << dc.export_size;
8560 big_size = dc.export_off;
8561 big_size += dc.export_size;
8562 if (big_size > object_size)
8563 outs() << " (past end of file)\n";
8564 else
8565 outs() << "\n";
8566}
8567
8568static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
8569 const char *Ptr) {
8570 if (dyld.cmd == MachO::LC_ID_DYLINKER)
8571 outs() << " cmd LC_ID_DYLINKER\n";
8572 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
8573 outs() << " cmd LC_LOAD_DYLINKER\n";
8574 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
8575 outs() << " cmd LC_DYLD_ENVIRONMENT\n";
8576 else
8577 outs() << " cmd ?(" << dyld.cmd << ")\n";
8578 outs() << " cmdsize " << dyld.cmdsize;
8579 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
8580 outs() << " Incorrect size\n";
8581 else
8582 outs() << "\n";
8583 if (dyld.name >= dyld.cmdsize)
8584 outs() << " name ?(bad offset " << dyld.name << ")\n";
8585 else {
8586 const char *P = (const char *)(Ptr) + dyld.name;
8587 outs() << " name " << P << " (offset " << dyld.name << ")\n";
8588 }
8589}
8590
8591static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
8592 outs() << " cmd LC_UUID\n";
8593 outs() << " cmdsize " << uuid.cmdsize;
8594 if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
8595 outs() << " Incorrect size\n";
8596 else
8597 outs() << "\n";
8598 outs() << " uuid ";
8599 for (int i = 0; i < 16; ++i) {
8600 outs() << format("%02" PRIX32"X", uuid.uuid[i]);
8601 if (i == 3 || i == 5 || i == 7 || i == 9)
8602 outs() << "-";
8603 }
8604 outs() << "\n";
8605}
8606
8607static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
8608 outs() << " cmd LC_RPATH\n";
8609 outs() << " cmdsize " << rpath.cmdsize;
8610 if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
8611 outs() << " Incorrect size\n";
8612 else
8613 outs() << "\n";
8614 if (rpath.path >= rpath.cmdsize)
8615 outs() << " path ?(bad offset " << rpath.path << ")\n";
8616 else {
8617 const char *P = (const char *)(Ptr) + rpath.path;
8618 outs() << " path " << P << " (offset " << rpath.path << ")\n";
8619 }
8620}
8621
8622static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
8623 StringRef LoadCmdName;
8624 switch (vd.cmd) {
8625 case MachO::LC_VERSION_MIN_MACOSX:
8626 LoadCmdName = "LC_VERSION_MIN_MACOSX";
8627 break;
8628 case MachO::LC_VERSION_MIN_IPHONEOS:
8629 LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
8630 break;
8631 case MachO::LC_VERSION_MIN_TVOS:
8632 LoadCmdName = "LC_VERSION_MIN_TVOS";
8633 break;
8634 case MachO::LC_VERSION_MIN_WATCHOS:
8635 LoadCmdName = "LC_VERSION_MIN_WATCHOS";
8636 break;
8637 default:
8638 llvm_unreachable("Unknown version min load command")::llvm::llvm_unreachable_internal("Unknown version min load command"
, "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-objdump/MachODump.cpp"
, 8638)
;
8639 }
8640
8641 outs() << " cmd " << LoadCmdName << '\n';
8642 outs() << " cmdsize " << vd.cmdsize;
8643 if (vd.cmdsize != sizeof(struct MachO::version_min_command))
8644 outs() << " Incorrect size\n";
8645 else
8646 outs() << "\n";
8647 outs() << " version "
8648 << MachOObjectFile::getVersionMinMajor(vd, false) << "."
8649 << MachOObjectFile::getVersionMinMinor(vd, false);
8650 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
8651 if (Update != 0)
8652 outs() << "." << Update;
8653 outs() << "\n";
8654 if (vd.sdk == 0)
8655 outs() << " sdk n/a";
8656 else {
8657 outs() << " sdk "
8658 << MachOObjectFile::getVersionMinMajor(vd, true) << "."
8659 << MachOObjectFile::getVersionMinMinor(vd, true);
8660 }
8661 Update = MachOObjectFile::getVersionMinUpdate(vd, true);
8662 if (Update != 0)
8663 outs() << "." << Update;
8664 outs() << "\n";
8665}
8666
8667static void PrintNoteLoadCommand(MachO::note_command Nt) {
8668 outs() << " cmd LC_NOTE\n";
8669 outs() << " cmdsize " << Nt.cmdsize;
8670 if (Nt.cmdsize != sizeof(struct MachO::note_command))
8671 outs() << " Incorrect size\n";
8672 else
8673 outs() << "\n";
8674 const char *d = Nt.data_owner;
8675 outs() << "data_owner " << format("%.16s\n", d);
8676 outs() << " offset " << Nt.offset << "\n";
8677 outs() << " size " << Nt.size << "\n";
8678}
8679
8680static void PrintBuildToolVersion(MachO::build_tool_version bv) {
8681 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n";
8682 outs() << " version " << MachOObjectFile::getVersionString(bv.version)
8683 << "\n";
8684}
8685
8686static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
8687 MachO::build_version_command bd) {
8688 outs() << " cmd LC_BUILD_VERSION\n";
8689 outs() << " cmdsize " << bd.cmdsize;
8690 if (bd.cmdsize !=
8691 sizeof(struct MachO::build_version_command) +
8692 bd.ntools * sizeof(struct MachO::build_tool_version))
8693 outs() << " Incorrect size\n";
8694 else
8695 outs() << "\n";
8696 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform)
8697 << "\n";
8698 if (bd.sdk)
8699 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk)
8700 << "\n";
8701 else
8702 outs() << " sdk n/a\n";
8703 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos)
8704 << "\n";
8705 outs() << " ntools " << bd.ntools << "\n";
8706 for (unsigned i = 0; i < bd.ntools; ++i) {
8707 MachO::build_tool_version bv = obj->getBuildToolVersion(i);
8708 PrintBuildToolVersion(bv);
8709 }
8710}
8711
8712static void PrintSourceVersionCommand(MachO::source_version_command sd) {
8713 outs() << " cmd LC_SOURCE_VERSION\n";
8714 outs() << " cmdsize " << sd.cmdsize;
8715 if (sd.cmdsize != sizeof(struct MachO::source_version_command))
8716 outs() << " Incorrect size\n";
8717 else
8718 outs() << "\n";
8719 uint64_t a = (sd.version >> 40) & 0xffffff;
8720 uint64_t b = (sd.version >> 30) & 0x3ff;
8721 uint64_t c = (sd.version >> 20) & 0x3ff;
8722 uint64_t d = (sd.version >> 10) & 0x3ff;
8723 uint64_t e = sd.version & 0x3ff;
8724 outs() << " version " << a << "." << b;
8725 if (e != 0)
8726 outs() << "." << c << "." << d << "." << e;
8727 else if (d != 0)
8728 outs() << "." << c << "." << d;
8729 else if (c != 0)
8730 outs() << "." << c;
8731 outs() << "\n";
8732}
8733
8734static void PrintEntryPointCommand(MachO::entry_point_command ep) {
8735 outs() << " cmd LC_MAIN\n";
8736 outs() << " cmdsize " << ep.cmdsize;
8737 if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
8738 outs() << " Incorrect size\n";
8739 else
8740 outs() << "\n";
8741 outs() << " entryoff " << ep.entryoff << "\n";
8742 outs() << " stacksize " << ep.stacksize << "\n";
8743}
8744
8745static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
8746 uint32_t object_size) {
8747 outs() << " cmd LC_ENCRYPTION_INFO\n";
8748 outs() << " cmdsize " << ec.cmdsize;
8749 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
8750 outs() << " Incorrect size\n";
8751 else
8752 outs() << "\n";
8753 outs() << " cryptoff " << ec.cryptoff;
8754 if (ec.cryptoff > object_size)
8755 outs() << " (past end of file)\n";
8756 else
8757 outs() << "\n";
8758 outs() << " cryptsize " << ec.cryptsize;
8759 if (ec.cryptsize > object_size)
8760 outs() << " (past end of file)\n";
8761 else
8762 outs() << "\n";
8763 outs() << " cryptid " << ec.cryptid << "\n";
8764}
8765
8766static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
8767 uint32_t object_size) {
8768 outs() << " cmd LC_ENCRYPTION_INFO_64\n";
8769 outs() << " cmdsize " << ec.cmdsize;
8770 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
8771 outs() << " Incorrect size\n";
8772 else
8773 outs() << "\n";
8774 outs() << " cryptoff " << ec.cryptoff;
8775 if (ec.cryptoff > object_size)
8776 outs() << " (past end of file)\n";
8777 else
8778 outs() << "\n";
8779 outs() << " cryptsize " << ec.cryptsize;
8780 if (ec.cryptsize > object_size)
8781 outs() << " (past end of file)\n";
8782 else
8783 outs() << "\n";
8784 outs() << " cryptid " << ec.cryptid << "\n";
8785 outs() << " pad " << ec.pad << "\n";
8786}
8787
8788static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
8789 const char *Ptr) {
8790 outs() << " cmd LC_LINKER_OPTION\n";
8791 outs() << " cmdsize " << lo.cmdsize;
8792 if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
8793 outs() << " Incorrect size\n";
8794 else
8795 outs() << "\n";
8796 outs() << " count " << lo.count << "\n";
8797 const char *string = Ptr + sizeof(struct MachO::linker_option_command);
8798 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
8799 uint32_t i = 0;
8800 while (left > 0) {
8801 while (*string == '\0' && left > 0) {
8802 string++;
8803 left--;
8804 }
8805 if (left > 0) {
8806 i++;
8807 outs() << " string #" << i << " " << format("%.*s\n", left, string);
8808 uint32_t NullPos = StringRef(string, left).find('\0');
8809 uint32_t len = std::min(NullPos, left) + 1;
8810 string += len;
8811 left -= len;
8812 }
8813 }
8814 if (lo.count != i)
8815 outs() << " count " << lo.count << " does not match number of strings "
8816 << i << "\n";
8817}
8818
8819static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
8820 const char *Ptr) {
8821 outs() << " cmd LC_SUB_FRAMEWORK\n";
8822 outs() << " cmdsize " << sub.cmdsize;
8823 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
8824 outs() << " Incorrect size\n";
8825 else
8826 outs() << "\n";
8827 if (sub.umbrella < sub.cmdsize) {
8828 const char *P = Ptr + sub.umbrella;
8829 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n";
8830 } else {
8831 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n";
8832 }
8833}
8834
8835static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
8836 const char *Ptr) {
8837 outs() << " cmd LC_SUB_UMBRELLA\n";
8838 outs() << " cmdsize " << sub.cmdsize;
8839 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
8840 outs() << " Incorrect size\n";
8841 else
8842 outs() << "\n";
8843 if (sub.sub_umbrella < sub.cmdsize) {
8844 const char *P = Ptr + sub.sub_umbrella;
8845 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
8846 } else {
8847 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
8848 }
8849}
8850
8851static void PrintSubLibraryCommand(MachO::sub_library_command sub,
8852 const char *Ptr) {
8853 outs() << " cmd LC_SUB_LIBRARY\n";
8854 outs() << " cmdsize " << sub.cmdsize;
8855 if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
8856 outs() << " Incorrect size\n";
8857 else
8858 outs() << "\n";
8859 if (sub.sub_library < sub.cmdsize) {
8860 const char *P = Ptr + sub.sub_library;
8861 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n";
8862 } else {
8863 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n";
8864 }
8865}
8866
8867static void PrintSubClientCommand(MachO::sub_client_command sub,
8868 const char *Ptr) {
8869 outs() << " cmd LC_SUB_CLIENT\n";
8870 outs() << " cmdsize " << sub.cmdsize;
8871 if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
8872 outs() << " Incorrect size\n";
8873 else
8874 outs() << "\n";
8875 if (sub.client < sub.cmdsize) {
8876 const char *P = Ptr + sub.client;
8877 outs() << " client " << P << " (offset " << sub.client << ")\n";
8878 } else {
8879 outs() << " client ?(bad offset " << sub.client << ")\n";
8880 }
8881}
8882
8883static void PrintRoutinesCommand(MachO::routines_command r) {
8884 outs() << " cmd LC_ROUTINES\n";
8885 outs() << " cmdsize " << r.cmdsize;
8886 if (r.cmdsize != sizeof(struct MachO::routines_command))
8887 outs() << " Incorrect size\n";
8888 else
8889 outs() << "\n";
8890 outs() << " init_address " << format("0x%08" PRIx32"x", r.init_address) << "\n";
8891 outs() << " init_module " << r.init_module << "\n";
8892 outs() << " reserved1 " << r.reserved1 << "\n";
8893 outs() << " reserved2 " << r.reserved2 << "\n";
8894 outs() << " reserved3 " << r.reserved3 << "\n";
8895 outs() << " reserved4 " << r.reserved4 << "\n";
8896 outs() << " reserved5 " << r.reserved5 << "\n";
8897 outs() << " reserved6 " << r.reserved6 << "\n";
8898}
8899
8900static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
8901 outs() << " cmd LC_ROUTINES_64\n";
8902 outs() << " cmdsize " << r.cmdsize;
8903 if (r.cmdsize != sizeof(struct MachO::routines_command_64))
8904 outs() << " Incorrect size\n";
8905 else
8906 outs() << "\n";
8907 outs() << " init_address " << format("0x%016" PRIx64"l" "x", r.init_address) << "\n";
8908 outs() << " init_module " << r.init_module << "\n";
8909 outs() << " reserved1 " << r.reserved1 << "\n";
8910 outs() << " reserved2 " << r.reserved2 << "\n";
8911 outs() << " reserved3 " << r.reserved3 << "\n";
8912 outs() << " reserved4 " << r.reserved4 << "\n";
8913 outs() << " reserved5 " << r.reserved5 << "\n";
8914 outs() << " reserved6 " << r.reserved6 << "\n";
8915}
8916
8917static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
8918 outs() << "\t eax " << format("0x%08" PRIx32"x", cpu32.eax);
8919 outs() << " ebx " << format("0x%08" PRIx32"x", cpu32.ebx);
8920 outs() << " ecx " << format("0x%08" PRIx32"x", cpu32.ecx);
8921 outs() << " edx " << format("0x%08" PRIx32"x", cpu32.edx) << "\n";
8922 outs() << "\t edi " << format("0x%08" PRIx32"x", cpu32.edi);
8923 outs() << " esi " << format("0x%08" PRIx32"x", cpu32.esi);
8924 outs() << " ebp " << format("0x%08" PRIx32"x", cpu32.ebp);
8925 outs() << " esp " << format("0x%08" PRIx32"x", cpu32.esp) << "\n";
8926 outs() << "\t ss " << format("0x%08" PRIx32"x", cpu32.ss);
8927 outs() << " eflags " << format("0x%08" PRIx32"x", cpu32.eflags);
8928 outs() << " eip " << format("0x%08" PRIx32"x", cpu32.eip);
8929 outs() << " cs " << format("0x%08" PRIx32"x", cpu32.cs) << "\n";
8930 outs() << "\t ds " << format("0x%08" PRIx32"x", cpu32.ds);
8931 outs() << " es " << format("0x%08" PRIx32"x", cpu32.es);
8932 outs() << " fs " << format("0x%08" PRIx32"x", cpu32.fs);
8933 outs() << " gs " << format("0x%08" PRIx32"x", cpu32.gs) << "\n";
8934}
8935
8936static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
8937 outs() << " rax " << format("0x%016" PRIx64"l" "x", cpu64.rax);
8938 outs() << " rbx " << format("0x%016" PRIx64"l" "x", cpu64.rbx);
8939 outs() << " rcx " << format("0x%016" PRIx64"l" "x", cpu64.rcx) << "\n";
8940 outs() << " rdx " << format("0x%016" PRIx64"l" "x", cpu64.rdx);
8941 outs() << " rdi " << format("0x%016" PRIx64"l" "x", cpu64.rdi);
8942 outs() << " rsi " << format("0x%016" PRIx64"l" "x", cpu64.rsi) << "\n";
8943 outs() << " rbp " << format("0x%016" PRIx64"l" "x", cpu64.rbp);
8944 outs() << " rsp " << format("0x%016" PRIx64"l" "x", cpu64.rsp);
8945 outs() << " r8 " << format("0x%016" PRIx64"l" "x", cpu64.r8) << "\n";
8946 outs() << " r9 " << format("0x%016" PRIx64"l" "x", cpu64.r9);
8947 outs() << " r10 " << format("0x%016" PRIx64"l" "x", cpu64.r10);
8948 outs() << " r11 " << format("0x%016" PRIx64"l" "x", cpu64.r11) << "\n";
8949 outs() << " r12 " << format("0x%016" PRIx64"l" "x", cpu64.r12);
8950 outs() << " r13 " << format("0x%016" PRIx64"l" "x", cpu64.r13);
8951 outs() << " r14 " << format("0x%016" PRIx64"l" "x", cpu64.r14) << "\n";
8952 outs() << " r15 " << format("0x%016" PRIx64"l" "x", cpu64.r15);
8953 outs() << " rip " << format("0x%016" PRIx64"l" "x", cpu64.rip) << "\n";
8954 outs() << "rflags " << format("0x%016" PRIx64"l" "x", cpu64.rflags);
8955 outs() << " cs " << format("0x%016" PRIx64"l" "x", cpu64.cs);
8956 outs() << " fs " << format("0x%016" PRIx64"l" "x", cpu64.fs) << "\n";
8957 outs() << " gs " << format("0x%016" PRIx64"l" "x", cpu64.gs) << "\n";
8958}
8959
8960static void Print_mmst_reg(MachO::mmst_reg_t &r) {
8961 uint32_t f;
8962 outs() << "\t mmst_reg ";
8963 for (f = 0; f < 10; f++)
8964 outs() << format("%02" PRIx32"x", (r.mmst_reg[f] & 0xff)) << " ";
8965 outs() << "\n";
8966 outs() << "\t mmst_rsrv ";
8967 for (f = 0; f < 6; f++)
8968 outs() << format("%02" PRIx32"x", (r.mmst_rsrv[f] & 0xff)) << " ";
8969 outs() << "\n";
8970}
8971
8972static void Print_xmm_reg(MachO::xmm_reg_t &r) {
8973 uint32_t f;
8974 outs() << "\t xmm_reg ";
8975 for (f = 0; f < 16; f++)
8976 outs() << format("%02" PRIx32"x", (r.xmm_reg[f] & 0xff)) << " ";
8977 outs() << "\n";
8978}
8979
8980static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
8981 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0];
8982 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
8983 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid;
8984 outs() << " denorm " << fpu.fpu_fcw.denorm;
8985 outs() << " zdiv " << fpu.fpu_fcw.zdiv;
8986 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
8987 outs() << " undfl " << fpu.fpu_fcw.undfl;
8988 outs() << " precis " << fpu.fpu_fcw.precis << "\n";
8989 outs() << "\t\t pc ";
8990 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
8991 outs() << "FP_PREC_24B ";
8992 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
8993 outs() << "FP_PREC_53B ";
8994 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
8995 outs() << "FP_PREC_64B ";
8996 else
8997 outs() << fpu.fpu_fcw.pc << " ";
8998 outs() << "rc ";
8999 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
9000 outs() << "FP_RND_NEAR ";
9001 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
9002 outs() << "FP_RND_DOWN ";
9003 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
9004 outs() << "FP_RND_UP ";
9005 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
9006 outs() << "FP_CHOP ";
9007 outs() << "\n";
9008 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid;
9009 outs() << " denorm " << fpu.fpu_fsw.denorm;
9010 outs() << " zdiv " << fpu.fpu_fsw.zdiv;
9011 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
9012 outs() << " undfl " << fpu.fpu_fsw.undfl;
9013 outs() << " precis " << fpu.fpu_fsw.precis;
9014 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
9015 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm;
9016 outs() << " c0 " << fpu.fpu_fsw.c0;
9017 outs() << " c1 " << fpu.fpu_fsw.c1;
9018 outs() << " c2 " << fpu.fpu_fsw.c2;
9019 outs() << " tos " << fpu.fpu_fsw.tos;
9020 outs() << " c3 " << fpu.fpu_fsw.c3;
9021 outs() << " busy " << fpu.fpu_fsw.busy << "\n";
9022 outs() << "\t fpu_ftw " << format("0x%02" PRIx32"x", fpu.fpu_ftw);
9023 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32"x", fpu.fpu_rsrv1);
9024 outs() << " fpu_fop " << format("0x%04" PRIx32"x", fpu.fpu_fop);
9025 outs() << " fpu_ip " << format("0x%08" PRIx32"x", fpu.fpu_ip) << "\n";
9026 outs() << "\t fpu_cs " << format("0x%04" PRIx32"x", fpu.fpu_cs);
9027 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32"x", fpu.fpu_rsrv2);
9028 outs() << " fpu_dp " << format("0x%08" PRIx32"x", fpu.fpu_dp);
9029 outs() << " fpu_ds " << format("0x%04" PRIx32"x", fpu.fpu_ds) << "\n";
9030 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32"x", fpu.fpu_rsrv3);
9031 outs() << " fpu_mxcsr " << format("0x%08" PRIx32"x", fpu.fpu_mxcsr);
9032 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32"x", fpu.fpu_mxcsrmask);
9033 outs() << "\n";
9034 outs() << "\t fpu_stmm0:\n";
9035 Print_mmst_reg(fpu.fpu_stmm0);
9036 outs() << "\t fpu_stmm1:\n";
9037 Print_mmst_reg(fpu.fpu_stmm1);
9038 outs() << "\t fpu_stmm2:\n";
9039 Print_mmst_reg(fpu.fpu_stmm2);
9040 outs() << "\t fpu_stmm3:\n";
9041 Print_mmst_reg(fpu.fpu_stmm3);
9042 outs() << "\t fpu_stmm4:\n";
9043 Print_mmst_reg(fpu.fpu_stmm4);
9044 outs() << "\t fpu_stmm5:\n";
9045 Print_mmst_reg(fpu.fpu_stmm5);
9046 outs() << "\t fpu_stmm6:\n";
9047 Print_mmst_reg(fpu.fpu_stmm6);
9048 outs() << "\t fpu_stmm7:\n";
9049 Print_mmst_reg(fpu.fpu_stmm7);
9050 outs() << "\t fpu_xmm0:\n";
9051 Print_xmm_reg(fpu.fpu_xmm0);
9052 outs() << "\t fpu_xmm1:\n";
9053 Print_xmm_reg(fpu.fpu_xmm1);
9054 outs() << "\t fpu_xmm2:\n";
9055 Print_xmm_reg(fpu.fpu_xmm2);
9056 outs() << "\t fpu_xmm3:\n";
9057 Print_xmm_reg(fpu.fpu_xmm3);
9058 outs() << "\t fpu_xmm4:\n";
9059 Print_xmm_reg(fpu.fpu_xmm4);
9060 outs() << "\t fpu_xmm5:\n";
9061 Print_xmm_reg(fpu.fpu_xmm5);
9062 outs() << "\t fpu_xmm6:\n";
9063 Print_xmm_reg(fpu.fpu_xmm6);
9064 outs() << "\t fpu_xmm7:\n";
9065 Print_xmm_reg(fpu.fpu_xmm7);
9066 outs() << "\t fpu_xmm8:\n";
9067 Print_xmm_reg(fpu.fpu_xmm8);
9068 outs() << "\t fpu_xmm9:\n";
9069 Print_xmm_reg(fpu.fpu_xmm9);
9070 outs() << "\t fpu_xmm10:\n";
9071 Print_xmm_reg(fpu.fpu_xmm10);
9072 outs() << "\t fpu_xmm11:\n";
9073 Print_xmm_reg(fpu.fpu_xmm11);
9074 outs() << "\t fpu_xmm12:\n";
9075 Print_xmm_reg(fpu.fpu_xmm12);
9076 outs() << "\t fpu_xmm13:\n";
9077 Print_xmm_reg(fpu.fpu_xmm13);
9078 outs() << "\t fpu_xmm14:\n";
9079 Print_xmm_reg(fpu.fpu_xmm14);
9080 outs() << "\t fpu_xmm15:\n";
9081 Print_xmm_reg(fpu.fpu_xmm15);
9082 outs() << "\t fpu_rsrv4:\n";
9083 for (uint32_t f = 0; f < 6; f++) {
9084 outs() << "\t ";
9085 for (uint32_t g = 0; g < 16; g++)
9086 outs() << format("%02" PRIx32"x", fpu.fpu_rsrv4[f * g]) << " ";
9087 outs() << "\n";
9088 }
9089 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32"x", fpu.fpu_reserved1);
9090 outs() << "\n";
9091}
9092
9093static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
9094 outs() << "\t trapno " << format("0x%08" PRIx32"x", exc64.trapno);
9095 outs() << " err " << format("0x%08" PRIx32"x", exc64.err);
9096 outs() << " faultvaddr " << format("0x%016" PRIx64"l" "x", exc64.faultvaddr) << "\n";
9097}
9098
9099static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
9100 outs() << "\t r0 " << format("0x%08" PRIx32"x", cpu32.r[0]);
9101 outs() << " r1 " << format("0x%08" PRIx32"x", cpu32.r[1]);
9102 outs() << " r2 " << format("0x%08" PRIx32"x", cpu32.r[2]);
9103 outs() << " r3 " << format("0x%08" PRIx32"x", cpu32.r[3]) << "\n";
9104 outs() << "\t r4 " << format("0x%08" PRIx32"x", cpu32.r[4]);
9105 outs() << " r5 " << format("0x%08" PRIx32"x", cpu32.r[5]);
9106 outs() << " r6 " << format("0x%08" PRIx32"x", cpu32.r[6]);
9107 outs() << " r7 " << format("0x%08" PRIx32"x", cpu32.r[7]) << "\n";
9108 outs() << "\t r8 " << format("0x%08" PRIx32"x", cpu32.r[8]);
9109 outs() << " r9 " << format("0x%08" PRIx32"x", cpu32.r[9]);
9110 outs() << " r10 " << format("0x%08" PRIx32"x", cpu32.r[10]);
9111 outs() << " r11 " << format("0x%08" PRIx32"x", cpu32.r[11]) << "\n";
9112 outs() << "\t r12 " << format("0x%08" PRIx32"x", cpu32.r[12]);
9113 outs() << " sp " << format("0x%08" PRIx32"x", cpu32.sp);
9114 outs() << " lr " << format("0x%08" PRIx32"x", cpu32.lr);
9115 outs() << " pc " << format("0x%08" PRIx32"x", cpu32.pc) << "\n";
9116 outs() << "\t cpsr " << format("0x%08" PRIx32"x", cpu32.cpsr) << "\n";
9117}
9118
9119static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
9120 outs() << "\t x0 " << format("0x%016" PRIx64"l" "x", cpu64.x[0]);
9121 outs() << " x1 " << format("0x%016" PRIx64"l" "x", cpu64.x[1]);
9122 outs() << " x2 " << format("0x%016" PRIx64"l" "x", cpu64.x[2]) << "\n";
9123 outs() << "\t x3 " << format("0x%016" PRIx64"l" "x", cpu64.x[3]);
9124 outs() << " x4 " << format("0x%016" PRIx64"l" "x", cpu64.x[4]);
9125 outs() << " x5 " << format("0x%016" PRIx64"l" "x", cpu64.x[5]) << "\n";
9126 outs() << "\t x6 " << format("0x%016" PRIx64"l" "x", cpu64.x[6]);
9127 outs() << " x7 " << format("0x%016" PRIx64"l" "x", cpu64.x[7]);
9128 outs() << " x8 " << format("0x%016" PRIx64"l" "x", cpu64.x[8]) << "\n";
9129 outs() << "\t x9 " << format("0x%016" PRIx64"l" "x", cpu64.x[9]);
9130 outs() << " x10 " << format("0x%016" PRIx64"l" "x", cpu64.x[10]);
9131 outs() << " x11 " << format("0x%016" PRIx64"l" "x", cpu64.x[11]) << "\n";
9132 outs() << "\t x12 " << format("0x%016" PRIx64"l" "x", cpu64.x[12]);
9133 outs() << " x13 " << format("0x%016" PRIx64"l" "x", cpu64.x[13]);
9134 outs() << " x14 " << format("0x%016" PRIx64"l" "x", cpu64.x[14]) << "\n";
9135 outs() << "\t x15 " << format("0x%016" PRIx64"l" "x", cpu64.x[15]);
9136 outs() << " x16 " << format("0x%016" PRIx64"l" "x", cpu64.x[16]);
9137 outs() << " x17 " << format("0x%016" PRIx64"l" "x", cpu64.x[17]) << "\n";
9138 outs() << "\t x18 " << format("0x%016" PRIx64"l" "x", cpu64.x[18]);
9139 outs() << " x19 " << format("0x%016" PRIx64"l" "x", cpu64.x[19]);
9140 outs() << " x20 " << format("0x%016" PRIx64"l" "x", cpu64.x[20]) << "\n";
9141 outs() << "\t x21 " << format("0x%016" PRIx64"l" "x", cpu64.x[21]);
9142 outs() << " x22 " << format("0x%016" PRIx64"l" "x", cpu64.x[22]);
9143 outs() << " x23 " << format("0x%016" PRIx64"l" "x", cpu64.x[23]) << "\n";
9144 outs() << "\t x24 " << format("0x%016" PRIx64"l" "x", cpu64.x[24]);
9145 outs() << " x25 " << format("0x%016" PRIx64"l" "x", cpu64.x[25]);
9146 outs() << " x26 " << format("0x%016" PRIx64"l" "x", cpu64.x[26]) << "\n";
9147 outs() << "\t x27 " << format("0x%016" PRIx64"l" "x", cpu64.x[27]);
9148 outs() << " x28 " << format("0x%016" PRIx64"l" "x", cpu64.x[28]);
9149 outs() << " fp " << format("0x%016" PRIx64"l" "x", cpu64.fp) << "\n";
9150 outs() << "\t lr " << format("0x%016" PRIx64"l" "x", cpu64.lr);
9151 outs() << " sp " << format("0x%016" PRIx64"l" "x", cpu64.sp);
9152 outs() << " pc " << format("0x%016" PRIx64"l" "x", cpu64.pc) << "\n";
9153 outs() << "\t cpsr " << format("0x%08" PRIx32"x", cpu64.cpsr) << "\n";
9154}
9155
9156static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
9157 bool isLittleEndian, uint32_t cputype) {
9158 if (t.cmd == MachO::LC_THREAD)
9159 outs() << " cmd LC_THREAD\n";
9160 else if (t.cmd == MachO::LC_UNIXTHREAD)
9161 outs() << " cmd LC_UNIXTHREAD\n";
9162 else
9163 outs() << " cmd " << t.cmd << " (unknown)\n";
9164 outs() << " cmdsize " << t.cmdsize;
9165 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
9166 outs() << " Incorrect size\n";
9167 else
9168 outs() << "\n";
9169
9170 const char *begin = Ptr + sizeof(struct MachO::thread_command);
9171 const char *end = Ptr + t.cmdsize;
9172 uint32_t flavor, count, left;
9173 if (cputype == MachO::CPU_TYPE_I386) {
9174 while (begin < end) {
9175 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9176 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9177 begin += sizeof(uint32_t);
9178 } else {
9179 flavor = 0;
9180 begin = end;
9181 }
9182 if (isLittleEndian != sys::IsLittleEndianHost)
9183 sys::swapByteOrder(flavor);
9184 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9185 memcpy((char *)&count, begin, sizeof(uint32_t));
9186 begin += sizeof(uint32_t);
9187 } else {
9188 count = 0;
9189 begin = end;
9190 }
9191 if (isLittleEndian != sys::IsLittleEndianHost)
9192 sys::swapByteOrder(count);
9193 if (flavor == MachO::x86_THREAD_STATE32) {
9194 outs() << " flavor i386_THREAD_STATE\n";
9195 if (count == MachO::x86_THREAD_STATE32_COUNT)
9196 outs() << " count i386_THREAD_STATE_COUNT\n";
9197 else
9198 outs() << " count " << count
9199 << " (not x86_THREAD_STATE32_COUNT)\n";
9200 MachO::x86_thread_state32_t cpu32;
9201 left = end - begin;
9202 if (left >= sizeof(MachO::x86_thread_state32_t)) {
9203 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
9204 begin += sizeof(MachO::x86_thread_state32_t);
9205 } else {
9206 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
9207 memcpy(&cpu32, begin, left);
9208 begin += left;
9209 }
9210 if (isLittleEndian != sys::IsLittleEndianHost)
9211 swapStruct(cpu32);
9212 Print_x86_thread_state32_t(cpu32);
9213 } else if (flavor == MachO::x86_THREAD_STATE) {
9214 outs() << " flavor x86_THREAD_STATE\n";
9215 if (count == MachO::x86_THREAD_STATE_COUNT)
9216 outs() << " count x86_THREAD_STATE_COUNT\n";
9217 else
9218 outs() << " count " << count
9219 << " (not x86_THREAD_STATE_COUNT)\n";
9220 struct MachO::x86_thread_state_t ts;
9221 left = end - begin;
9222 if (left >= sizeof(MachO::x86_thread_state_t)) {
9223 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9224 begin += sizeof(MachO::x86_thread_state_t);
9225 } else {
9226 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9227 memcpy(&ts, begin, left);
9228 begin += left;
9229 }
9230 if (isLittleEndian != sys::IsLittleEndianHost)
9231 swapStruct(ts);
9232 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
9233 outs() << "\t tsh.flavor x86_THREAD_STATE32 ";
9234 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
9235 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
9236 else
9237 outs() << "tsh.count " << ts.tsh.count
9238 << " (not x86_THREAD_STATE32_COUNT\n";
9239 Print_x86_thread_state32_t(ts.uts.ts32);
9240 } else {
9241 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count "
9242 << ts.tsh.count << "\n";
9243 }
9244 } else {
9245 outs() << " flavor " << flavor << " (unknown)\n";
9246 outs() << " count " << count << "\n";
9247 outs() << " state (unknown)\n";
9248 begin += count * sizeof(uint32_t);
9249 }
9250 }
9251 } else if (cputype == MachO::CPU_TYPE_X86_64) {
9252 while (begin < end) {
9253 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9254 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9255 begin += sizeof(uint32_t);
9256 } else {
9257 flavor = 0;
9258 begin = end;
9259 }
9260 if (isLittleEndian != sys::IsLittleEndianHost)
9261 sys::swapByteOrder(flavor);
9262 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9263 memcpy((char *)&count, begin, sizeof(uint32_t));
9264 begin += sizeof(uint32_t);
9265 } else {
9266 count = 0;
9267 begin = end;
9268 }
9269 if (isLittleEndian != sys::IsLittleEndianHost)
9270 sys::swapByteOrder(count);
9271 if (flavor == MachO::x86_THREAD_STATE64) {
9272 outs() << " flavor x86_THREAD_STATE64\n";
9273 if (count == MachO::x86_THREAD_STATE64_COUNT)
9274 outs() << " count x86_THREAD_STATE64_COUNT\n";
9275 else
9276 outs() << " count " << count
9277 << " (not x86_THREAD_STATE64_COUNT)\n";
9278 MachO::x86_thread_state64_t cpu64;
9279 left = end - begin;
9280 if (left >= sizeof(MachO::x86_thread_state64_t)) {
9281 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
9282 begin += sizeof(MachO::x86_thread_state64_t);
9283 } else {
9284 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
9285 memcpy(&cpu64, begin, left);
9286 begin += left;
9287 }
9288 if (isLittleEndian != sys::IsLittleEndianHost)
9289 swapStruct(cpu64);
9290 Print_x86_thread_state64_t(cpu64);
9291 } else if (flavor == MachO::x86_THREAD_STATE) {
9292 outs() << " flavor x86_THREAD_STATE\n";
9293 if (count == MachO::x86_THREAD_STATE_COUNT)
9294 outs() << " count x86_THREAD_STATE_COUNT\n";
9295 else
9296 outs() << " count " << count
9297 << " (not x86_THREAD_STATE_COUNT)\n";
9298 struct MachO::x86_thread_state_t ts;
9299 left = end - begin;
9300 if (left >= sizeof(MachO::x86_thread_state_t)) {
9301 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9302 begin += sizeof(MachO::x86_thread_state_t);
9303 } else {
9304 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9305 memcpy(&ts, begin, left);
9306 begin += left;
9307 }
9308 if (isLittleEndian != sys::IsLittleEndianHost)
9309 swapStruct(ts);
9310 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
9311 outs() << "\t tsh.flavor x86_THREAD_STATE64 ";
9312 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
9313 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
9314 else
9315 outs() << "tsh.count " << ts.tsh.count
9316 << " (not x86_THREAD_STATE64_COUNT\n";
9317 Print_x86_thread_state64_t(ts.uts.ts64);
9318 } else {
9319 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count "
9320 << ts.tsh.count << "\n";
9321 }
9322 } else if (flavor == MachO::x86_FLOAT_STATE) {
9323 outs() << " flavor x86_FLOAT_STATE\n";
9324 if (count == MachO::x86_FLOAT_STATE_COUNT)
9325 outs() << " count x86_FLOAT_STATE_COUNT\n";
9326 else
9327 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
9328 struct MachO::x86_float_state_t fs;
9329 left = end - begin;
9330 if (left >= sizeof(MachO::x86_float_state_t)) {
9331 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
9332 begin += sizeof(MachO::x86_float_state_t);
9333 } else {
9334 memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
9335 memcpy(&fs, begin, left);
9336 begin += left;
9337 }
9338 if (isLittleEndian != sys::IsLittleEndianHost)
9339 swapStruct(fs);
9340 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
9341 outs() << "\t fsh.flavor x86_FLOAT_STATE64 ";
9342 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
9343 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
9344 else
9345 outs() << "fsh.count " << fs.fsh.count
9346 << " (not x86_FLOAT_STATE64_COUNT\n";
9347 Print_x86_float_state_t(fs.ufs.fs64);
9348 } else {
9349 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count "
9350 << fs.fsh.count << "\n";
9351 }
9352 } else if (flavor == MachO::x86_EXCEPTION_STATE) {
9353 outs() << " flavor x86_EXCEPTION_STATE\n";
9354 if (count == MachO::x86_EXCEPTION_STATE_COUNT)
9355 outs() << " count x86_EXCEPTION_STATE_COUNT\n";
9356 else
9357 outs() << " count " << count
9358 << " (not x86_EXCEPTION_STATE_COUNT)\n";
9359 struct MachO::x86_exception_state_t es;
9360 left = end - begin;
9361 if (left >= sizeof(MachO::x86_exception_state_t)) {
9362 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
9363 begin += sizeof(MachO::x86_exception_state_t);
9364 } else {
9365 memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
9366 memcpy(&es, begin, left);
9367 begin += left;
9368 }
9369 if (isLittleEndian != sys::IsLittleEndianHost)
9370 swapStruct(es);
9371 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
9372 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n";
9373 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
9374 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n";
9375 else
9376 outs() << "\t esh.count " << es.esh.count
9377 << " (not x86_EXCEPTION_STATE64_COUNT\n";
9378 Print_x86_exception_state_t(es.ues.es64);
9379 } else {
9380 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count "
9381 << es.esh.count << "\n";
9382 }
9383 } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
9384 outs() << " flavor x86_EXCEPTION_STATE64\n";
9385 if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
9386 outs() << " count x86_EXCEPTION_STATE64_COUNT\n";
9387 else
9388 outs() << " count " << count
9389 << " (not x86_EXCEPTION_STATE64_COUNT)\n";
9390 struct MachO::x86_exception_state64_t es64;
9391 left = end - begin;
9392 if (left >= sizeof(MachO::x86_exception_state64_t)) {
9393 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
9394 begin += sizeof(MachO::x86_exception_state64_t);
9395 } else {
9396 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
9397 memcpy(&es64, begin, left);
9398 begin += left;
9399 }
9400 if (isLittleEndian != sys::IsLittleEndianHost)
9401 swapStruct(es64);
9402 Print_x86_exception_state_t(es64);
9403 } else {
9404 outs() << " flavor " << flavor << " (unknown)\n";
9405 outs() << " count " << count << "\n";
9406 outs() << " state (unknown)\n";
9407 begin += count * sizeof(uint32_t);
9408 }
9409 }
9410 } else if (cputype == MachO::CPU_TYPE_ARM) {
9411 while (begin < end) {
9412 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9413 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9414 begin += sizeof(uint32_t);
9415 } else {
9416 flavor = 0;
9417 begin = end;
9418 }
9419 if (isLittleEndian != sys::IsLittleEndianHost)
9420 sys::swapByteOrder(flavor);
9421 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9422 memcpy((char *)&count, begin, sizeof(uint32_t));
9423 begin += sizeof(uint32_t);
9424 } else {
9425 count = 0;
9426 begin = end;
9427 }
9428 if (isLittleEndian != sys::IsLittleEndianHost)
9429 sys::swapByteOrder(count);
9430 if (flavor == MachO::ARM_THREAD_STATE) {
9431 outs() << " flavor ARM_THREAD_STATE\n";
9432 if (count == MachO::ARM_THREAD_STATE_COUNT)
9433 outs() << " count ARM_THREAD_STATE_COUNT\n";
9434 else
9435 outs() << " count " << count
9436 << " (not ARM_THREAD_STATE_COUNT)\n";
9437 MachO::arm_thread_state32_t cpu32;
9438 left = end - begin;
9439 if (left >= sizeof(MachO::arm_thread_state32_t)) {
9440 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
9441 begin += sizeof(MachO::arm_thread_state32_t);
9442 } else {
9443 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
9444 memcpy(&cpu32, begin, left);
9445 begin += left;
9446 }
9447 if (isLittleEndian != sys::IsLittleEndianHost)
9448 swapStruct(cpu32);
9449 Print_arm_thread_state32_t(cpu32);
9450 } else {
9451 outs() << " flavor " << flavor << " (unknown)\n";
9452 outs() << " count " << count << "\n";
9453 outs() << " state (unknown)\n";
9454 begin += count * sizeof(uint32_t);
9455 }
9456 }
9457 } else if (cputype == MachO::CPU_TYPE_ARM64) {
9458 while (begin < end) {
9459 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9460 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9461 begin += sizeof(uint32_t);
9462 } else {
9463 flavor = 0;
9464 begin = end;
9465 }
9466 if (isLittleEndian != sys::IsLittleEndianHost)
9467 sys::swapByteOrder(flavor);
9468 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9469 memcpy((char *)&count, begin, sizeof(uint32_t));
9470 begin += sizeof(uint32_t);
9471 } else {
9472 count = 0;
9473 begin = end;
9474 }
9475 if (isLittleEndian != sys::IsLittleEndianHost)
9476 sys::swapByteOrder(count);
9477 if (flavor == MachO::ARM_THREAD_STATE64) {
9478 outs() << " flavor ARM_THREAD_STATE64\n";
9479 if (count == MachO::ARM_THREAD_STATE64_COUNT)
9480 outs() << " count ARM_THREAD_STATE64_COUNT\n";
9481 else
9482 outs() << " count " << count
9483 << " (not ARM_THREAD_STATE64_COUNT)\n";
9484 MachO::arm_thread_state64_t cpu64;
9485 left = end - begin;
9486 if (left >= sizeof(MachO::arm_thread_state64_t)) {
9487 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
9488 begin += sizeof(MachO::arm_thread_state64_t);
9489 } else {
9490 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
9491 memcpy(&cpu64, begin, left);
9492 begin += left;
9493 }
9494 if (isLittleEndian != sys::IsLittleEndianHost)
9495 swapStruct(cpu64);
9496 Print_arm_thread_state64_t(cpu64);
9497 } else {
9498 outs() << " flavor " << flavor << " (unknown)\n";
9499 outs() << " count " << count << "\n";
9500 outs() << " state (unknown)\n";
9501 begin += count * sizeof(uint32_t);
9502 }
9503 }
9504 } else {
9505 while (begin < end) {
9506 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9507 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9508 begin += sizeof(uint32_t);
9509 } else {
9510 flavor = 0;
9511 begin = end;
9512 }
9513 if (isLittleEndian != sys::IsLittleEndianHost)
9514 sys::swapByteOrder(flavor);
9515 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9516 memcpy((char *)&count, begin, sizeof(uint32_t));
9517 begin += sizeof(uint32_t);
9518 } else {
9519 count = 0;
9520 begin = end;
9521 }
9522 if (isLittleEndian != sys::IsLittleEndianHost)
9523 sys::swapByteOrder(count);
9524 outs() << " flavor " << flavor << "\n";
9525 outs() << " count " << count << "\n";
9526 outs() << " state (Unknown cputype/cpusubtype)\n";
9527 begin += count * sizeof(uint32_t);
9528 }
9529 }
9530}
9531
9532static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
9533 if (dl.cmd == MachO::LC_ID_DYLIB)
9534 outs() << " cmd LC_ID_DYLIB\n";
9535 else if (dl.cmd == MachO::LC_LOAD_DYLIB)
9536 outs() << " cmd LC_LOAD_DYLIB\n";
9537 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
9538 outs() << " cmd LC_LOAD_WEAK_DYLIB\n";
9539 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
9540 outs() << " cmd LC_REEXPORT_DYLIB\n";
9541 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
9542 outs() << " cmd LC_LAZY_LOAD_DYLIB\n";
9543 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
9544 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n";
9545 else
9546 outs() << " cmd " << dl.cmd << " (unknown)\n";
9547 outs() << " cmdsize " << dl.cmdsize;
9548 if (dl.cmdsize < sizeof(struct MachO::dylib_command))
9549 outs() << " Incorrect size\n";
9550 else
9551 outs() << "\n";
9552 if (dl.dylib.name < dl.cmdsize) {
9553 const char *P = (const char *)(Ptr) + dl.dylib.name;
9554 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n";
9555 } else {
9556 outs() << " name ?(bad offset " << dl.dylib.name << ")\n";
9557 }
9558 outs() << " time stamp " << dl.dylib.timestamp << " ";
9559 time_t t = dl.dylib.timestamp;
9560 outs() << ctime(&t);
9561 outs() << " current version ";
9562 if (dl.dylib.current_version == 0xffffffff)
9563 outs() << "n/a\n";
9564 else
9565 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
9566 << ((dl.dylib.current_version >> 8) & 0xff) << "."
9567 << (dl.dylib.current_version & 0xff) << "\n";
9568 outs() << "compatibility version ";
9569 if (dl.dylib.compatibility_version == 0xffffffff)
9570 outs() << "n/a\n";
9571 else
9572 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
9573 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
9574 << (dl.dylib.compatibility_version & 0xff) << "\n";
9575}
9576
9577static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
9578 uint32_t object_size) {
9579 if (ld.cmd == MachO::LC_CODE_SIGNATURE)
9580 outs() << " cmd LC_CODE_SIGNATURE\n";
9581 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
9582 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n";
9583 else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
9584 outs() << " cmd LC_FUNCTION_STARTS\n";
9585 else if (ld.cmd == MachO::LC_DATA_IN_CODE)
9586 outs() << " cmd LC_DATA_IN_CODE\n";
9587 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
9588 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n";
9589 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
9590 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n";
9591 else
9592 outs() << " cmd " << ld.cmd << " (?)\n";
9593 outs() << " cmdsize " << ld.cmdsize;
9594 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
9595 outs() << " Incorrect size\n";
9596 else
9597 outs() << "\n";
9598 outs() << " dataoff " << ld.dataoff;
9599 if (ld.dataoff > object_size)
9600 outs() << " (past end of file)\n";
9601 else
9602 outs() << "\n";
9603 outs() << " datasize " << ld.datasize;
9604 uint64_t big_size = ld.dataoff;
9605 big_size += ld.datasize;
9606 if (big_size > object_size)
9607 outs() << " (past end of file)\n";
9608 else
9609 outs() << "\n";
9610}
9611
9612static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
9613 uint32_t cputype, bool verbose) {
9614 StringRef Buf = Obj->getData();
9615 unsigned Index = 0;
9616 for (const auto &Command : Obj->load_commands()) {
9617 outs() << "Load command " << Index++ << "\n";
9618 if (Command.C.cmd == MachO::LC_SEGMENT) {
9619 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
9620 const char *sg_segname = SLC.segname;
9621 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
9622 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
9623 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
9624 verbose);
9625 for (unsigned j = 0; j < SLC.nsects; j++) {
9626 MachO::section S = Obj->getSection(Command, j);
9627 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
9628 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
9629 SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
9630 }
9631 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
9632 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
9633 const char *sg_segname = SLC_64.segname;
9634 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
9635 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
9636 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
9637 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
9638 for (unsigned j = 0; j < SLC_64.nsects; j++) {
9639 MachO::section_64 S_64 = Obj->getSection64(Command, j);
9640 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
9641 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
9642 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
9643 sg_segname, filetype, Buf.size(), verbose);
9644 }
9645 } else if (Command.C.cmd == MachO::LC_SYMTAB) {
9646 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
9647 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
9648 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
9649 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
9650 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
9651 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
9652 Obj->is64Bit());
9653 } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
9654 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
9655 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
9656 PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
9657 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
9658 Command.C.cmd == MachO::LC_ID_DYLINKER ||
9659 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
9660 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
9661 PrintDyldLoadCommand(Dyld, Command.Ptr);
9662 } else if (Command.C.cmd == MachO::LC_UUID) {
9663 MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
9664 PrintUuidLoadCommand(Uuid);
9665 } else if (Command.C.cmd == MachO::LC_RPATH) {
9666 MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
9667 PrintRpathLoadCommand(Rpath, Command.Ptr);
9668 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
9669 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
9670 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
9671 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
9672 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
9673 PrintVersionMinLoadCommand(Vd);
9674 } else if (Command.C.cmd == MachO::LC_NOTE) {
9675 MachO::note_command Nt = Obj->getNoteLoadCommand(Command);
9676 PrintNoteLoadCommand(Nt);
9677 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) {
9678 MachO::build_version_command Bv =
9679 Obj->getBuildVersionLoadCommand(Command);
9680 PrintBuildVersionLoadCommand(Obj, Bv);
9681 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
9682 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
9683 PrintSourceVersionCommand(Sd);
9684 } else if (Command.C.cmd == MachO::LC_MAIN) {
9685 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
9686 PrintEntryPointCommand(Ep);
9687 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
9688 MachO::encryption_info_command Ei =
9689 Obj->getEncryptionInfoCommand(Command);
9690 PrintEncryptionInfoCommand(Ei, Buf.size());
9691 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
9692 MachO::encryption_info_command_64 Ei =
9693 Obj->getEncryptionInfoCommand64(Command);
9694 PrintEncryptionInfoCommand64(Ei, Buf.size());
9695 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
9696 MachO::linker_option_command Lo =
9697 Obj->getLinkerOptionLoadCommand(Command);
9698 PrintLinkerOptionCommand(Lo, Command.Ptr);
9699 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
9700 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
9701 PrintSubFrameworkCommand(Sf, Command.Ptr);
9702 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
9703 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
9704 PrintSubUmbrellaCommand(Sf, Command.Ptr);
9705 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
9706 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
9707 PrintSubLibraryCommand(Sl, Command.Ptr);
9708 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
9709 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
9710 PrintSubClientCommand(Sc, Command.Ptr);
9711 } else if (Command.C.cmd == MachO::LC_ROUTINES) {
9712 MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
9713 PrintRoutinesCommand(Rc);
9714 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
9715 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
9716 PrintRoutinesCommand64(Rc);
9717 } else if (Command.C.cmd == MachO::LC_THREAD ||
9718 Command.C.cmd == MachO::LC_UNIXTHREAD) {
9719 MachO::thread_command Tc = Obj->getThreadCommand(Command);
9720 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
9721 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
9722 Command.C.cmd == MachO::LC_ID_DYLIB ||
9723 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
9724 Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
9725 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
9726 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
9727 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
9728 PrintDylibCommand(Dl, Command.Ptr);
9729 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
9730 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
9731 Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
9732 Command.C.cmd == MachO::LC_DATA_IN_CODE ||
9733 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
9734 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
9735 MachO::linkedit_data_command Ld =
9736 Obj->getLinkeditDataLoadCommand(Command);
9737 PrintLinkEditDataCommand(Ld, Buf.size());
9738 } else {
9739 outs() << " cmd ?(" << format("0x%08" PRIx32"x", Command.C.cmd)
9740 << ")\n";
9741 outs() << " cmdsize " << Command.C.cmdsize << "\n";
9742 // TODO: get and print the raw bytes of the load command.
9743 }
9744 // TODO: print all the other kinds of load commands.
9745 }
9746}
9747
9748static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
9749 if (Obj->is64Bit()) {
9750 MachO::mach_header_64 H_64;
9751 H_64 = Obj->getHeader64();
9752 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
9753 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
9754 } else {
9755 MachO::mach_header H;
9756 H = Obj->getHeader();
9757 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
9758 H.sizeofcmds, H.flags, verbose);
9759 }
9760}
9761
9762void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
9763 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
9764 PrintMachHeader(file, !NonVerbose);
9765}
9766
9767void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) {
9768 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
9769 uint32_t filetype = 0;
9770 uint32_t cputype = 0;
9771 if (file->is64Bit()) {
9772 MachO::mach_header_64 H_64;
9773 H_64 = file->getHeader64();
9774 filetype = H_64.filetype;
9775 cputype = H_64.cputype;
9776 } else {
9777 MachO::mach_header H;
9778 H = file->getHeader();
9779 filetype = H.filetype;
9780 cputype = H.cputype;
9781 }
9782 PrintLoadCommands(file, filetype, cputype, !NonVerbose);
9783}
9784
9785//===----------------------------------------------------------------------===//
9786// export trie dumping
9787//===----------------------------------------------------------------------===//
9788
9789void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) {
9790 uint64_t BaseSegmentAddress = 0;
9791 for (const auto &Command : Obj->load_commands()) {
9792 if (Command.C.cmd == MachO::LC_SEGMENT) {
9793 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command);
9794 if (Seg.fileoff == 0 && Seg.filesize != 0) {
9795 BaseSegmentAddress = Seg.vmaddr;
9796 break;
9797 }
9798 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
9799 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command);
9800 if (Seg.fileoff == 0 && Seg.filesize != 0) {
9801 BaseSegmentAddress = Seg.vmaddr;
9802 break;
9803 }
9804 }
9805 }
9806 Error Err = Error::success();
9807 for (const llvm::object::ExportEntry &Entry : Obj->exports(Err)) {
9808 uint64_t Flags = Entry.flags();
9809 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
9810 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
9811 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
9812 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
9813 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
9814 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
9815 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
9816 if (ReExport)
9817 outs() << "[re-export] ";
9818 else
9819 outs() << format("0x%08llX ",
9820 Entry.address() + BaseSegmentAddress);
9821 outs() << Entry.name();
9822 if (WeakDef || ThreadLocal || Resolver || Abs) {
9823 bool NeedsComma = false;
9824 outs() << " [";
9825 if (WeakDef) {
9826 outs() << "weak_def";
9827 NeedsComma = true;
9828 }
9829 if (ThreadLocal) {
9830 if (NeedsComma)
9831 outs() << ", ";
9832 outs() << "per-thread";
9833 NeedsComma = true;
9834 }
9835 if (Abs) {
9836 if (NeedsComma)
9837 outs() << ", ";
9838 outs() << "absolute";
9839 NeedsComma = true;
9840 }
9841 if (Resolver) {
9842 if (NeedsComma)
9843 outs() << ", ";
9844 outs() << format("resolver=0x%08llX", Entry.other());
9845 NeedsComma = true;
9846 }
9847 outs() << "]";
9848 }
9849 if (ReExport) {
9850 StringRef DylibName = "unknown";
9851 int Ordinal = Entry.other() - 1;
9852 Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
9853 if (Entry.otherName().empty())
9854 outs() << " (from " << DylibName << ")";
9855 else
9856 outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
9857 }
9858 outs() << "\n";
9859 }
9860 if (Err)
9861 report_error(Obj->getFileName(), std::move(Err));
9862}
9863
9864//===----------------------------------------------------------------------===//
9865// rebase table dumping
9866//===----------------------------------------------------------------------===//
9867
9868void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) {
9869 outs() << "segment section address type\n";
9870 Error Err = Error::success();
9871 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
9872 StringRef SegmentName = Entry.segmentName();
9873 StringRef SectionName = Entry.sectionName();
9874 uint64_t Address = Entry.address();
9875
9876 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer
9877 outs() << format("%-8s %-18s 0x%08" PRIX64"l" "X" " %s\n",
9878 SegmentName.str().c_str(), SectionName.str().c_str(),
9879 Address, Entry.typeName().str().c_str());
9880 }
9881 if (Err)
9882 report_error(Obj->getFileName(), std::move(Err));
9883}
9884
9885static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
9886 StringRef DylibName;
9887 switch (Ordinal) {
9888 case MachO::BIND_SPECIAL_DYLIB_SELF:
9889 return "this-image";
9890 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
9891 return "main-executable";
9892 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
9893 return "flat-namespace";
9894 default:
9895 if (Ordinal > 0) {
9896 std::error_code EC =
9897 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
9898 if (EC)
9899 return "<<bad library ordinal>>";
9900 return DylibName;
9901 }
9902 }
9903 return "<<unknown special ordinal>>";
9904}
9905
9906//===----------------------------------------------------------------------===//
9907// bind table dumping
9908//===----------------------------------------------------------------------===//
9909
9910void llvm::printMachOBindTable(object::MachOObjectFile *Obj) {
9911 // Build table of sections so names can used in final output.
9912 outs() << "segment section address type "
9913 "addend dylib symbol\n";
9914 Error Err = Error::success();
9915 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
9916 StringRef SegmentName = Entry.segmentName();
9917 StringRef SectionName = Entry.sectionName();
9918 uint64_t Address = Entry.address();
9919
9920 // Table lines look like:
9921 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard
9922 StringRef Attr;
9923 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
9924 Attr = " (weak_import)";
9925 outs() << left_justify(SegmentName, 8) << " "
9926 << left_justify(SectionName, 18) << " "
9927 << format_hex(Address, 10, true) << " "
9928 << left_justify(Entry.typeName(), 8) << " "
9929 << format_decimal(Entry.addend(), 8) << " "
9930 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
9931 << Entry.symbolName() << Attr << "\n";
9932 }
9933 if (Err)
9934 report_error(Obj->getFileName(), std::move(Err));
9935}
9936
9937//===----------------------------------------------------------------------===//
9938// lazy bind table dumping
9939//===----------------------------------------------------------------------===//
9940
9941void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) {
9942 outs() << "segment section address "
9943 "dylib symbol\n";
9944 Error Err = Error::success();
9945 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
9946 StringRef SegmentName = Entry.segmentName();
9947 StringRef SectionName = Entry.sectionName();
9948 uint64_t Address = Entry.address();
9949
9950 // Table lines look like:
9951 // __DATA __got 0x00012010 libSystem ___stack_chk_guard
9952 outs() << left_justify(SegmentName, 8) << " "
9953 << left_justify(SectionName, 18) << " "
9954 << format_hex(Address, 10, true) << " "
9955 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
9956 << Entry.symbolName() << "\n";
9957 }
9958 if (Err)
9959 report_error(Obj->getFileName(), std::move(Err));
9960}
9961
9962//===----------------------------------------------------------------------===//
9963// weak bind table dumping
9964//===----------------------------------------------------------------------===//
9965
9966void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) {
9967 outs() << "segment section address "
9968 "type addend symbol\n";
9969 Error Err = Error::success();
9970 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) {
9971 // Strong symbols don't have a location to update.
9972 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
9973 outs() << " strong "
9974 << Entry.symbolName() << "\n";
9975 continue;
9976 }
9977 StringRef SegmentName = Entry.segmentName();
9978 StringRef SectionName = Entry.sectionName();
9979 uint64_t Address = Entry.address();
9980
9981 // Table lines look like:
9982 // __DATA __data 0x00001000 pointer 0 _foo
9983 outs() << left_justify(SegmentName, 8) << " "
9984 << left_justify(SectionName, 18) << " "
9985 << format_hex(Address, 10, true) << " "
9986 << left_justify(Entry.typeName(), 8) << " "
9987 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName()
9988 << "\n";
9989 }
9990 if (Err)
9991 report_error(Obj->getFileName(), std::move(Err));
9992}
9993
9994// get_dyld_bind_info_symbolname() is used for disassembly and passed an
9995// address, ReferenceValue, in the Mach-O file and looks in the dyld bind
9996// information for that address. If the address is found its binding symbol
9997// name is returned. If not nullptr is returned.
9998static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
9999 struct DisassembleInfo *info) {
10000 if (info->bindtable == nullptr) {
10001 info->bindtable = llvm::make_unique<SymbolAddressMap>();
10002 Error Err = Error::success();
10003 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
10004 uint64_t Address = Entry.address();
10005 StringRef name = Entry.symbolName();
10006 if (!name.empty())
10007 (*info->bindtable)[Address] = name;
10008 }
10009 if (Err)
10010 report_error(info->O->getFileName(), std::move(Err));
10011 }
10012 auto name = info->bindtable->lookup(ReferenceValue);
10013 return !name.empty() ? name.data() : nullptr;
10014}
10015

/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Object/ObjectFile.h

1//===- ObjectFile.h - File format independent object file -------*- C++ -*-===//
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 declares a file format independent ObjectFile class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_OBJECT_OBJECTFILE_H
15#define LLVM_OBJECT_OBJECTFILE_H
16
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/Triple.h"
19#include "llvm/ADT/iterator_range.h"
20#include "llvm/BinaryFormat/Magic.h"
21#include "llvm/MC/SubtargetFeature.h"
22#include "llvm/Object/Binary.h"
23#include "llvm/Object/Error.h"
24#include "llvm/Object/SymbolicFile.h"
25#include "llvm/Support/Casting.h"
26#include "llvm/Support/Error.h"
27#include "llvm/Support/FileSystem.h"
28#include "llvm/Support/MemoryBuffer.h"
29#include <cassert>
30#include <cstdint>
31#include <memory>
32#include <system_error>
33
34namespace llvm {
35
36class ARMAttributeParser;
37
38namespace object {
39
40class COFFObjectFile;
41class MachOObjectFile;
42class ObjectFile;
43class SectionRef;
44class SymbolRef;
45class symbol_iterator;
46class WasmObjectFile;
47
48using section_iterator = content_iterator<SectionRef>;
49
50/// This is a value type class that represents a single relocation in the list
51/// of relocations in the object file.
52class RelocationRef {
53 DataRefImpl RelocationPimpl;
54 const ObjectFile *OwningObject = nullptr;
55
56public:
57 RelocationRef() = default;
58 RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner);
59
60 bool operator==(const RelocationRef &Other) const;
61
62 void moveNext();
63
64 uint64_t getOffset() const;
65 symbol_iterator getSymbol() const;
66 uint64_t getType() const;
67
68 /// Get a string that represents the type of this relocation.
69 ///
70 /// This is for display purposes only.
71 void getTypeName(SmallVectorImpl<char> &Result) const;
72
73 DataRefImpl getRawDataRefImpl() const;
74 const ObjectFile *getObject() const;
75};
76
77using relocation_iterator = content_iterator<RelocationRef>;
78
79/// This is a value type class that represents a single section in the list of
80/// sections in the object file.
81class SectionRef {
82 friend class SymbolRef;
83
84 DataRefImpl SectionPimpl;
85 const ObjectFile *OwningObject = nullptr;
86
87public:
88 SectionRef() = default;
89 SectionRef(DataRefImpl SectionP, const ObjectFile *Owner);
90
91 bool operator==(const SectionRef &Other) const;
92 bool operator!=(const SectionRef &Other) const;
93 bool operator<(const SectionRef &Other) const;
94
95 void moveNext();
96
97 std::error_code getName(StringRef &Result) const;
98 uint64_t getAddress() const;
99 uint64_t getIndex() const;
100 uint64_t getSize() const;
101 std::error_code getContents(StringRef &Result) const;
102
103 /// Get the alignment of this section as the actual value (not log 2).
104 uint64_t getAlignment() const;
105
106 bool isCompressed() const;
107 bool isText() const;
108 bool isData() const;
109 bool isBSS() const;
110 bool isVirtual() const;
111 bool isBitcode() const;
112 bool isStripped() const;
113
114 bool containsSymbol(SymbolRef S) const;
115
116 relocation_iterator relocation_begin() const;
117 relocation_iterator relocation_end() const;
118 iterator_range<relocation_iterator> relocations() const {
119 return make_range(relocation_begin(), relocation_end());
120 }
121 section_iterator getRelocatedSection() const;
122
123 DataRefImpl getRawDataRefImpl() const;
124 const ObjectFile *getObject() const;
125};
126
127/// This is a value type class that represents a single symbol in the list of
128/// symbols in the object file.
129class SymbolRef : public BasicSymbolRef {
130 friend class SectionRef;
131
132public:
133 enum Type {
134 ST_Unknown, // Type not specified
135 ST_Data,
136 ST_Debug,
137 ST_File,
138 ST_Function,
139 ST_Other
140 };
141
142 SymbolRef() = default;
143 SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner);
144 SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) {
145 assert(isa<ObjectFile>(BasicSymbolRef::getObject()))((isa<ObjectFile>(BasicSymbolRef::getObject())) ? static_cast
<void> (0) : __assert_fail ("isa<ObjectFile>(BasicSymbolRef::getObject())"
, "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Object/ObjectFile.h"
, 145, __PRETTY_FUNCTION__))
;
146 }
147
148 Expected<StringRef> getName() const;
149 /// Returns the symbol virtual address (i.e. address at which it will be
150 /// mapped).
151 Expected<uint64_t> getAddress() const;
152
153 /// Return the value of the symbol depending on the object this can be an
154 /// offset or a virtual address.
155 uint64_t getValue() const;
156
157 /// Get the alignment of this symbol as the actual value (not log 2).
158 uint32_t getAlignment() const;
159 uint64_t getCommonSize() const;
160 Expected<SymbolRef::Type> getType() const;
161
162 /// Get section this symbol is defined in reference to. Result is
163 /// end_sections() if it is undefined or is an absolute symbol.
164 Expected<section_iterator> getSection() const;
165
166 const ObjectFile *getObject() const;
167};
168
169class symbol_iterator : public basic_symbol_iterator {
170public:
171 symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {}
172 symbol_iterator(const basic_symbol_iterator &B)
173 : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(),
174 cast<ObjectFile>(B->getObject()))) {}
175
176 const SymbolRef *operator->() const {
177 const BasicSymbolRef &P = basic_symbol_iterator::operator *();
178 return static_cast<const SymbolRef*>(&P);
179 }
180
181 const SymbolRef &operator*() const {
182 const BasicSymbolRef &P = basic_symbol_iterator::operator *();
183 return static_cast<const SymbolRef&>(P);
184 }
185};
186
187/// This class is the base class for all object file types. Concrete instances
188/// of this object are created by createObjectFile, which figures out which type
189/// to create.
190class ObjectFile : public SymbolicFile {
191 virtual void anchor();
192
193protected:
194 ObjectFile(unsigned int Type, MemoryBufferRef Source);
195
196 const uint8_t *base() const {
197 return reinterpret_cast<const uint8_t *>(Data.getBufferStart());
198 }
199
200 // These functions are for SymbolRef to call internally. The main goal of
201 // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol
202 // entry in the memory mapped object file. SymbolPimpl cannot contain any
203 // virtual functions because then it could not point into the memory mapped
204 // file.
205 //
206 // Implementations assume that the DataRefImpl is valid and has not been
207 // modified externally. It's UB otherwise.
208 friend class SymbolRef;
209
210 virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
211 std::error_code printSymbolName(raw_ostream &OS,
212 DataRefImpl Symb) const override;
213 virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0;
214 virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0;
215 virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
216 virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0;
217 virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0;
218 virtual Expected<section_iterator>
219 getSymbolSection(DataRefImpl Symb) const = 0;
220
221 // Same as above for SectionRef.
222 friend class SectionRef;
223
224 virtual void moveSectionNext(DataRefImpl &Sec) const = 0;
225 virtual std::error_code getSectionName(DataRefImpl Sec,
226 StringRef &Res) const = 0;
227 virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0;
228 virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0;
229 virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0;
230 virtual std::error_code getSectionContents(DataRefImpl Sec,
231 StringRef &Res) const = 0;
232 virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
233 virtual bool isSectionCompressed(DataRefImpl Sec) const = 0;
234 virtual bool isSectionText(DataRefImpl Sec) const = 0;
235 virtual bool isSectionData(DataRefImpl Sec) const = 0;
236 virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
237 // A section is 'virtual' if its contents aren't present in the object image.
238 virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
239 virtual bool isSectionBitcode(DataRefImpl Sec) const;
240 virtual bool isSectionStripped(DataRefImpl Sec) const;
241 virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
242 virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
243 virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
244
245 // Same as above for RelocationRef.
246 friend class RelocationRef;
247 virtual void moveRelocationNext(DataRefImpl &Rel) const = 0;
248 virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0;
249 virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
250 virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0;
251 virtual void getRelocationTypeName(DataRefImpl Rel,
252 SmallVectorImpl<char> &Result) const = 0;
253
254 uint64_t getSymbolValue(DataRefImpl Symb) const;
255
256public:
257 ObjectFile() = delete;
258 ObjectFile(const ObjectFile &other) = delete;
259
260 uint64_t getCommonSymbolSize(DataRefImpl Symb) const {
261 assert(getSymbolFlags(Symb) & SymbolRef::SF_Common)((getSymbolFlags(Symb) & SymbolRef::SF_Common) ? static_cast
<void> (0) : __assert_fail ("getSymbolFlags(Symb) & SymbolRef::SF_Common"
, "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Object/ObjectFile.h"
, 261, __PRETTY_FUNCTION__))
;
262 return getCommonSymbolSizeImpl(Symb);
263 }
264
265 virtual std::vector<SectionRef> dynamic_relocation_sections() const {
266 return std::vector<SectionRef>();
267 }
268
269 using symbol_iterator_range = iterator_range<symbol_iterator>;
270 symbol_iterator_range symbols() const {
271 return symbol_iterator_range(symbol_begin(), symbol_end());
272 }
273
274 virtual section_iterator section_begin() const = 0;
275 virtual section_iterator section_end() const = 0;
276
277 using section_iterator_range = iterator_range<section_iterator>;
278 section_iterator_range sections() const {
279 return section_iterator_range(section_begin(), section_end());
280 }
281
282 /// The number of bytes used to represent an address in this object
283 /// file format.
284 virtual uint8_t getBytesInAddress() const = 0;
285
286 virtual StringRef getFileFormatName() const = 0;
287 virtual Triple::ArchType getArch() const = 0;
288 virtual SubtargetFeatures getFeatures() const = 0;
289 virtual void setARMSubArch(Triple &TheTriple) const { }
290 virtual Expected<uint64_t> getStartAddress() const {
291 return errorCodeToError(object_error::parse_failed);
292 };
293
294 /// Create a triple from the data in this object file.
295 Triple makeTriple() const;
296
297 virtual std::error_code
298 getBuildAttributes(ARMAttributeParser &Attributes) const {
299 return std::error_code();
300 }
301
302 /// Maps a debug section name to a standard DWARF section name.
303 virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; }
304
305 /// True if this is a relocatable object (.o/.obj).
306 virtual bool isRelocatableObject() const = 0;
307
308 /// @returns Pointer to ObjectFile subclass to handle this type of object.
309 /// @param ObjectPath The path to the object file. ObjectPath.isObject must
310 /// return true.
311 /// Create ObjectFile from path.
312 static Expected<OwningBinary<ObjectFile>>
313 createObjectFile(StringRef ObjectPath);
314
315 static Expected<std::unique_ptr<ObjectFile>>
316 createObjectFile(MemoryBufferRef Object, llvm::file_magic Type);
317 static Expected<std::unique_ptr<ObjectFile>>
318 createObjectFile(MemoryBufferRef Object) {
319 return createObjectFile(Object, llvm::file_magic::unknown);
320 }
321
322 static bool classof(const Binary *v) {
323 return v->isObject();
324 }
325
326 static Expected<std::unique_ptr<COFFObjectFile>>
327 createCOFFObjectFile(MemoryBufferRef Object);
328
329 static Expected<std::unique_ptr<ObjectFile>>
330 createELFObjectFile(MemoryBufferRef Object);
331
332 static Expected<std::unique_ptr<MachOObjectFile>>
333 createMachOObjectFile(MemoryBufferRef Object,
334 uint32_t UniversalCputype = 0,
335 uint32_t UniversalIndex = 0);
336
337 static Expected<std::unique_ptr<WasmObjectFile>>
338 createWasmObjectFile(MemoryBufferRef Object);
339};
340
341// Inline function definitions.
342inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner)
343 : BasicSymbolRef(SymbolP, Owner) {}
344
345inline Expected<StringRef> SymbolRef::getName() const {
346 return getObject()->getSymbolName(getRawDataRefImpl());
347}
348
349inline Expected<uint64_t> SymbolRef::getAddress() const {
350 return getObject()->getSymbolAddress(getRawDataRefImpl());
351}
352
353inline uint64_t SymbolRef::getValue() const {
354 return getObject()->getSymbolValue(getRawDataRefImpl());
355}
356
357inline uint32_t SymbolRef::getAlignment() const {
358 return getObject()->getSymbolAlignment(getRawDataRefImpl());
359}
360
361inline uint64_t SymbolRef::getCommonSize() const {
362 return getObject()->getCommonSymbolSize(getRawDataRefImpl());
363}
364
365inline Expected<section_iterator> SymbolRef::getSection() const {
366 return getObject()->getSymbolSection(getRawDataRefImpl());
367}
368
369inline Expected<SymbolRef::Type> SymbolRef::getType() const {
370 return getObject()->getSymbolType(getRawDataRefImpl());
371}
372
373inline const ObjectFile *SymbolRef::getObject() const {
374 const SymbolicFile *O = BasicSymbolRef::getObject();
375 return cast<ObjectFile>(O);
376}
377
378/// SectionRef
379inline SectionRef::SectionRef(DataRefImpl SectionP,
380 const ObjectFile *Owner)
381 : SectionPimpl(SectionP)
382 , OwningObject(Owner) {}
383
384inline bool SectionRef::operator==(const SectionRef &Other) const {
385 return SectionPimpl == Other.SectionPimpl;
386}
387
388inline bool SectionRef::operator!=(const SectionRef &Other) const {
389 return SectionPimpl != Other.SectionPimpl;
390}
391
392inline bool SectionRef::operator<(const SectionRef &Other) const {
393 return SectionPimpl < Other.SectionPimpl;
394}
395
396inline void SectionRef::moveNext() {
397 return OwningObject->moveSectionNext(SectionPimpl);
398}
399
400inline std::error_code SectionRef::getName(StringRef &Result) const {
401 return OwningObject->getSectionName(SectionPimpl, Result);
79
Called C++ object pointer is null
402}
403
404inline uint64_t SectionRef::getAddress() const {
405 return OwningObject->getSectionAddress(SectionPimpl);
406}
407
408inline uint64_t SectionRef::getIndex() const {
409 return OwningObject->getSectionIndex(SectionPimpl);
410}
411
412inline uint64_t SectionRef::getSize() const {
413 return OwningObject->getSectionSize(SectionPimpl);
414}
415
416inline std::error_code SectionRef::getContents(StringRef &Result) const {
417 return OwningObject->getSectionContents(SectionPimpl, Result);
418}
419
420inline uint64_t SectionRef::getAlignment() const {
421 return OwningObject->getSectionAlignment(SectionPimpl);
422}
423
424inline bool SectionRef::isCompressed() const {
425 return OwningObject->isSectionCompressed(SectionPimpl);
426}
427
428inline bool SectionRef::isText() const {
429 return OwningObject->isSectionText(SectionPimpl);
430}
431
432inline bool SectionRef::isData() const {
433 return OwningObject->isSectionData(SectionPimpl);
434}
435
436inline bool SectionRef::isBSS() const {
437 return OwningObject->isSectionBSS(SectionPimpl);
438}
439
440inline bool SectionRef::isVirtual() const {
441 return OwningObject->isSectionVirtual(SectionPimpl);
442}
443
444inline bool SectionRef::isBitcode() const {
445 return OwningObject->isSectionBitcode(SectionPimpl);
446}
447
448inline bool SectionRef::isStripped() const {
449 return OwningObject->isSectionStripped(SectionPimpl);
450}
451
452inline relocation_iterator SectionRef::relocation_begin() const {
453 return OwningObject->section_rel_begin(SectionPimpl);
454}
455
456inline relocation_iterator SectionRef::relocation_end() const {
457 return OwningObject->section_rel_end(SectionPimpl);
458}
459
460inline section_iterator SectionRef::getRelocatedSection() const {
461 return OwningObject->getRelocatedSection(SectionPimpl);
462}
463
464inline DataRefImpl SectionRef::getRawDataRefImpl() const {
465 return SectionPimpl;
466}
467
468inline const ObjectFile *SectionRef::getObject() const {
469 return OwningObject;
470}
471
472/// RelocationRef
473inline RelocationRef::RelocationRef(DataRefImpl RelocationP,
474 const ObjectFile *Owner)
475 : RelocationPimpl(RelocationP)
476 , OwningObject(Owner) {}
477
478inline bool RelocationRef::operator==(const RelocationRef &Other) const {
479 return RelocationPimpl == Other.RelocationPimpl;
480}
481
482inline void RelocationRef::moveNext() {
483 return OwningObject->moveRelocationNext(RelocationPimpl);
484}
485
486inline uint64_t RelocationRef::getOffset() const {
487 return OwningObject->getRelocationOffset(RelocationPimpl);
488}
489
490inline symbol_iterator RelocationRef::getSymbol() const {
491 return OwningObject->getRelocationSymbol(RelocationPimpl);
492}
493
494inline uint64_t RelocationRef::getType() const {
495 return OwningObject->getRelocationType(RelocationPimpl);
496}
497
498inline void RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const {
499 return OwningObject->getRelocationTypeName(RelocationPimpl, Result);
500}
501
502inline DataRefImpl RelocationRef::getRawDataRefImpl() const {
503 return RelocationPimpl;
504}
505
506inline const ObjectFile *RelocationRef::getObject() const {
507 return OwningObject;
508}
509
510} // end namespace object
511
512} // end namespace llvm
513
514#endif // LLVM_OBJECT_OBJECTFILE_H