xref: /aosp_15_r20/external/llvm/tools/llvm-objdump/MachODump.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- MachODump.cpp - Object file dumping utility for llvm --------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the MachO-specific dumper for llvm-objdump.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/MachO.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm-objdump.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm-c/Disassembler.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Triple.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Config/config.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/DIContext.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/DWARF/DWARFContext.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCDisassembler/MCDisassembler.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstPrinter.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrDesc.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/MachOUniversal.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Casting.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Endian.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FormattedStream.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/GraphWriter.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LEB128.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MachO.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetSelect.h"
45*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ToolOutputFile.h"
46*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
47*9880d681SAndroid Build Coastguard Worker #include <algorithm>
48*9880d681SAndroid Build Coastguard Worker #include <cstring>
49*9880d681SAndroid Build Coastguard Worker #include <system_error>
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker #if HAVE_CXXABI_H
52*9880d681SAndroid Build Coastguard Worker #include <cxxabi.h>
53*9880d681SAndroid Build Coastguard Worker #endif
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker #ifdef HAVE_LIBXAR
56*9880d681SAndroid Build Coastguard Worker extern "C" {
57*9880d681SAndroid Build Coastguard Worker #include <xar/xar.h>
58*9880d681SAndroid Build Coastguard Worker }
59*9880d681SAndroid Build Coastguard Worker #endif
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker using namespace llvm;
62*9880d681SAndroid Build Coastguard Worker using namespace object;
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
65*9880d681SAndroid Build Coastguard Worker     UseDbg("g",
66*9880d681SAndroid Build Coastguard Worker            cl::desc("Print line information from debug info if available"));
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string> DSYMFile("dsym",
69*9880d681SAndroid Build Coastguard Worker                                      cl::desc("Use .dSYM file for debug info"));
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> FullLeadingAddr("full-leading-addr",
72*9880d681SAndroid Build Coastguard Worker                                      cl::desc("Print full leading address"));
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> NoLeadingAddr("no-leading-addr",
75*9880d681SAndroid Build Coastguard Worker                                    cl::desc("Print no leading address"));
76*9880d681SAndroid Build Coastguard Worker 
77*9880d681SAndroid Build Coastguard Worker cl::opt<bool> llvm::UniversalHeaders("universal-headers",
78*9880d681SAndroid Build Coastguard Worker                                      cl::desc("Print Mach-O universal headers "
79*9880d681SAndroid Build Coastguard Worker                                               "(requires -macho)"));
80*9880d681SAndroid Build Coastguard Worker 
81*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
82*9880d681SAndroid Build Coastguard Worker     llvm::ArchiveHeaders("archive-headers",
83*9880d681SAndroid Build Coastguard Worker                          cl::desc("Print archive headers for Mach-O archives "
84*9880d681SAndroid Build Coastguard Worker                                   "(requires -macho)"));
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
87*9880d681SAndroid Build Coastguard Worker     ArchiveMemberOffsets("archive-member-offsets",
88*9880d681SAndroid Build Coastguard Worker                          cl::desc("Print the offset to each archive member for "
89*9880d681SAndroid Build Coastguard Worker                                   "Mach-O archives (requires -macho and "
90*9880d681SAndroid Build Coastguard Worker                                   "-archive-headers)"));
91*9880d681SAndroid Build Coastguard Worker 
92*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
93*9880d681SAndroid Build Coastguard Worker     llvm::IndirectSymbols("indirect-symbols",
94*9880d681SAndroid Build Coastguard Worker                           cl::desc("Print indirect symbol table for Mach-O "
95*9880d681SAndroid Build Coastguard Worker                                    "objects (requires -macho)"));
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
98*9880d681SAndroid Build Coastguard Worker     llvm::DataInCode("data-in-code",
99*9880d681SAndroid Build Coastguard Worker                      cl::desc("Print the data in code table for Mach-O objects "
100*9880d681SAndroid Build Coastguard Worker                               "(requires -macho)"));
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
103*9880d681SAndroid Build Coastguard Worker     llvm::LinkOptHints("link-opt-hints",
104*9880d681SAndroid Build Coastguard Worker                        cl::desc("Print the linker optimization hints for "
105*9880d681SAndroid Build Coastguard Worker                                 "Mach-O objects (requires -macho)"));
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
108*9880d681SAndroid Build Coastguard Worker     llvm::InfoPlist("info-plist",
109*9880d681SAndroid Build Coastguard Worker                     cl::desc("Print the info plist section as strings for "
110*9880d681SAndroid Build Coastguard Worker                              "Mach-O objects (requires -macho)"));
111*9880d681SAndroid Build Coastguard Worker 
112*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
113*9880d681SAndroid Build Coastguard Worker     llvm::DylibsUsed("dylibs-used",
114*9880d681SAndroid Build Coastguard Worker                      cl::desc("Print the shared libraries used for linked "
115*9880d681SAndroid Build Coastguard Worker                               "Mach-O files (requires -macho)"));
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
118*9880d681SAndroid Build Coastguard Worker     llvm::DylibId("dylib-id",
119*9880d681SAndroid Build Coastguard Worker                   cl::desc("Print the shared library's id for the dylib Mach-O "
120*9880d681SAndroid Build Coastguard Worker                            "file (requires -macho)"));
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
123*9880d681SAndroid Build Coastguard Worker     llvm::NonVerbose("non-verbose",
124*9880d681SAndroid Build Coastguard Worker                      cl::desc("Print the info for Mach-O objects in "
125*9880d681SAndroid Build Coastguard Worker                               "non-verbose or numeric form (requires -macho)"));
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
128*9880d681SAndroid Build Coastguard Worker     llvm::ObjcMetaData("objc-meta-data",
129*9880d681SAndroid Build Coastguard Worker                        cl::desc("Print the Objective-C runtime meta data for "
130*9880d681SAndroid Build Coastguard Worker                                 "Mach-O files (requires -macho)"));
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker cl::opt<std::string> llvm::DisSymName(
133*9880d681SAndroid Build Coastguard Worker     "dis-symname",
134*9880d681SAndroid Build Coastguard Worker     cl::desc("disassemble just this symbol's instructions (requires -macho"));
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> NoSymbolicOperands(
137*9880d681SAndroid Build Coastguard Worker     "no-symbolic-operands",
138*9880d681SAndroid Build Coastguard Worker     cl::desc("do not symbolic operands when disassembling (requires -macho)"));
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker static cl::list<std::string>
141*9880d681SAndroid Build Coastguard Worker     ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
142*9880d681SAndroid Build Coastguard Worker               cl::ZeroOrMore);
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker bool ArchAll = false;
145*9880d681SAndroid Build Coastguard Worker 
146*9880d681SAndroid Build Coastguard Worker static std::string ThumbTripleName;
147*9880d681SAndroid Build Coastguard Worker 
GetTarget(const MachOObjectFile * MachOObj,const char ** McpuDefault,const Target ** ThumbTarget)148*9880d681SAndroid Build Coastguard Worker static const Target *GetTarget(const MachOObjectFile *MachOObj,
149*9880d681SAndroid Build Coastguard Worker                                const char **McpuDefault,
150*9880d681SAndroid Build Coastguard Worker                                const Target **ThumbTarget) {
151*9880d681SAndroid Build Coastguard Worker   // Figure out the target triple.
152*9880d681SAndroid Build Coastguard Worker   llvm::Triple TT(TripleName);
153*9880d681SAndroid Build Coastguard Worker   if (TripleName.empty()) {
154*9880d681SAndroid Build Coastguard Worker     TT = MachOObj->getArchTriple(McpuDefault);
155*9880d681SAndroid Build Coastguard Worker     TripleName = TT.str();
156*9880d681SAndroid Build Coastguard Worker   }
157*9880d681SAndroid Build Coastguard Worker 
158*9880d681SAndroid Build Coastguard Worker   if (TT.getArch() == Triple::arm) {
159*9880d681SAndroid Build Coastguard Worker     // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
160*9880d681SAndroid Build Coastguard Worker     // that support ARM are also capable of Thumb mode.
161*9880d681SAndroid Build Coastguard Worker     llvm::Triple ThumbTriple = TT;
162*9880d681SAndroid Build Coastguard Worker     std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
163*9880d681SAndroid Build Coastguard Worker     ThumbTriple.setArchName(ThumbName);
164*9880d681SAndroid Build Coastguard Worker     ThumbTripleName = ThumbTriple.str();
165*9880d681SAndroid Build Coastguard Worker   }
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker   // Get the target specific parser.
168*9880d681SAndroid Build Coastguard Worker   std::string Error;
169*9880d681SAndroid Build Coastguard Worker   const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
170*9880d681SAndroid Build Coastguard Worker   if (TheTarget && ThumbTripleName.empty())
171*9880d681SAndroid Build Coastguard Worker     return TheTarget;
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker   *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
174*9880d681SAndroid Build Coastguard Worker   if (*ThumbTarget)
175*9880d681SAndroid Build Coastguard Worker     return TheTarget;
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker   errs() << "llvm-objdump: error: unable to get target for '";
178*9880d681SAndroid Build Coastguard Worker   if (!TheTarget)
179*9880d681SAndroid Build Coastguard Worker     errs() << TripleName;
180*9880d681SAndroid Build Coastguard Worker   else
181*9880d681SAndroid Build Coastguard Worker     errs() << ThumbTripleName;
182*9880d681SAndroid Build Coastguard Worker   errs() << "', see --version and --triple.\n";
183*9880d681SAndroid Build Coastguard Worker   return nullptr;
184*9880d681SAndroid Build Coastguard Worker }
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker struct SymbolSorter {
operator ()SymbolSorter187*9880d681SAndroid Build Coastguard Worker   bool operator()(const SymbolRef &A, const SymbolRef &B) {
188*9880d681SAndroid Build Coastguard Worker     Expected<SymbolRef::Type> ATypeOrErr = A.getType();
189*9880d681SAndroid Build Coastguard Worker     if (!ATypeOrErr) {
190*9880d681SAndroid Build Coastguard Worker       std::string Buf;
191*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Buf);
192*9880d681SAndroid Build Coastguard Worker       logAllUnhandledErrors(ATypeOrErr.takeError(), OS, "");
193*9880d681SAndroid Build Coastguard Worker       OS.flush();
194*9880d681SAndroid Build Coastguard Worker       report_fatal_error(Buf);
195*9880d681SAndroid Build Coastguard Worker     }
196*9880d681SAndroid Build Coastguard Worker     SymbolRef::Type AType = *ATypeOrErr;
197*9880d681SAndroid Build Coastguard Worker     Expected<SymbolRef::Type> BTypeOrErr = B.getType();
198*9880d681SAndroid Build Coastguard Worker     if (!BTypeOrErr) {
199*9880d681SAndroid Build Coastguard Worker       std::string Buf;
200*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Buf);
201*9880d681SAndroid Build Coastguard Worker       logAllUnhandledErrors(BTypeOrErr.takeError(), OS, "");
202*9880d681SAndroid Build Coastguard Worker       OS.flush();
203*9880d681SAndroid Build Coastguard Worker       report_fatal_error(Buf);
204*9880d681SAndroid Build Coastguard Worker     }
205*9880d681SAndroid Build Coastguard Worker     SymbolRef::Type BType = *BTypeOrErr;
206*9880d681SAndroid Build Coastguard Worker     uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
207*9880d681SAndroid Build Coastguard Worker     uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
208*9880d681SAndroid Build Coastguard Worker     return AAddr < BAddr;
209*9880d681SAndroid Build Coastguard Worker   }
210*9880d681SAndroid Build Coastguard Worker };
211*9880d681SAndroid Build Coastguard Worker 
212*9880d681SAndroid Build Coastguard Worker // Types for the storted data in code table that is built before disassembly
213*9880d681SAndroid Build Coastguard Worker // and the predicate function to sort them.
214*9880d681SAndroid Build Coastguard Worker typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
215*9880d681SAndroid Build Coastguard Worker typedef std::vector<DiceTableEntry> DiceTable;
216*9880d681SAndroid Build Coastguard Worker typedef DiceTable::iterator dice_table_iterator;
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker // This is used to search for a data in code table entry for the PC being
219*9880d681SAndroid Build Coastguard Worker // disassembled.  The j parameter has the PC in j.first.  A single data in code
220*9880d681SAndroid Build Coastguard Worker // table entry can cover many bytes for each of its Kind's.  So if the offset,
221*9880d681SAndroid Build Coastguard Worker // aka the i.first value, of the data in code table entry plus its Length
222*9880d681SAndroid Build Coastguard Worker // covers the PC being searched for this will return true.  If not it will
223*9880d681SAndroid Build Coastguard Worker // return false.
compareDiceTableEntries(const DiceTableEntry & i,const DiceTableEntry & j)224*9880d681SAndroid Build Coastguard Worker static bool compareDiceTableEntries(const DiceTableEntry &i,
225*9880d681SAndroid Build Coastguard Worker                                     const DiceTableEntry &j) {
226*9880d681SAndroid Build Coastguard Worker   uint16_t Length;
227*9880d681SAndroid Build Coastguard Worker   i.second.getLength(Length);
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker   return j.first >= i.first && j.first < i.first + Length;
230*9880d681SAndroid Build Coastguard Worker }
231*9880d681SAndroid Build Coastguard Worker 
DumpDataInCode(const uint8_t * bytes,uint64_t Length,unsigned short Kind)232*9880d681SAndroid Build Coastguard Worker static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
233*9880d681SAndroid Build Coastguard Worker                                unsigned short Kind) {
234*9880d681SAndroid Build Coastguard Worker   uint32_t Value, Size = 1;
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
237*9880d681SAndroid Build Coastguard Worker   default:
238*9880d681SAndroid Build Coastguard Worker   case MachO::DICE_KIND_DATA:
239*9880d681SAndroid Build Coastguard Worker     if (Length >= 4) {
240*9880d681SAndroid Build Coastguard Worker       if (!NoShowRawInsn)
241*9880d681SAndroid Build Coastguard Worker         dumpBytes(makeArrayRef(bytes, 4), outs());
242*9880d681SAndroid Build Coastguard Worker       Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
243*9880d681SAndroid Build Coastguard Worker       outs() << "\t.long " << Value;
244*9880d681SAndroid Build Coastguard Worker       Size = 4;
245*9880d681SAndroid Build Coastguard Worker     } else if (Length >= 2) {
246*9880d681SAndroid Build Coastguard Worker       if (!NoShowRawInsn)
247*9880d681SAndroid Build Coastguard Worker         dumpBytes(makeArrayRef(bytes, 2), outs());
248*9880d681SAndroid Build Coastguard Worker       Value = bytes[1] << 8 | bytes[0];
249*9880d681SAndroid Build Coastguard Worker       outs() << "\t.short " << Value;
250*9880d681SAndroid Build Coastguard Worker       Size = 2;
251*9880d681SAndroid Build Coastguard Worker     } else {
252*9880d681SAndroid Build Coastguard Worker       if (!NoShowRawInsn)
253*9880d681SAndroid Build Coastguard Worker         dumpBytes(makeArrayRef(bytes, 2), outs());
254*9880d681SAndroid Build Coastguard Worker       Value = bytes[0];
255*9880d681SAndroid Build Coastguard Worker       outs() << "\t.byte " << Value;
256*9880d681SAndroid Build Coastguard Worker       Size = 1;
257*9880d681SAndroid Build Coastguard Worker     }
258*9880d681SAndroid Build Coastguard Worker     if (Kind == MachO::DICE_KIND_DATA)
259*9880d681SAndroid Build Coastguard Worker       outs() << "\t@ KIND_DATA\n";
260*9880d681SAndroid Build Coastguard Worker     else
261*9880d681SAndroid Build Coastguard Worker       outs() << "\t@ data in code kind = " << Kind << "\n";
262*9880d681SAndroid Build Coastguard Worker     break;
263*9880d681SAndroid Build Coastguard Worker   case MachO::DICE_KIND_JUMP_TABLE8:
264*9880d681SAndroid Build Coastguard Worker     if (!NoShowRawInsn)
265*9880d681SAndroid Build Coastguard Worker       dumpBytes(makeArrayRef(bytes, 1), outs());
266*9880d681SAndroid Build Coastguard Worker     Value = bytes[0];
267*9880d681SAndroid Build Coastguard Worker     outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
268*9880d681SAndroid Build Coastguard Worker     Size = 1;
269*9880d681SAndroid Build Coastguard Worker     break;
270*9880d681SAndroid Build Coastguard Worker   case MachO::DICE_KIND_JUMP_TABLE16:
271*9880d681SAndroid Build Coastguard Worker     if (!NoShowRawInsn)
272*9880d681SAndroid Build Coastguard Worker       dumpBytes(makeArrayRef(bytes, 2), outs());
273*9880d681SAndroid Build Coastguard Worker     Value = bytes[1] << 8 | bytes[0];
274*9880d681SAndroid Build Coastguard Worker     outs() << "\t.short " << format("%5u", Value & 0xffff)
275*9880d681SAndroid Build Coastguard Worker            << "\t@ KIND_JUMP_TABLE16\n";
276*9880d681SAndroid Build Coastguard Worker     Size = 2;
277*9880d681SAndroid Build Coastguard Worker     break;
278*9880d681SAndroid Build Coastguard Worker   case MachO::DICE_KIND_JUMP_TABLE32:
279*9880d681SAndroid Build Coastguard Worker   case MachO::DICE_KIND_ABS_JUMP_TABLE32:
280*9880d681SAndroid Build Coastguard Worker     if (!NoShowRawInsn)
281*9880d681SAndroid Build Coastguard Worker       dumpBytes(makeArrayRef(bytes, 4), outs());
282*9880d681SAndroid Build Coastguard Worker     Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
283*9880d681SAndroid Build Coastguard Worker     outs() << "\t.long " << Value;
284*9880d681SAndroid Build Coastguard Worker     if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
285*9880d681SAndroid Build Coastguard Worker       outs() << "\t@ KIND_JUMP_TABLE32\n";
286*9880d681SAndroid Build Coastguard Worker     else
287*9880d681SAndroid Build Coastguard Worker       outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
288*9880d681SAndroid Build Coastguard Worker     Size = 4;
289*9880d681SAndroid Build Coastguard Worker     break;
290*9880d681SAndroid Build Coastguard Worker   }
291*9880d681SAndroid Build Coastguard Worker   return Size;
292*9880d681SAndroid Build Coastguard Worker }
293*9880d681SAndroid Build Coastguard Worker 
getSectionsAndSymbols(MachOObjectFile * MachOObj,std::vector<SectionRef> & Sections,std::vector<SymbolRef> & Symbols,SmallVectorImpl<uint64_t> & FoundFns,uint64_t & BaseSegmentAddress)294*9880d681SAndroid Build Coastguard Worker static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
295*9880d681SAndroid Build Coastguard Worker                                   std::vector<SectionRef> &Sections,
296*9880d681SAndroid Build Coastguard Worker                                   std::vector<SymbolRef> &Symbols,
297*9880d681SAndroid Build Coastguard Worker                                   SmallVectorImpl<uint64_t> &FoundFns,
298*9880d681SAndroid Build Coastguard Worker                                   uint64_t &BaseSegmentAddress) {
299*9880d681SAndroid Build Coastguard Worker   for (const SymbolRef &Symbol : MachOObj->symbols()) {
300*9880d681SAndroid Build Coastguard Worker     Expected<StringRef> SymName = Symbol.getName();
301*9880d681SAndroid Build Coastguard Worker     if (!SymName) {
302*9880d681SAndroid Build Coastguard Worker       std::string Buf;
303*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Buf);
304*9880d681SAndroid Build Coastguard Worker       logAllUnhandledErrors(SymName.takeError(), OS, "");
305*9880d681SAndroid Build Coastguard Worker       OS.flush();
306*9880d681SAndroid Build Coastguard Worker       report_fatal_error(Buf);
307*9880d681SAndroid Build Coastguard Worker     }
308*9880d681SAndroid Build Coastguard Worker     if (!SymName->startswith("ltmp"))
309*9880d681SAndroid Build Coastguard Worker       Symbols.push_back(Symbol);
310*9880d681SAndroid Build Coastguard Worker   }
311*9880d681SAndroid Build Coastguard Worker 
312*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : MachOObj->sections()) {
313*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
314*9880d681SAndroid Build Coastguard Worker     Section.getName(SectName);
315*9880d681SAndroid Build Coastguard Worker     Sections.push_back(Section);
316*9880d681SAndroid Build Coastguard Worker   }
317*9880d681SAndroid Build Coastguard Worker 
318*9880d681SAndroid Build Coastguard Worker   bool BaseSegmentAddressSet = false;
319*9880d681SAndroid Build Coastguard Worker   for (const auto &Command : MachOObj->load_commands()) {
320*9880d681SAndroid Build Coastguard Worker     if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
321*9880d681SAndroid Build Coastguard Worker       // We found a function starts segment, parse the addresses for later
322*9880d681SAndroid Build Coastguard Worker       // consumption.
323*9880d681SAndroid Build Coastguard Worker       MachO::linkedit_data_command LLC =
324*9880d681SAndroid Build Coastguard Worker           MachOObj->getLinkeditDataLoadCommand(Command);
325*9880d681SAndroid Build Coastguard Worker 
326*9880d681SAndroid Build Coastguard Worker       MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
327*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_SEGMENT) {
328*9880d681SAndroid Build Coastguard Worker       MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
329*9880d681SAndroid Build Coastguard Worker       StringRef SegName = SLC.segname;
330*9880d681SAndroid Build Coastguard Worker       if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
331*9880d681SAndroid Build Coastguard Worker         BaseSegmentAddressSet = true;
332*9880d681SAndroid Build Coastguard Worker         BaseSegmentAddress = SLC.vmaddr;
333*9880d681SAndroid Build Coastguard Worker       }
334*9880d681SAndroid Build Coastguard Worker     }
335*9880d681SAndroid Build Coastguard Worker   }
336*9880d681SAndroid Build Coastguard Worker }
337*9880d681SAndroid Build Coastguard Worker 
PrintIndirectSymbolTable(MachOObjectFile * O,bool verbose,uint32_t n,uint32_t count,uint32_t stride,uint64_t addr)338*9880d681SAndroid Build Coastguard Worker static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
339*9880d681SAndroid Build Coastguard Worker                                      uint32_t n, uint32_t count,
340*9880d681SAndroid Build Coastguard Worker                                      uint32_t stride, uint64_t addr) {
341*9880d681SAndroid Build Coastguard Worker   MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
342*9880d681SAndroid Build Coastguard Worker   uint32_t nindirectsyms = Dysymtab.nindirectsyms;
343*9880d681SAndroid Build Coastguard Worker   if (n > nindirectsyms)
344*9880d681SAndroid Build Coastguard Worker     outs() << " (entries start past the end of the indirect symbol "
345*9880d681SAndroid Build Coastguard Worker               "table) (reserved1 field greater than the table size)";
346*9880d681SAndroid Build Coastguard Worker   else if (n + count > nindirectsyms)
347*9880d681SAndroid Build Coastguard Worker     outs() << " (entries extends past the end of the indirect symbol "
348*9880d681SAndroid Build Coastguard Worker               "table)";
349*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
350*9880d681SAndroid Build Coastguard Worker   uint32_t cputype = O->getHeader().cputype;
351*9880d681SAndroid Build Coastguard Worker   if (cputype & MachO::CPU_ARCH_ABI64)
352*9880d681SAndroid Build Coastguard Worker     outs() << "address            index";
353*9880d681SAndroid Build Coastguard Worker   else
354*9880d681SAndroid Build Coastguard Worker     outs() << "address    index";
355*9880d681SAndroid Build Coastguard Worker   if (verbose)
356*9880d681SAndroid Build Coastguard Worker     outs() << " name\n";
357*9880d681SAndroid Build Coastguard Worker   else
358*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
359*9880d681SAndroid Build Coastguard Worker   for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
360*9880d681SAndroid Build Coastguard Worker     if (cputype & MachO::CPU_ARCH_ABI64)
361*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
362*9880d681SAndroid Build Coastguard Worker     else
363*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
364*9880d681SAndroid Build Coastguard Worker     MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
365*9880d681SAndroid Build Coastguard Worker     uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
366*9880d681SAndroid Build Coastguard Worker     if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
367*9880d681SAndroid Build Coastguard Worker       outs() << "LOCAL\n";
368*9880d681SAndroid Build Coastguard Worker       continue;
369*9880d681SAndroid Build Coastguard Worker     }
370*9880d681SAndroid Build Coastguard Worker     if (indirect_symbol ==
371*9880d681SAndroid Build Coastguard Worker         (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
372*9880d681SAndroid Build Coastguard Worker       outs() << "LOCAL ABSOLUTE\n";
373*9880d681SAndroid Build Coastguard Worker       continue;
374*9880d681SAndroid Build Coastguard Worker     }
375*9880d681SAndroid Build Coastguard Worker     if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
376*9880d681SAndroid Build Coastguard Worker       outs() << "ABSOLUTE\n";
377*9880d681SAndroid Build Coastguard Worker       continue;
378*9880d681SAndroid Build Coastguard Worker     }
379*9880d681SAndroid Build Coastguard Worker     outs() << format("%5u ", indirect_symbol);
380*9880d681SAndroid Build Coastguard Worker     if (verbose) {
381*9880d681SAndroid Build Coastguard Worker       MachO::symtab_command Symtab = O->getSymtabLoadCommand();
382*9880d681SAndroid Build Coastguard Worker       if (indirect_symbol < Symtab.nsyms) {
383*9880d681SAndroid Build Coastguard Worker         symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
384*9880d681SAndroid Build Coastguard Worker         SymbolRef Symbol = *Sym;
385*9880d681SAndroid Build Coastguard Worker         Expected<StringRef> SymName = Symbol.getName();
386*9880d681SAndroid Build Coastguard Worker         if (!SymName) {
387*9880d681SAndroid Build Coastguard Worker           std::string Buf;
388*9880d681SAndroid Build Coastguard Worker           raw_string_ostream OS(Buf);
389*9880d681SAndroid Build Coastguard Worker           logAllUnhandledErrors(SymName.takeError(), OS, "");
390*9880d681SAndroid Build Coastguard Worker           OS.flush();
391*9880d681SAndroid Build Coastguard Worker           report_fatal_error(Buf);
392*9880d681SAndroid Build Coastguard Worker         }
393*9880d681SAndroid Build Coastguard Worker         outs() << *SymName;
394*9880d681SAndroid Build Coastguard Worker       } else {
395*9880d681SAndroid Build Coastguard Worker         outs() << "?";
396*9880d681SAndroid Build Coastguard Worker       }
397*9880d681SAndroid Build Coastguard Worker     }
398*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
399*9880d681SAndroid Build Coastguard Worker   }
400*9880d681SAndroid Build Coastguard Worker }
401*9880d681SAndroid Build Coastguard Worker 
PrintIndirectSymbols(MachOObjectFile * O,bool verbose)402*9880d681SAndroid Build Coastguard Worker static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
403*9880d681SAndroid Build Coastguard Worker   for (const auto &Load : O->load_commands()) {
404*9880d681SAndroid Build Coastguard Worker     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
405*9880d681SAndroid Build Coastguard Worker       MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
406*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
407*9880d681SAndroid Build Coastguard Worker         MachO::section_64 Sec = O->getSection64(Load, J);
408*9880d681SAndroid Build Coastguard Worker         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
409*9880d681SAndroid Build Coastguard Worker         if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
410*9880d681SAndroid Build Coastguard Worker             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
411*9880d681SAndroid Build Coastguard Worker             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
412*9880d681SAndroid Build Coastguard Worker             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
413*9880d681SAndroid Build Coastguard Worker             section_type == MachO::S_SYMBOL_STUBS) {
414*9880d681SAndroid Build Coastguard Worker           uint32_t stride;
415*9880d681SAndroid Build Coastguard Worker           if (section_type == MachO::S_SYMBOL_STUBS)
416*9880d681SAndroid Build Coastguard Worker             stride = Sec.reserved2;
417*9880d681SAndroid Build Coastguard Worker           else
418*9880d681SAndroid Build Coastguard Worker             stride = 8;
419*9880d681SAndroid Build Coastguard Worker           if (stride == 0) {
420*9880d681SAndroid Build Coastguard Worker             outs() << "Can't print indirect symbols for (" << Sec.segname << ","
421*9880d681SAndroid Build Coastguard Worker                    << Sec.sectname << ") "
422*9880d681SAndroid Build Coastguard Worker                    << "(size of stubs in reserved2 field is zero)\n";
423*9880d681SAndroid Build Coastguard Worker             continue;
424*9880d681SAndroid Build Coastguard Worker           }
425*9880d681SAndroid Build Coastguard Worker           uint32_t count = Sec.size / stride;
426*9880d681SAndroid Build Coastguard Worker           outs() << "Indirect symbols for (" << Sec.segname << ","
427*9880d681SAndroid Build Coastguard Worker                  << Sec.sectname << ") " << count << " entries";
428*9880d681SAndroid Build Coastguard Worker           uint32_t n = Sec.reserved1;
429*9880d681SAndroid Build Coastguard Worker           PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
430*9880d681SAndroid Build Coastguard Worker         }
431*9880d681SAndroid Build Coastguard Worker       }
432*9880d681SAndroid Build Coastguard Worker     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
433*9880d681SAndroid Build Coastguard Worker       MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
434*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
435*9880d681SAndroid Build Coastguard Worker         MachO::section Sec = O->getSection(Load, J);
436*9880d681SAndroid Build Coastguard Worker         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
437*9880d681SAndroid Build Coastguard Worker         if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
438*9880d681SAndroid Build Coastguard Worker             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
439*9880d681SAndroid Build Coastguard Worker             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
440*9880d681SAndroid Build Coastguard Worker             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
441*9880d681SAndroid Build Coastguard Worker             section_type == MachO::S_SYMBOL_STUBS) {
442*9880d681SAndroid Build Coastguard Worker           uint32_t stride;
443*9880d681SAndroid Build Coastguard Worker           if (section_type == MachO::S_SYMBOL_STUBS)
444*9880d681SAndroid Build Coastguard Worker             stride = Sec.reserved2;
445*9880d681SAndroid Build Coastguard Worker           else
446*9880d681SAndroid Build Coastguard Worker             stride = 4;
447*9880d681SAndroid Build Coastguard Worker           if (stride == 0) {
448*9880d681SAndroid Build Coastguard Worker             outs() << "Can't print indirect symbols for (" << Sec.segname << ","
449*9880d681SAndroid Build Coastguard Worker                    << Sec.sectname << ") "
450*9880d681SAndroid Build Coastguard Worker                    << "(size of stubs in reserved2 field is zero)\n";
451*9880d681SAndroid Build Coastguard Worker             continue;
452*9880d681SAndroid Build Coastguard Worker           }
453*9880d681SAndroid Build Coastguard Worker           uint32_t count = Sec.size / stride;
454*9880d681SAndroid Build Coastguard Worker           outs() << "Indirect symbols for (" << Sec.segname << ","
455*9880d681SAndroid Build Coastguard Worker                  << Sec.sectname << ") " << count << " entries";
456*9880d681SAndroid Build Coastguard Worker           uint32_t n = Sec.reserved1;
457*9880d681SAndroid Build Coastguard Worker           PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
458*9880d681SAndroid Build Coastguard Worker         }
459*9880d681SAndroid Build Coastguard Worker       }
460*9880d681SAndroid Build Coastguard Worker     }
461*9880d681SAndroid Build Coastguard Worker   }
462*9880d681SAndroid Build Coastguard Worker }
463*9880d681SAndroid Build Coastguard Worker 
PrintDataInCodeTable(MachOObjectFile * O,bool verbose)464*9880d681SAndroid Build Coastguard Worker static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
465*9880d681SAndroid Build Coastguard Worker   MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
466*9880d681SAndroid Build Coastguard Worker   uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
467*9880d681SAndroid Build Coastguard Worker   outs() << "Data in code table (" << nentries << " entries)\n";
468*9880d681SAndroid Build Coastguard Worker   outs() << "offset     length kind\n";
469*9880d681SAndroid Build Coastguard Worker   for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
470*9880d681SAndroid Build Coastguard Worker        ++DI) {
471*9880d681SAndroid Build Coastguard Worker     uint32_t Offset;
472*9880d681SAndroid Build Coastguard Worker     DI->getOffset(Offset);
473*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%08" PRIx32, Offset) << " ";
474*9880d681SAndroid Build Coastguard Worker     uint16_t Length;
475*9880d681SAndroid Build Coastguard Worker     DI->getLength(Length);
476*9880d681SAndroid Build Coastguard Worker     outs() << format("%6u", Length) << " ";
477*9880d681SAndroid Build Coastguard Worker     uint16_t Kind;
478*9880d681SAndroid Build Coastguard Worker     DI->getKind(Kind);
479*9880d681SAndroid Build Coastguard Worker     if (verbose) {
480*9880d681SAndroid Build Coastguard Worker       switch (Kind) {
481*9880d681SAndroid Build Coastguard Worker       case MachO::DICE_KIND_DATA:
482*9880d681SAndroid Build Coastguard Worker         outs() << "DATA";
483*9880d681SAndroid Build Coastguard Worker         break;
484*9880d681SAndroid Build Coastguard Worker       case MachO::DICE_KIND_JUMP_TABLE8:
485*9880d681SAndroid Build Coastguard Worker         outs() << "JUMP_TABLE8";
486*9880d681SAndroid Build Coastguard Worker         break;
487*9880d681SAndroid Build Coastguard Worker       case MachO::DICE_KIND_JUMP_TABLE16:
488*9880d681SAndroid Build Coastguard Worker         outs() << "JUMP_TABLE16";
489*9880d681SAndroid Build Coastguard Worker         break;
490*9880d681SAndroid Build Coastguard Worker       case MachO::DICE_KIND_JUMP_TABLE32:
491*9880d681SAndroid Build Coastguard Worker         outs() << "JUMP_TABLE32";
492*9880d681SAndroid Build Coastguard Worker         break;
493*9880d681SAndroid Build Coastguard Worker       case MachO::DICE_KIND_ABS_JUMP_TABLE32:
494*9880d681SAndroid Build Coastguard Worker         outs() << "ABS_JUMP_TABLE32";
495*9880d681SAndroid Build Coastguard Worker         break;
496*9880d681SAndroid Build Coastguard Worker       default:
497*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%04" PRIx32, Kind);
498*9880d681SAndroid Build Coastguard Worker         break;
499*9880d681SAndroid Build Coastguard Worker       }
500*9880d681SAndroid Build Coastguard Worker     } else
501*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%04" PRIx32, Kind);
502*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
503*9880d681SAndroid Build Coastguard Worker   }
504*9880d681SAndroid Build Coastguard Worker }
505*9880d681SAndroid Build Coastguard Worker 
PrintLinkOptHints(MachOObjectFile * O)506*9880d681SAndroid Build Coastguard Worker static void PrintLinkOptHints(MachOObjectFile *O) {
507*9880d681SAndroid Build Coastguard Worker   MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
508*9880d681SAndroid Build Coastguard Worker   const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
509*9880d681SAndroid Build Coastguard Worker   uint32_t nloh = LohLC.datasize;
510*9880d681SAndroid Build Coastguard Worker   outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
511*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < nloh;) {
512*9880d681SAndroid Build Coastguard Worker     unsigned n;
513*9880d681SAndroid Build Coastguard Worker     uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
514*9880d681SAndroid Build Coastguard Worker     i += n;
515*9880d681SAndroid Build Coastguard Worker     outs() << "    identifier " << identifier << " ";
516*9880d681SAndroid Build Coastguard Worker     if (i >= nloh)
517*9880d681SAndroid Build Coastguard Worker       return;
518*9880d681SAndroid Build Coastguard Worker     switch (identifier) {
519*9880d681SAndroid Build Coastguard Worker     case 1:
520*9880d681SAndroid Build Coastguard Worker       outs() << "AdrpAdrp\n";
521*9880d681SAndroid Build Coastguard Worker       break;
522*9880d681SAndroid Build Coastguard Worker     case 2:
523*9880d681SAndroid Build Coastguard Worker       outs() << "AdrpLdr\n";
524*9880d681SAndroid Build Coastguard Worker       break;
525*9880d681SAndroid Build Coastguard Worker     case 3:
526*9880d681SAndroid Build Coastguard Worker       outs() << "AdrpAddLdr\n";
527*9880d681SAndroid Build Coastguard Worker       break;
528*9880d681SAndroid Build Coastguard Worker     case 4:
529*9880d681SAndroid Build Coastguard Worker       outs() << "AdrpLdrGotLdr\n";
530*9880d681SAndroid Build Coastguard Worker       break;
531*9880d681SAndroid Build Coastguard Worker     case 5:
532*9880d681SAndroid Build Coastguard Worker       outs() << "AdrpAddStr\n";
533*9880d681SAndroid Build Coastguard Worker       break;
534*9880d681SAndroid Build Coastguard Worker     case 6:
535*9880d681SAndroid Build Coastguard Worker       outs() << "AdrpLdrGotStr\n";
536*9880d681SAndroid Build Coastguard Worker       break;
537*9880d681SAndroid Build Coastguard Worker     case 7:
538*9880d681SAndroid Build Coastguard Worker       outs() << "AdrpAdd\n";
539*9880d681SAndroid Build Coastguard Worker       break;
540*9880d681SAndroid Build Coastguard Worker     case 8:
541*9880d681SAndroid Build Coastguard Worker       outs() << "AdrpLdrGot\n";
542*9880d681SAndroid Build Coastguard Worker       break;
543*9880d681SAndroid Build Coastguard Worker     default:
544*9880d681SAndroid Build Coastguard Worker       outs() << "Unknown identifier value\n";
545*9880d681SAndroid Build Coastguard Worker       break;
546*9880d681SAndroid Build Coastguard Worker     }
547*9880d681SAndroid Build Coastguard Worker     uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
548*9880d681SAndroid Build Coastguard Worker     i += n;
549*9880d681SAndroid Build Coastguard Worker     outs() << "    narguments " << narguments << "\n";
550*9880d681SAndroid Build Coastguard Worker     if (i >= nloh)
551*9880d681SAndroid Build Coastguard Worker       return;
552*9880d681SAndroid Build Coastguard Worker 
553*9880d681SAndroid Build Coastguard Worker     for (uint32_t j = 0; j < narguments; j++) {
554*9880d681SAndroid Build Coastguard Worker       uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
555*9880d681SAndroid Build Coastguard Worker       i += n;
556*9880d681SAndroid Build Coastguard Worker       outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
557*9880d681SAndroid Build Coastguard Worker       if (i >= nloh)
558*9880d681SAndroid Build Coastguard Worker         return;
559*9880d681SAndroid Build Coastguard Worker     }
560*9880d681SAndroid Build Coastguard Worker   }
561*9880d681SAndroid Build Coastguard Worker }
562*9880d681SAndroid Build Coastguard Worker 
PrintDylibs(MachOObjectFile * O,bool JustId)563*9880d681SAndroid Build Coastguard Worker static void PrintDylibs(MachOObjectFile *O, bool JustId) {
564*9880d681SAndroid Build Coastguard Worker   unsigned Index = 0;
565*9880d681SAndroid Build Coastguard Worker   for (const auto &Load : O->load_commands()) {
566*9880d681SAndroid Build Coastguard Worker     if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
567*9880d681SAndroid Build Coastguard Worker         (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
568*9880d681SAndroid Build Coastguard Worker                      Load.C.cmd == MachO::LC_LOAD_DYLIB ||
569*9880d681SAndroid Build Coastguard Worker                      Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
570*9880d681SAndroid Build Coastguard Worker                      Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
571*9880d681SAndroid Build Coastguard Worker                      Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
572*9880d681SAndroid Build Coastguard Worker                      Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
573*9880d681SAndroid Build Coastguard Worker       MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
574*9880d681SAndroid Build Coastguard Worker       if (dl.dylib.name < dl.cmdsize) {
575*9880d681SAndroid Build Coastguard Worker         const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
576*9880d681SAndroid Build Coastguard Worker         if (JustId)
577*9880d681SAndroid Build Coastguard Worker           outs() << p << "\n";
578*9880d681SAndroid Build Coastguard Worker         else {
579*9880d681SAndroid Build Coastguard Worker           outs() << "\t" << p;
580*9880d681SAndroid Build Coastguard Worker           outs() << " (compatibility version "
581*9880d681SAndroid Build Coastguard Worker                  << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
582*9880d681SAndroid Build Coastguard Worker                  << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
583*9880d681SAndroid Build Coastguard Worker                  << (dl.dylib.compatibility_version & 0xff) << ",";
584*9880d681SAndroid Build Coastguard Worker           outs() << " current version "
585*9880d681SAndroid Build Coastguard Worker                  << ((dl.dylib.current_version >> 16) & 0xffff) << "."
586*9880d681SAndroid Build Coastguard Worker                  << ((dl.dylib.current_version >> 8) & 0xff) << "."
587*9880d681SAndroid Build Coastguard Worker                  << (dl.dylib.current_version & 0xff) << ")\n";
588*9880d681SAndroid Build Coastguard Worker         }
589*9880d681SAndroid Build Coastguard Worker       } else {
590*9880d681SAndroid Build Coastguard Worker         outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
591*9880d681SAndroid Build Coastguard Worker         if (Load.C.cmd == MachO::LC_ID_DYLIB)
592*9880d681SAndroid Build Coastguard Worker           outs() << "LC_ID_DYLIB ";
593*9880d681SAndroid Build Coastguard Worker         else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
594*9880d681SAndroid Build Coastguard Worker           outs() << "LC_LOAD_DYLIB ";
595*9880d681SAndroid Build Coastguard Worker         else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
596*9880d681SAndroid Build Coastguard Worker           outs() << "LC_LOAD_WEAK_DYLIB ";
597*9880d681SAndroid Build Coastguard Worker         else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
598*9880d681SAndroid Build Coastguard Worker           outs() << "LC_LAZY_LOAD_DYLIB ";
599*9880d681SAndroid Build Coastguard Worker         else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
600*9880d681SAndroid Build Coastguard Worker           outs() << "LC_REEXPORT_DYLIB ";
601*9880d681SAndroid Build Coastguard Worker         else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
602*9880d681SAndroid Build Coastguard Worker           outs() << "LC_LOAD_UPWARD_DYLIB ";
603*9880d681SAndroid Build Coastguard Worker         else
604*9880d681SAndroid Build Coastguard Worker           outs() << "LC_??? ";
605*9880d681SAndroid Build Coastguard Worker         outs() << "command " << Index++ << "\n";
606*9880d681SAndroid Build Coastguard Worker       }
607*9880d681SAndroid Build Coastguard Worker     }
608*9880d681SAndroid Build Coastguard Worker   }
609*9880d681SAndroid Build Coastguard Worker }
610*9880d681SAndroid Build Coastguard Worker 
611*9880d681SAndroid Build Coastguard Worker typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
612*9880d681SAndroid Build Coastguard Worker 
CreateSymbolAddressMap(MachOObjectFile * O,SymbolAddressMap * AddrMap)613*9880d681SAndroid Build Coastguard Worker static void CreateSymbolAddressMap(MachOObjectFile *O,
614*9880d681SAndroid Build Coastguard Worker                                    SymbolAddressMap *AddrMap) {
615*9880d681SAndroid Build Coastguard Worker   // Create a map of symbol addresses to symbol names.
616*9880d681SAndroid Build Coastguard Worker   for (const SymbolRef &Symbol : O->symbols()) {
617*9880d681SAndroid Build Coastguard Worker     Expected<SymbolRef::Type> STOrErr = Symbol.getType();
618*9880d681SAndroid Build Coastguard Worker     if (!STOrErr) {
619*9880d681SAndroid Build Coastguard Worker       std::string Buf;
620*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Buf);
621*9880d681SAndroid Build Coastguard Worker       logAllUnhandledErrors(STOrErr.takeError(), OS, "");
622*9880d681SAndroid Build Coastguard Worker       OS.flush();
623*9880d681SAndroid Build Coastguard Worker       report_fatal_error(Buf);
624*9880d681SAndroid Build Coastguard Worker     }
625*9880d681SAndroid Build Coastguard Worker     SymbolRef::Type ST = *STOrErr;
626*9880d681SAndroid Build Coastguard Worker     if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
627*9880d681SAndroid Build Coastguard Worker         ST == SymbolRef::ST_Other) {
628*9880d681SAndroid Build Coastguard Worker       uint64_t Address = Symbol.getValue();
629*9880d681SAndroid Build Coastguard Worker       Expected<StringRef> SymNameOrErr = Symbol.getName();
630*9880d681SAndroid Build Coastguard Worker       if (!SymNameOrErr) {
631*9880d681SAndroid Build Coastguard Worker         std::string Buf;
632*9880d681SAndroid Build Coastguard Worker         raw_string_ostream OS(Buf);
633*9880d681SAndroid Build Coastguard Worker         logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
634*9880d681SAndroid Build Coastguard Worker         OS.flush();
635*9880d681SAndroid Build Coastguard Worker         report_fatal_error(Buf);
636*9880d681SAndroid Build Coastguard Worker       }
637*9880d681SAndroid Build Coastguard Worker       StringRef SymName = *SymNameOrErr;
638*9880d681SAndroid Build Coastguard Worker       if (!SymName.startswith(".objc"))
639*9880d681SAndroid Build Coastguard Worker         (*AddrMap)[Address] = SymName;
640*9880d681SAndroid Build Coastguard Worker     }
641*9880d681SAndroid Build Coastguard Worker   }
642*9880d681SAndroid Build Coastguard Worker }
643*9880d681SAndroid Build Coastguard Worker 
644*9880d681SAndroid Build Coastguard Worker // GuessSymbolName is passed the address of what might be a symbol and a
645*9880d681SAndroid Build Coastguard Worker // pointer to the SymbolAddressMap.  It returns the name of a symbol
646*9880d681SAndroid Build Coastguard Worker // with that address or nullptr if no symbol is found with that address.
GuessSymbolName(uint64_t value,SymbolAddressMap * AddrMap)647*9880d681SAndroid Build Coastguard Worker static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
648*9880d681SAndroid Build Coastguard Worker   const char *SymbolName = nullptr;
649*9880d681SAndroid Build Coastguard Worker   // A DenseMap can't lookup up some values.
650*9880d681SAndroid Build Coastguard Worker   if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
651*9880d681SAndroid Build Coastguard Worker     StringRef name = AddrMap->lookup(value);
652*9880d681SAndroid Build Coastguard Worker     if (!name.empty())
653*9880d681SAndroid Build Coastguard Worker       SymbolName = name.data();
654*9880d681SAndroid Build Coastguard Worker   }
655*9880d681SAndroid Build Coastguard Worker   return SymbolName;
656*9880d681SAndroid Build Coastguard Worker }
657*9880d681SAndroid Build Coastguard Worker 
DumpCstringChar(const char c)658*9880d681SAndroid Build Coastguard Worker static void DumpCstringChar(const char c) {
659*9880d681SAndroid Build Coastguard Worker   char p[2];
660*9880d681SAndroid Build Coastguard Worker   p[0] = c;
661*9880d681SAndroid Build Coastguard Worker   p[1] = '\0';
662*9880d681SAndroid Build Coastguard Worker   outs().write_escaped(p);
663*9880d681SAndroid Build Coastguard Worker }
664*9880d681SAndroid Build Coastguard Worker 
DumpCstringSection(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)665*9880d681SAndroid Build Coastguard Worker static void DumpCstringSection(MachOObjectFile *O, const char *sect,
666*9880d681SAndroid Build Coastguard Worker                                uint32_t sect_size, uint64_t sect_addr,
667*9880d681SAndroid Build Coastguard Worker                                bool print_addresses) {
668*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < sect_size; i++) {
669*9880d681SAndroid Build Coastguard Worker     if (print_addresses) {
670*9880d681SAndroid Build Coastguard Worker       if (O->is64Bit())
671*9880d681SAndroid Build Coastguard Worker         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
672*9880d681SAndroid Build Coastguard Worker       else
673*9880d681SAndroid Build Coastguard Worker         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
674*9880d681SAndroid Build Coastguard Worker     }
675*9880d681SAndroid Build Coastguard Worker     for (; i < sect_size && sect[i] != '\0'; i++)
676*9880d681SAndroid Build Coastguard Worker       DumpCstringChar(sect[i]);
677*9880d681SAndroid Build Coastguard Worker     if (i < sect_size && sect[i] == '\0')
678*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
679*9880d681SAndroid Build Coastguard Worker   }
680*9880d681SAndroid Build Coastguard Worker }
681*9880d681SAndroid Build Coastguard Worker 
DumpLiteral4(uint32_t l,float f)682*9880d681SAndroid Build Coastguard Worker static void DumpLiteral4(uint32_t l, float f) {
683*9880d681SAndroid Build Coastguard Worker   outs() << format("0x%08" PRIx32, l);
684*9880d681SAndroid Build Coastguard Worker   if ((l & 0x7f800000) != 0x7f800000)
685*9880d681SAndroid Build Coastguard Worker     outs() << format(" (%.16e)\n", f);
686*9880d681SAndroid Build Coastguard Worker   else {
687*9880d681SAndroid Build Coastguard Worker     if (l == 0x7f800000)
688*9880d681SAndroid Build Coastguard Worker       outs() << " (+Infinity)\n";
689*9880d681SAndroid Build Coastguard Worker     else if (l == 0xff800000)
690*9880d681SAndroid Build Coastguard Worker       outs() << " (-Infinity)\n";
691*9880d681SAndroid Build Coastguard Worker     else if ((l & 0x00400000) == 0x00400000)
692*9880d681SAndroid Build Coastguard Worker       outs() << " (non-signaling Not-a-Number)\n";
693*9880d681SAndroid Build Coastguard Worker     else
694*9880d681SAndroid Build Coastguard Worker       outs() << " (signaling Not-a-Number)\n";
695*9880d681SAndroid Build Coastguard Worker   }
696*9880d681SAndroid Build Coastguard Worker }
697*9880d681SAndroid Build Coastguard Worker 
DumpLiteral4Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)698*9880d681SAndroid Build Coastguard Worker static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
699*9880d681SAndroid Build Coastguard Worker                                 uint32_t sect_size, uint64_t sect_addr,
700*9880d681SAndroid Build Coastguard Worker                                 bool print_addresses) {
701*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
702*9880d681SAndroid Build Coastguard Worker     if (print_addresses) {
703*9880d681SAndroid Build Coastguard Worker       if (O->is64Bit())
704*9880d681SAndroid Build Coastguard Worker         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
705*9880d681SAndroid Build Coastguard Worker       else
706*9880d681SAndroid Build Coastguard Worker         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
707*9880d681SAndroid Build Coastguard Worker     }
708*9880d681SAndroid Build Coastguard Worker     float f;
709*9880d681SAndroid Build Coastguard Worker     memcpy(&f, sect + i, sizeof(float));
710*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost)
711*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(f);
712*9880d681SAndroid Build Coastguard Worker     uint32_t l;
713*9880d681SAndroid Build Coastguard Worker     memcpy(&l, sect + i, sizeof(uint32_t));
714*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost)
715*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(l);
716*9880d681SAndroid Build Coastguard Worker     DumpLiteral4(l, f);
717*9880d681SAndroid Build Coastguard Worker   }
718*9880d681SAndroid Build Coastguard Worker }
719*9880d681SAndroid Build Coastguard Worker 
DumpLiteral8(MachOObjectFile * O,uint32_t l0,uint32_t l1,double d)720*9880d681SAndroid Build Coastguard Worker static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
721*9880d681SAndroid Build Coastguard Worker                          double d) {
722*9880d681SAndroid Build Coastguard Worker   outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
723*9880d681SAndroid Build Coastguard Worker   uint32_t Hi, Lo;
724*9880d681SAndroid Build Coastguard Worker   Hi = (O->isLittleEndian()) ? l1 : l0;
725*9880d681SAndroid Build Coastguard Worker   Lo = (O->isLittleEndian()) ? l0 : l1;
726*9880d681SAndroid Build Coastguard Worker 
727*9880d681SAndroid Build Coastguard Worker   // Hi is the high word, so this is equivalent to if(isfinite(d))
728*9880d681SAndroid Build Coastguard Worker   if ((Hi & 0x7ff00000) != 0x7ff00000)
729*9880d681SAndroid Build Coastguard Worker     outs() << format(" (%.16e)\n", d);
730*9880d681SAndroid Build Coastguard Worker   else {
731*9880d681SAndroid Build Coastguard Worker     if (Hi == 0x7ff00000 && Lo == 0)
732*9880d681SAndroid Build Coastguard Worker       outs() << " (+Infinity)\n";
733*9880d681SAndroid Build Coastguard Worker     else if (Hi == 0xfff00000 && Lo == 0)
734*9880d681SAndroid Build Coastguard Worker       outs() << " (-Infinity)\n";
735*9880d681SAndroid Build Coastguard Worker     else if ((Hi & 0x00080000) == 0x00080000)
736*9880d681SAndroid Build Coastguard Worker       outs() << " (non-signaling Not-a-Number)\n";
737*9880d681SAndroid Build Coastguard Worker     else
738*9880d681SAndroid Build Coastguard Worker       outs() << " (signaling Not-a-Number)\n";
739*9880d681SAndroid Build Coastguard Worker   }
740*9880d681SAndroid Build Coastguard Worker }
741*9880d681SAndroid Build Coastguard Worker 
DumpLiteral8Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)742*9880d681SAndroid Build Coastguard Worker static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
743*9880d681SAndroid Build Coastguard Worker                                 uint32_t sect_size, uint64_t sect_addr,
744*9880d681SAndroid Build Coastguard Worker                                 bool print_addresses) {
745*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
746*9880d681SAndroid Build Coastguard Worker     if (print_addresses) {
747*9880d681SAndroid Build Coastguard Worker       if (O->is64Bit())
748*9880d681SAndroid Build Coastguard Worker         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
749*9880d681SAndroid Build Coastguard Worker       else
750*9880d681SAndroid Build Coastguard Worker         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
751*9880d681SAndroid Build Coastguard Worker     }
752*9880d681SAndroid Build Coastguard Worker     double d;
753*9880d681SAndroid Build Coastguard Worker     memcpy(&d, sect + i, sizeof(double));
754*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost)
755*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(d);
756*9880d681SAndroid Build Coastguard Worker     uint32_t l0, l1;
757*9880d681SAndroid Build Coastguard Worker     memcpy(&l0, sect + i, sizeof(uint32_t));
758*9880d681SAndroid Build Coastguard Worker     memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
759*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost) {
760*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(l0);
761*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(l1);
762*9880d681SAndroid Build Coastguard Worker     }
763*9880d681SAndroid Build Coastguard Worker     DumpLiteral8(O, l0, l1, d);
764*9880d681SAndroid Build Coastguard Worker   }
765*9880d681SAndroid Build Coastguard Worker }
766*9880d681SAndroid Build Coastguard Worker 
DumpLiteral16(uint32_t l0,uint32_t l1,uint32_t l2,uint32_t l3)767*9880d681SAndroid Build Coastguard Worker static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
768*9880d681SAndroid Build Coastguard Worker   outs() << format("0x%08" PRIx32, l0) << " ";
769*9880d681SAndroid Build Coastguard Worker   outs() << format("0x%08" PRIx32, l1) << " ";
770*9880d681SAndroid Build Coastguard Worker   outs() << format("0x%08" PRIx32, l2) << " ";
771*9880d681SAndroid Build Coastguard Worker   outs() << format("0x%08" PRIx32, l3) << "\n";
772*9880d681SAndroid Build Coastguard Worker }
773*9880d681SAndroid Build Coastguard Worker 
DumpLiteral16Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)774*9880d681SAndroid Build Coastguard Worker static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
775*9880d681SAndroid Build Coastguard Worker                                  uint32_t sect_size, uint64_t sect_addr,
776*9880d681SAndroid Build Coastguard Worker                                  bool print_addresses) {
777*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < sect_size; i += 16) {
778*9880d681SAndroid Build Coastguard Worker     if (print_addresses) {
779*9880d681SAndroid Build Coastguard Worker       if (O->is64Bit())
780*9880d681SAndroid Build Coastguard Worker         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
781*9880d681SAndroid Build Coastguard Worker       else
782*9880d681SAndroid Build Coastguard Worker         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
783*9880d681SAndroid Build Coastguard Worker     }
784*9880d681SAndroid Build Coastguard Worker     uint32_t l0, l1, l2, l3;
785*9880d681SAndroid Build Coastguard Worker     memcpy(&l0, sect + i, sizeof(uint32_t));
786*9880d681SAndroid Build Coastguard Worker     memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
787*9880d681SAndroid Build Coastguard Worker     memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
788*9880d681SAndroid Build Coastguard Worker     memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
789*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost) {
790*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(l0);
791*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(l1);
792*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(l2);
793*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(l3);
794*9880d681SAndroid Build Coastguard Worker     }
795*9880d681SAndroid Build Coastguard Worker     DumpLiteral16(l0, l1, l2, l3);
796*9880d681SAndroid Build Coastguard Worker   }
797*9880d681SAndroid Build Coastguard Worker }
798*9880d681SAndroid Build Coastguard Worker 
DumpLiteralPointerSection(MachOObjectFile * O,const SectionRef & Section,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)799*9880d681SAndroid Build Coastguard Worker static void DumpLiteralPointerSection(MachOObjectFile *O,
800*9880d681SAndroid Build Coastguard Worker                                       const SectionRef &Section,
801*9880d681SAndroid Build Coastguard Worker                                       const char *sect, uint32_t sect_size,
802*9880d681SAndroid Build Coastguard Worker                                       uint64_t sect_addr,
803*9880d681SAndroid Build Coastguard Worker                                       bool print_addresses) {
804*9880d681SAndroid Build Coastguard Worker   // Collect the literal sections in this Mach-O file.
805*9880d681SAndroid Build Coastguard Worker   std::vector<SectionRef> LiteralSections;
806*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : O->sections()) {
807*9880d681SAndroid Build Coastguard Worker     DataRefImpl Ref = Section.getRawDataRefImpl();
808*9880d681SAndroid Build Coastguard Worker     uint32_t section_type;
809*9880d681SAndroid Build Coastguard Worker     if (O->is64Bit()) {
810*9880d681SAndroid Build Coastguard Worker       const MachO::section_64 Sec = O->getSection64(Ref);
811*9880d681SAndroid Build Coastguard Worker       section_type = Sec.flags & MachO::SECTION_TYPE;
812*9880d681SAndroid Build Coastguard Worker     } else {
813*9880d681SAndroid Build Coastguard Worker       const MachO::section Sec = O->getSection(Ref);
814*9880d681SAndroid Build Coastguard Worker       section_type = Sec.flags & MachO::SECTION_TYPE;
815*9880d681SAndroid Build Coastguard Worker     }
816*9880d681SAndroid Build Coastguard Worker     if (section_type == MachO::S_CSTRING_LITERALS ||
817*9880d681SAndroid Build Coastguard Worker         section_type == MachO::S_4BYTE_LITERALS ||
818*9880d681SAndroid Build Coastguard Worker         section_type == MachO::S_8BYTE_LITERALS ||
819*9880d681SAndroid Build Coastguard Worker         section_type == MachO::S_16BYTE_LITERALS)
820*9880d681SAndroid Build Coastguard Worker       LiteralSections.push_back(Section);
821*9880d681SAndroid Build Coastguard Worker   }
822*9880d681SAndroid Build Coastguard Worker 
823*9880d681SAndroid Build Coastguard Worker   // Set the size of the literal pointer.
824*9880d681SAndroid Build Coastguard Worker   uint32_t lp_size = O->is64Bit() ? 8 : 4;
825*9880d681SAndroid Build Coastguard Worker 
826*9880d681SAndroid Build Coastguard Worker   // Collect the external relocation symbols for the literal pointers.
827*9880d681SAndroid Build Coastguard Worker   std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
828*9880d681SAndroid Build Coastguard Worker   for (const RelocationRef &Reloc : Section.relocations()) {
829*9880d681SAndroid Build Coastguard Worker     DataRefImpl Rel;
830*9880d681SAndroid Build Coastguard Worker     MachO::any_relocation_info RE;
831*9880d681SAndroid Build Coastguard Worker     bool isExtern = false;
832*9880d681SAndroid Build Coastguard Worker     Rel = Reloc.getRawDataRefImpl();
833*9880d681SAndroid Build Coastguard Worker     RE = O->getRelocation(Rel);
834*9880d681SAndroid Build Coastguard Worker     isExtern = O->getPlainRelocationExternal(RE);
835*9880d681SAndroid Build Coastguard Worker     if (isExtern) {
836*9880d681SAndroid Build Coastguard Worker       uint64_t RelocOffset = Reloc.getOffset();
837*9880d681SAndroid Build Coastguard Worker       symbol_iterator RelocSym = Reloc.getSymbol();
838*9880d681SAndroid Build Coastguard Worker       Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
839*9880d681SAndroid Build Coastguard Worker     }
840*9880d681SAndroid Build Coastguard Worker   }
841*9880d681SAndroid Build Coastguard Worker   array_pod_sort(Relocs.begin(), Relocs.end());
842*9880d681SAndroid Build Coastguard Worker 
843*9880d681SAndroid Build Coastguard Worker   // Dump each literal pointer.
844*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < sect_size; i += lp_size) {
845*9880d681SAndroid Build Coastguard Worker     if (print_addresses) {
846*9880d681SAndroid Build Coastguard Worker       if (O->is64Bit())
847*9880d681SAndroid Build Coastguard Worker         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
848*9880d681SAndroid Build Coastguard Worker       else
849*9880d681SAndroid Build Coastguard Worker         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
850*9880d681SAndroid Build Coastguard Worker     }
851*9880d681SAndroid Build Coastguard Worker     uint64_t lp;
852*9880d681SAndroid Build Coastguard Worker     if (O->is64Bit()) {
853*9880d681SAndroid Build Coastguard Worker       memcpy(&lp, sect + i, sizeof(uint64_t));
854*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost)
855*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(lp);
856*9880d681SAndroid Build Coastguard Worker     } else {
857*9880d681SAndroid Build Coastguard Worker       uint32_t li;
858*9880d681SAndroid Build Coastguard Worker       memcpy(&li, sect + i, sizeof(uint32_t));
859*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost)
860*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(li);
861*9880d681SAndroid Build Coastguard Worker       lp = li;
862*9880d681SAndroid Build Coastguard Worker     }
863*9880d681SAndroid Build Coastguard Worker 
864*9880d681SAndroid Build Coastguard Worker     // First look for an external relocation entry for this literal pointer.
865*9880d681SAndroid Build Coastguard Worker     auto Reloc = std::find_if(
866*9880d681SAndroid Build Coastguard Worker         Relocs.begin(), Relocs.end(),
867*9880d681SAndroid Build Coastguard Worker         [&](const std::pair<uint64_t, SymbolRef> &P) { return P.first == i; });
868*9880d681SAndroid Build Coastguard Worker     if (Reloc != Relocs.end()) {
869*9880d681SAndroid Build Coastguard Worker       symbol_iterator RelocSym = Reloc->second;
870*9880d681SAndroid Build Coastguard Worker       Expected<StringRef> SymName = RelocSym->getName();
871*9880d681SAndroid Build Coastguard Worker       if (!SymName) {
872*9880d681SAndroid Build Coastguard Worker         std::string Buf;
873*9880d681SAndroid Build Coastguard Worker         raw_string_ostream OS(Buf);
874*9880d681SAndroid Build Coastguard Worker         logAllUnhandledErrors(SymName.takeError(), OS, "");
875*9880d681SAndroid Build Coastguard Worker         OS.flush();
876*9880d681SAndroid Build Coastguard Worker         report_fatal_error(Buf);
877*9880d681SAndroid Build Coastguard Worker       }
878*9880d681SAndroid Build Coastguard Worker       outs() << "external relocation entry for symbol:" << *SymName << "\n";
879*9880d681SAndroid Build Coastguard Worker       continue;
880*9880d681SAndroid Build Coastguard Worker     }
881*9880d681SAndroid Build Coastguard Worker 
882*9880d681SAndroid Build Coastguard Worker     // For local references see what the section the literal pointer points to.
883*9880d681SAndroid Build Coastguard Worker     auto Sect = std::find_if(LiteralSections.begin(), LiteralSections.end(),
884*9880d681SAndroid Build Coastguard Worker                              [&](const SectionRef &R) {
885*9880d681SAndroid Build Coastguard Worker                                return lp >= R.getAddress() &&
886*9880d681SAndroid Build Coastguard Worker                                       lp < R.getAddress() + R.getSize();
887*9880d681SAndroid Build Coastguard Worker                              });
888*9880d681SAndroid Build Coastguard Worker     if (Sect == LiteralSections.end()) {
889*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
890*9880d681SAndroid Build Coastguard Worker       continue;
891*9880d681SAndroid Build Coastguard Worker     }
892*9880d681SAndroid Build Coastguard Worker 
893*9880d681SAndroid Build Coastguard Worker     uint64_t SectAddress = Sect->getAddress();
894*9880d681SAndroid Build Coastguard Worker     uint64_t SectSize = Sect->getSize();
895*9880d681SAndroid Build Coastguard Worker 
896*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
897*9880d681SAndroid Build Coastguard Worker     Sect->getName(SectName);
898*9880d681SAndroid Build Coastguard Worker     DataRefImpl Ref = Sect->getRawDataRefImpl();
899*9880d681SAndroid Build Coastguard Worker     StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
900*9880d681SAndroid Build Coastguard Worker     outs() << SegmentName << ":" << SectName << ":";
901*9880d681SAndroid Build Coastguard Worker 
902*9880d681SAndroid Build Coastguard Worker     uint32_t section_type;
903*9880d681SAndroid Build Coastguard Worker     if (O->is64Bit()) {
904*9880d681SAndroid Build Coastguard Worker       const MachO::section_64 Sec = O->getSection64(Ref);
905*9880d681SAndroid Build Coastguard Worker       section_type = Sec.flags & MachO::SECTION_TYPE;
906*9880d681SAndroid Build Coastguard Worker     } else {
907*9880d681SAndroid Build Coastguard Worker       const MachO::section Sec = O->getSection(Ref);
908*9880d681SAndroid Build Coastguard Worker       section_type = Sec.flags & MachO::SECTION_TYPE;
909*9880d681SAndroid Build Coastguard Worker     }
910*9880d681SAndroid Build Coastguard Worker 
911*9880d681SAndroid Build Coastguard Worker     StringRef BytesStr;
912*9880d681SAndroid Build Coastguard Worker     Sect->getContents(BytesStr);
913*9880d681SAndroid Build Coastguard Worker     const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
914*9880d681SAndroid Build Coastguard Worker 
915*9880d681SAndroid Build Coastguard Worker     switch (section_type) {
916*9880d681SAndroid Build Coastguard Worker     case MachO::S_CSTRING_LITERALS:
917*9880d681SAndroid Build Coastguard Worker       for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
918*9880d681SAndroid Build Coastguard Worker            i++) {
919*9880d681SAndroid Build Coastguard Worker         DumpCstringChar(Contents[i]);
920*9880d681SAndroid Build Coastguard Worker       }
921*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
922*9880d681SAndroid Build Coastguard Worker       break;
923*9880d681SAndroid Build Coastguard Worker     case MachO::S_4BYTE_LITERALS:
924*9880d681SAndroid Build Coastguard Worker       float f;
925*9880d681SAndroid Build Coastguard Worker       memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
926*9880d681SAndroid Build Coastguard Worker       uint32_t l;
927*9880d681SAndroid Build Coastguard Worker       memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
928*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
929*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(f);
930*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(l);
931*9880d681SAndroid Build Coastguard Worker       }
932*9880d681SAndroid Build Coastguard Worker       DumpLiteral4(l, f);
933*9880d681SAndroid Build Coastguard Worker       break;
934*9880d681SAndroid Build Coastguard Worker     case MachO::S_8BYTE_LITERALS: {
935*9880d681SAndroid Build Coastguard Worker       double d;
936*9880d681SAndroid Build Coastguard Worker       memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
937*9880d681SAndroid Build Coastguard Worker       uint32_t l0, l1;
938*9880d681SAndroid Build Coastguard Worker       memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
939*9880d681SAndroid Build Coastguard Worker       memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
940*9880d681SAndroid Build Coastguard Worker              sizeof(uint32_t));
941*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
942*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(f);
943*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(l0);
944*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(l1);
945*9880d681SAndroid Build Coastguard Worker       }
946*9880d681SAndroid Build Coastguard Worker       DumpLiteral8(O, l0, l1, d);
947*9880d681SAndroid Build Coastguard Worker       break;
948*9880d681SAndroid Build Coastguard Worker     }
949*9880d681SAndroid Build Coastguard Worker     case MachO::S_16BYTE_LITERALS: {
950*9880d681SAndroid Build Coastguard Worker       uint32_t l0, l1, l2, l3;
951*9880d681SAndroid Build Coastguard Worker       memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
952*9880d681SAndroid Build Coastguard Worker       memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
953*9880d681SAndroid Build Coastguard Worker              sizeof(uint32_t));
954*9880d681SAndroid Build Coastguard Worker       memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
955*9880d681SAndroid Build Coastguard Worker              sizeof(uint32_t));
956*9880d681SAndroid Build Coastguard Worker       memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
957*9880d681SAndroid Build Coastguard Worker              sizeof(uint32_t));
958*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
959*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(l0);
960*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(l1);
961*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(l2);
962*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(l3);
963*9880d681SAndroid Build Coastguard Worker       }
964*9880d681SAndroid Build Coastguard Worker       DumpLiteral16(l0, l1, l2, l3);
965*9880d681SAndroid Build Coastguard Worker       break;
966*9880d681SAndroid Build Coastguard Worker     }
967*9880d681SAndroid Build Coastguard Worker     }
968*9880d681SAndroid Build Coastguard Worker   }
969*9880d681SAndroid Build Coastguard Worker }
970*9880d681SAndroid Build Coastguard Worker 
DumpInitTermPointerSection(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,SymbolAddressMap * AddrMap,bool verbose)971*9880d681SAndroid Build Coastguard Worker static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
972*9880d681SAndroid Build Coastguard Worker                                        uint32_t sect_size, uint64_t sect_addr,
973*9880d681SAndroid Build Coastguard Worker                                        SymbolAddressMap *AddrMap,
974*9880d681SAndroid Build Coastguard Worker                                        bool verbose) {
975*9880d681SAndroid Build Coastguard Worker   uint32_t stride;
976*9880d681SAndroid Build Coastguard Worker   stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
977*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < sect_size; i += stride) {
978*9880d681SAndroid Build Coastguard Worker     const char *SymbolName = nullptr;
979*9880d681SAndroid Build Coastguard Worker     if (O->is64Bit()) {
980*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
981*9880d681SAndroid Build Coastguard Worker       uint64_t pointer_value;
982*9880d681SAndroid Build Coastguard Worker       memcpy(&pointer_value, sect + i, stride);
983*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost)
984*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(pointer_value);
985*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%016" PRIx64, pointer_value);
986*9880d681SAndroid Build Coastguard Worker       if (verbose)
987*9880d681SAndroid Build Coastguard Worker         SymbolName = GuessSymbolName(pointer_value, AddrMap);
988*9880d681SAndroid Build Coastguard Worker     } else {
989*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
990*9880d681SAndroid Build Coastguard Worker       uint32_t pointer_value;
991*9880d681SAndroid Build Coastguard Worker       memcpy(&pointer_value, sect + i, stride);
992*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost)
993*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(pointer_value);
994*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%08" PRIx32, pointer_value);
995*9880d681SAndroid Build Coastguard Worker       if (verbose)
996*9880d681SAndroid Build Coastguard Worker         SymbolName = GuessSymbolName(pointer_value, AddrMap);
997*9880d681SAndroid Build Coastguard Worker     }
998*9880d681SAndroid Build Coastguard Worker     if (SymbolName)
999*9880d681SAndroid Build Coastguard Worker       outs() << " " << SymbolName;
1000*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
1001*9880d681SAndroid Build Coastguard Worker   }
1002*9880d681SAndroid Build Coastguard Worker }
1003*9880d681SAndroid Build Coastguard Worker 
DumpRawSectionContents(MachOObjectFile * O,const char * sect,uint32_t size,uint64_t addr)1004*9880d681SAndroid Build Coastguard Worker static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1005*9880d681SAndroid Build Coastguard Worker                                    uint32_t size, uint64_t addr) {
1006*9880d681SAndroid Build Coastguard Worker   uint32_t cputype = O->getHeader().cputype;
1007*9880d681SAndroid Build Coastguard Worker   if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1008*9880d681SAndroid Build Coastguard Worker     uint32_t j;
1009*9880d681SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < size; i += j, addr += j) {
1010*9880d681SAndroid Build Coastguard Worker       if (O->is64Bit())
1011*9880d681SAndroid Build Coastguard Worker         outs() << format("%016" PRIx64, addr) << "\t";
1012*9880d681SAndroid Build Coastguard Worker       else
1013*9880d681SAndroid Build Coastguard Worker         outs() << format("%08" PRIx64, addr) << "\t";
1014*9880d681SAndroid Build Coastguard Worker       for (j = 0; j < 16 && i + j < size; j++) {
1015*9880d681SAndroid Build Coastguard Worker         uint8_t byte_word = *(sect + i + j);
1016*9880d681SAndroid Build Coastguard Worker         outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1017*9880d681SAndroid Build Coastguard Worker       }
1018*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
1019*9880d681SAndroid Build Coastguard Worker     }
1020*9880d681SAndroid Build Coastguard Worker   } else {
1021*9880d681SAndroid Build Coastguard Worker     uint32_t j;
1022*9880d681SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < size; i += j, addr += j) {
1023*9880d681SAndroid Build Coastguard Worker       if (O->is64Bit())
1024*9880d681SAndroid Build Coastguard Worker         outs() << format("%016" PRIx64, addr) << "\t";
1025*9880d681SAndroid Build Coastguard Worker       else
1026*9880d681SAndroid Build Coastguard Worker         outs() << format("%08" PRIx64, addr) << "\t";
1027*9880d681SAndroid Build Coastguard Worker       for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1028*9880d681SAndroid Build Coastguard Worker            j += sizeof(int32_t)) {
1029*9880d681SAndroid Build Coastguard Worker         if (i + j + sizeof(int32_t) <= size) {
1030*9880d681SAndroid Build Coastguard Worker           uint32_t long_word;
1031*9880d681SAndroid Build Coastguard Worker           memcpy(&long_word, sect + i + j, sizeof(int32_t));
1032*9880d681SAndroid Build Coastguard Worker           if (O->isLittleEndian() != sys::IsLittleEndianHost)
1033*9880d681SAndroid Build Coastguard Worker             sys::swapByteOrder(long_word);
1034*9880d681SAndroid Build Coastguard Worker           outs() << format("%08" PRIx32, long_word) << " ";
1035*9880d681SAndroid Build Coastguard Worker         } else {
1036*9880d681SAndroid Build Coastguard Worker           for (uint32_t k = 0; i + j + k < size; k++) {
1037*9880d681SAndroid Build Coastguard Worker             uint8_t byte_word = *(sect + i + j + k);
1038*9880d681SAndroid Build Coastguard Worker             outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1039*9880d681SAndroid Build Coastguard Worker           }
1040*9880d681SAndroid Build Coastguard Worker         }
1041*9880d681SAndroid Build Coastguard Worker       }
1042*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
1043*9880d681SAndroid Build Coastguard Worker     }
1044*9880d681SAndroid Build Coastguard Worker   }
1045*9880d681SAndroid Build Coastguard Worker }
1046*9880d681SAndroid Build Coastguard Worker 
1047*9880d681SAndroid Build Coastguard Worker static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1048*9880d681SAndroid Build Coastguard Worker                              StringRef DisSegName, StringRef DisSectName);
1049*9880d681SAndroid Build Coastguard Worker static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1050*9880d681SAndroid Build Coastguard Worker                                 uint32_t size, uint32_t addr);
1051*9880d681SAndroid Build Coastguard Worker #ifdef HAVE_LIBXAR
1052*9880d681SAndroid Build Coastguard Worker static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
1053*9880d681SAndroid Build Coastguard Worker                                 uint32_t size, bool verbose,
1054*9880d681SAndroid Build Coastguard Worker                                 bool PrintXarHeader, bool PrintXarFileHeaders,
1055*9880d681SAndroid Build Coastguard Worker                                 std::string XarMemberName);
1056*9880d681SAndroid Build Coastguard Worker #endif // defined(HAVE_LIBXAR)
1057*9880d681SAndroid Build Coastguard Worker 
DumpSectionContents(StringRef Filename,MachOObjectFile * O,bool verbose)1058*9880d681SAndroid Build Coastguard Worker static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1059*9880d681SAndroid Build Coastguard Worker                                 bool verbose) {
1060*9880d681SAndroid Build Coastguard Worker   SymbolAddressMap AddrMap;
1061*9880d681SAndroid Build Coastguard Worker   if (verbose)
1062*9880d681SAndroid Build Coastguard Worker     CreateSymbolAddressMap(O, &AddrMap);
1063*9880d681SAndroid Build Coastguard Worker 
1064*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < FilterSections.size(); ++i) {
1065*9880d681SAndroid Build Coastguard Worker     StringRef DumpSection = FilterSections[i];
1066*9880d681SAndroid Build Coastguard Worker     std::pair<StringRef, StringRef> DumpSegSectName;
1067*9880d681SAndroid Build Coastguard Worker     DumpSegSectName = DumpSection.split(',');
1068*9880d681SAndroid Build Coastguard Worker     StringRef DumpSegName, DumpSectName;
1069*9880d681SAndroid Build Coastguard Worker     if (DumpSegSectName.second.size()) {
1070*9880d681SAndroid Build Coastguard Worker       DumpSegName = DumpSegSectName.first;
1071*9880d681SAndroid Build Coastguard Worker       DumpSectName = DumpSegSectName.second;
1072*9880d681SAndroid Build Coastguard Worker     } else {
1073*9880d681SAndroid Build Coastguard Worker       DumpSegName = "";
1074*9880d681SAndroid Build Coastguard Worker       DumpSectName = DumpSegSectName.first;
1075*9880d681SAndroid Build Coastguard Worker     }
1076*9880d681SAndroid Build Coastguard Worker     for (const SectionRef &Section : O->sections()) {
1077*9880d681SAndroid Build Coastguard Worker       StringRef SectName;
1078*9880d681SAndroid Build Coastguard Worker       Section.getName(SectName);
1079*9880d681SAndroid Build Coastguard Worker       DataRefImpl Ref = Section.getRawDataRefImpl();
1080*9880d681SAndroid Build Coastguard Worker       StringRef SegName = O->getSectionFinalSegmentName(Ref);
1081*9880d681SAndroid Build Coastguard Worker       if ((DumpSegName.empty() || SegName == DumpSegName) &&
1082*9880d681SAndroid Build Coastguard Worker           (SectName == DumpSectName)) {
1083*9880d681SAndroid Build Coastguard Worker 
1084*9880d681SAndroid Build Coastguard Worker         uint32_t section_flags;
1085*9880d681SAndroid Build Coastguard Worker         if (O->is64Bit()) {
1086*9880d681SAndroid Build Coastguard Worker           const MachO::section_64 Sec = O->getSection64(Ref);
1087*9880d681SAndroid Build Coastguard Worker           section_flags = Sec.flags;
1088*9880d681SAndroid Build Coastguard Worker 
1089*9880d681SAndroid Build Coastguard Worker         } else {
1090*9880d681SAndroid Build Coastguard Worker           const MachO::section Sec = O->getSection(Ref);
1091*9880d681SAndroid Build Coastguard Worker           section_flags = Sec.flags;
1092*9880d681SAndroid Build Coastguard Worker         }
1093*9880d681SAndroid Build Coastguard Worker         uint32_t section_type = section_flags & MachO::SECTION_TYPE;
1094*9880d681SAndroid Build Coastguard Worker 
1095*9880d681SAndroid Build Coastguard Worker         StringRef BytesStr;
1096*9880d681SAndroid Build Coastguard Worker         Section.getContents(BytesStr);
1097*9880d681SAndroid Build Coastguard Worker         const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1098*9880d681SAndroid Build Coastguard Worker         uint32_t sect_size = BytesStr.size();
1099*9880d681SAndroid Build Coastguard Worker         uint64_t sect_addr = Section.getAddress();
1100*9880d681SAndroid Build Coastguard Worker 
1101*9880d681SAndroid Build Coastguard Worker         outs() << "Contents of (" << SegName << "," << SectName
1102*9880d681SAndroid Build Coastguard Worker                << ") section\n";
1103*9880d681SAndroid Build Coastguard Worker 
1104*9880d681SAndroid Build Coastguard Worker         if (verbose) {
1105*9880d681SAndroid Build Coastguard Worker           if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
1106*9880d681SAndroid Build Coastguard Worker               (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
1107*9880d681SAndroid Build Coastguard Worker             DisassembleMachO(Filename, O, SegName, SectName);
1108*9880d681SAndroid Build Coastguard Worker             continue;
1109*9880d681SAndroid Build Coastguard Worker           }
1110*9880d681SAndroid Build Coastguard Worker           if (SegName == "__TEXT" && SectName == "__info_plist") {
1111*9880d681SAndroid Build Coastguard Worker             outs() << sect;
1112*9880d681SAndroid Build Coastguard Worker             continue;
1113*9880d681SAndroid Build Coastguard Worker           }
1114*9880d681SAndroid Build Coastguard Worker           if (SegName == "__OBJC" && SectName == "__protocol") {
1115*9880d681SAndroid Build Coastguard Worker             DumpProtocolSection(O, sect, sect_size, sect_addr);
1116*9880d681SAndroid Build Coastguard Worker             continue;
1117*9880d681SAndroid Build Coastguard Worker           }
1118*9880d681SAndroid Build Coastguard Worker #ifdef HAVE_LIBXAR
1119*9880d681SAndroid Build Coastguard Worker           if (SegName == "__LLVM" && SectName == "__bundle") {
1120*9880d681SAndroid Build Coastguard Worker             DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
1121*9880d681SAndroid Build Coastguard Worker                                ArchiveHeaders, "");
1122*9880d681SAndroid Build Coastguard Worker             continue;
1123*9880d681SAndroid Build Coastguard Worker           }
1124*9880d681SAndroid Build Coastguard Worker #endif // defined(HAVE_LIBXAR)
1125*9880d681SAndroid Build Coastguard Worker           switch (section_type) {
1126*9880d681SAndroid Build Coastguard Worker           case MachO::S_REGULAR:
1127*9880d681SAndroid Build Coastguard Worker             DumpRawSectionContents(O, sect, sect_size, sect_addr);
1128*9880d681SAndroid Build Coastguard Worker             break;
1129*9880d681SAndroid Build Coastguard Worker           case MachO::S_ZEROFILL:
1130*9880d681SAndroid Build Coastguard Worker             outs() << "zerofill section and has no contents in the file\n";
1131*9880d681SAndroid Build Coastguard Worker             break;
1132*9880d681SAndroid Build Coastguard Worker           case MachO::S_CSTRING_LITERALS:
1133*9880d681SAndroid Build Coastguard Worker             DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1134*9880d681SAndroid Build Coastguard Worker             break;
1135*9880d681SAndroid Build Coastguard Worker           case MachO::S_4BYTE_LITERALS:
1136*9880d681SAndroid Build Coastguard Worker             DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1137*9880d681SAndroid Build Coastguard Worker             break;
1138*9880d681SAndroid Build Coastguard Worker           case MachO::S_8BYTE_LITERALS:
1139*9880d681SAndroid Build Coastguard Worker             DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1140*9880d681SAndroid Build Coastguard Worker             break;
1141*9880d681SAndroid Build Coastguard Worker           case MachO::S_16BYTE_LITERALS:
1142*9880d681SAndroid Build Coastguard Worker             DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1143*9880d681SAndroid Build Coastguard Worker             break;
1144*9880d681SAndroid Build Coastguard Worker           case MachO::S_LITERAL_POINTERS:
1145*9880d681SAndroid Build Coastguard Worker             DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
1146*9880d681SAndroid Build Coastguard Worker                                       !NoLeadingAddr);
1147*9880d681SAndroid Build Coastguard Worker             break;
1148*9880d681SAndroid Build Coastguard Worker           case MachO::S_MOD_INIT_FUNC_POINTERS:
1149*9880d681SAndroid Build Coastguard Worker           case MachO::S_MOD_TERM_FUNC_POINTERS:
1150*9880d681SAndroid Build Coastguard Worker             DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,
1151*9880d681SAndroid Build Coastguard Worker                                        verbose);
1152*9880d681SAndroid Build Coastguard Worker             break;
1153*9880d681SAndroid Build Coastguard Worker           default:
1154*9880d681SAndroid Build Coastguard Worker             outs() << "Unknown section type ("
1155*9880d681SAndroid Build Coastguard Worker                    << format("0x%08" PRIx32, section_type) << ")\n";
1156*9880d681SAndroid Build Coastguard Worker             DumpRawSectionContents(O, sect, sect_size, sect_addr);
1157*9880d681SAndroid Build Coastguard Worker             break;
1158*9880d681SAndroid Build Coastguard Worker           }
1159*9880d681SAndroid Build Coastguard Worker         } else {
1160*9880d681SAndroid Build Coastguard Worker           if (section_type == MachO::S_ZEROFILL)
1161*9880d681SAndroid Build Coastguard Worker             outs() << "zerofill section and has no contents in the file\n";
1162*9880d681SAndroid Build Coastguard Worker           else
1163*9880d681SAndroid Build Coastguard Worker             DumpRawSectionContents(O, sect, sect_size, sect_addr);
1164*9880d681SAndroid Build Coastguard Worker         }
1165*9880d681SAndroid Build Coastguard Worker       }
1166*9880d681SAndroid Build Coastguard Worker     }
1167*9880d681SAndroid Build Coastguard Worker   }
1168*9880d681SAndroid Build Coastguard Worker }
1169*9880d681SAndroid Build Coastguard Worker 
DumpInfoPlistSectionContents(StringRef Filename,MachOObjectFile * O)1170*9880d681SAndroid Build Coastguard Worker static void DumpInfoPlistSectionContents(StringRef Filename,
1171*9880d681SAndroid Build Coastguard Worker                                          MachOObjectFile *O) {
1172*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : O->sections()) {
1173*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
1174*9880d681SAndroid Build Coastguard Worker     Section.getName(SectName);
1175*9880d681SAndroid Build Coastguard Worker     DataRefImpl Ref = Section.getRawDataRefImpl();
1176*9880d681SAndroid Build Coastguard Worker     StringRef SegName = O->getSectionFinalSegmentName(Ref);
1177*9880d681SAndroid Build Coastguard Worker     if (SegName == "__TEXT" && SectName == "__info_plist") {
1178*9880d681SAndroid Build Coastguard Worker       outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
1179*9880d681SAndroid Build Coastguard Worker       StringRef BytesStr;
1180*9880d681SAndroid Build Coastguard Worker       Section.getContents(BytesStr);
1181*9880d681SAndroid Build Coastguard Worker       const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1182*9880d681SAndroid Build Coastguard Worker       outs() << sect;
1183*9880d681SAndroid Build Coastguard Worker       return;
1184*9880d681SAndroid Build Coastguard Worker     }
1185*9880d681SAndroid Build Coastguard Worker   }
1186*9880d681SAndroid Build Coastguard Worker }
1187*9880d681SAndroid Build Coastguard Worker 
1188*9880d681SAndroid Build Coastguard Worker // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
1189*9880d681SAndroid Build Coastguard Worker // and if it is and there is a list of architecture flags is specified then
1190*9880d681SAndroid Build Coastguard Worker // check to make sure this Mach-O file is one of those architectures or all
1191*9880d681SAndroid Build Coastguard Worker // architectures were specified.  If not then an error is generated and this
1192*9880d681SAndroid Build Coastguard Worker // routine returns false.  Else it returns true.
checkMachOAndArchFlags(ObjectFile * O,StringRef Filename)1193*9880d681SAndroid Build Coastguard Worker static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
1194*9880d681SAndroid Build Coastguard Worker   if (isa<MachOObjectFile>(O) && !ArchAll && ArchFlags.size() != 0) {
1195*9880d681SAndroid Build Coastguard Worker     MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O);
1196*9880d681SAndroid Build Coastguard Worker     bool ArchFound = false;
1197*9880d681SAndroid Build Coastguard Worker     MachO::mach_header H;
1198*9880d681SAndroid Build Coastguard Worker     MachO::mach_header_64 H_64;
1199*9880d681SAndroid Build Coastguard Worker     Triple T;
1200*9880d681SAndroid Build Coastguard Worker     if (MachO->is64Bit()) {
1201*9880d681SAndroid Build Coastguard Worker       H_64 = MachO->MachOObjectFile::getHeader64();
1202*9880d681SAndroid Build Coastguard Worker       T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype);
1203*9880d681SAndroid Build Coastguard Worker     } else {
1204*9880d681SAndroid Build Coastguard Worker       H = MachO->MachOObjectFile::getHeader();
1205*9880d681SAndroid Build Coastguard Worker       T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype);
1206*9880d681SAndroid Build Coastguard Worker     }
1207*9880d681SAndroid Build Coastguard Worker     unsigned i;
1208*9880d681SAndroid Build Coastguard Worker     for (i = 0; i < ArchFlags.size(); ++i) {
1209*9880d681SAndroid Build Coastguard Worker       if (ArchFlags[i] == T.getArchName())
1210*9880d681SAndroid Build Coastguard Worker         ArchFound = true;
1211*9880d681SAndroid Build Coastguard Worker       break;
1212*9880d681SAndroid Build Coastguard Worker     }
1213*9880d681SAndroid Build Coastguard Worker     if (!ArchFound) {
1214*9880d681SAndroid Build Coastguard Worker       errs() << "llvm-objdump: file: " + Filename + " does not contain "
1215*9880d681SAndroid Build Coastguard Worker              << "architecture: " + ArchFlags[i] + "\n";
1216*9880d681SAndroid Build Coastguard Worker       return false;
1217*9880d681SAndroid Build Coastguard Worker     }
1218*9880d681SAndroid Build Coastguard Worker   }
1219*9880d681SAndroid Build Coastguard Worker   return true;
1220*9880d681SAndroid Build Coastguard Worker }
1221*9880d681SAndroid Build Coastguard Worker 
1222*9880d681SAndroid Build Coastguard Worker static void printObjcMetaData(MachOObjectFile *O, bool verbose);
1223*9880d681SAndroid Build Coastguard Worker 
1224*9880d681SAndroid Build Coastguard Worker // ProcessMachO() is passed a single opened Mach-O file, which may be an
1225*9880d681SAndroid Build Coastguard Worker // archive member and or in a slice of a universal file.  It prints the
1226*9880d681SAndroid Build Coastguard Worker // the file name and header info and then processes it according to the
1227*9880d681SAndroid Build Coastguard Worker // command line options.
ProcessMachO(StringRef Filename,MachOObjectFile * MachOOF,StringRef ArchiveMemberName=StringRef (),StringRef ArchitectureName=StringRef ())1228*9880d681SAndroid Build Coastguard Worker static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
1229*9880d681SAndroid Build Coastguard Worker                          StringRef ArchiveMemberName = StringRef(),
1230*9880d681SAndroid Build Coastguard Worker                          StringRef ArchitectureName = StringRef()) {
1231*9880d681SAndroid Build Coastguard Worker   // If we are doing some processing here on the Mach-O file print the header
1232*9880d681SAndroid Build Coastguard Worker   // info.  And don't print it otherwise like in the case of printing the
1233*9880d681SAndroid Build Coastguard Worker   // UniversalHeaders or ArchiveHeaders.
1234*9880d681SAndroid Build Coastguard Worker   if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable ||
1235*9880d681SAndroid Build Coastguard Worker       LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
1236*9880d681SAndroid Build Coastguard Worker       DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
1237*9880d681SAndroid Build Coastguard Worker     outs() << Filename;
1238*9880d681SAndroid Build Coastguard Worker     if (!ArchiveMemberName.empty())
1239*9880d681SAndroid Build Coastguard Worker       outs() << '(' << ArchiveMemberName << ')';
1240*9880d681SAndroid Build Coastguard Worker     if (!ArchitectureName.empty())
1241*9880d681SAndroid Build Coastguard Worker       outs() << " (architecture " << ArchitectureName << ")";
1242*9880d681SAndroid Build Coastguard Worker     outs() << ":\n";
1243*9880d681SAndroid Build Coastguard Worker   }
1244*9880d681SAndroid Build Coastguard Worker 
1245*9880d681SAndroid Build Coastguard Worker   if (Disassemble)
1246*9880d681SAndroid Build Coastguard Worker     DisassembleMachO(Filename, MachOOF, "__TEXT", "__text");
1247*9880d681SAndroid Build Coastguard Worker   if (IndirectSymbols)
1248*9880d681SAndroid Build Coastguard Worker     PrintIndirectSymbols(MachOOF, !NonVerbose);
1249*9880d681SAndroid Build Coastguard Worker   if (DataInCode)
1250*9880d681SAndroid Build Coastguard Worker     PrintDataInCodeTable(MachOOF, !NonVerbose);
1251*9880d681SAndroid Build Coastguard Worker   if (LinkOptHints)
1252*9880d681SAndroid Build Coastguard Worker     PrintLinkOptHints(MachOOF);
1253*9880d681SAndroid Build Coastguard Worker   if (Relocations)
1254*9880d681SAndroid Build Coastguard Worker     PrintRelocations(MachOOF);
1255*9880d681SAndroid Build Coastguard Worker   if (SectionHeaders)
1256*9880d681SAndroid Build Coastguard Worker     PrintSectionHeaders(MachOOF);
1257*9880d681SAndroid Build Coastguard Worker   if (SectionContents)
1258*9880d681SAndroid Build Coastguard Worker     PrintSectionContents(MachOOF);
1259*9880d681SAndroid Build Coastguard Worker   if (FilterSections.size() != 0)
1260*9880d681SAndroid Build Coastguard Worker     DumpSectionContents(Filename, MachOOF, !NonVerbose);
1261*9880d681SAndroid Build Coastguard Worker   if (InfoPlist)
1262*9880d681SAndroid Build Coastguard Worker     DumpInfoPlistSectionContents(Filename, MachOOF);
1263*9880d681SAndroid Build Coastguard Worker   if (DylibsUsed)
1264*9880d681SAndroid Build Coastguard Worker     PrintDylibs(MachOOF, false);
1265*9880d681SAndroid Build Coastguard Worker   if (DylibId)
1266*9880d681SAndroid Build Coastguard Worker     PrintDylibs(MachOOF, true);
1267*9880d681SAndroid Build Coastguard Worker   if (SymbolTable) {
1268*9880d681SAndroid Build Coastguard Worker     StringRef ArchiveName = ArchiveMemberName == StringRef() ? "" : Filename;
1269*9880d681SAndroid Build Coastguard Worker     PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName);
1270*9880d681SAndroid Build Coastguard Worker   }
1271*9880d681SAndroid Build Coastguard Worker   if (UnwindInfo)
1272*9880d681SAndroid Build Coastguard Worker     printMachOUnwindInfo(MachOOF);
1273*9880d681SAndroid Build Coastguard Worker   if (PrivateHeaders) {
1274*9880d681SAndroid Build Coastguard Worker     printMachOFileHeader(MachOOF);
1275*9880d681SAndroid Build Coastguard Worker     printMachOLoadCommands(MachOOF);
1276*9880d681SAndroid Build Coastguard Worker   }
1277*9880d681SAndroid Build Coastguard Worker   if (FirstPrivateHeader)
1278*9880d681SAndroid Build Coastguard Worker     printMachOFileHeader(MachOOF);
1279*9880d681SAndroid Build Coastguard Worker   if (ObjcMetaData)
1280*9880d681SAndroid Build Coastguard Worker     printObjcMetaData(MachOOF, !NonVerbose);
1281*9880d681SAndroid Build Coastguard Worker   if (ExportsTrie)
1282*9880d681SAndroid Build Coastguard Worker     printExportsTrie(MachOOF);
1283*9880d681SAndroid Build Coastguard Worker   if (Rebase)
1284*9880d681SAndroid Build Coastguard Worker     printRebaseTable(MachOOF);
1285*9880d681SAndroid Build Coastguard Worker   if (Bind)
1286*9880d681SAndroid Build Coastguard Worker     printBindTable(MachOOF);
1287*9880d681SAndroid Build Coastguard Worker   if (LazyBind)
1288*9880d681SAndroid Build Coastguard Worker     printLazyBindTable(MachOOF);
1289*9880d681SAndroid Build Coastguard Worker   if (WeakBind)
1290*9880d681SAndroid Build Coastguard Worker     printWeakBindTable(MachOOF);
1291*9880d681SAndroid Build Coastguard Worker 
1292*9880d681SAndroid Build Coastguard Worker   if (DwarfDumpType != DIDT_Null) {
1293*9880d681SAndroid Build Coastguard Worker     std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*MachOOF));
1294*9880d681SAndroid Build Coastguard Worker     // Dump the complete DWARF structure.
1295*9880d681SAndroid Build Coastguard Worker     DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */);
1296*9880d681SAndroid Build Coastguard Worker   }
1297*9880d681SAndroid Build Coastguard Worker }
1298*9880d681SAndroid Build Coastguard Worker 
1299*9880d681SAndroid Build Coastguard Worker // printUnknownCPUType() helps print_fat_headers for unknown CPU's.
printUnknownCPUType(uint32_t cputype,uint32_t cpusubtype)1300*9880d681SAndroid Build Coastguard Worker static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
1301*9880d681SAndroid Build Coastguard Worker   outs() << "    cputype (" << cputype << ")\n";
1302*9880d681SAndroid Build Coastguard Worker   outs() << "    cpusubtype (" << cpusubtype << ")\n";
1303*9880d681SAndroid Build Coastguard Worker }
1304*9880d681SAndroid Build Coastguard Worker 
1305*9880d681SAndroid Build Coastguard Worker // printCPUType() helps print_fat_headers by printing the cputype and
1306*9880d681SAndroid Build Coastguard Worker // pusubtype (symbolically for the one's it knows about).
printCPUType(uint32_t cputype,uint32_t cpusubtype)1307*9880d681SAndroid Build Coastguard Worker static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
1308*9880d681SAndroid Build Coastguard Worker   switch (cputype) {
1309*9880d681SAndroid Build Coastguard Worker   case MachO::CPU_TYPE_I386:
1310*9880d681SAndroid Build Coastguard Worker     switch (cpusubtype) {
1311*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_I386_ALL:
1312*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_I386\n";
1313*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_I386_ALL\n";
1314*9880d681SAndroid Build Coastguard Worker       break;
1315*9880d681SAndroid Build Coastguard Worker     default:
1316*9880d681SAndroid Build Coastguard Worker       printUnknownCPUType(cputype, cpusubtype);
1317*9880d681SAndroid Build Coastguard Worker       break;
1318*9880d681SAndroid Build Coastguard Worker     }
1319*9880d681SAndroid Build Coastguard Worker     break;
1320*9880d681SAndroid Build Coastguard Worker   case MachO::CPU_TYPE_X86_64:
1321*9880d681SAndroid Build Coastguard Worker     switch (cpusubtype) {
1322*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_X86_64_ALL:
1323*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_X86_64\n";
1324*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
1325*9880d681SAndroid Build Coastguard Worker       break;
1326*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_X86_64_H:
1327*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_X86_64\n";
1328*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_X86_64_H\n";
1329*9880d681SAndroid Build Coastguard Worker       break;
1330*9880d681SAndroid Build Coastguard Worker     default:
1331*9880d681SAndroid Build Coastguard Worker       printUnknownCPUType(cputype, cpusubtype);
1332*9880d681SAndroid Build Coastguard Worker       break;
1333*9880d681SAndroid Build Coastguard Worker     }
1334*9880d681SAndroid Build Coastguard Worker     break;
1335*9880d681SAndroid Build Coastguard Worker   case MachO::CPU_TYPE_ARM:
1336*9880d681SAndroid Build Coastguard Worker     switch (cpusubtype) {
1337*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_ALL:
1338*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1339*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_ALL\n";
1340*9880d681SAndroid Build Coastguard Worker       break;
1341*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V4T:
1342*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1343*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V4T\n";
1344*9880d681SAndroid Build Coastguard Worker       break;
1345*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1346*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1347*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
1348*9880d681SAndroid Build Coastguard Worker       break;
1349*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_XSCALE:
1350*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1351*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
1352*9880d681SAndroid Build Coastguard Worker       break;
1353*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V6:
1354*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1355*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6\n";
1356*9880d681SAndroid Build Coastguard Worker       break;
1357*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V6M:
1358*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1359*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6M\n";
1360*9880d681SAndroid Build Coastguard Worker       break;
1361*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V7:
1362*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1363*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7\n";
1364*9880d681SAndroid Build Coastguard Worker       break;
1365*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V7EM:
1366*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1367*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
1368*9880d681SAndroid Build Coastguard Worker       break;
1369*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V7K:
1370*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1371*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7K\n";
1372*9880d681SAndroid Build Coastguard Worker       break;
1373*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V7M:
1374*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1375*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7M\n";
1376*9880d681SAndroid Build Coastguard Worker       break;
1377*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM_V7S:
1378*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM\n";
1379*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7S\n";
1380*9880d681SAndroid Build Coastguard Worker       break;
1381*9880d681SAndroid Build Coastguard Worker     default:
1382*9880d681SAndroid Build Coastguard Worker       printUnknownCPUType(cputype, cpusubtype);
1383*9880d681SAndroid Build Coastguard Worker       break;
1384*9880d681SAndroid Build Coastguard Worker     }
1385*9880d681SAndroid Build Coastguard Worker     break;
1386*9880d681SAndroid Build Coastguard Worker   case MachO::CPU_TYPE_ARM64:
1387*9880d681SAndroid Build Coastguard Worker     switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
1388*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_SUBTYPE_ARM64_ALL:
1389*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype CPU_TYPE_ARM64\n";
1390*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
1391*9880d681SAndroid Build Coastguard Worker       break;
1392*9880d681SAndroid Build Coastguard Worker     default:
1393*9880d681SAndroid Build Coastguard Worker       printUnknownCPUType(cputype, cpusubtype);
1394*9880d681SAndroid Build Coastguard Worker       break;
1395*9880d681SAndroid Build Coastguard Worker     }
1396*9880d681SAndroid Build Coastguard Worker     break;
1397*9880d681SAndroid Build Coastguard Worker   default:
1398*9880d681SAndroid Build Coastguard Worker     printUnknownCPUType(cputype, cpusubtype);
1399*9880d681SAndroid Build Coastguard Worker     break;
1400*9880d681SAndroid Build Coastguard Worker   }
1401*9880d681SAndroid Build Coastguard Worker }
1402*9880d681SAndroid Build Coastguard Worker 
printMachOUniversalHeaders(const object::MachOUniversalBinary * UB,bool verbose)1403*9880d681SAndroid Build Coastguard Worker static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
1404*9880d681SAndroid Build Coastguard Worker                                        bool verbose) {
1405*9880d681SAndroid Build Coastguard Worker   outs() << "Fat headers\n";
1406*9880d681SAndroid Build Coastguard Worker   if (verbose) {
1407*9880d681SAndroid Build Coastguard Worker     if (UB->getMagic() == MachO::FAT_MAGIC)
1408*9880d681SAndroid Build Coastguard Worker       outs() << "fat_magic FAT_MAGIC\n";
1409*9880d681SAndroid Build Coastguard Worker     else // UB->getMagic() == MachO::FAT_MAGIC_64
1410*9880d681SAndroid Build Coastguard Worker       outs() << "fat_magic FAT_MAGIC_64\n";
1411*9880d681SAndroid Build Coastguard Worker   } else
1412*9880d681SAndroid Build Coastguard Worker     outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
1413*9880d681SAndroid Build Coastguard Worker 
1414*9880d681SAndroid Build Coastguard Worker   uint32_t nfat_arch = UB->getNumberOfObjects();
1415*9880d681SAndroid Build Coastguard Worker   StringRef Buf = UB->getData();
1416*9880d681SAndroid Build Coastguard Worker   uint64_t size = Buf.size();
1417*9880d681SAndroid Build Coastguard Worker   uint64_t big_size = sizeof(struct MachO::fat_header) +
1418*9880d681SAndroid Build Coastguard Worker                       nfat_arch * sizeof(struct MachO::fat_arch);
1419*9880d681SAndroid Build Coastguard Worker   outs() << "nfat_arch " << UB->getNumberOfObjects();
1420*9880d681SAndroid Build Coastguard Worker   if (nfat_arch == 0)
1421*9880d681SAndroid Build Coastguard Worker     outs() << " (malformed, contains zero architecture types)\n";
1422*9880d681SAndroid Build Coastguard Worker   else if (big_size > size)
1423*9880d681SAndroid Build Coastguard Worker     outs() << " (malformed, architectures past end of file)\n";
1424*9880d681SAndroid Build Coastguard Worker   else
1425*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
1426*9880d681SAndroid Build Coastguard Worker 
1427*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < nfat_arch; ++i) {
1428*9880d681SAndroid Build Coastguard Worker     MachOUniversalBinary::ObjectForArch OFA(UB, i);
1429*9880d681SAndroid Build Coastguard Worker     uint32_t cputype = OFA.getCPUType();
1430*9880d681SAndroid Build Coastguard Worker     uint32_t cpusubtype = OFA.getCPUSubType();
1431*9880d681SAndroid Build Coastguard Worker     outs() << "architecture ";
1432*9880d681SAndroid Build Coastguard Worker     for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
1433*9880d681SAndroid Build Coastguard Worker       MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
1434*9880d681SAndroid Build Coastguard Worker       uint32_t other_cputype = other_OFA.getCPUType();
1435*9880d681SAndroid Build Coastguard Worker       uint32_t other_cpusubtype = other_OFA.getCPUSubType();
1436*9880d681SAndroid Build Coastguard Worker       if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
1437*9880d681SAndroid Build Coastguard Worker           (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
1438*9880d681SAndroid Build Coastguard Worker               (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
1439*9880d681SAndroid Build Coastguard Worker         outs() << "(illegal duplicate architecture) ";
1440*9880d681SAndroid Build Coastguard Worker         break;
1441*9880d681SAndroid Build Coastguard Worker       }
1442*9880d681SAndroid Build Coastguard Worker     }
1443*9880d681SAndroid Build Coastguard Worker     if (verbose) {
1444*9880d681SAndroid Build Coastguard Worker       outs() << OFA.getArchTypeName() << "\n";
1445*9880d681SAndroid Build Coastguard Worker       printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
1446*9880d681SAndroid Build Coastguard Worker     } else {
1447*9880d681SAndroid Build Coastguard Worker       outs() << i << "\n";
1448*9880d681SAndroid Build Coastguard Worker       outs() << "    cputype " << cputype << "\n";
1449*9880d681SAndroid Build Coastguard Worker       outs() << "    cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
1450*9880d681SAndroid Build Coastguard Worker              << "\n";
1451*9880d681SAndroid Build Coastguard Worker     }
1452*9880d681SAndroid Build Coastguard Worker     if (verbose &&
1453*9880d681SAndroid Build Coastguard Worker         (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
1454*9880d681SAndroid Build Coastguard Worker       outs() << "    capabilities CPU_SUBTYPE_LIB64\n";
1455*9880d681SAndroid Build Coastguard Worker     else
1456*9880d681SAndroid Build Coastguard Worker       outs() << "    capabilities "
1457*9880d681SAndroid Build Coastguard Worker              << format("0x%" PRIx32,
1458*9880d681SAndroid Build Coastguard Worker                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
1459*9880d681SAndroid Build Coastguard Worker     outs() << "    offset " << OFA.getOffset();
1460*9880d681SAndroid Build Coastguard Worker     if (OFA.getOffset() > size)
1461*9880d681SAndroid Build Coastguard Worker       outs() << " (past end of file)";
1462*9880d681SAndroid Build Coastguard Worker     if (OFA.getOffset() % (1 << OFA.getAlign()) != 0)
1463*9880d681SAndroid Build Coastguard Worker       outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
1464*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
1465*9880d681SAndroid Build Coastguard Worker     outs() << "    size " << OFA.getSize();
1466*9880d681SAndroid Build Coastguard Worker     big_size = OFA.getOffset() + OFA.getSize();
1467*9880d681SAndroid Build Coastguard Worker     if (big_size > size)
1468*9880d681SAndroid Build Coastguard Worker       outs() << " (past end of file)";
1469*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
1470*9880d681SAndroid Build Coastguard Worker     outs() << "    align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
1471*9880d681SAndroid Build Coastguard Worker            << ")\n";
1472*9880d681SAndroid Build Coastguard Worker   }
1473*9880d681SAndroid Build Coastguard Worker }
1474*9880d681SAndroid Build Coastguard Worker 
printArchiveChild(const Archive::Child & C,bool verbose,bool print_offset)1475*9880d681SAndroid Build Coastguard Worker static void printArchiveChild(const Archive::Child &C, bool verbose,
1476*9880d681SAndroid Build Coastguard Worker                               bool print_offset) {
1477*9880d681SAndroid Build Coastguard Worker   if (print_offset)
1478*9880d681SAndroid Build Coastguard Worker     outs() << C.getChildOffset() << "\t";
1479*9880d681SAndroid Build Coastguard Worker   sys::fs::perms Mode = C.getAccessMode();
1480*9880d681SAndroid Build Coastguard Worker   if (verbose) {
1481*9880d681SAndroid Build Coastguard Worker     // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
1482*9880d681SAndroid Build Coastguard Worker     // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
1483*9880d681SAndroid Build Coastguard Worker     outs() << "-";
1484*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
1485*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
1486*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
1487*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
1488*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
1489*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
1490*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
1491*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
1492*9880d681SAndroid Build Coastguard Worker     outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
1493*9880d681SAndroid Build Coastguard Worker   } else {
1494*9880d681SAndroid Build Coastguard Worker     outs() << format("0%o ", Mode);
1495*9880d681SAndroid Build Coastguard Worker   }
1496*9880d681SAndroid Build Coastguard Worker 
1497*9880d681SAndroid Build Coastguard Worker   unsigned UID = C.getUID();
1498*9880d681SAndroid Build Coastguard Worker   outs() << format("%3d/", UID);
1499*9880d681SAndroid Build Coastguard Worker   unsigned GID = C.getGID();
1500*9880d681SAndroid Build Coastguard Worker   outs() << format("%-3d ", GID);
1501*9880d681SAndroid Build Coastguard Worker   ErrorOr<uint64_t> Size = C.getRawSize();
1502*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = Size.getError())
1503*9880d681SAndroid Build Coastguard Worker     report_fatal_error(EC.message());
1504*9880d681SAndroid Build Coastguard Worker   outs() << format("%5" PRId64, Size.get()) << " ";
1505*9880d681SAndroid Build Coastguard Worker 
1506*9880d681SAndroid Build Coastguard Worker   StringRef RawLastModified = C.getRawLastModified();
1507*9880d681SAndroid Build Coastguard Worker   if (verbose) {
1508*9880d681SAndroid Build Coastguard Worker     unsigned Seconds;
1509*9880d681SAndroid Build Coastguard Worker     if (RawLastModified.getAsInteger(10, Seconds))
1510*9880d681SAndroid Build Coastguard Worker       outs() << "(date: \"%s\" contains non-decimal chars) " << RawLastModified;
1511*9880d681SAndroid Build Coastguard Worker     else {
1512*9880d681SAndroid Build Coastguard Worker       // Since cime(3) returns a 26 character string of the form:
1513*9880d681SAndroid Build Coastguard Worker       // "Sun Sep 16 01:03:52 1973\n\0"
1514*9880d681SAndroid Build Coastguard Worker       // just print 24 characters.
1515*9880d681SAndroid Build Coastguard Worker       time_t t = Seconds;
1516*9880d681SAndroid Build Coastguard Worker       outs() << format("%.24s ", ctime(&t));
1517*9880d681SAndroid Build Coastguard Worker     }
1518*9880d681SAndroid Build Coastguard Worker   } else {
1519*9880d681SAndroid Build Coastguard Worker     outs() << RawLastModified << " ";
1520*9880d681SAndroid Build Coastguard Worker   }
1521*9880d681SAndroid Build Coastguard Worker 
1522*9880d681SAndroid Build Coastguard Worker   if (verbose) {
1523*9880d681SAndroid Build Coastguard Worker     ErrorOr<StringRef> NameOrErr = C.getName();
1524*9880d681SAndroid Build Coastguard Worker     if (NameOrErr.getError()) {
1525*9880d681SAndroid Build Coastguard Worker       StringRef RawName = C.getRawName();
1526*9880d681SAndroid Build Coastguard Worker       outs() << RawName << "\n";
1527*9880d681SAndroid Build Coastguard Worker     } else {
1528*9880d681SAndroid Build Coastguard Worker       StringRef Name = NameOrErr.get();
1529*9880d681SAndroid Build Coastguard Worker       outs() << Name << "\n";
1530*9880d681SAndroid Build Coastguard Worker     }
1531*9880d681SAndroid Build Coastguard Worker   } else {
1532*9880d681SAndroid Build Coastguard Worker     StringRef RawName = C.getRawName();
1533*9880d681SAndroid Build Coastguard Worker     outs() << RawName << "\n";
1534*9880d681SAndroid Build Coastguard Worker   }
1535*9880d681SAndroid Build Coastguard Worker }
1536*9880d681SAndroid Build Coastguard Worker 
printArchiveHeaders(Archive * A,bool verbose,bool print_offset)1537*9880d681SAndroid Build Coastguard Worker static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) {
1538*9880d681SAndroid Build Coastguard Worker   Error Err;
1539*9880d681SAndroid Build Coastguard Worker   for (const auto &C : A->children(Err, false))
1540*9880d681SAndroid Build Coastguard Worker     printArchiveChild(C, verbose, print_offset);
1541*9880d681SAndroid Build Coastguard Worker   if (Err)
1542*9880d681SAndroid Build Coastguard Worker     report_fatal_error(std::move(Err));
1543*9880d681SAndroid Build Coastguard Worker }
1544*9880d681SAndroid Build Coastguard Worker 
1545*9880d681SAndroid Build Coastguard Worker // ParseInputMachO() parses the named Mach-O file in Filename and handles the
1546*9880d681SAndroid Build Coastguard Worker // -arch flags selecting just those slices as specified by them and also parses
1547*9880d681SAndroid Build Coastguard Worker // archive files.  Then for each individual Mach-O file ProcessMachO() is
1548*9880d681SAndroid Build Coastguard Worker // called to process the file based on the command line options.
ParseInputMachO(StringRef Filename)1549*9880d681SAndroid Build Coastguard Worker void llvm::ParseInputMachO(StringRef Filename) {
1550*9880d681SAndroid Build Coastguard Worker   // Check for -arch all and verifiy the -arch flags are valid.
1551*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < ArchFlags.size(); ++i) {
1552*9880d681SAndroid Build Coastguard Worker     if (ArchFlags[i] == "all") {
1553*9880d681SAndroid Build Coastguard Worker       ArchAll = true;
1554*9880d681SAndroid Build Coastguard Worker     } else {
1555*9880d681SAndroid Build Coastguard Worker       if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
1556*9880d681SAndroid Build Coastguard Worker         errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] +
1557*9880d681SAndroid Build Coastguard Worker                       "'for the -arch option\n";
1558*9880d681SAndroid Build Coastguard Worker         return;
1559*9880d681SAndroid Build Coastguard Worker       }
1560*9880d681SAndroid Build Coastguard Worker     }
1561*9880d681SAndroid Build Coastguard Worker   }
1562*9880d681SAndroid Build Coastguard Worker 
1563*9880d681SAndroid Build Coastguard Worker   // Attempt to open the binary.
1564*9880d681SAndroid Build Coastguard Worker   Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
1565*9880d681SAndroid Build Coastguard Worker   if (!BinaryOrErr)
1566*9880d681SAndroid Build Coastguard Worker     report_error(Filename, BinaryOrErr.takeError());
1567*9880d681SAndroid Build Coastguard Worker   Binary &Bin = *BinaryOrErr.get().getBinary();
1568*9880d681SAndroid Build Coastguard Worker 
1569*9880d681SAndroid Build Coastguard Worker   if (Archive *A = dyn_cast<Archive>(&Bin)) {
1570*9880d681SAndroid Build Coastguard Worker     outs() << "Archive : " << Filename << "\n";
1571*9880d681SAndroid Build Coastguard Worker     if (ArchiveHeaders)
1572*9880d681SAndroid Build Coastguard Worker       printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets);
1573*9880d681SAndroid Build Coastguard Worker     Error Err;
1574*9880d681SAndroid Build Coastguard Worker     for (auto &C : A->children(Err)) {
1575*9880d681SAndroid Build Coastguard Worker       Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
1576*9880d681SAndroid Build Coastguard Worker       if (!ChildOrErr) {
1577*9880d681SAndroid Build Coastguard Worker         if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1578*9880d681SAndroid Build Coastguard Worker           report_error(Filename, C, std::move(E));
1579*9880d681SAndroid Build Coastguard Worker         continue;
1580*9880d681SAndroid Build Coastguard Worker       }
1581*9880d681SAndroid Build Coastguard Worker       if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
1582*9880d681SAndroid Build Coastguard Worker         if (!checkMachOAndArchFlags(O, Filename))
1583*9880d681SAndroid Build Coastguard Worker           return;
1584*9880d681SAndroid Build Coastguard Worker         ProcessMachO(Filename, O, O->getFileName());
1585*9880d681SAndroid Build Coastguard Worker       }
1586*9880d681SAndroid Build Coastguard Worker     }
1587*9880d681SAndroid Build Coastguard Worker     if (Err)
1588*9880d681SAndroid Build Coastguard Worker       report_error(Filename, std::move(Err));
1589*9880d681SAndroid Build Coastguard Worker     return;
1590*9880d681SAndroid Build Coastguard Worker   }
1591*9880d681SAndroid Build Coastguard Worker   if (UniversalHeaders) {
1592*9880d681SAndroid Build Coastguard Worker     if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
1593*9880d681SAndroid Build Coastguard Worker       printMachOUniversalHeaders(UB, !NonVerbose);
1594*9880d681SAndroid Build Coastguard Worker   }
1595*9880d681SAndroid Build Coastguard Worker   if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
1596*9880d681SAndroid Build Coastguard Worker     // If we have a list of architecture flags specified dump only those.
1597*9880d681SAndroid Build Coastguard Worker     if (!ArchAll && ArchFlags.size() != 0) {
1598*9880d681SAndroid Build Coastguard Worker       // Look for a slice in the universal binary that matches each ArchFlag.
1599*9880d681SAndroid Build Coastguard Worker       bool ArchFound;
1600*9880d681SAndroid Build Coastguard Worker       for (unsigned i = 0; i < ArchFlags.size(); ++i) {
1601*9880d681SAndroid Build Coastguard Worker         ArchFound = false;
1602*9880d681SAndroid Build Coastguard Worker         for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
1603*9880d681SAndroid Build Coastguard Worker                                                    E = UB->end_objects();
1604*9880d681SAndroid Build Coastguard Worker              I != E; ++I) {
1605*9880d681SAndroid Build Coastguard Worker           if (ArchFlags[i] == I->getArchTypeName()) {
1606*9880d681SAndroid Build Coastguard Worker             ArchFound = true;
1607*9880d681SAndroid Build Coastguard Worker             Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
1608*9880d681SAndroid Build Coastguard Worker                 I->getAsObjectFile();
1609*9880d681SAndroid Build Coastguard Worker             std::string ArchitectureName = "";
1610*9880d681SAndroid Build Coastguard Worker             if (ArchFlags.size() > 1)
1611*9880d681SAndroid Build Coastguard Worker               ArchitectureName = I->getArchTypeName();
1612*9880d681SAndroid Build Coastguard Worker             if (ObjOrErr) {
1613*9880d681SAndroid Build Coastguard Worker               ObjectFile &O = *ObjOrErr.get();
1614*9880d681SAndroid Build Coastguard Worker               if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
1615*9880d681SAndroid Build Coastguard Worker                 ProcessMachO(Filename, MachOOF, "", ArchitectureName);
1616*9880d681SAndroid Build Coastguard Worker             } else if (auto E = isNotObjectErrorInvalidFileType(
1617*9880d681SAndroid Build Coastguard Worker                        ObjOrErr.takeError())) {
1618*9880d681SAndroid Build Coastguard Worker               report_error(Filename, StringRef(), std::move(E),
1619*9880d681SAndroid Build Coastguard Worker                            ArchitectureName);
1620*9880d681SAndroid Build Coastguard Worker               continue;
1621*9880d681SAndroid Build Coastguard Worker             } else if (Expected<std::unique_ptr<Archive>> AOrErr =
1622*9880d681SAndroid Build Coastguard Worker                            I->getAsArchive()) {
1623*9880d681SAndroid Build Coastguard Worker               std::unique_ptr<Archive> &A = *AOrErr;
1624*9880d681SAndroid Build Coastguard Worker               outs() << "Archive : " << Filename;
1625*9880d681SAndroid Build Coastguard Worker               if (!ArchitectureName.empty())
1626*9880d681SAndroid Build Coastguard Worker                 outs() << " (architecture " << ArchitectureName << ")";
1627*9880d681SAndroid Build Coastguard Worker               outs() << "\n";
1628*9880d681SAndroid Build Coastguard Worker               if (ArchiveHeaders)
1629*9880d681SAndroid Build Coastguard Worker                 printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
1630*9880d681SAndroid Build Coastguard Worker               Error Err;
1631*9880d681SAndroid Build Coastguard Worker               for (auto &C : A->children(Err)) {
1632*9880d681SAndroid Build Coastguard Worker                 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
1633*9880d681SAndroid Build Coastguard Worker                 if (!ChildOrErr) {
1634*9880d681SAndroid Build Coastguard Worker                   if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1635*9880d681SAndroid Build Coastguard Worker                     report_error(Filename, C, std::move(E), ArchitectureName);
1636*9880d681SAndroid Build Coastguard Worker                   continue;
1637*9880d681SAndroid Build Coastguard Worker                 }
1638*9880d681SAndroid Build Coastguard Worker                 if (MachOObjectFile *O =
1639*9880d681SAndroid Build Coastguard Worker                         dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
1640*9880d681SAndroid Build Coastguard Worker                   ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
1641*9880d681SAndroid Build Coastguard Worker               }
1642*9880d681SAndroid Build Coastguard Worker               if (Err)
1643*9880d681SAndroid Build Coastguard Worker                 report_error(Filename, std::move(Err));
1644*9880d681SAndroid Build Coastguard Worker             } else {
1645*9880d681SAndroid Build Coastguard Worker               consumeError(AOrErr.takeError());
1646*9880d681SAndroid Build Coastguard Worker               error("Mach-O universal file: " + Filename + " for " +
1647*9880d681SAndroid Build Coastguard Worker                     "architecture " + StringRef(I->getArchTypeName()) +
1648*9880d681SAndroid Build Coastguard Worker                     " is not a Mach-O file or an archive file");
1649*9880d681SAndroid Build Coastguard Worker             }
1650*9880d681SAndroid Build Coastguard Worker           }
1651*9880d681SAndroid Build Coastguard Worker         }
1652*9880d681SAndroid Build Coastguard Worker         if (!ArchFound) {
1653*9880d681SAndroid Build Coastguard Worker           errs() << "llvm-objdump: file: " + Filename + " does not contain "
1654*9880d681SAndroid Build Coastguard Worker                  << "architecture: " + ArchFlags[i] + "\n";
1655*9880d681SAndroid Build Coastguard Worker           return;
1656*9880d681SAndroid Build Coastguard Worker         }
1657*9880d681SAndroid Build Coastguard Worker       }
1658*9880d681SAndroid Build Coastguard Worker       return;
1659*9880d681SAndroid Build Coastguard Worker     }
1660*9880d681SAndroid Build Coastguard Worker     // No architecture flags were specified so if this contains a slice that
1661*9880d681SAndroid Build Coastguard Worker     // matches the host architecture dump only that.
1662*9880d681SAndroid Build Coastguard Worker     if (!ArchAll) {
1663*9880d681SAndroid Build Coastguard Worker       for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
1664*9880d681SAndroid Build Coastguard Worker                                                  E = UB->end_objects();
1665*9880d681SAndroid Build Coastguard Worker            I != E; ++I) {
1666*9880d681SAndroid Build Coastguard Worker         if (MachOObjectFile::getHostArch().getArchName() ==
1667*9880d681SAndroid Build Coastguard Worker             I->getArchTypeName()) {
1668*9880d681SAndroid Build Coastguard Worker           Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
1669*9880d681SAndroid Build Coastguard Worker           std::string ArchiveName;
1670*9880d681SAndroid Build Coastguard Worker           ArchiveName.clear();
1671*9880d681SAndroid Build Coastguard Worker           if (ObjOrErr) {
1672*9880d681SAndroid Build Coastguard Worker             ObjectFile &O = *ObjOrErr.get();
1673*9880d681SAndroid Build Coastguard Worker             if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
1674*9880d681SAndroid Build Coastguard Worker               ProcessMachO(Filename, MachOOF);
1675*9880d681SAndroid Build Coastguard Worker           } else if (auto E = isNotObjectErrorInvalidFileType(
1676*9880d681SAndroid Build Coastguard Worker                      ObjOrErr.takeError())) {
1677*9880d681SAndroid Build Coastguard Worker             report_error(Filename, std::move(E));
1678*9880d681SAndroid Build Coastguard Worker             continue;
1679*9880d681SAndroid Build Coastguard Worker           } else if (Expected<std::unique_ptr<Archive>> AOrErr =
1680*9880d681SAndroid Build Coastguard Worker                          I->getAsArchive()) {
1681*9880d681SAndroid Build Coastguard Worker             std::unique_ptr<Archive> &A = *AOrErr;
1682*9880d681SAndroid Build Coastguard Worker             outs() << "Archive : " << Filename << "\n";
1683*9880d681SAndroid Build Coastguard Worker             if (ArchiveHeaders)
1684*9880d681SAndroid Build Coastguard Worker               printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
1685*9880d681SAndroid Build Coastguard Worker             Error Err;
1686*9880d681SAndroid Build Coastguard Worker             for (auto &C : A->children(Err)) {
1687*9880d681SAndroid Build Coastguard Worker               Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
1688*9880d681SAndroid Build Coastguard Worker               if (!ChildOrErr) {
1689*9880d681SAndroid Build Coastguard Worker                 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1690*9880d681SAndroid Build Coastguard Worker                   report_error(Filename, C, std::move(E));
1691*9880d681SAndroid Build Coastguard Worker                 continue;
1692*9880d681SAndroid Build Coastguard Worker               }
1693*9880d681SAndroid Build Coastguard Worker               if (MachOObjectFile *O =
1694*9880d681SAndroid Build Coastguard Worker                       dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
1695*9880d681SAndroid Build Coastguard Worker                 ProcessMachO(Filename, O, O->getFileName());
1696*9880d681SAndroid Build Coastguard Worker             }
1697*9880d681SAndroid Build Coastguard Worker             if (Err)
1698*9880d681SAndroid Build Coastguard Worker               report_error(Filename, std::move(Err));
1699*9880d681SAndroid Build Coastguard Worker           } else {
1700*9880d681SAndroid Build Coastguard Worker             consumeError(AOrErr.takeError());
1701*9880d681SAndroid Build Coastguard Worker             error("Mach-O universal file: " + Filename + " for architecture " +
1702*9880d681SAndroid Build Coastguard Worker                   StringRef(I->getArchTypeName()) +
1703*9880d681SAndroid Build Coastguard Worker                   " is not a Mach-O file or an archive file");
1704*9880d681SAndroid Build Coastguard Worker           }
1705*9880d681SAndroid Build Coastguard Worker           return;
1706*9880d681SAndroid Build Coastguard Worker         }
1707*9880d681SAndroid Build Coastguard Worker       }
1708*9880d681SAndroid Build Coastguard Worker     }
1709*9880d681SAndroid Build Coastguard Worker     // Either all architectures have been specified or none have been specified
1710*9880d681SAndroid Build Coastguard Worker     // and this does not contain the host architecture so dump all the slices.
1711*9880d681SAndroid Build Coastguard Worker     bool moreThanOneArch = UB->getNumberOfObjects() > 1;
1712*9880d681SAndroid Build Coastguard Worker     for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
1713*9880d681SAndroid Build Coastguard Worker                                                E = UB->end_objects();
1714*9880d681SAndroid Build Coastguard Worker          I != E; ++I) {
1715*9880d681SAndroid Build Coastguard Worker       Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
1716*9880d681SAndroid Build Coastguard Worker       std::string ArchitectureName = "";
1717*9880d681SAndroid Build Coastguard Worker       if (moreThanOneArch)
1718*9880d681SAndroid Build Coastguard Worker         ArchitectureName = I->getArchTypeName();
1719*9880d681SAndroid Build Coastguard Worker       if (ObjOrErr) {
1720*9880d681SAndroid Build Coastguard Worker         ObjectFile &Obj = *ObjOrErr.get();
1721*9880d681SAndroid Build Coastguard Worker         if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
1722*9880d681SAndroid Build Coastguard Worker           ProcessMachO(Filename, MachOOF, "", ArchitectureName);
1723*9880d681SAndroid Build Coastguard Worker       } else if (auto E = isNotObjectErrorInvalidFileType(
1724*9880d681SAndroid Build Coastguard Worker                  ObjOrErr.takeError())) {
1725*9880d681SAndroid Build Coastguard Worker         report_error(StringRef(), Filename, std::move(E), ArchitectureName);
1726*9880d681SAndroid Build Coastguard Worker         continue;
1727*9880d681SAndroid Build Coastguard Worker       } else if (Expected<std::unique_ptr<Archive>> AOrErr =
1728*9880d681SAndroid Build Coastguard Worker                    I->getAsArchive()) {
1729*9880d681SAndroid Build Coastguard Worker         std::unique_ptr<Archive> &A = *AOrErr;
1730*9880d681SAndroid Build Coastguard Worker         outs() << "Archive : " << Filename;
1731*9880d681SAndroid Build Coastguard Worker         if (!ArchitectureName.empty())
1732*9880d681SAndroid Build Coastguard Worker           outs() << " (architecture " << ArchitectureName << ")";
1733*9880d681SAndroid Build Coastguard Worker         outs() << "\n";
1734*9880d681SAndroid Build Coastguard Worker         if (ArchiveHeaders)
1735*9880d681SAndroid Build Coastguard Worker           printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
1736*9880d681SAndroid Build Coastguard Worker         Error Err;
1737*9880d681SAndroid Build Coastguard Worker         for (auto &C : A->children(Err)) {
1738*9880d681SAndroid Build Coastguard Worker           Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
1739*9880d681SAndroid Build Coastguard Worker           if (!ChildOrErr) {
1740*9880d681SAndroid Build Coastguard Worker             if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1741*9880d681SAndroid Build Coastguard Worker               report_error(Filename, C, std::move(E), ArchitectureName);
1742*9880d681SAndroid Build Coastguard Worker             continue;
1743*9880d681SAndroid Build Coastguard Worker           }
1744*9880d681SAndroid Build Coastguard Worker           if (MachOObjectFile *O =
1745*9880d681SAndroid Build Coastguard Worker                   dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
1746*9880d681SAndroid Build Coastguard Worker             if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
1747*9880d681SAndroid Build Coastguard Worker               ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
1748*9880d681SAndroid Build Coastguard Worker                            ArchitectureName);
1749*9880d681SAndroid Build Coastguard Worker           }
1750*9880d681SAndroid Build Coastguard Worker         }
1751*9880d681SAndroid Build Coastguard Worker         if (Err)
1752*9880d681SAndroid Build Coastguard Worker           report_error(Filename, std::move(Err));
1753*9880d681SAndroid Build Coastguard Worker       } else {
1754*9880d681SAndroid Build Coastguard Worker         consumeError(AOrErr.takeError());
1755*9880d681SAndroid Build Coastguard Worker         error("Mach-O universal file: " + Filename + " for architecture " +
1756*9880d681SAndroid Build Coastguard Worker               StringRef(I->getArchTypeName()) +
1757*9880d681SAndroid Build Coastguard Worker               " is not a Mach-O file or an archive file");
1758*9880d681SAndroid Build Coastguard Worker       }
1759*9880d681SAndroid Build Coastguard Worker     }
1760*9880d681SAndroid Build Coastguard Worker     return;
1761*9880d681SAndroid Build Coastguard Worker   }
1762*9880d681SAndroid Build Coastguard Worker   if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
1763*9880d681SAndroid Build Coastguard Worker     if (!checkMachOAndArchFlags(O, Filename))
1764*9880d681SAndroid Build Coastguard Worker       return;
1765*9880d681SAndroid Build Coastguard Worker     if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) {
1766*9880d681SAndroid Build Coastguard Worker       ProcessMachO(Filename, MachOOF);
1767*9880d681SAndroid Build Coastguard Worker     } else
1768*9880d681SAndroid Build Coastguard Worker       errs() << "llvm-objdump: '" << Filename << "': "
1769*9880d681SAndroid Build Coastguard Worker              << "Object is not a Mach-O file type.\n";
1770*9880d681SAndroid Build Coastguard Worker     return;
1771*9880d681SAndroid Build Coastguard Worker   }
1772*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Input object can't be invalid at this point");
1773*9880d681SAndroid Build Coastguard Worker }
1774*9880d681SAndroid Build Coastguard Worker 
1775*9880d681SAndroid Build Coastguard Worker typedef std::pair<uint64_t, const char *> BindInfoEntry;
1776*9880d681SAndroid Build Coastguard Worker typedef std::vector<BindInfoEntry> BindTable;
1777*9880d681SAndroid Build Coastguard Worker typedef BindTable::iterator bind_table_iterator;
1778*9880d681SAndroid Build Coastguard Worker 
1779*9880d681SAndroid Build Coastguard Worker // The block of info used by the Symbolizer call backs.
1780*9880d681SAndroid Build Coastguard Worker struct DisassembleInfo {
1781*9880d681SAndroid Build Coastguard Worker   bool verbose;
1782*9880d681SAndroid Build Coastguard Worker   MachOObjectFile *O;
1783*9880d681SAndroid Build Coastguard Worker   SectionRef S;
1784*9880d681SAndroid Build Coastguard Worker   SymbolAddressMap *AddrMap;
1785*9880d681SAndroid Build Coastguard Worker   std::vector<SectionRef> *Sections;
1786*9880d681SAndroid Build Coastguard Worker   const char *class_name;
1787*9880d681SAndroid Build Coastguard Worker   const char *selector_name;
1788*9880d681SAndroid Build Coastguard Worker   char *method;
1789*9880d681SAndroid Build Coastguard Worker   char *demangled_name;
1790*9880d681SAndroid Build Coastguard Worker   uint64_t adrp_addr;
1791*9880d681SAndroid Build Coastguard Worker   uint32_t adrp_inst;
1792*9880d681SAndroid Build Coastguard Worker   BindTable *bindtable;
1793*9880d681SAndroid Build Coastguard Worker   uint32_t depth;
1794*9880d681SAndroid Build Coastguard Worker };
1795*9880d681SAndroid Build Coastguard Worker 
1796*9880d681SAndroid Build Coastguard Worker // SymbolizerGetOpInfo() is the operand information call back function.
1797*9880d681SAndroid Build Coastguard Worker // This is called to get the symbolic information for operand(s) of an
1798*9880d681SAndroid Build Coastguard Worker // instruction when it is being done.  This routine does this from
1799*9880d681SAndroid Build Coastguard Worker // the relocation information, symbol table, etc. That block of information
1800*9880d681SAndroid Build Coastguard Worker // is a pointer to the struct DisassembleInfo that was passed when the
1801*9880d681SAndroid Build Coastguard Worker // disassembler context was created and passed to back to here when
1802*9880d681SAndroid Build Coastguard Worker // called back by the disassembler for instruction operands that could have
1803*9880d681SAndroid Build Coastguard Worker // relocation information. The address of the instruction containing operand is
1804*9880d681SAndroid Build Coastguard Worker // at the Pc parameter.  The immediate value the operand has is passed in
1805*9880d681SAndroid Build Coastguard Worker // op_info->Value and is at Offset past the start of the instruction and has a
1806*9880d681SAndroid Build Coastguard Worker // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
1807*9880d681SAndroid Build Coastguard Worker // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
1808*9880d681SAndroid Build Coastguard Worker // names and addends of the symbolic expression to add for the operand.  The
1809*9880d681SAndroid Build Coastguard Worker // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
1810*9880d681SAndroid Build Coastguard Worker // information is returned then this function returns 1 else it returns 0.
SymbolizerGetOpInfo(void * DisInfo,uint64_t Pc,uint64_t Offset,uint64_t Size,int TagType,void * TagBuf)1811*9880d681SAndroid Build Coastguard Worker static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
1812*9880d681SAndroid Build Coastguard Worker                                uint64_t Size, int TagType, void *TagBuf) {
1813*9880d681SAndroid Build Coastguard Worker   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
1814*9880d681SAndroid Build Coastguard Worker   struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
1815*9880d681SAndroid Build Coastguard Worker   uint64_t value = op_info->Value;
1816*9880d681SAndroid Build Coastguard Worker 
1817*9880d681SAndroid Build Coastguard Worker   // Make sure all fields returned are zero if we don't set them.
1818*9880d681SAndroid Build Coastguard Worker   memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
1819*9880d681SAndroid Build Coastguard Worker   op_info->Value = value;
1820*9880d681SAndroid Build Coastguard Worker 
1821*9880d681SAndroid Build Coastguard Worker   // If the TagType is not the value 1 which it code knows about or if no
1822*9880d681SAndroid Build Coastguard Worker   // verbose symbolic information is wanted then just return 0, indicating no
1823*9880d681SAndroid Build Coastguard Worker   // information is being returned.
1824*9880d681SAndroid Build Coastguard Worker   if (TagType != 1 || !info->verbose)
1825*9880d681SAndroid Build Coastguard Worker     return 0;
1826*9880d681SAndroid Build Coastguard Worker 
1827*9880d681SAndroid Build Coastguard Worker   unsigned int Arch = info->O->getArch();
1828*9880d681SAndroid Build Coastguard Worker   if (Arch == Triple::x86) {
1829*9880d681SAndroid Build Coastguard Worker     if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
1830*9880d681SAndroid Build Coastguard Worker       return 0;
1831*9880d681SAndroid Build Coastguard Worker     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
1832*9880d681SAndroid Build Coastguard Worker       // TODO:
1833*9880d681SAndroid Build Coastguard Worker       // Search the external relocation entries of a fully linked image
1834*9880d681SAndroid Build Coastguard Worker       // (if any) for an entry that matches this segment offset.
1835*9880d681SAndroid Build Coastguard Worker       // uint32_t seg_offset = (Pc + Offset);
1836*9880d681SAndroid Build Coastguard Worker       return 0;
1837*9880d681SAndroid Build Coastguard Worker     }
1838*9880d681SAndroid Build Coastguard Worker     // In MH_OBJECT filetypes search the section's relocation entries (if any)
1839*9880d681SAndroid Build Coastguard Worker     // for an entry for this section offset.
1840*9880d681SAndroid Build Coastguard Worker     uint32_t sect_addr = info->S.getAddress();
1841*9880d681SAndroid Build Coastguard Worker     uint32_t sect_offset = (Pc + Offset) - sect_addr;
1842*9880d681SAndroid Build Coastguard Worker     bool reloc_found = false;
1843*9880d681SAndroid Build Coastguard Worker     DataRefImpl Rel;
1844*9880d681SAndroid Build Coastguard Worker     MachO::any_relocation_info RE;
1845*9880d681SAndroid Build Coastguard Worker     bool isExtern = false;
1846*9880d681SAndroid Build Coastguard Worker     SymbolRef Symbol;
1847*9880d681SAndroid Build Coastguard Worker     bool r_scattered = false;
1848*9880d681SAndroid Build Coastguard Worker     uint32_t r_value, pair_r_value, r_type;
1849*9880d681SAndroid Build Coastguard Worker     for (const RelocationRef &Reloc : info->S.relocations()) {
1850*9880d681SAndroid Build Coastguard Worker       uint64_t RelocOffset = Reloc.getOffset();
1851*9880d681SAndroid Build Coastguard Worker       if (RelocOffset == sect_offset) {
1852*9880d681SAndroid Build Coastguard Worker         Rel = Reloc.getRawDataRefImpl();
1853*9880d681SAndroid Build Coastguard Worker         RE = info->O->getRelocation(Rel);
1854*9880d681SAndroid Build Coastguard Worker         r_type = info->O->getAnyRelocationType(RE);
1855*9880d681SAndroid Build Coastguard Worker         r_scattered = info->O->isRelocationScattered(RE);
1856*9880d681SAndroid Build Coastguard Worker         if (r_scattered) {
1857*9880d681SAndroid Build Coastguard Worker           r_value = info->O->getScatteredRelocationValue(RE);
1858*9880d681SAndroid Build Coastguard Worker           if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
1859*9880d681SAndroid Build Coastguard Worker               r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
1860*9880d681SAndroid Build Coastguard Worker             DataRefImpl RelNext = Rel;
1861*9880d681SAndroid Build Coastguard Worker             info->O->moveRelocationNext(RelNext);
1862*9880d681SAndroid Build Coastguard Worker             MachO::any_relocation_info RENext;
1863*9880d681SAndroid Build Coastguard Worker             RENext = info->O->getRelocation(RelNext);
1864*9880d681SAndroid Build Coastguard Worker             if (info->O->isRelocationScattered(RENext))
1865*9880d681SAndroid Build Coastguard Worker               pair_r_value = info->O->getScatteredRelocationValue(RENext);
1866*9880d681SAndroid Build Coastguard Worker             else
1867*9880d681SAndroid Build Coastguard Worker               return 0;
1868*9880d681SAndroid Build Coastguard Worker           }
1869*9880d681SAndroid Build Coastguard Worker         } else {
1870*9880d681SAndroid Build Coastguard Worker           isExtern = info->O->getPlainRelocationExternal(RE);
1871*9880d681SAndroid Build Coastguard Worker           if (isExtern) {
1872*9880d681SAndroid Build Coastguard Worker             symbol_iterator RelocSym = Reloc.getSymbol();
1873*9880d681SAndroid Build Coastguard Worker             Symbol = *RelocSym;
1874*9880d681SAndroid Build Coastguard Worker           }
1875*9880d681SAndroid Build Coastguard Worker         }
1876*9880d681SAndroid Build Coastguard Worker         reloc_found = true;
1877*9880d681SAndroid Build Coastguard Worker         break;
1878*9880d681SAndroid Build Coastguard Worker       }
1879*9880d681SAndroid Build Coastguard Worker     }
1880*9880d681SAndroid Build Coastguard Worker     if (reloc_found && isExtern) {
1881*9880d681SAndroid Build Coastguard Worker       Expected<StringRef> SymName = Symbol.getName();
1882*9880d681SAndroid Build Coastguard Worker       if (!SymName) {
1883*9880d681SAndroid Build Coastguard Worker         std::string Buf;
1884*9880d681SAndroid Build Coastguard Worker         raw_string_ostream OS(Buf);
1885*9880d681SAndroid Build Coastguard Worker         logAllUnhandledErrors(SymName.takeError(), OS, "");
1886*9880d681SAndroid Build Coastguard Worker         OS.flush();
1887*9880d681SAndroid Build Coastguard Worker         report_fatal_error(Buf);
1888*9880d681SAndroid Build Coastguard Worker       }
1889*9880d681SAndroid Build Coastguard Worker       const char *name = SymName->data();
1890*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Present = 1;
1891*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Name = name;
1892*9880d681SAndroid Build Coastguard Worker       // For i386 extern relocation entries the value in the instruction is
1893*9880d681SAndroid Build Coastguard Worker       // the offset from the symbol, and value is already set in op_info->Value.
1894*9880d681SAndroid Build Coastguard Worker       return 1;
1895*9880d681SAndroid Build Coastguard Worker     }
1896*9880d681SAndroid Build Coastguard Worker     if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
1897*9880d681SAndroid Build Coastguard Worker                         r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
1898*9880d681SAndroid Build Coastguard Worker       const char *add = GuessSymbolName(r_value, info->AddrMap);
1899*9880d681SAndroid Build Coastguard Worker       const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
1900*9880d681SAndroid Build Coastguard Worker       uint32_t offset = value - (r_value - pair_r_value);
1901*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Present = 1;
1902*9880d681SAndroid Build Coastguard Worker       if (add != nullptr)
1903*9880d681SAndroid Build Coastguard Worker         op_info->AddSymbol.Name = add;
1904*9880d681SAndroid Build Coastguard Worker       else
1905*9880d681SAndroid Build Coastguard Worker         op_info->AddSymbol.Value = r_value;
1906*9880d681SAndroid Build Coastguard Worker       op_info->SubtractSymbol.Present = 1;
1907*9880d681SAndroid Build Coastguard Worker       if (sub != nullptr)
1908*9880d681SAndroid Build Coastguard Worker         op_info->SubtractSymbol.Name = sub;
1909*9880d681SAndroid Build Coastguard Worker       else
1910*9880d681SAndroid Build Coastguard Worker         op_info->SubtractSymbol.Value = pair_r_value;
1911*9880d681SAndroid Build Coastguard Worker       op_info->Value = offset;
1912*9880d681SAndroid Build Coastguard Worker       return 1;
1913*9880d681SAndroid Build Coastguard Worker     }
1914*9880d681SAndroid Build Coastguard Worker     return 0;
1915*9880d681SAndroid Build Coastguard Worker   }
1916*9880d681SAndroid Build Coastguard Worker   if (Arch == Triple::x86_64) {
1917*9880d681SAndroid Build Coastguard Worker     if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
1918*9880d681SAndroid Build Coastguard Worker       return 0;
1919*9880d681SAndroid Build Coastguard Worker     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
1920*9880d681SAndroid Build Coastguard Worker       // TODO:
1921*9880d681SAndroid Build Coastguard Worker       // Search the external relocation entries of a fully linked image
1922*9880d681SAndroid Build Coastguard Worker       // (if any) for an entry that matches this segment offset.
1923*9880d681SAndroid Build Coastguard Worker       // uint64_t seg_offset = (Pc + Offset);
1924*9880d681SAndroid Build Coastguard Worker       return 0;
1925*9880d681SAndroid Build Coastguard Worker     }
1926*9880d681SAndroid Build Coastguard Worker     // In MH_OBJECT filetypes search the section's relocation entries (if any)
1927*9880d681SAndroid Build Coastguard Worker     // for an entry for this section offset.
1928*9880d681SAndroid Build Coastguard Worker     uint64_t sect_addr = info->S.getAddress();
1929*9880d681SAndroid Build Coastguard Worker     uint64_t sect_offset = (Pc + Offset) - sect_addr;
1930*9880d681SAndroid Build Coastguard Worker     bool reloc_found = false;
1931*9880d681SAndroid Build Coastguard Worker     DataRefImpl Rel;
1932*9880d681SAndroid Build Coastguard Worker     MachO::any_relocation_info RE;
1933*9880d681SAndroid Build Coastguard Worker     bool isExtern = false;
1934*9880d681SAndroid Build Coastguard Worker     SymbolRef Symbol;
1935*9880d681SAndroid Build Coastguard Worker     for (const RelocationRef &Reloc : info->S.relocations()) {
1936*9880d681SAndroid Build Coastguard Worker       uint64_t RelocOffset = Reloc.getOffset();
1937*9880d681SAndroid Build Coastguard Worker       if (RelocOffset == sect_offset) {
1938*9880d681SAndroid Build Coastguard Worker         Rel = Reloc.getRawDataRefImpl();
1939*9880d681SAndroid Build Coastguard Worker         RE = info->O->getRelocation(Rel);
1940*9880d681SAndroid Build Coastguard Worker         // NOTE: Scattered relocations don't exist on x86_64.
1941*9880d681SAndroid Build Coastguard Worker         isExtern = info->O->getPlainRelocationExternal(RE);
1942*9880d681SAndroid Build Coastguard Worker         if (isExtern) {
1943*9880d681SAndroid Build Coastguard Worker           symbol_iterator RelocSym = Reloc.getSymbol();
1944*9880d681SAndroid Build Coastguard Worker           Symbol = *RelocSym;
1945*9880d681SAndroid Build Coastguard Worker         }
1946*9880d681SAndroid Build Coastguard Worker         reloc_found = true;
1947*9880d681SAndroid Build Coastguard Worker         break;
1948*9880d681SAndroid Build Coastguard Worker       }
1949*9880d681SAndroid Build Coastguard Worker     }
1950*9880d681SAndroid Build Coastguard Worker     if (reloc_found && isExtern) {
1951*9880d681SAndroid Build Coastguard Worker       // The Value passed in will be adjusted by the Pc if the instruction
1952*9880d681SAndroid Build Coastguard Worker       // adds the Pc.  But for x86_64 external relocation entries the Value
1953*9880d681SAndroid Build Coastguard Worker       // is the offset from the external symbol.
1954*9880d681SAndroid Build Coastguard Worker       if (info->O->getAnyRelocationPCRel(RE))
1955*9880d681SAndroid Build Coastguard Worker         op_info->Value -= Pc + Offset + Size;
1956*9880d681SAndroid Build Coastguard Worker       Expected<StringRef> SymName = Symbol.getName();
1957*9880d681SAndroid Build Coastguard Worker       if (!SymName) {
1958*9880d681SAndroid Build Coastguard Worker         std::string Buf;
1959*9880d681SAndroid Build Coastguard Worker         raw_string_ostream OS(Buf);
1960*9880d681SAndroid Build Coastguard Worker         logAllUnhandledErrors(SymName.takeError(), OS, "");
1961*9880d681SAndroid Build Coastguard Worker         OS.flush();
1962*9880d681SAndroid Build Coastguard Worker         report_fatal_error(Buf);
1963*9880d681SAndroid Build Coastguard Worker       }
1964*9880d681SAndroid Build Coastguard Worker       const char *name = SymName->data();
1965*9880d681SAndroid Build Coastguard Worker       unsigned Type = info->O->getAnyRelocationType(RE);
1966*9880d681SAndroid Build Coastguard Worker       if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
1967*9880d681SAndroid Build Coastguard Worker         DataRefImpl RelNext = Rel;
1968*9880d681SAndroid Build Coastguard Worker         info->O->moveRelocationNext(RelNext);
1969*9880d681SAndroid Build Coastguard Worker         MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
1970*9880d681SAndroid Build Coastguard Worker         unsigned TypeNext = info->O->getAnyRelocationType(RENext);
1971*9880d681SAndroid Build Coastguard Worker         bool isExternNext = info->O->getPlainRelocationExternal(RENext);
1972*9880d681SAndroid Build Coastguard Worker         unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
1973*9880d681SAndroid Build Coastguard Worker         if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
1974*9880d681SAndroid Build Coastguard Worker           op_info->SubtractSymbol.Present = 1;
1975*9880d681SAndroid Build Coastguard Worker           op_info->SubtractSymbol.Name = name;
1976*9880d681SAndroid Build Coastguard Worker           symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
1977*9880d681SAndroid Build Coastguard Worker           Symbol = *RelocSymNext;
1978*9880d681SAndroid Build Coastguard Worker           Expected<StringRef> SymNameNext = Symbol.getName();
1979*9880d681SAndroid Build Coastguard Worker           if (!SymNameNext) {
1980*9880d681SAndroid Build Coastguard Worker             std::string Buf;
1981*9880d681SAndroid Build Coastguard Worker             raw_string_ostream OS(Buf);
1982*9880d681SAndroid Build Coastguard Worker             logAllUnhandledErrors(SymNameNext.takeError(), OS, "");
1983*9880d681SAndroid Build Coastguard Worker             OS.flush();
1984*9880d681SAndroid Build Coastguard Worker             report_fatal_error(Buf);
1985*9880d681SAndroid Build Coastguard Worker           }
1986*9880d681SAndroid Build Coastguard Worker           name = SymNameNext->data();
1987*9880d681SAndroid Build Coastguard Worker         }
1988*9880d681SAndroid Build Coastguard Worker       }
1989*9880d681SAndroid Build Coastguard Worker       // TODO: add the VariantKinds to op_info->VariantKind for relocation types
1990*9880d681SAndroid Build Coastguard Worker       // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
1991*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Present = 1;
1992*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Name = name;
1993*9880d681SAndroid Build Coastguard Worker       return 1;
1994*9880d681SAndroid Build Coastguard Worker     }
1995*9880d681SAndroid Build Coastguard Worker     return 0;
1996*9880d681SAndroid Build Coastguard Worker   }
1997*9880d681SAndroid Build Coastguard Worker   if (Arch == Triple::arm) {
1998*9880d681SAndroid Build Coastguard Worker     if (Offset != 0 || (Size != 4 && Size != 2))
1999*9880d681SAndroid Build Coastguard Worker       return 0;
2000*9880d681SAndroid Build Coastguard Worker     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2001*9880d681SAndroid Build Coastguard Worker       // TODO:
2002*9880d681SAndroid Build Coastguard Worker       // Search the external relocation entries of a fully linked image
2003*9880d681SAndroid Build Coastguard Worker       // (if any) for an entry that matches this segment offset.
2004*9880d681SAndroid Build Coastguard Worker       // uint32_t seg_offset = (Pc + Offset);
2005*9880d681SAndroid Build Coastguard Worker       return 0;
2006*9880d681SAndroid Build Coastguard Worker     }
2007*9880d681SAndroid Build Coastguard Worker     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2008*9880d681SAndroid Build Coastguard Worker     // for an entry for this section offset.
2009*9880d681SAndroid Build Coastguard Worker     uint32_t sect_addr = info->S.getAddress();
2010*9880d681SAndroid Build Coastguard Worker     uint32_t sect_offset = (Pc + Offset) - sect_addr;
2011*9880d681SAndroid Build Coastguard Worker     DataRefImpl Rel;
2012*9880d681SAndroid Build Coastguard Worker     MachO::any_relocation_info RE;
2013*9880d681SAndroid Build Coastguard Worker     bool isExtern = false;
2014*9880d681SAndroid Build Coastguard Worker     SymbolRef Symbol;
2015*9880d681SAndroid Build Coastguard Worker     bool r_scattered = false;
2016*9880d681SAndroid Build Coastguard Worker     uint32_t r_value, pair_r_value, r_type, r_length, other_half;
2017*9880d681SAndroid Build Coastguard Worker     auto Reloc =
2018*9880d681SAndroid Build Coastguard Worker         std::find_if(info->S.relocations().begin(), info->S.relocations().end(),
2019*9880d681SAndroid Build Coastguard Worker                      [&](const RelocationRef &Reloc) {
2020*9880d681SAndroid Build Coastguard Worker                        uint64_t RelocOffset = Reloc.getOffset();
2021*9880d681SAndroid Build Coastguard Worker                        return RelocOffset == sect_offset;
2022*9880d681SAndroid Build Coastguard Worker                      });
2023*9880d681SAndroid Build Coastguard Worker 
2024*9880d681SAndroid Build Coastguard Worker     if (Reloc == info->S.relocations().end())
2025*9880d681SAndroid Build Coastguard Worker       return 0;
2026*9880d681SAndroid Build Coastguard Worker 
2027*9880d681SAndroid Build Coastguard Worker     Rel = Reloc->getRawDataRefImpl();
2028*9880d681SAndroid Build Coastguard Worker     RE = info->O->getRelocation(Rel);
2029*9880d681SAndroid Build Coastguard Worker     r_length = info->O->getAnyRelocationLength(RE);
2030*9880d681SAndroid Build Coastguard Worker     r_scattered = info->O->isRelocationScattered(RE);
2031*9880d681SAndroid Build Coastguard Worker     if (r_scattered) {
2032*9880d681SAndroid Build Coastguard Worker       r_value = info->O->getScatteredRelocationValue(RE);
2033*9880d681SAndroid Build Coastguard Worker       r_type = info->O->getScatteredRelocationType(RE);
2034*9880d681SAndroid Build Coastguard Worker     } else {
2035*9880d681SAndroid Build Coastguard Worker       r_type = info->O->getAnyRelocationType(RE);
2036*9880d681SAndroid Build Coastguard Worker       isExtern = info->O->getPlainRelocationExternal(RE);
2037*9880d681SAndroid Build Coastguard Worker       if (isExtern) {
2038*9880d681SAndroid Build Coastguard Worker         symbol_iterator RelocSym = Reloc->getSymbol();
2039*9880d681SAndroid Build Coastguard Worker         Symbol = *RelocSym;
2040*9880d681SAndroid Build Coastguard Worker       }
2041*9880d681SAndroid Build Coastguard Worker     }
2042*9880d681SAndroid Build Coastguard Worker     if (r_type == MachO::ARM_RELOC_HALF ||
2043*9880d681SAndroid Build Coastguard Worker         r_type == MachO::ARM_RELOC_SECTDIFF ||
2044*9880d681SAndroid Build Coastguard Worker         r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
2045*9880d681SAndroid Build Coastguard Worker         r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2046*9880d681SAndroid Build Coastguard Worker       DataRefImpl RelNext = Rel;
2047*9880d681SAndroid Build Coastguard Worker       info->O->moveRelocationNext(RelNext);
2048*9880d681SAndroid Build Coastguard Worker       MachO::any_relocation_info RENext;
2049*9880d681SAndroid Build Coastguard Worker       RENext = info->O->getRelocation(RelNext);
2050*9880d681SAndroid Build Coastguard Worker       other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
2051*9880d681SAndroid Build Coastguard Worker       if (info->O->isRelocationScattered(RENext))
2052*9880d681SAndroid Build Coastguard Worker         pair_r_value = info->O->getScatteredRelocationValue(RENext);
2053*9880d681SAndroid Build Coastguard Worker     }
2054*9880d681SAndroid Build Coastguard Worker 
2055*9880d681SAndroid Build Coastguard Worker     if (isExtern) {
2056*9880d681SAndroid Build Coastguard Worker       Expected<StringRef> SymName = Symbol.getName();
2057*9880d681SAndroid Build Coastguard Worker       if (!SymName) {
2058*9880d681SAndroid Build Coastguard Worker         std::string Buf;
2059*9880d681SAndroid Build Coastguard Worker         raw_string_ostream OS(Buf);
2060*9880d681SAndroid Build Coastguard Worker         logAllUnhandledErrors(SymName.takeError(), OS, "");
2061*9880d681SAndroid Build Coastguard Worker         OS.flush();
2062*9880d681SAndroid Build Coastguard Worker         report_fatal_error(Buf);
2063*9880d681SAndroid Build Coastguard Worker       }
2064*9880d681SAndroid Build Coastguard Worker       const char *name = SymName->data();
2065*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Present = 1;
2066*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Name = name;
2067*9880d681SAndroid Build Coastguard Worker       switch (r_type) {
2068*9880d681SAndroid Build Coastguard Worker       case MachO::ARM_RELOC_HALF:
2069*9880d681SAndroid Build Coastguard Worker         if ((r_length & 0x1) == 1) {
2070*9880d681SAndroid Build Coastguard Worker           op_info->Value = value << 16 | other_half;
2071*9880d681SAndroid Build Coastguard Worker           op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2072*9880d681SAndroid Build Coastguard Worker         } else {
2073*9880d681SAndroid Build Coastguard Worker           op_info->Value = other_half << 16 | value;
2074*9880d681SAndroid Build Coastguard Worker           op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2075*9880d681SAndroid Build Coastguard Worker         }
2076*9880d681SAndroid Build Coastguard Worker         break;
2077*9880d681SAndroid Build Coastguard Worker       default:
2078*9880d681SAndroid Build Coastguard Worker         break;
2079*9880d681SAndroid Build Coastguard Worker       }
2080*9880d681SAndroid Build Coastguard Worker       return 1;
2081*9880d681SAndroid Build Coastguard Worker     }
2082*9880d681SAndroid Build Coastguard Worker     // If we have a branch that is not an external relocation entry then
2083*9880d681SAndroid Build Coastguard Worker     // return 0 so the code in tryAddingSymbolicOperand() can use the
2084*9880d681SAndroid Build Coastguard Worker     // SymbolLookUp call back with the branch target address to look up the
2085*9880d681SAndroid Build Coastguard Worker     // symbol and possiblity add an annotation for a symbol stub.
2086*9880d681SAndroid Build Coastguard Worker     if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
2087*9880d681SAndroid Build Coastguard Worker                           r_type == MachO::ARM_THUMB_RELOC_BR22))
2088*9880d681SAndroid Build Coastguard Worker       return 0;
2089*9880d681SAndroid Build Coastguard Worker 
2090*9880d681SAndroid Build Coastguard Worker     uint32_t offset = 0;
2091*9880d681SAndroid Build Coastguard Worker     if (r_type == MachO::ARM_RELOC_HALF ||
2092*9880d681SAndroid Build Coastguard Worker         r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2093*9880d681SAndroid Build Coastguard Worker       if ((r_length & 0x1) == 1)
2094*9880d681SAndroid Build Coastguard Worker         value = value << 16 | other_half;
2095*9880d681SAndroid Build Coastguard Worker       else
2096*9880d681SAndroid Build Coastguard Worker         value = other_half << 16 | value;
2097*9880d681SAndroid Build Coastguard Worker     }
2098*9880d681SAndroid Build Coastguard Worker     if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
2099*9880d681SAndroid Build Coastguard Worker                         r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
2100*9880d681SAndroid Build Coastguard Worker       offset = value - r_value;
2101*9880d681SAndroid Build Coastguard Worker       value = r_value;
2102*9880d681SAndroid Build Coastguard Worker     }
2103*9880d681SAndroid Build Coastguard Worker 
2104*9880d681SAndroid Build Coastguard Worker     if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2105*9880d681SAndroid Build Coastguard Worker       if ((r_length & 0x1) == 1)
2106*9880d681SAndroid Build Coastguard Worker         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2107*9880d681SAndroid Build Coastguard Worker       else
2108*9880d681SAndroid Build Coastguard Worker         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2109*9880d681SAndroid Build Coastguard Worker       const char *add = GuessSymbolName(r_value, info->AddrMap);
2110*9880d681SAndroid Build Coastguard Worker       const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2111*9880d681SAndroid Build Coastguard Worker       int32_t offset = value - (r_value - pair_r_value);
2112*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Present = 1;
2113*9880d681SAndroid Build Coastguard Worker       if (add != nullptr)
2114*9880d681SAndroid Build Coastguard Worker         op_info->AddSymbol.Name = add;
2115*9880d681SAndroid Build Coastguard Worker       else
2116*9880d681SAndroid Build Coastguard Worker         op_info->AddSymbol.Value = r_value;
2117*9880d681SAndroid Build Coastguard Worker       op_info->SubtractSymbol.Present = 1;
2118*9880d681SAndroid Build Coastguard Worker       if (sub != nullptr)
2119*9880d681SAndroid Build Coastguard Worker         op_info->SubtractSymbol.Name = sub;
2120*9880d681SAndroid Build Coastguard Worker       else
2121*9880d681SAndroid Build Coastguard Worker         op_info->SubtractSymbol.Value = pair_r_value;
2122*9880d681SAndroid Build Coastguard Worker       op_info->Value = offset;
2123*9880d681SAndroid Build Coastguard Worker       return 1;
2124*9880d681SAndroid Build Coastguard Worker     }
2125*9880d681SAndroid Build Coastguard Worker 
2126*9880d681SAndroid Build Coastguard Worker     op_info->AddSymbol.Present = 1;
2127*9880d681SAndroid Build Coastguard Worker     op_info->Value = offset;
2128*9880d681SAndroid Build Coastguard Worker     if (r_type == MachO::ARM_RELOC_HALF) {
2129*9880d681SAndroid Build Coastguard Worker       if ((r_length & 0x1) == 1)
2130*9880d681SAndroid Build Coastguard Worker         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2131*9880d681SAndroid Build Coastguard Worker       else
2132*9880d681SAndroid Build Coastguard Worker         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2133*9880d681SAndroid Build Coastguard Worker     }
2134*9880d681SAndroid Build Coastguard Worker     const char *add = GuessSymbolName(value, info->AddrMap);
2135*9880d681SAndroid Build Coastguard Worker     if (add != nullptr) {
2136*9880d681SAndroid Build Coastguard Worker       op_info->AddSymbol.Name = add;
2137*9880d681SAndroid Build Coastguard Worker       return 1;
2138*9880d681SAndroid Build Coastguard Worker     }
2139*9880d681SAndroid Build Coastguard Worker     op_info->AddSymbol.Value = value;
2140*9880d681SAndroid Build Coastguard Worker     return 1;
2141*9880d681SAndroid Build Coastguard Worker   }
2142*9880d681SAndroid Build Coastguard Worker   if (Arch == Triple::aarch64) {
2143*9880d681SAndroid Build Coastguard Worker     if (Offset != 0 || Size != 4)
2144*9880d681SAndroid Build Coastguard Worker       return 0;
2145*9880d681SAndroid Build Coastguard Worker     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2146*9880d681SAndroid Build Coastguard Worker       // TODO:
2147*9880d681SAndroid Build Coastguard Worker       // Search the external relocation entries of a fully linked image
2148*9880d681SAndroid Build Coastguard Worker       // (if any) for an entry that matches this segment offset.
2149*9880d681SAndroid Build Coastguard Worker       // uint64_t seg_offset = (Pc + Offset);
2150*9880d681SAndroid Build Coastguard Worker       return 0;
2151*9880d681SAndroid Build Coastguard Worker     }
2152*9880d681SAndroid Build Coastguard Worker     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2153*9880d681SAndroid Build Coastguard Worker     // for an entry for this section offset.
2154*9880d681SAndroid Build Coastguard Worker     uint64_t sect_addr = info->S.getAddress();
2155*9880d681SAndroid Build Coastguard Worker     uint64_t sect_offset = (Pc + Offset) - sect_addr;
2156*9880d681SAndroid Build Coastguard Worker     auto Reloc =
2157*9880d681SAndroid Build Coastguard Worker         std::find_if(info->S.relocations().begin(), info->S.relocations().end(),
2158*9880d681SAndroid Build Coastguard Worker                      [&](const RelocationRef &Reloc) {
2159*9880d681SAndroid Build Coastguard Worker                        uint64_t RelocOffset = Reloc.getOffset();
2160*9880d681SAndroid Build Coastguard Worker                        return RelocOffset == sect_offset;
2161*9880d681SAndroid Build Coastguard Worker                      });
2162*9880d681SAndroid Build Coastguard Worker 
2163*9880d681SAndroid Build Coastguard Worker     if (Reloc == info->S.relocations().end())
2164*9880d681SAndroid Build Coastguard Worker       return 0;
2165*9880d681SAndroid Build Coastguard Worker 
2166*9880d681SAndroid Build Coastguard Worker     DataRefImpl Rel = Reloc->getRawDataRefImpl();
2167*9880d681SAndroid Build Coastguard Worker     MachO::any_relocation_info RE = info->O->getRelocation(Rel);
2168*9880d681SAndroid Build Coastguard Worker     uint32_t r_type = info->O->getAnyRelocationType(RE);
2169*9880d681SAndroid Build Coastguard Worker     if (r_type == MachO::ARM64_RELOC_ADDEND) {
2170*9880d681SAndroid Build Coastguard Worker       DataRefImpl RelNext = Rel;
2171*9880d681SAndroid Build Coastguard Worker       info->O->moveRelocationNext(RelNext);
2172*9880d681SAndroid Build Coastguard Worker       MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2173*9880d681SAndroid Build Coastguard Worker       if (value == 0) {
2174*9880d681SAndroid Build Coastguard Worker         value = info->O->getPlainRelocationSymbolNum(RENext);
2175*9880d681SAndroid Build Coastguard Worker         op_info->Value = value;
2176*9880d681SAndroid Build Coastguard Worker       }
2177*9880d681SAndroid Build Coastguard Worker     }
2178*9880d681SAndroid Build Coastguard Worker     // NOTE: Scattered relocations don't exist on arm64.
2179*9880d681SAndroid Build Coastguard Worker     if (!info->O->getPlainRelocationExternal(RE))
2180*9880d681SAndroid Build Coastguard Worker       return 0;
2181*9880d681SAndroid Build Coastguard Worker     Expected<StringRef> SymName = Reloc->getSymbol()->getName();
2182*9880d681SAndroid Build Coastguard Worker     if (!SymName) {
2183*9880d681SAndroid Build Coastguard Worker       std::string Buf;
2184*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Buf);
2185*9880d681SAndroid Build Coastguard Worker       logAllUnhandledErrors(SymName.takeError(), OS, "");
2186*9880d681SAndroid Build Coastguard Worker       OS.flush();
2187*9880d681SAndroid Build Coastguard Worker       report_fatal_error(Buf);
2188*9880d681SAndroid Build Coastguard Worker     }
2189*9880d681SAndroid Build Coastguard Worker     const char *name = SymName->data();
2190*9880d681SAndroid Build Coastguard Worker     op_info->AddSymbol.Present = 1;
2191*9880d681SAndroid Build Coastguard Worker     op_info->AddSymbol.Name = name;
2192*9880d681SAndroid Build Coastguard Worker 
2193*9880d681SAndroid Build Coastguard Worker     switch (r_type) {
2194*9880d681SAndroid Build Coastguard Worker     case MachO::ARM64_RELOC_PAGE21:
2195*9880d681SAndroid Build Coastguard Worker       /* @page */
2196*9880d681SAndroid Build Coastguard Worker       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
2197*9880d681SAndroid Build Coastguard Worker       break;
2198*9880d681SAndroid Build Coastguard Worker     case MachO::ARM64_RELOC_PAGEOFF12:
2199*9880d681SAndroid Build Coastguard Worker       /* @pageoff */
2200*9880d681SAndroid Build Coastguard Worker       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
2201*9880d681SAndroid Build Coastguard Worker       break;
2202*9880d681SAndroid Build Coastguard Worker     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
2203*9880d681SAndroid Build Coastguard Worker       /* @gotpage */
2204*9880d681SAndroid Build Coastguard Worker       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
2205*9880d681SAndroid Build Coastguard Worker       break;
2206*9880d681SAndroid Build Coastguard Worker     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
2207*9880d681SAndroid Build Coastguard Worker       /* @gotpageoff */
2208*9880d681SAndroid Build Coastguard Worker       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
2209*9880d681SAndroid Build Coastguard Worker       break;
2210*9880d681SAndroid Build Coastguard Worker     case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
2211*9880d681SAndroid Build Coastguard Worker       /* @tvlppage is not implemented in llvm-mc */
2212*9880d681SAndroid Build Coastguard Worker       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
2213*9880d681SAndroid Build Coastguard Worker       break;
2214*9880d681SAndroid Build Coastguard Worker     case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
2215*9880d681SAndroid Build Coastguard Worker       /* @tvlppageoff is not implemented in llvm-mc */
2216*9880d681SAndroid Build Coastguard Worker       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
2217*9880d681SAndroid Build Coastguard Worker       break;
2218*9880d681SAndroid Build Coastguard Worker     default:
2219*9880d681SAndroid Build Coastguard Worker     case MachO::ARM64_RELOC_BRANCH26:
2220*9880d681SAndroid Build Coastguard Worker       op_info->VariantKind = LLVMDisassembler_VariantKind_None;
2221*9880d681SAndroid Build Coastguard Worker       break;
2222*9880d681SAndroid Build Coastguard Worker     }
2223*9880d681SAndroid Build Coastguard Worker     return 1;
2224*9880d681SAndroid Build Coastguard Worker   }
2225*9880d681SAndroid Build Coastguard Worker   return 0;
2226*9880d681SAndroid Build Coastguard Worker }
2227*9880d681SAndroid Build Coastguard Worker 
2228*9880d681SAndroid Build Coastguard Worker // GuessCstringPointer is passed the address of what might be a pointer to a
2229*9880d681SAndroid Build Coastguard Worker // literal string in a cstring section.  If that address is in a cstring section
2230*9880d681SAndroid Build Coastguard Worker // it returns a pointer to that string.  Else it returns nullptr.
GuessCstringPointer(uint64_t ReferenceValue,struct DisassembleInfo * info)2231*9880d681SAndroid Build Coastguard Worker static const char *GuessCstringPointer(uint64_t ReferenceValue,
2232*9880d681SAndroid Build Coastguard Worker                                        struct DisassembleInfo *info) {
2233*9880d681SAndroid Build Coastguard Worker   for (const auto &Load : info->O->load_commands()) {
2234*9880d681SAndroid Build Coastguard Worker     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2235*9880d681SAndroid Build Coastguard Worker       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2236*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
2237*9880d681SAndroid Build Coastguard Worker         MachO::section_64 Sec = info->O->getSection64(Load, J);
2238*9880d681SAndroid Build Coastguard Worker         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2239*9880d681SAndroid Build Coastguard Worker         if (section_type == MachO::S_CSTRING_LITERALS &&
2240*9880d681SAndroid Build Coastguard Worker             ReferenceValue >= Sec.addr &&
2241*9880d681SAndroid Build Coastguard Worker             ReferenceValue < Sec.addr + Sec.size) {
2242*9880d681SAndroid Build Coastguard Worker           uint64_t sect_offset = ReferenceValue - Sec.addr;
2243*9880d681SAndroid Build Coastguard Worker           uint64_t object_offset = Sec.offset + sect_offset;
2244*9880d681SAndroid Build Coastguard Worker           StringRef MachOContents = info->O->getData();
2245*9880d681SAndroid Build Coastguard Worker           uint64_t object_size = MachOContents.size();
2246*9880d681SAndroid Build Coastguard Worker           const char *object_addr = (const char *)MachOContents.data();
2247*9880d681SAndroid Build Coastguard Worker           if (object_offset < object_size) {
2248*9880d681SAndroid Build Coastguard Worker             const char *name = object_addr + object_offset;
2249*9880d681SAndroid Build Coastguard Worker             return name;
2250*9880d681SAndroid Build Coastguard Worker           } else {
2251*9880d681SAndroid Build Coastguard Worker             return nullptr;
2252*9880d681SAndroid Build Coastguard Worker           }
2253*9880d681SAndroid Build Coastguard Worker         }
2254*9880d681SAndroid Build Coastguard Worker       }
2255*9880d681SAndroid Build Coastguard Worker     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2256*9880d681SAndroid Build Coastguard Worker       MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2257*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
2258*9880d681SAndroid Build Coastguard Worker         MachO::section Sec = info->O->getSection(Load, J);
2259*9880d681SAndroid Build Coastguard Worker         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2260*9880d681SAndroid Build Coastguard Worker         if (section_type == MachO::S_CSTRING_LITERALS &&
2261*9880d681SAndroid Build Coastguard Worker             ReferenceValue >= Sec.addr &&
2262*9880d681SAndroid Build Coastguard Worker             ReferenceValue < Sec.addr + Sec.size) {
2263*9880d681SAndroid Build Coastguard Worker           uint64_t sect_offset = ReferenceValue - Sec.addr;
2264*9880d681SAndroid Build Coastguard Worker           uint64_t object_offset = Sec.offset + sect_offset;
2265*9880d681SAndroid Build Coastguard Worker           StringRef MachOContents = info->O->getData();
2266*9880d681SAndroid Build Coastguard Worker           uint64_t object_size = MachOContents.size();
2267*9880d681SAndroid Build Coastguard Worker           const char *object_addr = (const char *)MachOContents.data();
2268*9880d681SAndroid Build Coastguard Worker           if (object_offset < object_size) {
2269*9880d681SAndroid Build Coastguard Worker             const char *name = object_addr + object_offset;
2270*9880d681SAndroid Build Coastguard Worker             return name;
2271*9880d681SAndroid Build Coastguard Worker           } else {
2272*9880d681SAndroid Build Coastguard Worker             return nullptr;
2273*9880d681SAndroid Build Coastguard Worker           }
2274*9880d681SAndroid Build Coastguard Worker         }
2275*9880d681SAndroid Build Coastguard Worker       }
2276*9880d681SAndroid Build Coastguard Worker     }
2277*9880d681SAndroid Build Coastguard Worker   }
2278*9880d681SAndroid Build Coastguard Worker   return nullptr;
2279*9880d681SAndroid Build Coastguard Worker }
2280*9880d681SAndroid Build Coastguard Worker 
2281*9880d681SAndroid Build Coastguard Worker // GuessIndirectSymbol returns the name of the indirect symbol for the
2282*9880d681SAndroid Build Coastguard Worker // ReferenceValue passed in or nullptr.  This is used when ReferenceValue maybe
2283*9880d681SAndroid Build Coastguard Worker // an address of a symbol stub or a lazy or non-lazy pointer to associate the
2284*9880d681SAndroid Build Coastguard Worker // symbol name being referenced by the stub or pointer.
GuessIndirectSymbol(uint64_t ReferenceValue,struct DisassembleInfo * info)2285*9880d681SAndroid Build Coastguard Worker static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
2286*9880d681SAndroid Build Coastguard Worker                                        struct DisassembleInfo *info) {
2287*9880d681SAndroid Build Coastguard Worker   MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
2288*9880d681SAndroid Build Coastguard Worker   MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
2289*9880d681SAndroid Build Coastguard Worker   for (const auto &Load : info->O->load_commands()) {
2290*9880d681SAndroid Build Coastguard Worker     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2291*9880d681SAndroid Build Coastguard Worker       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2292*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
2293*9880d681SAndroid Build Coastguard Worker         MachO::section_64 Sec = info->O->getSection64(Load, J);
2294*9880d681SAndroid Build Coastguard Worker         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2295*9880d681SAndroid Build Coastguard Worker         if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2296*9880d681SAndroid Build Coastguard Worker              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2297*9880d681SAndroid Build Coastguard Worker              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2298*9880d681SAndroid Build Coastguard Worker              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2299*9880d681SAndroid Build Coastguard Worker              section_type == MachO::S_SYMBOL_STUBS) &&
2300*9880d681SAndroid Build Coastguard Worker             ReferenceValue >= Sec.addr &&
2301*9880d681SAndroid Build Coastguard Worker             ReferenceValue < Sec.addr + Sec.size) {
2302*9880d681SAndroid Build Coastguard Worker           uint32_t stride;
2303*9880d681SAndroid Build Coastguard Worker           if (section_type == MachO::S_SYMBOL_STUBS)
2304*9880d681SAndroid Build Coastguard Worker             stride = Sec.reserved2;
2305*9880d681SAndroid Build Coastguard Worker           else
2306*9880d681SAndroid Build Coastguard Worker             stride = 8;
2307*9880d681SAndroid Build Coastguard Worker           if (stride == 0)
2308*9880d681SAndroid Build Coastguard Worker             return nullptr;
2309*9880d681SAndroid Build Coastguard Worker           uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2310*9880d681SAndroid Build Coastguard Worker           if (index < Dysymtab.nindirectsyms) {
2311*9880d681SAndroid Build Coastguard Worker             uint32_t indirect_symbol =
2312*9880d681SAndroid Build Coastguard Worker                 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2313*9880d681SAndroid Build Coastguard Worker             if (indirect_symbol < Symtab.nsyms) {
2314*9880d681SAndroid Build Coastguard Worker               symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2315*9880d681SAndroid Build Coastguard Worker               SymbolRef Symbol = *Sym;
2316*9880d681SAndroid Build Coastguard Worker               Expected<StringRef> SymName = Symbol.getName();
2317*9880d681SAndroid Build Coastguard Worker               if (!SymName) {
2318*9880d681SAndroid Build Coastguard Worker                 std::string Buf;
2319*9880d681SAndroid Build Coastguard Worker                 raw_string_ostream OS(Buf);
2320*9880d681SAndroid Build Coastguard Worker                 logAllUnhandledErrors(SymName.takeError(), OS, "");
2321*9880d681SAndroid Build Coastguard Worker                 OS.flush();
2322*9880d681SAndroid Build Coastguard Worker                 report_fatal_error(Buf);
2323*9880d681SAndroid Build Coastguard Worker               }
2324*9880d681SAndroid Build Coastguard Worker               const char *name = SymName->data();
2325*9880d681SAndroid Build Coastguard Worker               return name;
2326*9880d681SAndroid Build Coastguard Worker             }
2327*9880d681SAndroid Build Coastguard Worker           }
2328*9880d681SAndroid Build Coastguard Worker         }
2329*9880d681SAndroid Build Coastguard Worker       }
2330*9880d681SAndroid Build Coastguard Worker     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2331*9880d681SAndroid Build Coastguard Worker       MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2332*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
2333*9880d681SAndroid Build Coastguard Worker         MachO::section Sec = info->O->getSection(Load, J);
2334*9880d681SAndroid Build Coastguard Worker         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2335*9880d681SAndroid Build Coastguard Worker         if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2336*9880d681SAndroid Build Coastguard Worker              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2337*9880d681SAndroid Build Coastguard Worker              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2338*9880d681SAndroid Build Coastguard Worker              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2339*9880d681SAndroid Build Coastguard Worker              section_type == MachO::S_SYMBOL_STUBS) &&
2340*9880d681SAndroid Build Coastguard Worker             ReferenceValue >= Sec.addr &&
2341*9880d681SAndroid Build Coastguard Worker             ReferenceValue < Sec.addr + Sec.size) {
2342*9880d681SAndroid Build Coastguard Worker           uint32_t stride;
2343*9880d681SAndroid Build Coastguard Worker           if (section_type == MachO::S_SYMBOL_STUBS)
2344*9880d681SAndroid Build Coastguard Worker             stride = Sec.reserved2;
2345*9880d681SAndroid Build Coastguard Worker           else
2346*9880d681SAndroid Build Coastguard Worker             stride = 4;
2347*9880d681SAndroid Build Coastguard Worker           if (stride == 0)
2348*9880d681SAndroid Build Coastguard Worker             return nullptr;
2349*9880d681SAndroid Build Coastguard Worker           uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2350*9880d681SAndroid Build Coastguard Worker           if (index < Dysymtab.nindirectsyms) {
2351*9880d681SAndroid Build Coastguard Worker             uint32_t indirect_symbol =
2352*9880d681SAndroid Build Coastguard Worker                 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2353*9880d681SAndroid Build Coastguard Worker             if (indirect_symbol < Symtab.nsyms) {
2354*9880d681SAndroid Build Coastguard Worker               symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2355*9880d681SAndroid Build Coastguard Worker               SymbolRef Symbol = *Sym;
2356*9880d681SAndroid Build Coastguard Worker               Expected<StringRef> SymName = Symbol.getName();
2357*9880d681SAndroid Build Coastguard Worker               if (!SymName) {
2358*9880d681SAndroid Build Coastguard Worker                 std::string Buf;
2359*9880d681SAndroid Build Coastguard Worker                 raw_string_ostream OS(Buf);
2360*9880d681SAndroid Build Coastguard Worker                 logAllUnhandledErrors(SymName.takeError(), OS, "");
2361*9880d681SAndroid Build Coastguard Worker                 OS.flush();
2362*9880d681SAndroid Build Coastguard Worker                 report_fatal_error(Buf);
2363*9880d681SAndroid Build Coastguard Worker               }
2364*9880d681SAndroid Build Coastguard Worker               const char *name = SymName->data();
2365*9880d681SAndroid Build Coastguard Worker               return name;
2366*9880d681SAndroid Build Coastguard Worker             }
2367*9880d681SAndroid Build Coastguard Worker           }
2368*9880d681SAndroid Build Coastguard Worker         }
2369*9880d681SAndroid Build Coastguard Worker       }
2370*9880d681SAndroid Build Coastguard Worker     }
2371*9880d681SAndroid Build Coastguard Worker   }
2372*9880d681SAndroid Build Coastguard Worker   return nullptr;
2373*9880d681SAndroid Build Coastguard Worker }
2374*9880d681SAndroid Build Coastguard Worker 
2375*9880d681SAndroid Build Coastguard Worker // method_reference() is called passing it the ReferenceName that might be
2376*9880d681SAndroid Build Coastguard Worker // a reference it to an Objective-C method call.  If so then it allocates and
2377*9880d681SAndroid Build Coastguard Worker // assembles a method call string with the values last seen and saved in
2378*9880d681SAndroid Build Coastguard Worker // the DisassembleInfo's class_name and selector_name fields.  This is saved
2379*9880d681SAndroid Build Coastguard Worker // into the method field of the info and any previous string is free'ed.
2380*9880d681SAndroid Build Coastguard Worker // Then the class_name field in the info is set to nullptr.  The method call
2381*9880d681SAndroid Build Coastguard Worker // string is set into ReferenceName and ReferenceType is set to
2382*9880d681SAndroid Build Coastguard Worker // LLVMDisassembler_ReferenceType_Out_Objc_Message.  If this not a method call
2383*9880d681SAndroid Build Coastguard Worker // then both ReferenceType and ReferenceName are left unchanged.
method_reference(struct DisassembleInfo * info,uint64_t * ReferenceType,const char ** ReferenceName)2384*9880d681SAndroid Build Coastguard Worker static void method_reference(struct DisassembleInfo *info,
2385*9880d681SAndroid Build Coastguard Worker                              uint64_t *ReferenceType,
2386*9880d681SAndroid Build Coastguard Worker                              const char **ReferenceName) {
2387*9880d681SAndroid Build Coastguard Worker   unsigned int Arch = info->O->getArch();
2388*9880d681SAndroid Build Coastguard Worker   if (*ReferenceName != nullptr) {
2389*9880d681SAndroid Build Coastguard Worker     if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
2390*9880d681SAndroid Build Coastguard Worker       if (info->selector_name != nullptr) {
2391*9880d681SAndroid Build Coastguard Worker         if (info->method != nullptr)
2392*9880d681SAndroid Build Coastguard Worker           free(info->method);
2393*9880d681SAndroid Build Coastguard Worker         if (info->class_name != nullptr) {
2394*9880d681SAndroid Build Coastguard Worker           info->method = (char *)malloc(5 + strlen(info->class_name) +
2395*9880d681SAndroid Build Coastguard Worker                                         strlen(info->selector_name));
2396*9880d681SAndroid Build Coastguard Worker           if (info->method != nullptr) {
2397*9880d681SAndroid Build Coastguard Worker             strcpy(info->method, "+[");
2398*9880d681SAndroid Build Coastguard Worker             strcat(info->method, info->class_name);
2399*9880d681SAndroid Build Coastguard Worker             strcat(info->method, " ");
2400*9880d681SAndroid Build Coastguard Worker             strcat(info->method, info->selector_name);
2401*9880d681SAndroid Build Coastguard Worker             strcat(info->method, "]");
2402*9880d681SAndroid Build Coastguard Worker             *ReferenceName = info->method;
2403*9880d681SAndroid Build Coastguard Worker             *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2404*9880d681SAndroid Build Coastguard Worker           }
2405*9880d681SAndroid Build Coastguard Worker         } else {
2406*9880d681SAndroid Build Coastguard Worker           info->method = (char *)malloc(9 + strlen(info->selector_name));
2407*9880d681SAndroid Build Coastguard Worker           if (info->method != nullptr) {
2408*9880d681SAndroid Build Coastguard Worker             if (Arch == Triple::x86_64)
2409*9880d681SAndroid Build Coastguard Worker               strcpy(info->method, "-[%rdi ");
2410*9880d681SAndroid Build Coastguard Worker             else if (Arch == Triple::aarch64)
2411*9880d681SAndroid Build Coastguard Worker               strcpy(info->method, "-[x0 ");
2412*9880d681SAndroid Build Coastguard Worker             else
2413*9880d681SAndroid Build Coastguard Worker               strcpy(info->method, "-[r? ");
2414*9880d681SAndroid Build Coastguard Worker             strcat(info->method, info->selector_name);
2415*9880d681SAndroid Build Coastguard Worker             strcat(info->method, "]");
2416*9880d681SAndroid Build Coastguard Worker             *ReferenceName = info->method;
2417*9880d681SAndroid Build Coastguard Worker             *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2418*9880d681SAndroid Build Coastguard Worker           }
2419*9880d681SAndroid Build Coastguard Worker         }
2420*9880d681SAndroid Build Coastguard Worker         info->class_name = nullptr;
2421*9880d681SAndroid Build Coastguard Worker       }
2422*9880d681SAndroid Build Coastguard Worker     } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
2423*9880d681SAndroid Build Coastguard Worker       if (info->selector_name != nullptr) {
2424*9880d681SAndroid Build Coastguard Worker         if (info->method != nullptr)
2425*9880d681SAndroid Build Coastguard Worker           free(info->method);
2426*9880d681SAndroid Build Coastguard Worker         info->method = (char *)malloc(17 + strlen(info->selector_name));
2427*9880d681SAndroid Build Coastguard Worker         if (info->method != nullptr) {
2428*9880d681SAndroid Build Coastguard Worker           if (Arch == Triple::x86_64)
2429*9880d681SAndroid Build Coastguard Worker             strcpy(info->method, "-[[%rdi super] ");
2430*9880d681SAndroid Build Coastguard Worker           else if (Arch == Triple::aarch64)
2431*9880d681SAndroid Build Coastguard Worker             strcpy(info->method, "-[[x0 super] ");
2432*9880d681SAndroid Build Coastguard Worker           else
2433*9880d681SAndroid Build Coastguard Worker             strcpy(info->method, "-[[r? super] ");
2434*9880d681SAndroid Build Coastguard Worker           strcat(info->method, info->selector_name);
2435*9880d681SAndroid Build Coastguard Worker           strcat(info->method, "]");
2436*9880d681SAndroid Build Coastguard Worker           *ReferenceName = info->method;
2437*9880d681SAndroid Build Coastguard Worker           *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2438*9880d681SAndroid Build Coastguard Worker         }
2439*9880d681SAndroid Build Coastguard Worker         info->class_name = nullptr;
2440*9880d681SAndroid Build Coastguard Worker       }
2441*9880d681SAndroid Build Coastguard Worker     }
2442*9880d681SAndroid Build Coastguard Worker   }
2443*9880d681SAndroid Build Coastguard Worker }
2444*9880d681SAndroid Build Coastguard Worker 
2445*9880d681SAndroid Build Coastguard Worker // GuessPointerPointer() is passed the address of what might be a pointer to
2446*9880d681SAndroid Build Coastguard Worker // a reference to an Objective-C class, selector, message ref or cfstring.
2447*9880d681SAndroid Build Coastguard Worker // If so the value of the pointer is returned and one of the booleans are set
2448*9880d681SAndroid Build Coastguard Worker // to true.  If not zero is returned and all the booleans are set to false.
GuessPointerPointer(uint64_t ReferenceValue,struct DisassembleInfo * info,bool & classref,bool & selref,bool & msgref,bool & cfstring)2449*9880d681SAndroid Build Coastguard Worker static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
2450*9880d681SAndroid Build Coastguard Worker                                     struct DisassembleInfo *info,
2451*9880d681SAndroid Build Coastguard Worker                                     bool &classref, bool &selref, bool &msgref,
2452*9880d681SAndroid Build Coastguard Worker                                     bool &cfstring) {
2453*9880d681SAndroid Build Coastguard Worker   classref = false;
2454*9880d681SAndroid Build Coastguard Worker   selref = false;
2455*9880d681SAndroid Build Coastguard Worker   msgref = false;
2456*9880d681SAndroid Build Coastguard Worker   cfstring = false;
2457*9880d681SAndroid Build Coastguard Worker   for (const auto &Load : info->O->load_commands()) {
2458*9880d681SAndroid Build Coastguard Worker     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2459*9880d681SAndroid Build Coastguard Worker       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2460*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
2461*9880d681SAndroid Build Coastguard Worker         MachO::section_64 Sec = info->O->getSection64(Load, J);
2462*9880d681SAndroid Build Coastguard Worker         if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
2463*9880d681SAndroid Build Coastguard Worker              strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2464*9880d681SAndroid Build Coastguard Worker              strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
2465*9880d681SAndroid Build Coastguard Worker              strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
2466*9880d681SAndroid Build Coastguard Worker              strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
2467*9880d681SAndroid Build Coastguard Worker             ReferenceValue >= Sec.addr &&
2468*9880d681SAndroid Build Coastguard Worker             ReferenceValue < Sec.addr + Sec.size) {
2469*9880d681SAndroid Build Coastguard Worker           uint64_t sect_offset = ReferenceValue - Sec.addr;
2470*9880d681SAndroid Build Coastguard Worker           uint64_t object_offset = Sec.offset + sect_offset;
2471*9880d681SAndroid Build Coastguard Worker           StringRef MachOContents = info->O->getData();
2472*9880d681SAndroid Build Coastguard Worker           uint64_t object_size = MachOContents.size();
2473*9880d681SAndroid Build Coastguard Worker           const char *object_addr = (const char *)MachOContents.data();
2474*9880d681SAndroid Build Coastguard Worker           if (object_offset < object_size) {
2475*9880d681SAndroid Build Coastguard Worker             uint64_t pointer_value;
2476*9880d681SAndroid Build Coastguard Worker             memcpy(&pointer_value, object_addr + object_offset,
2477*9880d681SAndroid Build Coastguard Worker                    sizeof(uint64_t));
2478*9880d681SAndroid Build Coastguard Worker             if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2479*9880d681SAndroid Build Coastguard Worker               sys::swapByteOrder(pointer_value);
2480*9880d681SAndroid Build Coastguard Worker             if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
2481*9880d681SAndroid Build Coastguard Worker               selref = true;
2482*9880d681SAndroid Build Coastguard Worker             else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2483*9880d681SAndroid Build Coastguard Worker                      strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
2484*9880d681SAndroid Build Coastguard Worker               classref = true;
2485*9880d681SAndroid Build Coastguard Worker             else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
2486*9880d681SAndroid Build Coastguard Worker                      ReferenceValue + 8 < Sec.addr + Sec.size) {
2487*9880d681SAndroid Build Coastguard Worker               msgref = true;
2488*9880d681SAndroid Build Coastguard Worker               memcpy(&pointer_value, object_addr + object_offset + 8,
2489*9880d681SAndroid Build Coastguard Worker                      sizeof(uint64_t));
2490*9880d681SAndroid Build Coastguard Worker               if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2491*9880d681SAndroid Build Coastguard Worker                 sys::swapByteOrder(pointer_value);
2492*9880d681SAndroid Build Coastguard Worker             } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
2493*9880d681SAndroid Build Coastguard Worker               cfstring = true;
2494*9880d681SAndroid Build Coastguard Worker             return pointer_value;
2495*9880d681SAndroid Build Coastguard Worker           } else {
2496*9880d681SAndroid Build Coastguard Worker             return 0;
2497*9880d681SAndroid Build Coastguard Worker           }
2498*9880d681SAndroid Build Coastguard Worker         }
2499*9880d681SAndroid Build Coastguard Worker       }
2500*9880d681SAndroid Build Coastguard Worker     }
2501*9880d681SAndroid Build Coastguard Worker     // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
2502*9880d681SAndroid Build Coastguard Worker   }
2503*9880d681SAndroid Build Coastguard Worker   return 0;
2504*9880d681SAndroid Build Coastguard Worker }
2505*9880d681SAndroid Build Coastguard Worker 
2506*9880d681SAndroid Build Coastguard Worker // get_pointer_64 returns a pointer to the bytes in the object file at the
2507*9880d681SAndroid Build Coastguard Worker // Address from a section in the Mach-O file.  And indirectly returns the
2508*9880d681SAndroid Build Coastguard Worker // offset into the section, number of bytes left in the section past the offset
2509*9880d681SAndroid Build Coastguard Worker // and which section is was being referenced.  If the Address is not in a
2510*9880d681SAndroid Build Coastguard Worker // section nullptr is returned.
get_pointer_64(uint64_t Address,uint32_t & offset,uint32_t & left,SectionRef & S,DisassembleInfo * info,bool objc_only=false)2511*9880d681SAndroid Build Coastguard Worker static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
2512*9880d681SAndroid Build Coastguard Worker                                   uint32_t &left, SectionRef &S,
2513*9880d681SAndroid Build Coastguard Worker                                   DisassembleInfo *info,
2514*9880d681SAndroid Build Coastguard Worker                                   bool objc_only = false) {
2515*9880d681SAndroid Build Coastguard Worker   offset = 0;
2516*9880d681SAndroid Build Coastguard Worker   left = 0;
2517*9880d681SAndroid Build Coastguard Worker   S = SectionRef();
2518*9880d681SAndroid Build Coastguard Worker   for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
2519*9880d681SAndroid Build Coastguard Worker     uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
2520*9880d681SAndroid Build Coastguard Worker     uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
2521*9880d681SAndroid Build Coastguard Worker     if (SectSize == 0)
2522*9880d681SAndroid Build Coastguard Worker       continue;
2523*9880d681SAndroid Build Coastguard Worker     if (objc_only) {
2524*9880d681SAndroid Build Coastguard Worker       StringRef SectName;
2525*9880d681SAndroid Build Coastguard Worker       ((*(info->Sections))[SectIdx]).getName(SectName);
2526*9880d681SAndroid Build Coastguard Worker       DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
2527*9880d681SAndroid Build Coastguard Worker       StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
2528*9880d681SAndroid Build Coastguard Worker       if (SegName != "__OBJC" && SectName != "__cstring")
2529*9880d681SAndroid Build Coastguard Worker         continue;
2530*9880d681SAndroid Build Coastguard Worker     }
2531*9880d681SAndroid Build Coastguard Worker     if (Address >= SectAddress && Address < SectAddress + SectSize) {
2532*9880d681SAndroid Build Coastguard Worker       S = (*(info->Sections))[SectIdx];
2533*9880d681SAndroid Build Coastguard Worker       offset = Address - SectAddress;
2534*9880d681SAndroid Build Coastguard Worker       left = SectSize - offset;
2535*9880d681SAndroid Build Coastguard Worker       StringRef SectContents;
2536*9880d681SAndroid Build Coastguard Worker       ((*(info->Sections))[SectIdx]).getContents(SectContents);
2537*9880d681SAndroid Build Coastguard Worker       return SectContents.data() + offset;
2538*9880d681SAndroid Build Coastguard Worker     }
2539*9880d681SAndroid Build Coastguard Worker   }
2540*9880d681SAndroid Build Coastguard Worker   return nullptr;
2541*9880d681SAndroid Build Coastguard Worker }
2542*9880d681SAndroid Build Coastguard Worker 
get_pointer_32(uint32_t Address,uint32_t & offset,uint32_t & left,SectionRef & S,DisassembleInfo * info,bool objc_only=false)2543*9880d681SAndroid Build Coastguard Worker static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
2544*9880d681SAndroid Build Coastguard Worker                                   uint32_t &left, SectionRef &S,
2545*9880d681SAndroid Build Coastguard Worker                                   DisassembleInfo *info,
2546*9880d681SAndroid Build Coastguard Worker                                   bool objc_only = false) {
2547*9880d681SAndroid Build Coastguard Worker   return get_pointer_64(Address, offset, left, S, info, objc_only);
2548*9880d681SAndroid Build Coastguard Worker }
2549*9880d681SAndroid Build Coastguard Worker 
2550*9880d681SAndroid Build Coastguard Worker // get_symbol_64() returns the name of a symbol (or nullptr) and the address of
2551*9880d681SAndroid Build Coastguard Worker // the symbol indirectly through n_value. Based on the relocation information
2552*9880d681SAndroid Build Coastguard Worker // for the specified section offset in the specified section reference.
2553*9880d681SAndroid Build Coastguard Worker // If no relocation information is found and a non-zero ReferenceValue for the
2554*9880d681SAndroid Build Coastguard Worker // symbol is passed, look up that address in the info's AddrMap.
get_symbol_64(uint32_t sect_offset,SectionRef S,DisassembleInfo * info,uint64_t & n_value,uint64_t ReferenceValue=0)2555*9880d681SAndroid Build Coastguard Worker static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
2556*9880d681SAndroid Build Coastguard Worker                                  DisassembleInfo *info, uint64_t &n_value,
2557*9880d681SAndroid Build Coastguard Worker                                  uint64_t ReferenceValue = 0) {
2558*9880d681SAndroid Build Coastguard Worker   n_value = 0;
2559*9880d681SAndroid Build Coastguard Worker   if (!info->verbose)
2560*9880d681SAndroid Build Coastguard Worker     return nullptr;
2561*9880d681SAndroid Build Coastguard Worker 
2562*9880d681SAndroid Build Coastguard Worker   // See if there is an external relocation entry at the sect_offset.
2563*9880d681SAndroid Build Coastguard Worker   bool reloc_found = false;
2564*9880d681SAndroid Build Coastguard Worker   DataRefImpl Rel;
2565*9880d681SAndroid Build Coastguard Worker   MachO::any_relocation_info RE;
2566*9880d681SAndroid Build Coastguard Worker   bool isExtern = false;
2567*9880d681SAndroid Build Coastguard Worker   SymbolRef Symbol;
2568*9880d681SAndroid Build Coastguard Worker   for (const RelocationRef &Reloc : S.relocations()) {
2569*9880d681SAndroid Build Coastguard Worker     uint64_t RelocOffset = Reloc.getOffset();
2570*9880d681SAndroid Build Coastguard Worker     if (RelocOffset == sect_offset) {
2571*9880d681SAndroid Build Coastguard Worker       Rel = Reloc.getRawDataRefImpl();
2572*9880d681SAndroid Build Coastguard Worker       RE = info->O->getRelocation(Rel);
2573*9880d681SAndroid Build Coastguard Worker       if (info->O->isRelocationScattered(RE))
2574*9880d681SAndroid Build Coastguard Worker         continue;
2575*9880d681SAndroid Build Coastguard Worker       isExtern = info->O->getPlainRelocationExternal(RE);
2576*9880d681SAndroid Build Coastguard Worker       if (isExtern) {
2577*9880d681SAndroid Build Coastguard Worker         symbol_iterator RelocSym = Reloc.getSymbol();
2578*9880d681SAndroid Build Coastguard Worker         Symbol = *RelocSym;
2579*9880d681SAndroid Build Coastguard Worker       }
2580*9880d681SAndroid Build Coastguard Worker       reloc_found = true;
2581*9880d681SAndroid Build Coastguard Worker       break;
2582*9880d681SAndroid Build Coastguard Worker     }
2583*9880d681SAndroid Build Coastguard Worker   }
2584*9880d681SAndroid Build Coastguard Worker   // If there is an external relocation entry for a symbol in this section
2585*9880d681SAndroid Build Coastguard Worker   // at this section_offset then use that symbol's value for the n_value
2586*9880d681SAndroid Build Coastguard Worker   // and return its name.
2587*9880d681SAndroid Build Coastguard Worker   const char *SymbolName = nullptr;
2588*9880d681SAndroid Build Coastguard Worker   if (reloc_found && isExtern) {
2589*9880d681SAndroid Build Coastguard Worker     n_value = Symbol.getValue();
2590*9880d681SAndroid Build Coastguard Worker     Expected<StringRef> NameOrError = Symbol.getName();
2591*9880d681SAndroid Build Coastguard Worker     if (!NameOrError) {
2592*9880d681SAndroid Build Coastguard Worker       std::string Buf;
2593*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Buf);
2594*9880d681SAndroid Build Coastguard Worker       logAllUnhandledErrors(NameOrError.takeError(), OS, "");
2595*9880d681SAndroid Build Coastguard Worker       OS.flush();
2596*9880d681SAndroid Build Coastguard Worker       report_fatal_error(Buf);
2597*9880d681SAndroid Build Coastguard Worker     }
2598*9880d681SAndroid Build Coastguard Worker     StringRef Name = *NameOrError;
2599*9880d681SAndroid Build Coastguard Worker     if (!Name.empty()) {
2600*9880d681SAndroid Build Coastguard Worker       SymbolName = Name.data();
2601*9880d681SAndroid Build Coastguard Worker       return SymbolName;
2602*9880d681SAndroid Build Coastguard Worker     }
2603*9880d681SAndroid Build Coastguard Worker   }
2604*9880d681SAndroid Build Coastguard Worker 
2605*9880d681SAndroid Build Coastguard Worker   // TODO: For fully linked images, look through the external relocation
2606*9880d681SAndroid Build Coastguard Worker   // entries off the dynamic symtab command. For these the r_offset is from the
2607*9880d681SAndroid Build Coastguard Worker   // start of the first writeable segment in the Mach-O file.  So the offset
2608*9880d681SAndroid Build Coastguard Worker   // to this section from that segment is passed to this routine by the caller,
2609*9880d681SAndroid Build Coastguard Worker   // as the database_offset. Which is the difference of the section's starting
2610*9880d681SAndroid Build Coastguard Worker   // address and the first writable segment.
2611*9880d681SAndroid Build Coastguard Worker   //
2612*9880d681SAndroid Build Coastguard Worker   // NOTE: need add passing the database_offset to this routine.
2613*9880d681SAndroid Build Coastguard Worker 
2614*9880d681SAndroid Build Coastguard Worker   // We did not find an external relocation entry so look up the ReferenceValue
2615*9880d681SAndroid Build Coastguard Worker   // as an address of a symbol and if found return that symbol's name.
2616*9880d681SAndroid Build Coastguard Worker   SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
2617*9880d681SAndroid Build Coastguard Worker 
2618*9880d681SAndroid Build Coastguard Worker   return SymbolName;
2619*9880d681SAndroid Build Coastguard Worker }
2620*9880d681SAndroid Build Coastguard Worker 
get_symbol_32(uint32_t sect_offset,SectionRef S,DisassembleInfo * info,uint32_t ReferenceValue)2621*9880d681SAndroid Build Coastguard Worker static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
2622*9880d681SAndroid Build Coastguard Worker                                  DisassembleInfo *info,
2623*9880d681SAndroid Build Coastguard Worker                                  uint32_t ReferenceValue) {
2624*9880d681SAndroid Build Coastguard Worker   uint64_t n_value64;
2625*9880d681SAndroid Build Coastguard Worker   return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
2626*9880d681SAndroid Build Coastguard Worker }
2627*9880d681SAndroid Build Coastguard Worker 
2628*9880d681SAndroid Build Coastguard Worker // These are structs in the Objective-C meta data and read to produce the
2629*9880d681SAndroid Build Coastguard Worker // comments for disassembly.  While these are part of the ABI they are no
2630*9880d681SAndroid Build Coastguard Worker // public defintions.  So the are here not in include/llvm/Support/MachO.h .
2631*9880d681SAndroid Build Coastguard Worker 
2632*9880d681SAndroid Build Coastguard Worker // The cfstring object in a 64-bit Mach-O file.
2633*9880d681SAndroid Build Coastguard Worker struct cfstring64_t {
2634*9880d681SAndroid Build Coastguard Worker   uint64_t isa;        // class64_t * (64-bit pointer)
2635*9880d681SAndroid Build Coastguard Worker   uint64_t flags;      // flag bits
2636*9880d681SAndroid Build Coastguard Worker   uint64_t characters; // char * (64-bit pointer)
2637*9880d681SAndroid Build Coastguard Worker   uint64_t length;     // number of non-NULL characters in above
2638*9880d681SAndroid Build Coastguard Worker };
2639*9880d681SAndroid Build Coastguard Worker 
2640*9880d681SAndroid Build Coastguard Worker // The class object in a 64-bit Mach-O file.
2641*9880d681SAndroid Build Coastguard Worker struct class64_t {
2642*9880d681SAndroid Build Coastguard Worker   uint64_t isa;        // class64_t * (64-bit pointer)
2643*9880d681SAndroid Build Coastguard Worker   uint64_t superclass; // class64_t * (64-bit pointer)
2644*9880d681SAndroid Build Coastguard Worker   uint64_t cache;      // Cache (64-bit pointer)
2645*9880d681SAndroid Build Coastguard Worker   uint64_t vtable;     // IMP * (64-bit pointer)
2646*9880d681SAndroid Build Coastguard Worker   uint64_t data;       // class_ro64_t * (64-bit pointer)
2647*9880d681SAndroid Build Coastguard Worker };
2648*9880d681SAndroid Build Coastguard Worker 
2649*9880d681SAndroid Build Coastguard Worker struct class32_t {
2650*9880d681SAndroid Build Coastguard Worker   uint32_t isa;        /* class32_t * (32-bit pointer) */
2651*9880d681SAndroid Build Coastguard Worker   uint32_t superclass; /* class32_t * (32-bit pointer) */
2652*9880d681SAndroid Build Coastguard Worker   uint32_t cache;      /* Cache (32-bit pointer) */
2653*9880d681SAndroid Build Coastguard Worker   uint32_t vtable;     /* IMP * (32-bit pointer) */
2654*9880d681SAndroid Build Coastguard Worker   uint32_t data;       /* class_ro32_t * (32-bit pointer) */
2655*9880d681SAndroid Build Coastguard Worker };
2656*9880d681SAndroid Build Coastguard Worker 
2657*9880d681SAndroid Build Coastguard Worker struct class_ro64_t {
2658*9880d681SAndroid Build Coastguard Worker   uint32_t flags;
2659*9880d681SAndroid Build Coastguard Worker   uint32_t instanceStart;
2660*9880d681SAndroid Build Coastguard Worker   uint32_t instanceSize;
2661*9880d681SAndroid Build Coastguard Worker   uint32_t reserved;
2662*9880d681SAndroid Build Coastguard Worker   uint64_t ivarLayout;     // const uint8_t * (64-bit pointer)
2663*9880d681SAndroid Build Coastguard Worker   uint64_t name;           // const char * (64-bit pointer)
2664*9880d681SAndroid Build Coastguard Worker   uint64_t baseMethods;    // const method_list_t * (64-bit pointer)
2665*9880d681SAndroid Build Coastguard Worker   uint64_t baseProtocols;  // const protocol_list_t * (64-bit pointer)
2666*9880d681SAndroid Build Coastguard Worker   uint64_t ivars;          // const ivar_list_t * (64-bit pointer)
2667*9880d681SAndroid Build Coastguard Worker   uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
2668*9880d681SAndroid Build Coastguard Worker   uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
2669*9880d681SAndroid Build Coastguard Worker };
2670*9880d681SAndroid Build Coastguard Worker 
2671*9880d681SAndroid Build Coastguard Worker struct class_ro32_t {
2672*9880d681SAndroid Build Coastguard Worker   uint32_t flags;
2673*9880d681SAndroid Build Coastguard Worker   uint32_t instanceStart;
2674*9880d681SAndroid Build Coastguard Worker   uint32_t instanceSize;
2675*9880d681SAndroid Build Coastguard Worker   uint32_t ivarLayout;     /* const uint8_t * (32-bit pointer) */
2676*9880d681SAndroid Build Coastguard Worker   uint32_t name;           /* const char * (32-bit pointer) */
2677*9880d681SAndroid Build Coastguard Worker   uint32_t baseMethods;    /* const method_list_t * (32-bit pointer) */
2678*9880d681SAndroid Build Coastguard Worker   uint32_t baseProtocols;  /* const protocol_list_t * (32-bit pointer) */
2679*9880d681SAndroid Build Coastguard Worker   uint32_t ivars;          /* const ivar_list_t * (32-bit pointer) */
2680*9880d681SAndroid Build Coastguard Worker   uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
2681*9880d681SAndroid Build Coastguard Worker   uint32_t baseProperties; /* const struct objc_property_list *
2682*9880d681SAndroid Build Coastguard Worker                                                    (32-bit pointer) */
2683*9880d681SAndroid Build Coastguard Worker };
2684*9880d681SAndroid Build Coastguard Worker 
2685*9880d681SAndroid Build Coastguard Worker /* Values for class_ro{64,32}_t->flags */
2686*9880d681SAndroid Build Coastguard Worker #define RO_META (1 << 0)
2687*9880d681SAndroid Build Coastguard Worker #define RO_ROOT (1 << 1)
2688*9880d681SAndroid Build Coastguard Worker #define RO_HAS_CXX_STRUCTORS (1 << 2)
2689*9880d681SAndroid Build Coastguard Worker 
2690*9880d681SAndroid Build Coastguard Worker struct method_list64_t {
2691*9880d681SAndroid Build Coastguard Worker   uint32_t entsize;
2692*9880d681SAndroid Build Coastguard Worker   uint32_t count;
2693*9880d681SAndroid Build Coastguard Worker   /* struct method64_t first;  These structures follow inline */
2694*9880d681SAndroid Build Coastguard Worker };
2695*9880d681SAndroid Build Coastguard Worker 
2696*9880d681SAndroid Build Coastguard Worker struct method_list32_t {
2697*9880d681SAndroid Build Coastguard Worker   uint32_t entsize;
2698*9880d681SAndroid Build Coastguard Worker   uint32_t count;
2699*9880d681SAndroid Build Coastguard Worker   /* struct method32_t first;  These structures follow inline */
2700*9880d681SAndroid Build Coastguard Worker };
2701*9880d681SAndroid Build Coastguard Worker 
2702*9880d681SAndroid Build Coastguard Worker struct method64_t {
2703*9880d681SAndroid Build Coastguard Worker   uint64_t name;  /* SEL (64-bit pointer) */
2704*9880d681SAndroid Build Coastguard Worker   uint64_t types; /* const char * (64-bit pointer) */
2705*9880d681SAndroid Build Coastguard Worker   uint64_t imp;   /* IMP (64-bit pointer) */
2706*9880d681SAndroid Build Coastguard Worker };
2707*9880d681SAndroid Build Coastguard Worker 
2708*9880d681SAndroid Build Coastguard Worker struct method32_t {
2709*9880d681SAndroid Build Coastguard Worker   uint32_t name;  /* SEL (32-bit pointer) */
2710*9880d681SAndroid Build Coastguard Worker   uint32_t types; /* const char * (32-bit pointer) */
2711*9880d681SAndroid Build Coastguard Worker   uint32_t imp;   /* IMP (32-bit pointer) */
2712*9880d681SAndroid Build Coastguard Worker };
2713*9880d681SAndroid Build Coastguard Worker 
2714*9880d681SAndroid Build Coastguard Worker struct protocol_list64_t {
2715*9880d681SAndroid Build Coastguard Worker   uint64_t count; /* uintptr_t (a 64-bit value) */
2716*9880d681SAndroid Build Coastguard Worker   /* struct protocol64_t * list[0];  These pointers follow inline */
2717*9880d681SAndroid Build Coastguard Worker };
2718*9880d681SAndroid Build Coastguard Worker 
2719*9880d681SAndroid Build Coastguard Worker struct protocol_list32_t {
2720*9880d681SAndroid Build Coastguard Worker   uint32_t count; /* uintptr_t (a 32-bit value) */
2721*9880d681SAndroid Build Coastguard Worker   /* struct protocol32_t * list[0];  These pointers follow inline */
2722*9880d681SAndroid Build Coastguard Worker };
2723*9880d681SAndroid Build Coastguard Worker 
2724*9880d681SAndroid Build Coastguard Worker struct protocol64_t {
2725*9880d681SAndroid Build Coastguard Worker   uint64_t isa;                     /* id * (64-bit pointer) */
2726*9880d681SAndroid Build Coastguard Worker   uint64_t name;                    /* const char * (64-bit pointer) */
2727*9880d681SAndroid Build Coastguard Worker   uint64_t protocols;               /* struct protocol_list64_t *
2728*9880d681SAndroid Build Coastguard Worker                                                     (64-bit pointer) */
2729*9880d681SAndroid Build Coastguard Worker   uint64_t instanceMethods;         /* method_list_t * (64-bit pointer) */
2730*9880d681SAndroid Build Coastguard Worker   uint64_t classMethods;            /* method_list_t * (64-bit pointer) */
2731*9880d681SAndroid Build Coastguard Worker   uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
2732*9880d681SAndroid Build Coastguard Worker   uint64_t optionalClassMethods;    /* method_list_t * (64-bit pointer) */
2733*9880d681SAndroid Build Coastguard Worker   uint64_t instanceProperties;      /* struct objc_property_list *
2734*9880d681SAndroid Build Coastguard Worker                                                        (64-bit pointer) */
2735*9880d681SAndroid Build Coastguard Worker };
2736*9880d681SAndroid Build Coastguard Worker 
2737*9880d681SAndroid Build Coastguard Worker struct protocol32_t {
2738*9880d681SAndroid Build Coastguard Worker   uint32_t isa;                     /* id * (32-bit pointer) */
2739*9880d681SAndroid Build Coastguard Worker   uint32_t name;                    /* const char * (32-bit pointer) */
2740*9880d681SAndroid Build Coastguard Worker   uint32_t protocols;               /* struct protocol_list_t *
2741*9880d681SAndroid Build Coastguard Worker                                                     (32-bit pointer) */
2742*9880d681SAndroid Build Coastguard Worker   uint32_t instanceMethods;         /* method_list_t * (32-bit pointer) */
2743*9880d681SAndroid Build Coastguard Worker   uint32_t classMethods;            /* method_list_t * (32-bit pointer) */
2744*9880d681SAndroid Build Coastguard Worker   uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
2745*9880d681SAndroid Build Coastguard Worker   uint32_t optionalClassMethods;    /* method_list_t * (32-bit pointer) */
2746*9880d681SAndroid Build Coastguard Worker   uint32_t instanceProperties;      /* struct objc_property_list *
2747*9880d681SAndroid Build Coastguard Worker                                                        (32-bit pointer) */
2748*9880d681SAndroid Build Coastguard Worker };
2749*9880d681SAndroid Build Coastguard Worker 
2750*9880d681SAndroid Build Coastguard Worker struct ivar_list64_t {
2751*9880d681SAndroid Build Coastguard Worker   uint32_t entsize;
2752*9880d681SAndroid Build Coastguard Worker   uint32_t count;
2753*9880d681SAndroid Build Coastguard Worker   /* struct ivar64_t first;  These structures follow inline */
2754*9880d681SAndroid Build Coastguard Worker };
2755*9880d681SAndroid Build Coastguard Worker 
2756*9880d681SAndroid Build Coastguard Worker struct ivar_list32_t {
2757*9880d681SAndroid Build Coastguard Worker   uint32_t entsize;
2758*9880d681SAndroid Build Coastguard Worker   uint32_t count;
2759*9880d681SAndroid Build Coastguard Worker   /* struct ivar32_t first;  These structures follow inline */
2760*9880d681SAndroid Build Coastguard Worker };
2761*9880d681SAndroid Build Coastguard Worker 
2762*9880d681SAndroid Build Coastguard Worker struct ivar64_t {
2763*9880d681SAndroid Build Coastguard Worker   uint64_t offset; /* uintptr_t * (64-bit pointer) */
2764*9880d681SAndroid Build Coastguard Worker   uint64_t name;   /* const char * (64-bit pointer) */
2765*9880d681SAndroid Build Coastguard Worker   uint64_t type;   /* const char * (64-bit pointer) */
2766*9880d681SAndroid Build Coastguard Worker   uint32_t alignment;
2767*9880d681SAndroid Build Coastguard Worker   uint32_t size;
2768*9880d681SAndroid Build Coastguard Worker };
2769*9880d681SAndroid Build Coastguard Worker 
2770*9880d681SAndroid Build Coastguard Worker struct ivar32_t {
2771*9880d681SAndroid Build Coastguard Worker   uint32_t offset; /* uintptr_t * (32-bit pointer) */
2772*9880d681SAndroid Build Coastguard Worker   uint32_t name;   /* const char * (32-bit pointer) */
2773*9880d681SAndroid Build Coastguard Worker   uint32_t type;   /* const char * (32-bit pointer) */
2774*9880d681SAndroid Build Coastguard Worker   uint32_t alignment;
2775*9880d681SAndroid Build Coastguard Worker   uint32_t size;
2776*9880d681SAndroid Build Coastguard Worker };
2777*9880d681SAndroid Build Coastguard Worker 
2778*9880d681SAndroid Build Coastguard Worker struct objc_property_list64 {
2779*9880d681SAndroid Build Coastguard Worker   uint32_t entsize;
2780*9880d681SAndroid Build Coastguard Worker   uint32_t count;
2781*9880d681SAndroid Build Coastguard Worker   /* struct objc_property64 first;  These structures follow inline */
2782*9880d681SAndroid Build Coastguard Worker };
2783*9880d681SAndroid Build Coastguard Worker 
2784*9880d681SAndroid Build Coastguard Worker struct objc_property_list32 {
2785*9880d681SAndroid Build Coastguard Worker   uint32_t entsize;
2786*9880d681SAndroid Build Coastguard Worker   uint32_t count;
2787*9880d681SAndroid Build Coastguard Worker   /* struct objc_property32 first;  These structures follow inline */
2788*9880d681SAndroid Build Coastguard Worker };
2789*9880d681SAndroid Build Coastguard Worker 
2790*9880d681SAndroid Build Coastguard Worker struct objc_property64 {
2791*9880d681SAndroid Build Coastguard Worker   uint64_t name;       /* const char * (64-bit pointer) */
2792*9880d681SAndroid Build Coastguard Worker   uint64_t attributes; /* const char * (64-bit pointer) */
2793*9880d681SAndroid Build Coastguard Worker };
2794*9880d681SAndroid Build Coastguard Worker 
2795*9880d681SAndroid Build Coastguard Worker struct objc_property32 {
2796*9880d681SAndroid Build Coastguard Worker   uint32_t name;       /* const char * (32-bit pointer) */
2797*9880d681SAndroid Build Coastguard Worker   uint32_t attributes; /* const char * (32-bit pointer) */
2798*9880d681SAndroid Build Coastguard Worker };
2799*9880d681SAndroid Build Coastguard Worker 
2800*9880d681SAndroid Build Coastguard Worker struct category64_t {
2801*9880d681SAndroid Build Coastguard Worker   uint64_t name;               /* const char * (64-bit pointer) */
2802*9880d681SAndroid Build Coastguard Worker   uint64_t cls;                /* struct class_t * (64-bit pointer) */
2803*9880d681SAndroid Build Coastguard Worker   uint64_t instanceMethods;    /* struct method_list_t * (64-bit pointer) */
2804*9880d681SAndroid Build Coastguard Worker   uint64_t classMethods;       /* struct method_list_t * (64-bit pointer) */
2805*9880d681SAndroid Build Coastguard Worker   uint64_t protocols;          /* struct protocol_list_t * (64-bit pointer) */
2806*9880d681SAndroid Build Coastguard Worker   uint64_t instanceProperties; /* struct objc_property_list *
2807*9880d681SAndroid Build Coastguard Worker                                   (64-bit pointer) */
2808*9880d681SAndroid Build Coastguard Worker };
2809*9880d681SAndroid Build Coastguard Worker 
2810*9880d681SAndroid Build Coastguard Worker struct category32_t {
2811*9880d681SAndroid Build Coastguard Worker   uint32_t name;               /* const char * (32-bit pointer) */
2812*9880d681SAndroid Build Coastguard Worker   uint32_t cls;                /* struct class_t * (32-bit pointer) */
2813*9880d681SAndroid Build Coastguard Worker   uint32_t instanceMethods;    /* struct method_list_t * (32-bit pointer) */
2814*9880d681SAndroid Build Coastguard Worker   uint32_t classMethods;       /* struct method_list_t * (32-bit pointer) */
2815*9880d681SAndroid Build Coastguard Worker   uint32_t protocols;          /* struct protocol_list_t * (32-bit pointer) */
2816*9880d681SAndroid Build Coastguard Worker   uint32_t instanceProperties; /* struct objc_property_list *
2817*9880d681SAndroid Build Coastguard Worker                                   (32-bit pointer) */
2818*9880d681SAndroid Build Coastguard Worker };
2819*9880d681SAndroid Build Coastguard Worker 
2820*9880d681SAndroid Build Coastguard Worker struct objc_image_info64 {
2821*9880d681SAndroid Build Coastguard Worker   uint32_t version;
2822*9880d681SAndroid Build Coastguard Worker   uint32_t flags;
2823*9880d681SAndroid Build Coastguard Worker };
2824*9880d681SAndroid Build Coastguard Worker struct objc_image_info32 {
2825*9880d681SAndroid Build Coastguard Worker   uint32_t version;
2826*9880d681SAndroid Build Coastguard Worker   uint32_t flags;
2827*9880d681SAndroid Build Coastguard Worker };
2828*9880d681SAndroid Build Coastguard Worker struct imageInfo_t {
2829*9880d681SAndroid Build Coastguard Worker   uint32_t version;
2830*9880d681SAndroid Build Coastguard Worker   uint32_t flags;
2831*9880d681SAndroid Build Coastguard Worker };
2832*9880d681SAndroid Build Coastguard Worker /* masks for objc_image_info.flags */
2833*9880d681SAndroid Build Coastguard Worker #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
2834*9880d681SAndroid Build Coastguard Worker #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
2835*9880d681SAndroid Build Coastguard Worker 
2836*9880d681SAndroid Build Coastguard Worker struct message_ref64 {
2837*9880d681SAndroid Build Coastguard Worker   uint64_t imp; /* IMP (64-bit pointer) */
2838*9880d681SAndroid Build Coastguard Worker   uint64_t sel; /* SEL (64-bit pointer) */
2839*9880d681SAndroid Build Coastguard Worker };
2840*9880d681SAndroid Build Coastguard Worker 
2841*9880d681SAndroid Build Coastguard Worker struct message_ref32 {
2842*9880d681SAndroid Build Coastguard Worker   uint32_t imp; /* IMP (32-bit pointer) */
2843*9880d681SAndroid Build Coastguard Worker   uint32_t sel; /* SEL (32-bit pointer) */
2844*9880d681SAndroid Build Coastguard Worker };
2845*9880d681SAndroid Build Coastguard Worker 
2846*9880d681SAndroid Build Coastguard Worker // Objective-C 1 (32-bit only) meta data structs.
2847*9880d681SAndroid Build Coastguard Worker 
2848*9880d681SAndroid Build Coastguard Worker struct objc_module_t {
2849*9880d681SAndroid Build Coastguard Worker   uint32_t version;
2850*9880d681SAndroid Build Coastguard Worker   uint32_t size;
2851*9880d681SAndroid Build Coastguard Worker   uint32_t name;   /* char * (32-bit pointer) */
2852*9880d681SAndroid Build Coastguard Worker   uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
2853*9880d681SAndroid Build Coastguard Worker };
2854*9880d681SAndroid Build Coastguard Worker 
2855*9880d681SAndroid Build Coastguard Worker struct objc_symtab_t {
2856*9880d681SAndroid Build Coastguard Worker   uint32_t sel_ref_cnt;
2857*9880d681SAndroid Build Coastguard Worker   uint32_t refs; /* SEL * (32-bit pointer) */
2858*9880d681SAndroid Build Coastguard Worker   uint16_t cls_def_cnt;
2859*9880d681SAndroid Build Coastguard Worker   uint16_t cat_def_cnt;
2860*9880d681SAndroid Build Coastguard Worker   // uint32_t defs[1];        /* void * (32-bit pointer) variable size */
2861*9880d681SAndroid Build Coastguard Worker };
2862*9880d681SAndroid Build Coastguard Worker 
2863*9880d681SAndroid Build Coastguard Worker struct objc_class_t {
2864*9880d681SAndroid Build Coastguard Worker   uint32_t isa;         /* struct objc_class * (32-bit pointer) */
2865*9880d681SAndroid Build Coastguard Worker   uint32_t super_class; /* struct objc_class * (32-bit pointer) */
2866*9880d681SAndroid Build Coastguard Worker   uint32_t name;        /* const char * (32-bit pointer) */
2867*9880d681SAndroid Build Coastguard Worker   int32_t version;
2868*9880d681SAndroid Build Coastguard Worker   int32_t info;
2869*9880d681SAndroid Build Coastguard Worker   int32_t instance_size;
2870*9880d681SAndroid Build Coastguard Worker   uint32_t ivars;       /* struct objc_ivar_list * (32-bit pointer) */
2871*9880d681SAndroid Build Coastguard Worker   uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
2872*9880d681SAndroid Build Coastguard Worker   uint32_t cache;       /* struct objc_cache * (32-bit pointer) */
2873*9880d681SAndroid Build Coastguard Worker   uint32_t protocols;   /* struct objc_protocol_list * (32-bit pointer) */
2874*9880d681SAndroid Build Coastguard Worker };
2875*9880d681SAndroid Build Coastguard Worker 
2876*9880d681SAndroid Build Coastguard Worker #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
2877*9880d681SAndroid Build Coastguard Worker // class is not a metaclass
2878*9880d681SAndroid Build Coastguard Worker #define CLS_CLASS 0x1
2879*9880d681SAndroid Build Coastguard Worker // class is a metaclass
2880*9880d681SAndroid Build Coastguard Worker #define CLS_META 0x2
2881*9880d681SAndroid Build Coastguard Worker 
2882*9880d681SAndroid Build Coastguard Worker struct objc_category_t {
2883*9880d681SAndroid Build Coastguard Worker   uint32_t category_name;    /* char * (32-bit pointer) */
2884*9880d681SAndroid Build Coastguard Worker   uint32_t class_name;       /* char * (32-bit pointer) */
2885*9880d681SAndroid Build Coastguard Worker   uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
2886*9880d681SAndroid Build Coastguard Worker   uint32_t class_methods;    /* struct objc_method_list * (32-bit pointer) */
2887*9880d681SAndroid Build Coastguard Worker   uint32_t protocols;        /* struct objc_protocol_list * (32-bit ptr) */
2888*9880d681SAndroid Build Coastguard Worker };
2889*9880d681SAndroid Build Coastguard Worker 
2890*9880d681SAndroid Build Coastguard Worker struct objc_ivar_t {
2891*9880d681SAndroid Build Coastguard Worker   uint32_t ivar_name; /* char * (32-bit pointer) */
2892*9880d681SAndroid Build Coastguard Worker   uint32_t ivar_type; /* char * (32-bit pointer) */
2893*9880d681SAndroid Build Coastguard Worker   int32_t ivar_offset;
2894*9880d681SAndroid Build Coastguard Worker };
2895*9880d681SAndroid Build Coastguard Worker 
2896*9880d681SAndroid Build Coastguard Worker struct objc_ivar_list_t {
2897*9880d681SAndroid Build Coastguard Worker   int32_t ivar_count;
2898*9880d681SAndroid Build Coastguard Worker   // struct objc_ivar_t ivar_list[1];          /* variable length structure */
2899*9880d681SAndroid Build Coastguard Worker };
2900*9880d681SAndroid Build Coastguard Worker 
2901*9880d681SAndroid Build Coastguard Worker struct objc_method_list_t {
2902*9880d681SAndroid Build Coastguard Worker   uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
2903*9880d681SAndroid Build Coastguard Worker   int32_t method_count;
2904*9880d681SAndroid Build Coastguard Worker   // struct objc_method_t method_list[1];      /* variable length structure */
2905*9880d681SAndroid Build Coastguard Worker };
2906*9880d681SAndroid Build Coastguard Worker 
2907*9880d681SAndroid Build Coastguard Worker struct objc_method_t {
2908*9880d681SAndroid Build Coastguard Worker   uint32_t method_name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
2909*9880d681SAndroid Build Coastguard Worker   uint32_t method_types; /* char * (32-bit pointer) */
2910*9880d681SAndroid Build Coastguard Worker   uint32_t method_imp;   /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
2911*9880d681SAndroid Build Coastguard Worker                             (32-bit pointer) */
2912*9880d681SAndroid Build Coastguard Worker };
2913*9880d681SAndroid Build Coastguard Worker 
2914*9880d681SAndroid Build Coastguard Worker struct objc_protocol_list_t {
2915*9880d681SAndroid Build Coastguard Worker   uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
2916*9880d681SAndroid Build Coastguard Worker   int32_t count;
2917*9880d681SAndroid Build Coastguard Worker   // uint32_t list[1];   /* Protocol *, aka struct objc_protocol_t *
2918*9880d681SAndroid Build Coastguard Worker   //                        (32-bit pointer) */
2919*9880d681SAndroid Build Coastguard Worker };
2920*9880d681SAndroid Build Coastguard Worker 
2921*9880d681SAndroid Build Coastguard Worker struct objc_protocol_t {
2922*9880d681SAndroid Build Coastguard Worker   uint32_t isa;              /* struct objc_class * (32-bit pointer) */
2923*9880d681SAndroid Build Coastguard Worker   uint32_t protocol_name;    /* char * (32-bit pointer) */
2924*9880d681SAndroid Build Coastguard Worker   uint32_t protocol_list;    /* struct objc_protocol_list * (32-bit pointer) */
2925*9880d681SAndroid Build Coastguard Worker   uint32_t instance_methods; /* struct objc_method_description_list *
2926*9880d681SAndroid Build Coastguard Worker                                 (32-bit pointer) */
2927*9880d681SAndroid Build Coastguard Worker   uint32_t class_methods;    /* struct objc_method_description_list *
2928*9880d681SAndroid Build Coastguard Worker                                 (32-bit pointer) */
2929*9880d681SAndroid Build Coastguard Worker };
2930*9880d681SAndroid Build Coastguard Worker 
2931*9880d681SAndroid Build Coastguard Worker struct objc_method_description_list_t {
2932*9880d681SAndroid Build Coastguard Worker   int32_t count;
2933*9880d681SAndroid Build Coastguard Worker   // struct objc_method_description_t list[1];
2934*9880d681SAndroid Build Coastguard Worker };
2935*9880d681SAndroid Build Coastguard Worker 
2936*9880d681SAndroid Build Coastguard Worker struct objc_method_description_t {
2937*9880d681SAndroid Build Coastguard Worker   uint32_t name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
2938*9880d681SAndroid Build Coastguard Worker   uint32_t types; /* char * (32-bit pointer) */
2939*9880d681SAndroid Build Coastguard Worker };
2940*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct cfstring64_t & cfs)2941*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct cfstring64_t &cfs) {
2942*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cfs.isa);
2943*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cfs.flags);
2944*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cfs.characters);
2945*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cfs.length);
2946*9880d681SAndroid Build Coastguard Worker }
2947*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct class64_t & c)2948*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct class64_t &c) {
2949*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.isa);
2950*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.superclass);
2951*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.cache);
2952*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.vtable);
2953*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.data);
2954*9880d681SAndroid Build Coastguard Worker }
2955*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct class32_t & c)2956*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct class32_t &c) {
2957*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.isa);
2958*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.superclass);
2959*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.cache);
2960*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.vtable);
2961*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.data);
2962*9880d681SAndroid Build Coastguard Worker }
2963*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct class_ro64_t & cro)2964*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct class_ro64_t &cro) {
2965*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.flags);
2966*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.instanceStart);
2967*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.instanceSize);
2968*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.reserved);
2969*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.ivarLayout);
2970*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.name);
2971*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.baseMethods);
2972*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.baseProtocols);
2973*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.ivars);
2974*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.weakIvarLayout);
2975*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.baseProperties);
2976*9880d681SAndroid Build Coastguard Worker }
2977*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct class_ro32_t & cro)2978*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct class_ro32_t &cro) {
2979*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.flags);
2980*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.instanceStart);
2981*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.instanceSize);
2982*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.ivarLayout);
2983*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.name);
2984*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.baseMethods);
2985*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.baseProtocols);
2986*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.ivars);
2987*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.weakIvarLayout);
2988*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(cro.baseProperties);
2989*9880d681SAndroid Build Coastguard Worker }
2990*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct method_list64_t & ml)2991*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct method_list64_t &ml) {
2992*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(ml.entsize);
2993*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(ml.count);
2994*9880d681SAndroid Build Coastguard Worker }
2995*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct method_list32_t & ml)2996*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct method_list32_t &ml) {
2997*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(ml.entsize);
2998*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(ml.count);
2999*9880d681SAndroid Build Coastguard Worker }
3000*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct method64_t & m)3001*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct method64_t &m) {
3002*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(m.name);
3003*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(m.types);
3004*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(m.imp);
3005*9880d681SAndroid Build Coastguard Worker }
3006*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct method32_t & m)3007*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct method32_t &m) {
3008*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(m.name);
3009*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(m.types);
3010*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(m.imp);
3011*9880d681SAndroid Build Coastguard Worker }
3012*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct protocol_list64_t & pl)3013*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct protocol_list64_t &pl) {
3014*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(pl.count);
3015*9880d681SAndroid Build Coastguard Worker }
3016*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct protocol_list32_t & pl)3017*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct protocol_list32_t &pl) {
3018*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(pl.count);
3019*9880d681SAndroid Build Coastguard Worker }
3020*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct protocol64_t & p)3021*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct protocol64_t &p) {
3022*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.isa);
3023*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.name);
3024*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.protocols);
3025*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.instanceMethods);
3026*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.classMethods);
3027*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.optionalInstanceMethods);
3028*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.optionalClassMethods);
3029*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.instanceProperties);
3030*9880d681SAndroid Build Coastguard Worker }
3031*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct protocol32_t & p)3032*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct protocol32_t &p) {
3033*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.isa);
3034*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.name);
3035*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.protocols);
3036*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.instanceMethods);
3037*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.classMethods);
3038*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.optionalInstanceMethods);
3039*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.optionalClassMethods);
3040*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(p.instanceProperties);
3041*9880d681SAndroid Build Coastguard Worker }
3042*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct ivar_list64_t & il)3043*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct ivar_list64_t &il) {
3044*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(il.entsize);
3045*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(il.count);
3046*9880d681SAndroid Build Coastguard Worker }
3047*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct ivar_list32_t & il)3048*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct ivar_list32_t &il) {
3049*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(il.entsize);
3050*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(il.count);
3051*9880d681SAndroid Build Coastguard Worker }
3052*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct ivar64_t & i)3053*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct ivar64_t &i) {
3054*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.offset);
3055*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.name);
3056*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.type);
3057*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.alignment);
3058*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.size);
3059*9880d681SAndroid Build Coastguard Worker }
3060*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct ivar32_t & i)3061*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct ivar32_t &i) {
3062*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.offset);
3063*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.name);
3064*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.type);
3065*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.alignment);
3066*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(i.size);
3067*9880d681SAndroid Build Coastguard Worker }
3068*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_property_list64 & pl)3069*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_property_list64 &pl) {
3070*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(pl.entsize);
3071*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(pl.count);
3072*9880d681SAndroid Build Coastguard Worker }
3073*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_property_list32 & pl)3074*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_property_list32 &pl) {
3075*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(pl.entsize);
3076*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(pl.count);
3077*9880d681SAndroid Build Coastguard Worker }
3078*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_property64 & op)3079*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_property64 &op) {
3080*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(op.name);
3081*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(op.attributes);
3082*9880d681SAndroid Build Coastguard Worker }
3083*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_property32 & op)3084*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_property32 &op) {
3085*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(op.name);
3086*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(op.attributes);
3087*9880d681SAndroid Build Coastguard Worker }
3088*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct category64_t & c)3089*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct category64_t &c) {
3090*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.name);
3091*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.cls);
3092*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.instanceMethods);
3093*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.classMethods);
3094*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.protocols);
3095*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.instanceProperties);
3096*9880d681SAndroid Build Coastguard Worker }
3097*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct category32_t & c)3098*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct category32_t &c) {
3099*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.name);
3100*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.cls);
3101*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.instanceMethods);
3102*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.classMethods);
3103*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.protocols);
3104*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(c.instanceProperties);
3105*9880d681SAndroid Build Coastguard Worker }
3106*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_image_info64 & o)3107*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_image_info64 &o) {
3108*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(o.version);
3109*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(o.flags);
3110*9880d681SAndroid Build Coastguard Worker }
3111*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_image_info32 & o)3112*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_image_info32 &o) {
3113*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(o.version);
3114*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(o.flags);
3115*9880d681SAndroid Build Coastguard Worker }
3116*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct imageInfo_t & o)3117*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct imageInfo_t &o) {
3118*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(o.version);
3119*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(o.flags);
3120*9880d681SAndroid Build Coastguard Worker }
3121*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct message_ref64 & mr)3122*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct message_ref64 &mr) {
3123*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(mr.imp);
3124*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(mr.sel);
3125*9880d681SAndroid Build Coastguard Worker }
3126*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct message_ref32 & mr)3127*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct message_ref32 &mr) {
3128*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(mr.imp);
3129*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(mr.sel);
3130*9880d681SAndroid Build Coastguard Worker }
3131*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_module_t & module)3132*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_module_t &module) {
3133*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(module.version);
3134*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(module.size);
3135*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(module.name);
3136*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(module.symtab);
3137*9880d681SAndroid Build Coastguard Worker }
3138*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_symtab_t & symtab)3139*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_symtab_t &symtab) {
3140*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(symtab.sel_ref_cnt);
3141*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(symtab.refs);
3142*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(symtab.cls_def_cnt);
3143*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(symtab.cat_def_cnt);
3144*9880d681SAndroid Build Coastguard Worker }
3145*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_class_t & objc_class)3146*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_class_t &objc_class) {
3147*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.isa);
3148*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.super_class);
3149*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.name);
3150*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.version);
3151*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.info);
3152*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.instance_size);
3153*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.ivars);
3154*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.methodLists);
3155*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.cache);
3156*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_class.protocols);
3157*9880d681SAndroid Build Coastguard Worker }
3158*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_category_t & objc_category)3159*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_category_t &objc_category) {
3160*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_category.category_name);
3161*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_category.class_name);
3162*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_category.instance_methods);
3163*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_category.class_methods);
3164*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_category.protocols);
3165*9880d681SAndroid Build Coastguard Worker }
3166*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_ivar_list_t & objc_ivar_list)3167*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
3168*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_ivar_list.ivar_count);
3169*9880d681SAndroid Build Coastguard Worker }
3170*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_ivar_t & objc_ivar)3171*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_ivar_t &objc_ivar) {
3172*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_ivar.ivar_name);
3173*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_ivar.ivar_type);
3174*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(objc_ivar.ivar_offset);
3175*9880d681SAndroid Build Coastguard Worker }
3176*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_method_list_t & method_list)3177*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_method_list_t &method_list) {
3178*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(method_list.obsolete);
3179*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(method_list.method_count);
3180*9880d681SAndroid Build Coastguard Worker }
3181*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_method_t & method)3182*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_method_t &method) {
3183*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(method.method_name);
3184*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(method.method_types);
3185*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(method.method_imp);
3186*9880d681SAndroid Build Coastguard Worker }
3187*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_protocol_list_t & protocol_list)3188*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
3189*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(protocol_list.next);
3190*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(protocol_list.count);
3191*9880d681SAndroid Build Coastguard Worker }
3192*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_protocol_t & protocol)3193*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_protocol_t &protocol) {
3194*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(protocol.isa);
3195*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(protocol.protocol_name);
3196*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(protocol.protocol_list);
3197*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(protocol.instance_methods);
3198*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(protocol.class_methods);
3199*9880d681SAndroid Build Coastguard Worker }
3200*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_method_description_list_t & mdl)3201*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_method_description_list_t &mdl) {
3202*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(mdl.count);
3203*9880d681SAndroid Build Coastguard Worker }
3204*9880d681SAndroid Build Coastguard Worker 
swapStruct(struct objc_method_description_t & md)3205*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct objc_method_description_t &md) {
3206*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(md.name);
3207*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(md.types);
3208*9880d681SAndroid Build Coastguard Worker }
3209*9880d681SAndroid Build Coastguard Worker 
3210*9880d681SAndroid Build Coastguard Worker static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
3211*9880d681SAndroid Build Coastguard Worker                                                  struct DisassembleInfo *info);
3212*9880d681SAndroid Build Coastguard Worker 
3213*9880d681SAndroid Build Coastguard Worker // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
3214*9880d681SAndroid Build Coastguard Worker // to an Objective-C class and returns the class name.  It is also passed the
3215*9880d681SAndroid Build Coastguard Worker // address of the pointer, so when the pointer is zero as it can be in an .o
3216*9880d681SAndroid Build Coastguard Worker // file, that is used to look for an external relocation entry with a symbol
3217*9880d681SAndroid Build Coastguard Worker // name.
get_objc2_64bit_class_name(uint64_t pointer_value,uint64_t ReferenceValue,struct DisassembleInfo * info)3218*9880d681SAndroid Build Coastguard Worker static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
3219*9880d681SAndroid Build Coastguard Worker                                               uint64_t ReferenceValue,
3220*9880d681SAndroid Build Coastguard Worker                                               struct DisassembleInfo *info) {
3221*9880d681SAndroid Build Coastguard Worker   const char *r;
3222*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
3223*9880d681SAndroid Build Coastguard Worker   SectionRef S;
3224*9880d681SAndroid Build Coastguard Worker 
3225*9880d681SAndroid Build Coastguard Worker   // The pointer_value can be 0 in an object file and have a relocation
3226*9880d681SAndroid Build Coastguard Worker   // entry for the class symbol at the ReferenceValue (the address of the
3227*9880d681SAndroid Build Coastguard Worker   // pointer).
3228*9880d681SAndroid Build Coastguard Worker   if (pointer_value == 0) {
3229*9880d681SAndroid Build Coastguard Worker     r = get_pointer_64(ReferenceValue, offset, left, S, info);
3230*9880d681SAndroid Build Coastguard Worker     if (r == nullptr || left < sizeof(uint64_t))
3231*9880d681SAndroid Build Coastguard Worker       return nullptr;
3232*9880d681SAndroid Build Coastguard Worker     uint64_t n_value;
3233*9880d681SAndroid Build Coastguard Worker     const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3234*9880d681SAndroid Build Coastguard Worker     if (symbol_name == nullptr)
3235*9880d681SAndroid Build Coastguard Worker       return nullptr;
3236*9880d681SAndroid Build Coastguard Worker     const char *class_name = strrchr(symbol_name, '$');
3237*9880d681SAndroid Build Coastguard Worker     if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
3238*9880d681SAndroid Build Coastguard Worker       return class_name + 2;
3239*9880d681SAndroid Build Coastguard Worker     else
3240*9880d681SAndroid Build Coastguard Worker       return nullptr;
3241*9880d681SAndroid Build Coastguard Worker   }
3242*9880d681SAndroid Build Coastguard Worker 
3243*9880d681SAndroid Build Coastguard Worker   // The case were the pointer_value is non-zero and points to a class defined
3244*9880d681SAndroid Build Coastguard Worker   // in this Mach-O file.
3245*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(pointer_value, offset, left, S, info);
3246*9880d681SAndroid Build Coastguard Worker   if (r == nullptr || left < sizeof(struct class64_t))
3247*9880d681SAndroid Build Coastguard Worker     return nullptr;
3248*9880d681SAndroid Build Coastguard Worker   struct class64_t c;
3249*9880d681SAndroid Build Coastguard Worker   memcpy(&c, r, sizeof(struct class64_t));
3250*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3251*9880d681SAndroid Build Coastguard Worker     swapStruct(c);
3252*9880d681SAndroid Build Coastguard Worker   if (c.data == 0)
3253*9880d681SAndroid Build Coastguard Worker     return nullptr;
3254*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(c.data, offset, left, S, info);
3255*9880d681SAndroid Build Coastguard Worker   if (r == nullptr || left < sizeof(struct class_ro64_t))
3256*9880d681SAndroid Build Coastguard Worker     return nullptr;
3257*9880d681SAndroid Build Coastguard Worker   struct class_ro64_t cro;
3258*9880d681SAndroid Build Coastguard Worker   memcpy(&cro, r, sizeof(struct class_ro64_t));
3259*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3260*9880d681SAndroid Build Coastguard Worker     swapStruct(cro);
3261*9880d681SAndroid Build Coastguard Worker   if (cro.name == 0)
3262*9880d681SAndroid Build Coastguard Worker     return nullptr;
3263*9880d681SAndroid Build Coastguard Worker   const char *name = get_pointer_64(cro.name, offset, left, S, info);
3264*9880d681SAndroid Build Coastguard Worker   return name;
3265*9880d681SAndroid Build Coastguard Worker }
3266*9880d681SAndroid Build Coastguard Worker 
3267*9880d681SAndroid Build Coastguard Worker // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
3268*9880d681SAndroid Build Coastguard Worker // pointer to a cfstring and returns its name or nullptr.
get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,struct DisassembleInfo * info)3269*9880d681SAndroid Build Coastguard Worker static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
3270*9880d681SAndroid Build Coastguard Worker                                                  struct DisassembleInfo *info) {
3271*9880d681SAndroid Build Coastguard Worker   const char *r, *name;
3272*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
3273*9880d681SAndroid Build Coastguard Worker   SectionRef S;
3274*9880d681SAndroid Build Coastguard Worker   struct cfstring64_t cfs;
3275*9880d681SAndroid Build Coastguard Worker   uint64_t cfs_characters;
3276*9880d681SAndroid Build Coastguard Worker 
3277*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(ReferenceValue, offset, left, S, info);
3278*9880d681SAndroid Build Coastguard Worker   if (r == nullptr || left < sizeof(struct cfstring64_t))
3279*9880d681SAndroid Build Coastguard Worker     return nullptr;
3280*9880d681SAndroid Build Coastguard Worker   memcpy(&cfs, r, sizeof(struct cfstring64_t));
3281*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3282*9880d681SAndroid Build Coastguard Worker     swapStruct(cfs);
3283*9880d681SAndroid Build Coastguard Worker   if (cfs.characters == 0) {
3284*9880d681SAndroid Build Coastguard Worker     uint64_t n_value;
3285*9880d681SAndroid Build Coastguard Worker     const char *symbol_name = get_symbol_64(
3286*9880d681SAndroid Build Coastguard Worker         offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
3287*9880d681SAndroid Build Coastguard Worker     if (symbol_name == nullptr)
3288*9880d681SAndroid Build Coastguard Worker       return nullptr;
3289*9880d681SAndroid Build Coastguard Worker     cfs_characters = n_value;
3290*9880d681SAndroid Build Coastguard Worker   } else
3291*9880d681SAndroid Build Coastguard Worker     cfs_characters = cfs.characters;
3292*9880d681SAndroid Build Coastguard Worker   name = get_pointer_64(cfs_characters, offset, left, S, info);
3293*9880d681SAndroid Build Coastguard Worker 
3294*9880d681SAndroid Build Coastguard Worker   return name;
3295*9880d681SAndroid Build Coastguard Worker }
3296*9880d681SAndroid Build Coastguard Worker 
3297*9880d681SAndroid Build Coastguard Worker // get_objc2_64bit_selref() is used for disassembly and is passed a the address
3298*9880d681SAndroid Build Coastguard Worker // of a pointer to an Objective-C selector reference when the pointer value is
3299*9880d681SAndroid Build Coastguard Worker // zero as in a .o file and is likely to have a external relocation entry with
3300*9880d681SAndroid Build Coastguard Worker // who's symbol's n_value is the real pointer to the selector name.  If that is
3301*9880d681SAndroid Build Coastguard Worker // the case the real pointer to the selector name is returned else 0 is
3302*9880d681SAndroid Build Coastguard Worker // returned
get_objc2_64bit_selref(uint64_t ReferenceValue,struct DisassembleInfo * info)3303*9880d681SAndroid Build Coastguard Worker static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
3304*9880d681SAndroid Build Coastguard Worker                                        struct DisassembleInfo *info) {
3305*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
3306*9880d681SAndroid Build Coastguard Worker   SectionRef S;
3307*9880d681SAndroid Build Coastguard Worker 
3308*9880d681SAndroid Build Coastguard Worker   const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
3309*9880d681SAndroid Build Coastguard Worker   if (r == nullptr || left < sizeof(uint64_t))
3310*9880d681SAndroid Build Coastguard Worker     return 0;
3311*9880d681SAndroid Build Coastguard Worker   uint64_t n_value;
3312*9880d681SAndroid Build Coastguard Worker   const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3313*9880d681SAndroid Build Coastguard Worker   if (symbol_name == nullptr)
3314*9880d681SAndroid Build Coastguard Worker     return 0;
3315*9880d681SAndroid Build Coastguard Worker   return n_value;
3316*9880d681SAndroid Build Coastguard Worker }
3317*9880d681SAndroid Build Coastguard Worker 
get_section(MachOObjectFile * O,const char * segname,const char * sectname)3318*9880d681SAndroid Build Coastguard Worker static const SectionRef get_section(MachOObjectFile *O, const char *segname,
3319*9880d681SAndroid Build Coastguard Worker                                     const char *sectname) {
3320*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : O->sections()) {
3321*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
3322*9880d681SAndroid Build Coastguard Worker     Section.getName(SectName);
3323*9880d681SAndroid Build Coastguard Worker     DataRefImpl Ref = Section.getRawDataRefImpl();
3324*9880d681SAndroid Build Coastguard Worker     StringRef SegName = O->getSectionFinalSegmentName(Ref);
3325*9880d681SAndroid Build Coastguard Worker     if (SegName == segname && SectName == sectname)
3326*9880d681SAndroid Build Coastguard Worker       return Section;
3327*9880d681SAndroid Build Coastguard Worker   }
3328*9880d681SAndroid Build Coastguard Worker   return SectionRef();
3329*9880d681SAndroid Build Coastguard Worker }
3330*9880d681SAndroid Build Coastguard Worker 
3331*9880d681SAndroid Build Coastguard Worker static void
walk_pointer_list_64(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint64_t,struct DisassembleInfo * info))3332*9880d681SAndroid Build Coastguard Worker walk_pointer_list_64(const char *listname, const SectionRef S,
3333*9880d681SAndroid Build Coastguard Worker                      MachOObjectFile *O, struct DisassembleInfo *info,
3334*9880d681SAndroid Build Coastguard Worker                      void (*func)(uint64_t, struct DisassembleInfo *info)) {
3335*9880d681SAndroid Build Coastguard Worker   if (S == SectionRef())
3336*9880d681SAndroid Build Coastguard Worker     return;
3337*9880d681SAndroid Build Coastguard Worker 
3338*9880d681SAndroid Build Coastguard Worker   StringRef SectName;
3339*9880d681SAndroid Build Coastguard Worker   S.getName(SectName);
3340*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ref = S.getRawDataRefImpl();
3341*9880d681SAndroid Build Coastguard Worker   StringRef SegName = O->getSectionFinalSegmentName(Ref);
3342*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3343*9880d681SAndroid Build Coastguard Worker 
3344*9880d681SAndroid Build Coastguard Worker   StringRef BytesStr;
3345*9880d681SAndroid Build Coastguard Worker   S.getContents(BytesStr);
3346*9880d681SAndroid Build Coastguard Worker   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3347*9880d681SAndroid Build Coastguard Worker 
3348*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
3349*9880d681SAndroid Build Coastguard Worker     uint32_t left = S.getSize() - i;
3350*9880d681SAndroid Build Coastguard Worker     uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
3351*9880d681SAndroid Build Coastguard Worker     uint64_t p = 0;
3352*9880d681SAndroid Build Coastguard Worker     memcpy(&p, Contents + i, size);
3353*9880d681SAndroid Build Coastguard Worker     if (i + sizeof(uint64_t) > S.getSize())
3354*9880d681SAndroid Build Coastguard Worker       outs() << listname << " list pointer extends past end of (" << SegName
3355*9880d681SAndroid Build Coastguard Worker              << "," << SectName << ") section\n";
3356*9880d681SAndroid Build Coastguard Worker     outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
3357*9880d681SAndroid Build Coastguard Worker 
3358*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost)
3359*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(p);
3360*9880d681SAndroid Build Coastguard Worker 
3361*9880d681SAndroid Build Coastguard Worker     uint64_t n_value = 0;
3362*9880d681SAndroid Build Coastguard Worker     const char *name = get_symbol_64(i, S, info, n_value, p);
3363*9880d681SAndroid Build Coastguard Worker     if (name == nullptr)
3364*9880d681SAndroid Build Coastguard Worker       name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
3365*9880d681SAndroid Build Coastguard Worker 
3366*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
3367*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
3368*9880d681SAndroid Build Coastguard Worker       if (p != 0)
3369*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, p);
3370*9880d681SAndroid Build Coastguard Worker     } else
3371*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, p);
3372*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3373*9880d681SAndroid Build Coastguard Worker       outs() << " " << name;
3374*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3375*9880d681SAndroid Build Coastguard Worker 
3376*9880d681SAndroid Build Coastguard Worker     p += n_value;
3377*9880d681SAndroid Build Coastguard Worker     if (func)
3378*9880d681SAndroid Build Coastguard Worker       func(p, info);
3379*9880d681SAndroid Build Coastguard Worker   }
3380*9880d681SAndroid Build Coastguard Worker }
3381*9880d681SAndroid Build Coastguard Worker 
3382*9880d681SAndroid Build Coastguard Worker static void
walk_pointer_list_32(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint32_t,struct DisassembleInfo * info))3383*9880d681SAndroid Build Coastguard Worker walk_pointer_list_32(const char *listname, const SectionRef S,
3384*9880d681SAndroid Build Coastguard Worker                      MachOObjectFile *O, struct DisassembleInfo *info,
3385*9880d681SAndroid Build Coastguard Worker                      void (*func)(uint32_t, struct DisassembleInfo *info)) {
3386*9880d681SAndroid Build Coastguard Worker   if (S == SectionRef())
3387*9880d681SAndroid Build Coastguard Worker     return;
3388*9880d681SAndroid Build Coastguard Worker 
3389*9880d681SAndroid Build Coastguard Worker   StringRef SectName;
3390*9880d681SAndroid Build Coastguard Worker   S.getName(SectName);
3391*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ref = S.getRawDataRefImpl();
3392*9880d681SAndroid Build Coastguard Worker   StringRef SegName = O->getSectionFinalSegmentName(Ref);
3393*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3394*9880d681SAndroid Build Coastguard Worker 
3395*9880d681SAndroid Build Coastguard Worker   StringRef BytesStr;
3396*9880d681SAndroid Build Coastguard Worker   S.getContents(BytesStr);
3397*9880d681SAndroid Build Coastguard Worker   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3398*9880d681SAndroid Build Coastguard Worker 
3399*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
3400*9880d681SAndroid Build Coastguard Worker     uint32_t left = S.getSize() - i;
3401*9880d681SAndroid Build Coastguard Worker     uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
3402*9880d681SAndroid Build Coastguard Worker     uint32_t p = 0;
3403*9880d681SAndroid Build Coastguard Worker     memcpy(&p, Contents + i, size);
3404*9880d681SAndroid Build Coastguard Worker     if (i + sizeof(uint32_t) > S.getSize())
3405*9880d681SAndroid Build Coastguard Worker       outs() << listname << " list pointer extends past end of (" << SegName
3406*9880d681SAndroid Build Coastguard Worker              << "," << SectName << ") section\n";
3407*9880d681SAndroid Build Coastguard Worker     uint32_t Address = S.getAddress() + i;
3408*9880d681SAndroid Build Coastguard Worker     outs() << format("%08" PRIx32, Address) << " ";
3409*9880d681SAndroid Build Coastguard Worker 
3410*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost)
3411*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(p);
3412*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx32, p);
3413*9880d681SAndroid Build Coastguard Worker 
3414*9880d681SAndroid Build Coastguard Worker     const char *name = get_symbol_32(i, S, info, p);
3415*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3416*9880d681SAndroid Build Coastguard Worker       outs() << " " << name;
3417*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3418*9880d681SAndroid Build Coastguard Worker 
3419*9880d681SAndroid Build Coastguard Worker     if (func)
3420*9880d681SAndroid Build Coastguard Worker       func(p, info);
3421*9880d681SAndroid Build Coastguard Worker   }
3422*9880d681SAndroid Build Coastguard Worker }
3423*9880d681SAndroid Build Coastguard Worker 
print_layout_map(const char * layout_map,uint32_t left)3424*9880d681SAndroid Build Coastguard Worker static void print_layout_map(const char *layout_map, uint32_t left) {
3425*9880d681SAndroid Build Coastguard Worker   if (layout_map == nullptr)
3426*9880d681SAndroid Build Coastguard Worker     return;
3427*9880d681SAndroid Build Coastguard Worker   outs() << "                layout map: ";
3428*9880d681SAndroid Build Coastguard Worker   do {
3429*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
3430*9880d681SAndroid Build Coastguard Worker     left--;
3431*9880d681SAndroid Build Coastguard Worker     layout_map++;
3432*9880d681SAndroid Build Coastguard Worker   } while (*layout_map != '\0' && left != 0);
3433*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
3434*9880d681SAndroid Build Coastguard Worker }
3435*9880d681SAndroid Build Coastguard Worker 
print_layout_map64(uint64_t p,struct DisassembleInfo * info)3436*9880d681SAndroid Build Coastguard Worker static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
3437*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
3438*9880d681SAndroid Build Coastguard Worker   SectionRef S;
3439*9880d681SAndroid Build Coastguard Worker   const char *layout_map;
3440*9880d681SAndroid Build Coastguard Worker 
3441*9880d681SAndroid Build Coastguard Worker   if (p == 0)
3442*9880d681SAndroid Build Coastguard Worker     return;
3443*9880d681SAndroid Build Coastguard Worker   layout_map = get_pointer_64(p, offset, left, S, info);
3444*9880d681SAndroid Build Coastguard Worker   print_layout_map(layout_map, left);
3445*9880d681SAndroid Build Coastguard Worker }
3446*9880d681SAndroid Build Coastguard Worker 
print_layout_map32(uint32_t p,struct DisassembleInfo * info)3447*9880d681SAndroid Build Coastguard Worker static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
3448*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
3449*9880d681SAndroid Build Coastguard Worker   SectionRef S;
3450*9880d681SAndroid Build Coastguard Worker   const char *layout_map;
3451*9880d681SAndroid Build Coastguard Worker 
3452*9880d681SAndroid Build Coastguard Worker   if (p == 0)
3453*9880d681SAndroid Build Coastguard Worker     return;
3454*9880d681SAndroid Build Coastguard Worker   layout_map = get_pointer_32(p, offset, left, S, info);
3455*9880d681SAndroid Build Coastguard Worker   print_layout_map(layout_map, left);
3456*9880d681SAndroid Build Coastguard Worker }
3457*9880d681SAndroid Build Coastguard Worker 
print_method_list64_t(uint64_t p,struct DisassembleInfo * info,const char * indent)3458*9880d681SAndroid Build Coastguard Worker static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
3459*9880d681SAndroid Build Coastguard Worker                                   const char *indent) {
3460*9880d681SAndroid Build Coastguard Worker   struct method_list64_t ml;
3461*9880d681SAndroid Build Coastguard Worker   struct method64_t m;
3462*9880d681SAndroid Build Coastguard Worker   const char *r;
3463*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left, i;
3464*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
3465*9880d681SAndroid Build Coastguard Worker   const char *name, *sym_name;
3466*9880d681SAndroid Build Coastguard Worker   uint64_t n_value;
3467*9880d681SAndroid Build Coastguard Worker 
3468*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(p, offset, left, S, info);
3469*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
3470*9880d681SAndroid Build Coastguard Worker     return;
3471*9880d681SAndroid Build Coastguard Worker   memset(&ml, '\0', sizeof(struct method_list64_t));
3472*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct method_list64_t)) {
3473*9880d681SAndroid Build Coastguard Worker     memcpy(&ml, r, left);
3474*9880d681SAndroid Build Coastguard Worker     outs() << "   (method_list_t entends past the end of the section)\n";
3475*9880d681SAndroid Build Coastguard Worker   } else
3476*9880d681SAndroid Build Coastguard Worker     memcpy(&ml, r, sizeof(struct method_list64_t));
3477*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3478*9880d681SAndroid Build Coastguard Worker     swapStruct(ml);
3479*9880d681SAndroid Build Coastguard Worker   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
3480*9880d681SAndroid Build Coastguard Worker   outs() << indent << "\t\t     count " << ml.count << "\n";
3481*9880d681SAndroid Build Coastguard Worker 
3482*9880d681SAndroid Build Coastguard Worker   p += sizeof(struct method_list64_t);
3483*9880d681SAndroid Build Coastguard Worker   offset += sizeof(struct method_list64_t);
3484*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < ml.count; i++) {
3485*9880d681SAndroid Build Coastguard Worker     r = get_pointer_64(p, offset, left, S, info);
3486*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
3487*9880d681SAndroid Build Coastguard Worker       return;
3488*9880d681SAndroid Build Coastguard Worker     memset(&m, '\0', sizeof(struct method64_t));
3489*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct method64_t)) {
3490*9880d681SAndroid Build Coastguard Worker       memcpy(&m, r, left);
3491*9880d681SAndroid Build Coastguard Worker       outs() << indent << "   (method_t extends past the end of the section)\n";
3492*9880d681SAndroid Build Coastguard Worker     } else
3493*9880d681SAndroid Build Coastguard Worker       memcpy(&m, r, sizeof(struct method64_t));
3494*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3495*9880d681SAndroid Build Coastguard Worker       swapStruct(m);
3496*9880d681SAndroid Build Coastguard Worker 
3497*9880d681SAndroid Build Coastguard Worker     outs() << indent << "\t\t      name ";
3498*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
3499*9880d681SAndroid Build Coastguard Worker                              info, n_value, m.name);
3500*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
3501*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
3502*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
3503*9880d681SAndroid Build Coastguard Worker       else
3504*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
3505*9880d681SAndroid Build Coastguard Worker       if (m.name != 0)
3506*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, m.name);
3507*9880d681SAndroid Build Coastguard Worker     } else
3508*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, m.name);
3509*9880d681SAndroid Build Coastguard Worker     name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
3510*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3511*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
3512*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3513*9880d681SAndroid Build Coastguard Worker 
3514*9880d681SAndroid Build Coastguard Worker     outs() << indent << "\t\t     types ";
3515*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
3516*9880d681SAndroid Build Coastguard Worker                              info, n_value, m.types);
3517*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
3518*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
3519*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
3520*9880d681SAndroid Build Coastguard Worker       else
3521*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
3522*9880d681SAndroid Build Coastguard Worker       if (m.types != 0)
3523*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, m.types);
3524*9880d681SAndroid Build Coastguard Worker     } else
3525*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, m.types);
3526*9880d681SAndroid Build Coastguard Worker     name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
3527*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3528*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
3529*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3530*9880d681SAndroid Build Coastguard Worker 
3531*9880d681SAndroid Build Coastguard Worker     outs() << indent << "\t\t       imp ";
3532*9880d681SAndroid Build Coastguard Worker     name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
3533*9880d681SAndroid Build Coastguard Worker                          n_value, m.imp);
3534*9880d681SAndroid Build Coastguard Worker     if (info->verbose && name == nullptr) {
3535*9880d681SAndroid Build Coastguard Worker       if (n_value != 0) {
3536*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value) << " ";
3537*9880d681SAndroid Build Coastguard Worker         if (m.imp != 0)
3538*9880d681SAndroid Build Coastguard Worker           outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
3539*9880d681SAndroid Build Coastguard Worker       } else
3540*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, m.imp) << " ";
3541*9880d681SAndroid Build Coastguard Worker     }
3542*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3543*9880d681SAndroid Build Coastguard Worker       outs() << name;
3544*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3545*9880d681SAndroid Build Coastguard Worker 
3546*9880d681SAndroid Build Coastguard Worker     p += sizeof(struct method64_t);
3547*9880d681SAndroid Build Coastguard Worker     offset += sizeof(struct method64_t);
3548*9880d681SAndroid Build Coastguard Worker   }
3549*9880d681SAndroid Build Coastguard Worker }
3550*9880d681SAndroid Build Coastguard Worker 
print_method_list32_t(uint64_t p,struct DisassembleInfo * info,const char * indent)3551*9880d681SAndroid Build Coastguard Worker static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
3552*9880d681SAndroid Build Coastguard Worker                                   const char *indent) {
3553*9880d681SAndroid Build Coastguard Worker   struct method_list32_t ml;
3554*9880d681SAndroid Build Coastguard Worker   struct method32_t m;
3555*9880d681SAndroid Build Coastguard Worker   const char *r, *name;
3556*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left, i;
3557*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
3558*9880d681SAndroid Build Coastguard Worker 
3559*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
3560*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
3561*9880d681SAndroid Build Coastguard Worker     return;
3562*9880d681SAndroid Build Coastguard Worker   memset(&ml, '\0', sizeof(struct method_list32_t));
3563*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct method_list32_t)) {
3564*9880d681SAndroid Build Coastguard Worker     memcpy(&ml, r, left);
3565*9880d681SAndroid Build Coastguard Worker     outs() << "   (method_list_t entends past the end of the section)\n";
3566*9880d681SAndroid Build Coastguard Worker   } else
3567*9880d681SAndroid Build Coastguard Worker     memcpy(&ml, r, sizeof(struct method_list32_t));
3568*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3569*9880d681SAndroid Build Coastguard Worker     swapStruct(ml);
3570*9880d681SAndroid Build Coastguard Worker   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
3571*9880d681SAndroid Build Coastguard Worker   outs() << indent << "\t\t     count " << ml.count << "\n";
3572*9880d681SAndroid Build Coastguard Worker 
3573*9880d681SAndroid Build Coastguard Worker   p += sizeof(struct method_list32_t);
3574*9880d681SAndroid Build Coastguard Worker   offset += sizeof(struct method_list32_t);
3575*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < ml.count; i++) {
3576*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(p, offset, left, S, info);
3577*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
3578*9880d681SAndroid Build Coastguard Worker       return;
3579*9880d681SAndroid Build Coastguard Worker     memset(&m, '\0', sizeof(struct method32_t));
3580*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct method32_t)) {
3581*9880d681SAndroid Build Coastguard Worker       memcpy(&ml, r, left);
3582*9880d681SAndroid Build Coastguard Worker       outs() << indent << "   (method_t entends past the end of the section)\n";
3583*9880d681SAndroid Build Coastguard Worker     } else
3584*9880d681SAndroid Build Coastguard Worker       memcpy(&m, r, sizeof(struct method32_t));
3585*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3586*9880d681SAndroid Build Coastguard Worker       swapStruct(m);
3587*9880d681SAndroid Build Coastguard Worker 
3588*9880d681SAndroid Build Coastguard Worker     outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
3589*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(m.name, xoffset, left, xS, info);
3590*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3591*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
3592*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3593*9880d681SAndroid Build Coastguard Worker 
3594*9880d681SAndroid Build Coastguard Worker     outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
3595*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(m.types, xoffset, left, xS, info);
3596*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3597*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
3598*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3599*9880d681SAndroid Build Coastguard Worker 
3600*9880d681SAndroid Build Coastguard Worker     outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
3601*9880d681SAndroid Build Coastguard Worker     name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
3602*9880d681SAndroid Build Coastguard Worker                          m.imp);
3603*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3604*9880d681SAndroid Build Coastguard Worker       outs() << " " << name;
3605*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3606*9880d681SAndroid Build Coastguard Worker 
3607*9880d681SAndroid Build Coastguard Worker     p += sizeof(struct method32_t);
3608*9880d681SAndroid Build Coastguard Worker     offset += sizeof(struct method32_t);
3609*9880d681SAndroid Build Coastguard Worker   }
3610*9880d681SAndroid Build Coastguard Worker }
3611*9880d681SAndroid Build Coastguard Worker 
print_method_list(uint32_t p,struct DisassembleInfo * info)3612*9880d681SAndroid Build Coastguard Worker static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
3613*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left, xleft;
3614*9880d681SAndroid Build Coastguard Worker   SectionRef S;
3615*9880d681SAndroid Build Coastguard Worker   struct objc_method_list_t method_list;
3616*9880d681SAndroid Build Coastguard Worker   struct objc_method_t method;
3617*9880d681SAndroid Build Coastguard Worker   const char *r, *methods, *name, *SymbolName;
3618*9880d681SAndroid Build Coastguard Worker   int32_t i;
3619*9880d681SAndroid Build Coastguard Worker 
3620*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info, true);
3621*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
3622*9880d681SAndroid Build Coastguard Worker     return true;
3623*9880d681SAndroid Build Coastguard Worker 
3624*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
3625*9880d681SAndroid Build Coastguard Worker   if (left > sizeof(struct objc_method_list_t)) {
3626*9880d681SAndroid Build Coastguard Worker     memcpy(&method_list, r, sizeof(struct objc_method_list_t));
3627*9880d681SAndroid Build Coastguard Worker   } else {
3628*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t objc_method_list extends past end of the section\n";
3629*9880d681SAndroid Build Coastguard Worker     memset(&method_list, '\0', sizeof(struct objc_method_list_t));
3630*9880d681SAndroid Build Coastguard Worker     memcpy(&method_list, r, left);
3631*9880d681SAndroid Build Coastguard Worker   }
3632*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3633*9880d681SAndroid Build Coastguard Worker     swapStruct(method_list);
3634*9880d681SAndroid Build Coastguard Worker 
3635*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t         obsolete "
3636*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, method_list.obsolete) << "\n";
3637*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t     method_count " << method_list.method_count << "\n";
3638*9880d681SAndroid Build Coastguard Worker 
3639*9880d681SAndroid Build Coastguard Worker   methods = r + sizeof(struct objc_method_list_t);
3640*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < method_list.method_count; i++) {
3641*9880d681SAndroid Build Coastguard Worker     if ((i + 1) * sizeof(struct objc_method_t) > left) {
3642*9880d681SAndroid Build Coastguard Worker       outs() << "\t\t remaining method's extend past the of the section\n";
3643*9880d681SAndroid Build Coastguard Worker       break;
3644*9880d681SAndroid Build Coastguard Worker     }
3645*9880d681SAndroid Build Coastguard Worker     memcpy(&method, methods + i * sizeof(struct objc_method_t),
3646*9880d681SAndroid Build Coastguard Worker            sizeof(struct objc_method_t));
3647*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3648*9880d681SAndroid Build Coastguard Worker       swapStruct(method);
3649*9880d681SAndroid Build Coastguard Worker 
3650*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t      method_name "
3651*9880d681SAndroid Build Coastguard Worker            << format("0x%08" PRIx32, method.method_name);
3652*9880d681SAndroid Build Coastguard Worker     if (info->verbose) {
3653*9880d681SAndroid Build Coastguard Worker       name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
3654*9880d681SAndroid Build Coastguard Worker       if (name != nullptr)
3655*9880d681SAndroid Build Coastguard Worker         outs() << format(" %.*s", xleft, name);
3656*9880d681SAndroid Build Coastguard Worker       else
3657*9880d681SAndroid Build Coastguard Worker         outs() << " (not in an __OBJC section)";
3658*9880d681SAndroid Build Coastguard Worker     }
3659*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3660*9880d681SAndroid Build Coastguard Worker 
3661*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t     method_types "
3662*9880d681SAndroid Build Coastguard Worker            << format("0x%08" PRIx32, method.method_types);
3663*9880d681SAndroid Build Coastguard Worker     if (info->verbose) {
3664*9880d681SAndroid Build Coastguard Worker       name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
3665*9880d681SAndroid Build Coastguard Worker       if (name != nullptr)
3666*9880d681SAndroid Build Coastguard Worker         outs() << format(" %.*s", xleft, name);
3667*9880d681SAndroid Build Coastguard Worker       else
3668*9880d681SAndroid Build Coastguard Worker         outs() << " (not in an __OBJC section)";
3669*9880d681SAndroid Build Coastguard Worker     }
3670*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3671*9880d681SAndroid Build Coastguard Worker 
3672*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t       method_imp "
3673*9880d681SAndroid Build Coastguard Worker            << format("0x%08" PRIx32, method.method_imp) << " ";
3674*9880d681SAndroid Build Coastguard Worker     if (info->verbose) {
3675*9880d681SAndroid Build Coastguard Worker       SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
3676*9880d681SAndroid Build Coastguard Worker       if (SymbolName != nullptr)
3677*9880d681SAndroid Build Coastguard Worker         outs() << SymbolName;
3678*9880d681SAndroid Build Coastguard Worker     }
3679*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3680*9880d681SAndroid Build Coastguard Worker   }
3681*9880d681SAndroid Build Coastguard Worker   return false;
3682*9880d681SAndroid Build Coastguard Worker }
3683*9880d681SAndroid Build Coastguard Worker 
print_protocol_list64_t(uint64_t p,struct DisassembleInfo * info)3684*9880d681SAndroid Build Coastguard Worker static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
3685*9880d681SAndroid Build Coastguard Worker   struct protocol_list64_t pl;
3686*9880d681SAndroid Build Coastguard Worker   uint64_t q, n_value;
3687*9880d681SAndroid Build Coastguard Worker   struct protocol64_t pc;
3688*9880d681SAndroid Build Coastguard Worker   const char *r;
3689*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left, i;
3690*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
3691*9880d681SAndroid Build Coastguard Worker   const char *name, *sym_name;
3692*9880d681SAndroid Build Coastguard Worker 
3693*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(p, offset, left, S, info);
3694*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
3695*9880d681SAndroid Build Coastguard Worker     return;
3696*9880d681SAndroid Build Coastguard Worker   memset(&pl, '\0', sizeof(struct protocol_list64_t));
3697*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct protocol_list64_t)) {
3698*9880d681SAndroid Build Coastguard Worker     memcpy(&pl, r, left);
3699*9880d681SAndroid Build Coastguard Worker     outs() << "   (protocol_list_t entends past the end of the section)\n";
3700*9880d681SAndroid Build Coastguard Worker   } else
3701*9880d681SAndroid Build Coastguard Worker     memcpy(&pl, r, sizeof(struct protocol_list64_t));
3702*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3703*9880d681SAndroid Build Coastguard Worker     swapStruct(pl);
3704*9880d681SAndroid Build Coastguard Worker   outs() << "                      count " << pl.count << "\n";
3705*9880d681SAndroid Build Coastguard Worker 
3706*9880d681SAndroid Build Coastguard Worker   p += sizeof(struct protocol_list64_t);
3707*9880d681SAndroid Build Coastguard Worker   offset += sizeof(struct protocol_list64_t);
3708*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < pl.count; i++) {
3709*9880d681SAndroid Build Coastguard Worker     r = get_pointer_64(p, offset, left, S, info);
3710*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
3711*9880d681SAndroid Build Coastguard Worker       return;
3712*9880d681SAndroid Build Coastguard Worker     q = 0;
3713*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(uint64_t)) {
3714*9880d681SAndroid Build Coastguard Worker       memcpy(&q, r, left);
3715*9880d681SAndroid Build Coastguard Worker       outs() << "   (protocol_t * entends past the end of the section)\n";
3716*9880d681SAndroid Build Coastguard Worker     } else
3717*9880d681SAndroid Build Coastguard Worker       memcpy(&q, r, sizeof(uint64_t));
3718*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3719*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(q);
3720*9880d681SAndroid Build Coastguard Worker 
3721*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t      list[" << i << "] ";
3722*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset, S, info, n_value, q);
3723*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
3724*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
3725*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
3726*9880d681SAndroid Build Coastguard Worker       else
3727*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
3728*9880d681SAndroid Build Coastguard Worker       if (q != 0)
3729*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, q);
3730*9880d681SAndroid Build Coastguard Worker     } else
3731*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, q);
3732*9880d681SAndroid Build Coastguard Worker     outs() << " (struct protocol_t *)\n";
3733*9880d681SAndroid Build Coastguard Worker 
3734*9880d681SAndroid Build Coastguard Worker     r = get_pointer_64(q + n_value, offset, left, S, info);
3735*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
3736*9880d681SAndroid Build Coastguard Worker       return;
3737*9880d681SAndroid Build Coastguard Worker     memset(&pc, '\0', sizeof(struct protocol64_t));
3738*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct protocol64_t)) {
3739*9880d681SAndroid Build Coastguard Worker       memcpy(&pc, r, left);
3740*9880d681SAndroid Build Coastguard Worker       outs() << "   (protocol_t entends past the end of the section)\n";
3741*9880d681SAndroid Build Coastguard Worker     } else
3742*9880d681SAndroid Build Coastguard Worker       memcpy(&pc, r, sizeof(struct protocol64_t));
3743*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3744*9880d681SAndroid Build Coastguard Worker       swapStruct(pc);
3745*9880d681SAndroid Build Coastguard Worker 
3746*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t      isa " << format("0x%" PRIx64, pc.isa) << "\n";
3747*9880d681SAndroid Build Coastguard Worker 
3748*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     name ";
3749*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
3750*9880d681SAndroid Build Coastguard Worker                              info, n_value, pc.name);
3751*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
3752*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
3753*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
3754*9880d681SAndroid Build Coastguard Worker       else
3755*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
3756*9880d681SAndroid Build Coastguard Worker       if (pc.name != 0)
3757*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, pc.name);
3758*9880d681SAndroid Build Coastguard Worker     } else
3759*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, pc.name);
3760*9880d681SAndroid Build Coastguard Worker     name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
3761*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3762*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
3763*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3764*9880d681SAndroid Build Coastguard Worker 
3765*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
3766*9880d681SAndroid Build Coastguard Worker 
3767*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t  instanceMethods ";
3768*9880d681SAndroid Build Coastguard Worker     sym_name =
3769*9880d681SAndroid Build Coastguard Worker         get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
3770*9880d681SAndroid Build Coastguard Worker                       S, info, n_value, pc.instanceMethods);
3771*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
3772*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
3773*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
3774*9880d681SAndroid Build Coastguard Worker       else
3775*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
3776*9880d681SAndroid Build Coastguard Worker       if (pc.instanceMethods != 0)
3777*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
3778*9880d681SAndroid Build Coastguard Worker     } else
3779*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, pc.instanceMethods);
3780*9880d681SAndroid Build Coastguard Worker     outs() << " (struct method_list_t *)\n";
3781*9880d681SAndroid Build Coastguard Worker     if (pc.instanceMethods + n_value != 0)
3782*9880d681SAndroid Build Coastguard Worker       print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
3783*9880d681SAndroid Build Coastguard Worker 
3784*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t     classMethods ";
3785*9880d681SAndroid Build Coastguard Worker     sym_name =
3786*9880d681SAndroid Build Coastguard Worker         get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
3787*9880d681SAndroid Build Coastguard Worker                       info, n_value, pc.classMethods);
3788*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
3789*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
3790*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
3791*9880d681SAndroid Build Coastguard Worker       else
3792*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
3793*9880d681SAndroid Build Coastguard Worker       if (pc.classMethods != 0)
3794*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, pc.classMethods);
3795*9880d681SAndroid Build Coastguard Worker     } else
3796*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, pc.classMethods);
3797*9880d681SAndroid Build Coastguard Worker     outs() << " (struct method_list_t *)\n";
3798*9880d681SAndroid Build Coastguard Worker     if (pc.classMethods + n_value != 0)
3799*9880d681SAndroid Build Coastguard Worker       print_method_list64_t(pc.classMethods + n_value, info, "\t");
3800*9880d681SAndroid Build Coastguard Worker 
3801*9880d681SAndroid Build Coastguard Worker     outs() << "\t  optionalInstanceMethods "
3802*9880d681SAndroid Build Coastguard Worker            << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
3803*9880d681SAndroid Build Coastguard Worker     outs() << "\t     optionalClassMethods "
3804*9880d681SAndroid Build Coastguard Worker            << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
3805*9880d681SAndroid Build Coastguard Worker     outs() << "\t       instanceProperties "
3806*9880d681SAndroid Build Coastguard Worker            << format("0x%" PRIx64, pc.instanceProperties) << "\n";
3807*9880d681SAndroid Build Coastguard Worker 
3808*9880d681SAndroid Build Coastguard Worker     p += sizeof(uint64_t);
3809*9880d681SAndroid Build Coastguard Worker     offset += sizeof(uint64_t);
3810*9880d681SAndroid Build Coastguard Worker   }
3811*9880d681SAndroid Build Coastguard Worker }
3812*9880d681SAndroid Build Coastguard Worker 
print_protocol_list32_t(uint32_t p,struct DisassembleInfo * info)3813*9880d681SAndroid Build Coastguard Worker static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
3814*9880d681SAndroid Build Coastguard Worker   struct protocol_list32_t pl;
3815*9880d681SAndroid Build Coastguard Worker   uint32_t q;
3816*9880d681SAndroid Build Coastguard Worker   struct protocol32_t pc;
3817*9880d681SAndroid Build Coastguard Worker   const char *r;
3818*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left, i;
3819*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
3820*9880d681SAndroid Build Coastguard Worker   const char *name;
3821*9880d681SAndroid Build Coastguard Worker 
3822*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
3823*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
3824*9880d681SAndroid Build Coastguard Worker     return;
3825*9880d681SAndroid Build Coastguard Worker   memset(&pl, '\0', sizeof(struct protocol_list32_t));
3826*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct protocol_list32_t)) {
3827*9880d681SAndroid Build Coastguard Worker     memcpy(&pl, r, left);
3828*9880d681SAndroid Build Coastguard Worker     outs() << "   (protocol_list_t entends past the end of the section)\n";
3829*9880d681SAndroid Build Coastguard Worker   } else
3830*9880d681SAndroid Build Coastguard Worker     memcpy(&pl, r, sizeof(struct protocol_list32_t));
3831*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3832*9880d681SAndroid Build Coastguard Worker     swapStruct(pl);
3833*9880d681SAndroid Build Coastguard Worker   outs() << "                      count " << pl.count << "\n";
3834*9880d681SAndroid Build Coastguard Worker 
3835*9880d681SAndroid Build Coastguard Worker   p += sizeof(struct protocol_list32_t);
3836*9880d681SAndroid Build Coastguard Worker   offset += sizeof(struct protocol_list32_t);
3837*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < pl.count; i++) {
3838*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(p, offset, left, S, info);
3839*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
3840*9880d681SAndroid Build Coastguard Worker       return;
3841*9880d681SAndroid Build Coastguard Worker     q = 0;
3842*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(uint32_t)) {
3843*9880d681SAndroid Build Coastguard Worker       memcpy(&q, r, left);
3844*9880d681SAndroid Build Coastguard Worker       outs() << "   (protocol_t * entends past the end of the section)\n";
3845*9880d681SAndroid Build Coastguard Worker     } else
3846*9880d681SAndroid Build Coastguard Worker       memcpy(&q, r, sizeof(uint32_t));
3847*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3848*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(q);
3849*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t      list[" << i << "] " << format("0x%" PRIx32, q)
3850*9880d681SAndroid Build Coastguard Worker            << " (struct protocol_t *)\n";
3851*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(q, offset, left, S, info);
3852*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
3853*9880d681SAndroid Build Coastguard Worker       return;
3854*9880d681SAndroid Build Coastguard Worker     memset(&pc, '\0', sizeof(struct protocol32_t));
3855*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct protocol32_t)) {
3856*9880d681SAndroid Build Coastguard Worker       memcpy(&pc, r, left);
3857*9880d681SAndroid Build Coastguard Worker       outs() << "   (protocol_t entends past the end of the section)\n";
3858*9880d681SAndroid Build Coastguard Worker     } else
3859*9880d681SAndroid Build Coastguard Worker       memcpy(&pc, r, sizeof(struct protocol32_t));
3860*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3861*9880d681SAndroid Build Coastguard Worker       swapStruct(pc);
3862*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t      isa " << format("0x%" PRIx32, pc.isa) << "\n";
3863*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     name " << format("0x%" PRIx32, pc.name);
3864*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(pc.name, xoffset, left, xS, info);
3865*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
3866*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
3867*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3868*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
3869*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t  instanceMethods "
3870*9880d681SAndroid Build Coastguard Worker            << format("0x%" PRIx32, pc.instanceMethods)
3871*9880d681SAndroid Build Coastguard Worker            << " (struct method_list_t *)\n";
3872*9880d681SAndroid Build Coastguard Worker     if (pc.instanceMethods != 0)
3873*9880d681SAndroid Build Coastguard Worker       print_method_list32_t(pc.instanceMethods, info, "\t");
3874*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t     classMethods " << format("0x%" PRIx32, pc.classMethods)
3875*9880d681SAndroid Build Coastguard Worker            << " (struct method_list_t *)\n";
3876*9880d681SAndroid Build Coastguard Worker     if (pc.classMethods != 0)
3877*9880d681SAndroid Build Coastguard Worker       print_method_list32_t(pc.classMethods, info, "\t");
3878*9880d681SAndroid Build Coastguard Worker     outs() << "\t  optionalInstanceMethods "
3879*9880d681SAndroid Build Coastguard Worker            << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
3880*9880d681SAndroid Build Coastguard Worker     outs() << "\t     optionalClassMethods "
3881*9880d681SAndroid Build Coastguard Worker            << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
3882*9880d681SAndroid Build Coastguard Worker     outs() << "\t       instanceProperties "
3883*9880d681SAndroid Build Coastguard Worker            << format("0x%" PRIx32, pc.instanceProperties) << "\n";
3884*9880d681SAndroid Build Coastguard Worker     p += sizeof(uint32_t);
3885*9880d681SAndroid Build Coastguard Worker     offset += sizeof(uint32_t);
3886*9880d681SAndroid Build Coastguard Worker   }
3887*9880d681SAndroid Build Coastguard Worker }
3888*9880d681SAndroid Build Coastguard Worker 
print_indent(uint32_t indent)3889*9880d681SAndroid Build Coastguard Worker static void print_indent(uint32_t indent) {
3890*9880d681SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < indent;) {
3891*9880d681SAndroid Build Coastguard Worker     if (indent - i >= 8) {
3892*9880d681SAndroid Build Coastguard Worker       outs() << "\t";
3893*9880d681SAndroid Build Coastguard Worker       i += 8;
3894*9880d681SAndroid Build Coastguard Worker     } else {
3895*9880d681SAndroid Build Coastguard Worker       for (uint32_t j = i; j < indent; j++)
3896*9880d681SAndroid Build Coastguard Worker         outs() << " ";
3897*9880d681SAndroid Build Coastguard Worker       return;
3898*9880d681SAndroid Build Coastguard Worker     }
3899*9880d681SAndroid Build Coastguard Worker   }
3900*9880d681SAndroid Build Coastguard Worker }
3901*9880d681SAndroid Build Coastguard Worker 
print_method_description_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)3902*9880d681SAndroid Build Coastguard Worker static bool print_method_description_list(uint32_t p, uint32_t indent,
3903*9880d681SAndroid Build Coastguard Worker                                           struct DisassembleInfo *info) {
3904*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left, xleft;
3905*9880d681SAndroid Build Coastguard Worker   SectionRef S;
3906*9880d681SAndroid Build Coastguard Worker   struct objc_method_description_list_t mdl;
3907*9880d681SAndroid Build Coastguard Worker   struct objc_method_description_t md;
3908*9880d681SAndroid Build Coastguard Worker   const char *r, *list, *name;
3909*9880d681SAndroid Build Coastguard Worker   int32_t i;
3910*9880d681SAndroid Build Coastguard Worker 
3911*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info, true);
3912*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
3913*9880d681SAndroid Build Coastguard Worker     return true;
3914*9880d681SAndroid Build Coastguard Worker 
3915*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
3916*9880d681SAndroid Build Coastguard Worker   if (left > sizeof(struct objc_method_description_list_t)) {
3917*9880d681SAndroid Build Coastguard Worker     memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
3918*9880d681SAndroid Build Coastguard Worker   } else {
3919*9880d681SAndroid Build Coastguard Worker     print_indent(indent);
3920*9880d681SAndroid Build Coastguard Worker     outs() << " objc_method_description_list extends past end of the section\n";
3921*9880d681SAndroid Build Coastguard Worker     memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
3922*9880d681SAndroid Build Coastguard Worker     memcpy(&mdl, r, left);
3923*9880d681SAndroid Build Coastguard Worker   }
3924*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3925*9880d681SAndroid Build Coastguard Worker     swapStruct(mdl);
3926*9880d681SAndroid Build Coastguard Worker 
3927*9880d681SAndroid Build Coastguard Worker   print_indent(indent);
3928*9880d681SAndroid Build Coastguard Worker   outs() << "        count " << mdl.count << "\n";
3929*9880d681SAndroid Build Coastguard Worker 
3930*9880d681SAndroid Build Coastguard Worker   list = r + sizeof(struct objc_method_description_list_t);
3931*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < mdl.count; i++) {
3932*9880d681SAndroid Build Coastguard Worker     if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
3933*9880d681SAndroid Build Coastguard Worker       print_indent(indent);
3934*9880d681SAndroid Build Coastguard Worker       outs() << " remaining list entries extend past the of the section\n";
3935*9880d681SAndroid Build Coastguard Worker       break;
3936*9880d681SAndroid Build Coastguard Worker     }
3937*9880d681SAndroid Build Coastguard Worker     print_indent(indent);
3938*9880d681SAndroid Build Coastguard Worker     outs() << "        list[" << i << "]\n";
3939*9880d681SAndroid Build Coastguard Worker     memcpy(&md, list + i * sizeof(struct objc_method_description_t),
3940*9880d681SAndroid Build Coastguard Worker            sizeof(struct objc_method_description_t));
3941*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3942*9880d681SAndroid Build Coastguard Worker       swapStruct(md);
3943*9880d681SAndroid Build Coastguard Worker 
3944*9880d681SAndroid Build Coastguard Worker     print_indent(indent);
3945*9880d681SAndroid Build Coastguard Worker     outs() << "             name " << format("0x%08" PRIx32, md.name);
3946*9880d681SAndroid Build Coastguard Worker     if (info->verbose) {
3947*9880d681SAndroid Build Coastguard Worker       name = get_pointer_32(md.name, offset, xleft, S, info, true);
3948*9880d681SAndroid Build Coastguard Worker       if (name != nullptr)
3949*9880d681SAndroid Build Coastguard Worker         outs() << format(" %.*s", xleft, name);
3950*9880d681SAndroid Build Coastguard Worker       else
3951*9880d681SAndroid Build Coastguard Worker         outs() << " (not in an __OBJC section)";
3952*9880d681SAndroid Build Coastguard Worker     }
3953*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3954*9880d681SAndroid Build Coastguard Worker 
3955*9880d681SAndroid Build Coastguard Worker     print_indent(indent);
3956*9880d681SAndroid Build Coastguard Worker     outs() << "            types " << format("0x%08" PRIx32, md.types);
3957*9880d681SAndroid Build Coastguard Worker     if (info->verbose) {
3958*9880d681SAndroid Build Coastguard Worker       name = get_pointer_32(md.types, offset, xleft, S, info, true);
3959*9880d681SAndroid Build Coastguard Worker       if (name != nullptr)
3960*9880d681SAndroid Build Coastguard Worker         outs() << format(" %.*s", xleft, name);
3961*9880d681SAndroid Build Coastguard Worker       else
3962*9880d681SAndroid Build Coastguard Worker         outs() << " (not in an __OBJC section)";
3963*9880d681SAndroid Build Coastguard Worker     }
3964*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
3965*9880d681SAndroid Build Coastguard Worker   }
3966*9880d681SAndroid Build Coastguard Worker   return false;
3967*9880d681SAndroid Build Coastguard Worker }
3968*9880d681SAndroid Build Coastguard Worker 
3969*9880d681SAndroid Build Coastguard Worker static bool print_protocol_list(uint32_t p, uint32_t indent,
3970*9880d681SAndroid Build Coastguard Worker                                 struct DisassembleInfo *info);
3971*9880d681SAndroid Build Coastguard Worker 
print_protocol(uint32_t p,uint32_t indent,struct DisassembleInfo * info)3972*9880d681SAndroid Build Coastguard Worker static bool print_protocol(uint32_t p, uint32_t indent,
3973*9880d681SAndroid Build Coastguard Worker                            struct DisassembleInfo *info) {
3974*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
3975*9880d681SAndroid Build Coastguard Worker   SectionRef S;
3976*9880d681SAndroid Build Coastguard Worker   struct objc_protocol_t protocol;
3977*9880d681SAndroid Build Coastguard Worker   const char *r, *name;
3978*9880d681SAndroid Build Coastguard Worker 
3979*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info, true);
3980*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
3981*9880d681SAndroid Build Coastguard Worker     return true;
3982*9880d681SAndroid Build Coastguard Worker 
3983*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
3984*9880d681SAndroid Build Coastguard Worker   if (left >= sizeof(struct objc_protocol_t)) {
3985*9880d681SAndroid Build Coastguard Worker     memcpy(&protocol, r, sizeof(struct objc_protocol_t));
3986*9880d681SAndroid Build Coastguard Worker   } else {
3987*9880d681SAndroid Build Coastguard Worker     print_indent(indent);
3988*9880d681SAndroid Build Coastguard Worker     outs() << "            Protocol extends past end of the section\n";
3989*9880d681SAndroid Build Coastguard Worker     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
3990*9880d681SAndroid Build Coastguard Worker     memcpy(&protocol, r, left);
3991*9880d681SAndroid Build Coastguard Worker   }
3992*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3993*9880d681SAndroid Build Coastguard Worker     swapStruct(protocol);
3994*9880d681SAndroid Build Coastguard Worker 
3995*9880d681SAndroid Build Coastguard Worker   print_indent(indent);
3996*9880d681SAndroid Build Coastguard Worker   outs() << "              isa " << format("0x%08" PRIx32, protocol.isa)
3997*9880d681SAndroid Build Coastguard Worker          << "\n";
3998*9880d681SAndroid Build Coastguard Worker 
3999*9880d681SAndroid Build Coastguard Worker   print_indent(indent);
4000*9880d681SAndroid Build Coastguard Worker   outs() << "    protocol_name "
4001*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, protocol.protocol_name);
4002*9880d681SAndroid Build Coastguard Worker   if (info->verbose) {
4003*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
4004*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4005*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4006*9880d681SAndroid Build Coastguard Worker     else
4007*9880d681SAndroid Build Coastguard Worker       outs() << " (not in an __OBJC section)";
4008*9880d681SAndroid Build Coastguard Worker   }
4009*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4010*9880d681SAndroid Build Coastguard Worker 
4011*9880d681SAndroid Build Coastguard Worker   print_indent(indent);
4012*9880d681SAndroid Build Coastguard Worker   outs() << "    protocol_list "
4013*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, protocol.protocol_list);
4014*9880d681SAndroid Build Coastguard Worker   if (print_protocol_list(protocol.protocol_list, indent + 4, info))
4015*9880d681SAndroid Build Coastguard Worker     outs() << " (not in an __OBJC section)\n";
4016*9880d681SAndroid Build Coastguard Worker 
4017*9880d681SAndroid Build Coastguard Worker   print_indent(indent);
4018*9880d681SAndroid Build Coastguard Worker   outs() << " instance_methods "
4019*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, protocol.instance_methods);
4020*9880d681SAndroid Build Coastguard Worker   if (print_method_description_list(protocol.instance_methods, indent, info))
4021*9880d681SAndroid Build Coastguard Worker     outs() << " (not in an __OBJC section)\n";
4022*9880d681SAndroid Build Coastguard Worker 
4023*9880d681SAndroid Build Coastguard Worker   print_indent(indent);
4024*9880d681SAndroid Build Coastguard Worker   outs() << "    class_methods "
4025*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, protocol.class_methods);
4026*9880d681SAndroid Build Coastguard Worker   if (print_method_description_list(protocol.class_methods, indent, info))
4027*9880d681SAndroid Build Coastguard Worker     outs() << " (not in an __OBJC section)\n";
4028*9880d681SAndroid Build Coastguard Worker 
4029*9880d681SAndroid Build Coastguard Worker   return false;
4030*9880d681SAndroid Build Coastguard Worker }
4031*9880d681SAndroid Build Coastguard Worker 
print_protocol_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)4032*9880d681SAndroid Build Coastguard Worker static bool print_protocol_list(uint32_t p, uint32_t indent,
4033*9880d681SAndroid Build Coastguard Worker                                 struct DisassembleInfo *info) {
4034*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left, l;
4035*9880d681SAndroid Build Coastguard Worker   SectionRef S;
4036*9880d681SAndroid Build Coastguard Worker   struct objc_protocol_list_t protocol_list;
4037*9880d681SAndroid Build Coastguard Worker   const char *r, *list;
4038*9880d681SAndroid Build Coastguard Worker   int32_t i;
4039*9880d681SAndroid Build Coastguard Worker 
4040*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info, true);
4041*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
4042*9880d681SAndroid Build Coastguard Worker     return true;
4043*9880d681SAndroid Build Coastguard Worker 
4044*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4045*9880d681SAndroid Build Coastguard Worker   if (left > sizeof(struct objc_protocol_list_t)) {
4046*9880d681SAndroid Build Coastguard Worker     memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
4047*9880d681SAndroid Build Coastguard Worker   } else {
4048*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
4049*9880d681SAndroid Build Coastguard Worker     memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
4050*9880d681SAndroid Build Coastguard Worker     memcpy(&protocol_list, r, left);
4051*9880d681SAndroid Build Coastguard Worker   }
4052*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4053*9880d681SAndroid Build Coastguard Worker     swapStruct(protocol_list);
4054*9880d681SAndroid Build Coastguard Worker 
4055*9880d681SAndroid Build Coastguard Worker   print_indent(indent);
4056*9880d681SAndroid Build Coastguard Worker   outs() << "         next " << format("0x%08" PRIx32, protocol_list.next)
4057*9880d681SAndroid Build Coastguard Worker          << "\n";
4058*9880d681SAndroid Build Coastguard Worker   print_indent(indent);
4059*9880d681SAndroid Build Coastguard Worker   outs() << "        count " << protocol_list.count << "\n";
4060*9880d681SAndroid Build Coastguard Worker 
4061*9880d681SAndroid Build Coastguard Worker   list = r + sizeof(struct objc_protocol_list_t);
4062*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < protocol_list.count; i++) {
4063*9880d681SAndroid Build Coastguard Worker     if ((i + 1) * sizeof(uint32_t) > left) {
4064*9880d681SAndroid Build Coastguard Worker       outs() << "\t\t remaining list entries extend past the of the section\n";
4065*9880d681SAndroid Build Coastguard Worker       break;
4066*9880d681SAndroid Build Coastguard Worker     }
4067*9880d681SAndroid Build Coastguard Worker     memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
4068*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4069*9880d681SAndroid Build Coastguard Worker       sys::swapByteOrder(l);
4070*9880d681SAndroid Build Coastguard Worker 
4071*9880d681SAndroid Build Coastguard Worker     print_indent(indent);
4072*9880d681SAndroid Build Coastguard Worker     outs() << "      list[" << i << "] " << format("0x%08" PRIx32, l);
4073*9880d681SAndroid Build Coastguard Worker     if (print_protocol(l, indent, info))
4074*9880d681SAndroid Build Coastguard Worker       outs() << "(not in an __OBJC section)\n";
4075*9880d681SAndroid Build Coastguard Worker   }
4076*9880d681SAndroid Build Coastguard Worker   return false;
4077*9880d681SAndroid Build Coastguard Worker }
4078*9880d681SAndroid Build Coastguard Worker 
print_ivar_list64_t(uint64_t p,struct DisassembleInfo * info)4079*9880d681SAndroid Build Coastguard Worker static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
4080*9880d681SAndroid Build Coastguard Worker   struct ivar_list64_t il;
4081*9880d681SAndroid Build Coastguard Worker   struct ivar64_t i;
4082*9880d681SAndroid Build Coastguard Worker   const char *r;
4083*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left, j;
4084*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
4085*9880d681SAndroid Build Coastguard Worker   const char *name, *sym_name, *ivar_offset_p;
4086*9880d681SAndroid Build Coastguard Worker   uint64_t ivar_offset, n_value;
4087*9880d681SAndroid Build Coastguard Worker 
4088*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(p, offset, left, S, info);
4089*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
4090*9880d681SAndroid Build Coastguard Worker     return;
4091*9880d681SAndroid Build Coastguard Worker   memset(&il, '\0', sizeof(struct ivar_list64_t));
4092*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct ivar_list64_t)) {
4093*9880d681SAndroid Build Coastguard Worker     memcpy(&il, r, left);
4094*9880d681SAndroid Build Coastguard Worker     outs() << "   (ivar_list_t entends past the end of the section)\n";
4095*9880d681SAndroid Build Coastguard Worker   } else
4096*9880d681SAndroid Build Coastguard Worker     memcpy(&il, r, sizeof(struct ivar_list64_t));
4097*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4098*9880d681SAndroid Build Coastguard Worker     swapStruct(il);
4099*9880d681SAndroid Build Coastguard Worker   outs() << "                    entsize " << il.entsize << "\n";
4100*9880d681SAndroid Build Coastguard Worker   outs() << "                      count " << il.count << "\n";
4101*9880d681SAndroid Build Coastguard Worker 
4102*9880d681SAndroid Build Coastguard Worker   p += sizeof(struct ivar_list64_t);
4103*9880d681SAndroid Build Coastguard Worker   offset += sizeof(struct ivar_list64_t);
4104*9880d681SAndroid Build Coastguard Worker   for (j = 0; j < il.count; j++) {
4105*9880d681SAndroid Build Coastguard Worker     r = get_pointer_64(p, offset, left, S, info);
4106*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
4107*9880d681SAndroid Build Coastguard Worker       return;
4108*9880d681SAndroid Build Coastguard Worker     memset(&i, '\0', sizeof(struct ivar64_t));
4109*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct ivar64_t)) {
4110*9880d681SAndroid Build Coastguard Worker       memcpy(&i, r, left);
4111*9880d681SAndroid Build Coastguard Worker       outs() << "   (ivar_t entends past the end of the section)\n";
4112*9880d681SAndroid Build Coastguard Worker     } else
4113*9880d681SAndroid Build Coastguard Worker       memcpy(&i, r, sizeof(struct ivar64_t));
4114*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4115*9880d681SAndroid Build Coastguard Worker       swapStruct(i);
4116*9880d681SAndroid Build Coastguard Worker 
4117*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t   offset ";
4118*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
4119*9880d681SAndroid Build Coastguard Worker                              info, n_value, i.offset);
4120*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
4121*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
4122*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
4123*9880d681SAndroid Build Coastguard Worker       else
4124*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
4125*9880d681SAndroid Build Coastguard Worker       if (i.offset != 0)
4126*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, i.offset);
4127*9880d681SAndroid Build Coastguard Worker     } else
4128*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, i.offset);
4129*9880d681SAndroid Build Coastguard Worker     ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
4130*9880d681SAndroid Build Coastguard Worker     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4131*9880d681SAndroid Build Coastguard Worker       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4132*9880d681SAndroid Build Coastguard Worker       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4133*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(ivar_offset);
4134*9880d681SAndroid Build Coastguard Worker       outs() << " " << ivar_offset << "\n";
4135*9880d681SAndroid Build Coastguard Worker     } else
4136*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
4137*9880d681SAndroid Build Coastguard Worker 
4138*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     name ";
4139*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
4140*9880d681SAndroid Build Coastguard Worker                              n_value, i.name);
4141*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
4142*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
4143*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
4144*9880d681SAndroid Build Coastguard Worker       else
4145*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
4146*9880d681SAndroid Build Coastguard Worker       if (i.name != 0)
4147*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, i.name);
4148*9880d681SAndroid Build Coastguard Worker     } else
4149*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, i.name);
4150*9880d681SAndroid Build Coastguard Worker     name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
4151*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4152*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4153*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
4154*9880d681SAndroid Build Coastguard Worker 
4155*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     type ";
4156*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
4157*9880d681SAndroid Build Coastguard Worker                              n_value, i.name);
4158*9880d681SAndroid Build Coastguard Worker     name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
4159*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
4160*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
4161*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
4162*9880d681SAndroid Build Coastguard Worker       else
4163*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
4164*9880d681SAndroid Build Coastguard Worker       if (i.type != 0)
4165*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, i.type);
4166*9880d681SAndroid Build Coastguard Worker     } else
4167*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, i.type);
4168*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4169*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4170*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
4171*9880d681SAndroid Build Coastguard Worker 
4172*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\talignment " << i.alignment << "\n";
4173*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     size " << i.size << "\n";
4174*9880d681SAndroid Build Coastguard Worker 
4175*9880d681SAndroid Build Coastguard Worker     p += sizeof(struct ivar64_t);
4176*9880d681SAndroid Build Coastguard Worker     offset += sizeof(struct ivar64_t);
4177*9880d681SAndroid Build Coastguard Worker   }
4178*9880d681SAndroid Build Coastguard Worker }
4179*9880d681SAndroid Build Coastguard Worker 
print_ivar_list32_t(uint32_t p,struct DisassembleInfo * info)4180*9880d681SAndroid Build Coastguard Worker static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
4181*9880d681SAndroid Build Coastguard Worker   struct ivar_list32_t il;
4182*9880d681SAndroid Build Coastguard Worker   struct ivar32_t i;
4183*9880d681SAndroid Build Coastguard Worker   const char *r;
4184*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left, j;
4185*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
4186*9880d681SAndroid Build Coastguard Worker   const char *name, *ivar_offset_p;
4187*9880d681SAndroid Build Coastguard Worker   uint32_t ivar_offset;
4188*9880d681SAndroid Build Coastguard Worker 
4189*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
4190*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
4191*9880d681SAndroid Build Coastguard Worker     return;
4192*9880d681SAndroid Build Coastguard Worker   memset(&il, '\0', sizeof(struct ivar_list32_t));
4193*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct ivar_list32_t)) {
4194*9880d681SAndroid Build Coastguard Worker     memcpy(&il, r, left);
4195*9880d681SAndroid Build Coastguard Worker     outs() << "   (ivar_list_t entends past the end of the section)\n";
4196*9880d681SAndroid Build Coastguard Worker   } else
4197*9880d681SAndroid Build Coastguard Worker     memcpy(&il, r, sizeof(struct ivar_list32_t));
4198*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4199*9880d681SAndroid Build Coastguard Worker     swapStruct(il);
4200*9880d681SAndroid Build Coastguard Worker   outs() << "                    entsize " << il.entsize << "\n";
4201*9880d681SAndroid Build Coastguard Worker   outs() << "                      count " << il.count << "\n";
4202*9880d681SAndroid Build Coastguard Worker 
4203*9880d681SAndroid Build Coastguard Worker   p += sizeof(struct ivar_list32_t);
4204*9880d681SAndroid Build Coastguard Worker   offset += sizeof(struct ivar_list32_t);
4205*9880d681SAndroid Build Coastguard Worker   for (j = 0; j < il.count; j++) {
4206*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(p, offset, left, S, info);
4207*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
4208*9880d681SAndroid Build Coastguard Worker       return;
4209*9880d681SAndroid Build Coastguard Worker     memset(&i, '\0', sizeof(struct ivar32_t));
4210*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct ivar32_t)) {
4211*9880d681SAndroid Build Coastguard Worker       memcpy(&i, r, left);
4212*9880d681SAndroid Build Coastguard Worker       outs() << "   (ivar_t entends past the end of the section)\n";
4213*9880d681SAndroid Build Coastguard Worker     } else
4214*9880d681SAndroid Build Coastguard Worker       memcpy(&i, r, sizeof(struct ivar32_t));
4215*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4216*9880d681SAndroid Build Coastguard Worker       swapStruct(i);
4217*9880d681SAndroid Build Coastguard Worker 
4218*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t   offset " << format("0x%" PRIx32, i.offset);
4219*9880d681SAndroid Build Coastguard Worker     ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
4220*9880d681SAndroid Build Coastguard Worker     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4221*9880d681SAndroid Build Coastguard Worker       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4222*9880d681SAndroid Build Coastguard Worker       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4223*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(ivar_offset);
4224*9880d681SAndroid Build Coastguard Worker       outs() << " " << ivar_offset << "\n";
4225*9880d681SAndroid Build Coastguard Worker     } else
4226*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
4227*9880d681SAndroid Build Coastguard Worker 
4228*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     name " << format("0x%" PRIx32, i.name);
4229*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(i.name, xoffset, left, xS, info);
4230*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4231*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4232*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
4233*9880d681SAndroid Build Coastguard Worker 
4234*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     type " << format("0x%" PRIx32, i.type);
4235*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(i.type, xoffset, left, xS, info);
4236*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4237*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4238*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
4239*9880d681SAndroid Build Coastguard Worker 
4240*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\talignment " << i.alignment << "\n";
4241*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     size " << i.size << "\n";
4242*9880d681SAndroid Build Coastguard Worker 
4243*9880d681SAndroid Build Coastguard Worker     p += sizeof(struct ivar32_t);
4244*9880d681SAndroid Build Coastguard Worker     offset += sizeof(struct ivar32_t);
4245*9880d681SAndroid Build Coastguard Worker   }
4246*9880d681SAndroid Build Coastguard Worker }
4247*9880d681SAndroid Build Coastguard Worker 
print_objc_property_list64(uint64_t p,struct DisassembleInfo * info)4248*9880d681SAndroid Build Coastguard Worker static void print_objc_property_list64(uint64_t p,
4249*9880d681SAndroid Build Coastguard Worker                                        struct DisassembleInfo *info) {
4250*9880d681SAndroid Build Coastguard Worker   struct objc_property_list64 opl;
4251*9880d681SAndroid Build Coastguard Worker   struct objc_property64 op;
4252*9880d681SAndroid Build Coastguard Worker   const char *r;
4253*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left, j;
4254*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
4255*9880d681SAndroid Build Coastguard Worker   const char *name, *sym_name;
4256*9880d681SAndroid Build Coastguard Worker   uint64_t n_value;
4257*9880d681SAndroid Build Coastguard Worker 
4258*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(p, offset, left, S, info);
4259*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
4260*9880d681SAndroid Build Coastguard Worker     return;
4261*9880d681SAndroid Build Coastguard Worker   memset(&opl, '\0', sizeof(struct objc_property_list64));
4262*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct objc_property_list64)) {
4263*9880d681SAndroid Build Coastguard Worker     memcpy(&opl, r, left);
4264*9880d681SAndroid Build Coastguard Worker     outs() << "   (objc_property_list entends past the end of the section)\n";
4265*9880d681SAndroid Build Coastguard Worker   } else
4266*9880d681SAndroid Build Coastguard Worker     memcpy(&opl, r, sizeof(struct objc_property_list64));
4267*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4268*9880d681SAndroid Build Coastguard Worker     swapStruct(opl);
4269*9880d681SAndroid Build Coastguard Worker   outs() << "                    entsize " << opl.entsize << "\n";
4270*9880d681SAndroid Build Coastguard Worker   outs() << "                      count " << opl.count << "\n";
4271*9880d681SAndroid Build Coastguard Worker 
4272*9880d681SAndroid Build Coastguard Worker   p += sizeof(struct objc_property_list64);
4273*9880d681SAndroid Build Coastguard Worker   offset += sizeof(struct objc_property_list64);
4274*9880d681SAndroid Build Coastguard Worker   for (j = 0; j < opl.count; j++) {
4275*9880d681SAndroid Build Coastguard Worker     r = get_pointer_64(p, offset, left, S, info);
4276*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
4277*9880d681SAndroid Build Coastguard Worker       return;
4278*9880d681SAndroid Build Coastguard Worker     memset(&op, '\0', sizeof(struct objc_property64));
4279*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct objc_property64)) {
4280*9880d681SAndroid Build Coastguard Worker       memcpy(&op, r, left);
4281*9880d681SAndroid Build Coastguard Worker       outs() << "   (objc_property entends past the end of the section)\n";
4282*9880d681SAndroid Build Coastguard Worker     } else
4283*9880d681SAndroid Build Coastguard Worker       memcpy(&op, r, sizeof(struct objc_property64));
4284*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4285*9880d681SAndroid Build Coastguard Worker       swapStruct(op);
4286*9880d681SAndroid Build Coastguard Worker 
4287*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     name ";
4288*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
4289*9880d681SAndroid Build Coastguard Worker                              info, n_value, op.name);
4290*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
4291*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
4292*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
4293*9880d681SAndroid Build Coastguard Worker       else
4294*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
4295*9880d681SAndroid Build Coastguard Worker       if (op.name != 0)
4296*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, op.name);
4297*9880d681SAndroid Build Coastguard Worker     } else
4298*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, op.name);
4299*9880d681SAndroid Build Coastguard Worker     name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
4300*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4301*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4302*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
4303*9880d681SAndroid Build Coastguard Worker 
4304*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\tattributes ";
4305*9880d681SAndroid Build Coastguard Worker     sym_name =
4306*9880d681SAndroid Build Coastguard Worker         get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
4307*9880d681SAndroid Build Coastguard Worker                       info, n_value, op.attributes);
4308*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
4309*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
4310*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
4311*9880d681SAndroid Build Coastguard Worker       else
4312*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
4313*9880d681SAndroid Build Coastguard Worker       if (op.attributes != 0)
4314*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, op.attributes);
4315*9880d681SAndroid Build Coastguard Worker     } else
4316*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, op.attributes);
4317*9880d681SAndroid Build Coastguard Worker     name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
4318*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4319*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4320*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
4321*9880d681SAndroid Build Coastguard Worker 
4322*9880d681SAndroid Build Coastguard Worker     p += sizeof(struct objc_property64);
4323*9880d681SAndroid Build Coastguard Worker     offset += sizeof(struct objc_property64);
4324*9880d681SAndroid Build Coastguard Worker   }
4325*9880d681SAndroid Build Coastguard Worker }
4326*9880d681SAndroid Build Coastguard Worker 
print_objc_property_list32(uint32_t p,struct DisassembleInfo * info)4327*9880d681SAndroid Build Coastguard Worker static void print_objc_property_list32(uint32_t p,
4328*9880d681SAndroid Build Coastguard Worker                                        struct DisassembleInfo *info) {
4329*9880d681SAndroid Build Coastguard Worker   struct objc_property_list32 opl;
4330*9880d681SAndroid Build Coastguard Worker   struct objc_property32 op;
4331*9880d681SAndroid Build Coastguard Worker   const char *r;
4332*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left, j;
4333*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
4334*9880d681SAndroid Build Coastguard Worker   const char *name;
4335*9880d681SAndroid Build Coastguard Worker 
4336*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
4337*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
4338*9880d681SAndroid Build Coastguard Worker     return;
4339*9880d681SAndroid Build Coastguard Worker   memset(&opl, '\0', sizeof(struct objc_property_list32));
4340*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct objc_property_list32)) {
4341*9880d681SAndroid Build Coastguard Worker     memcpy(&opl, r, left);
4342*9880d681SAndroid Build Coastguard Worker     outs() << "   (objc_property_list entends past the end of the section)\n";
4343*9880d681SAndroid Build Coastguard Worker   } else
4344*9880d681SAndroid Build Coastguard Worker     memcpy(&opl, r, sizeof(struct objc_property_list32));
4345*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4346*9880d681SAndroid Build Coastguard Worker     swapStruct(opl);
4347*9880d681SAndroid Build Coastguard Worker   outs() << "                    entsize " << opl.entsize << "\n";
4348*9880d681SAndroid Build Coastguard Worker   outs() << "                      count " << opl.count << "\n";
4349*9880d681SAndroid Build Coastguard Worker 
4350*9880d681SAndroid Build Coastguard Worker   p += sizeof(struct objc_property_list32);
4351*9880d681SAndroid Build Coastguard Worker   offset += sizeof(struct objc_property_list32);
4352*9880d681SAndroid Build Coastguard Worker   for (j = 0; j < opl.count; j++) {
4353*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(p, offset, left, S, info);
4354*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
4355*9880d681SAndroid Build Coastguard Worker       return;
4356*9880d681SAndroid Build Coastguard Worker     memset(&op, '\0', sizeof(struct objc_property32));
4357*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct objc_property32)) {
4358*9880d681SAndroid Build Coastguard Worker       memcpy(&op, r, left);
4359*9880d681SAndroid Build Coastguard Worker       outs() << "   (objc_property entends past the end of the section)\n";
4360*9880d681SAndroid Build Coastguard Worker     } else
4361*9880d681SAndroid Build Coastguard Worker       memcpy(&op, r, sizeof(struct objc_property32));
4362*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4363*9880d681SAndroid Build Coastguard Worker       swapStruct(op);
4364*9880d681SAndroid Build Coastguard Worker 
4365*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\t     name " << format("0x%" PRIx32, op.name);
4366*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(op.name, xoffset, left, xS, info);
4367*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4368*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4369*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
4370*9880d681SAndroid Build Coastguard Worker 
4371*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
4372*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(op.attributes, xoffset, left, xS, info);
4373*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4374*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4375*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
4376*9880d681SAndroid Build Coastguard Worker 
4377*9880d681SAndroid Build Coastguard Worker     p += sizeof(struct objc_property32);
4378*9880d681SAndroid Build Coastguard Worker     offset += sizeof(struct objc_property32);
4379*9880d681SAndroid Build Coastguard Worker   }
4380*9880d681SAndroid Build Coastguard Worker }
4381*9880d681SAndroid Build Coastguard Worker 
print_class_ro64_t(uint64_t p,struct DisassembleInfo * info,bool & is_meta_class)4382*9880d681SAndroid Build Coastguard Worker static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
4383*9880d681SAndroid Build Coastguard Worker                                bool &is_meta_class) {
4384*9880d681SAndroid Build Coastguard Worker   struct class_ro64_t cro;
4385*9880d681SAndroid Build Coastguard Worker   const char *r;
4386*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left;
4387*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
4388*9880d681SAndroid Build Coastguard Worker   const char *name, *sym_name;
4389*9880d681SAndroid Build Coastguard Worker   uint64_t n_value;
4390*9880d681SAndroid Build Coastguard Worker 
4391*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(p, offset, left, S, info);
4392*9880d681SAndroid Build Coastguard Worker   if (r == nullptr || left < sizeof(struct class_ro64_t))
4393*9880d681SAndroid Build Coastguard Worker     return false;
4394*9880d681SAndroid Build Coastguard Worker   memset(&cro, '\0', sizeof(struct class_ro64_t));
4395*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct class_ro64_t)) {
4396*9880d681SAndroid Build Coastguard Worker     memcpy(&cro, r, left);
4397*9880d681SAndroid Build Coastguard Worker     outs() << "   (class_ro_t entends past the end of the section)\n";
4398*9880d681SAndroid Build Coastguard Worker   } else
4399*9880d681SAndroid Build Coastguard Worker     memcpy(&cro, r, sizeof(struct class_ro64_t));
4400*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4401*9880d681SAndroid Build Coastguard Worker     swapStruct(cro);
4402*9880d681SAndroid Build Coastguard Worker   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
4403*9880d681SAndroid Build Coastguard Worker   if (cro.flags & RO_META)
4404*9880d681SAndroid Build Coastguard Worker     outs() << " RO_META";
4405*9880d681SAndroid Build Coastguard Worker   if (cro.flags & RO_ROOT)
4406*9880d681SAndroid Build Coastguard Worker     outs() << " RO_ROOT";
4407*9880d681SAndroid Build Coastguard Worker   if (cro.flags & RO_HAS_CXX_STRUCTORS)
4408*9880d681SAndroid Build Coastguard Worker     outs() << " RO_HAS_CXX_STRUCTORS";
4409*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4410*9880d681SAndroid Build Coastguard Worker   outs() << "            instanceStart " << cro.instanceStart << "\n";
4411*9880d681SAndroid Build Coastguard Worker   outs() << "             instanceSize " << cro.instanceSize << "\n";
4412*9880d681SAndroid Build Coastguard Worker   outs() << "                 reserved " << format("0x%" PRIx32, cro.reserved)
4413*9880d681SAndroid Build Coastguard Worker          << "\n";
4414*9880d681SAndroid Build Coastguard Worker   outs() << "               ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
4415*9880d681SAndroid Build Coastguard Worker          << "\n";
4416*9880d681SAndroid Build Coastguard Worker   print_layout_map64(cro.ivarLayout, info);
4417*9880d681SAndroid Build Coastguard Worker 
4418*9880d681SAndroid Build Coastguard Worker   outs() << "                     name ";
4419*9880d681SAndroid Build Coastguard Worker   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
4420*9880d681SAndroid Build Coastguard Worker                            info, n_value, cro.name);
4421*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4422*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4423*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4424*9880d681SAndroid Build Coastguard Worker     else
4425*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4426*9880d681SAndroid Build Coastguard Worker     if (cro.name != 0)
4427*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, cro.name);
4428*9880d681SAndroid Build Coastguard Worker   } else
4429*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, cro.name);
4430*9880d681SAndroid Build Coastguard Worker   name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
4431*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4432*9880d681SAndroid Build Coastguard Worker     outs() << format(" %.*s", left, name);
4433*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4434*9880d681SAndroid Build Coastguard Worker 
4435*9880d681SAndroid Build Coastguard Worker   outs() << "              baseMethods ";
4436*9880d681SAndroid Build Coastguard Worker   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
4437*9880d681SAndroid Build Coastguard Worker                            S, info, n_value, cro.baseMethods);
4438*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4439*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4440*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4441*9880d681SAndroid Build Coastguard Worker     else
4442*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4443*9880d681SAndroid Build Coastguard Worker     if (cro.baseMethods != 0)
4444*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
4445*9880d681SAndroid Build Coastguard Worker   } else
4446*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, cro.baseMethods);
4447*9880d681SAndroid Build Coastguard Worker   outs() << " (struct method_list_t *)\n";
4448*9880d681SAndroid Build Coastguard Worker   if (cro.baseMethods + n_value != 0)
4449*9880d681SAndroid Build Coastguard Worker     print_method_list64_t(cro.baseMethods + n_value, info, "");
4450*9880d681SAndroid Build Coastguard Worker 
4451*9880d681SAndroid Build Coastguard Worker   outs() << "            baseProtocols ";
4452*9880d681SAndroid Build Coastguard Worker   sym_name =
4453*9880d681SAndroid Build Coastguard Worker       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
4454*9880d681SAndroid Build Coastguard Worker                     info, n_value, cro.baseProtocols);
4455*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4456*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4457*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4458*9880d681SAndroid Build Coastguard Worker     else
4459*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4460*9880d681SAndroid Build Coastguard Worker     if (cro.baseProtocols != 0)
4461*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
4462*9880d681SAndroid Build Coastguard Worker   } else
4463*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, cro.baseProtocols);
4464*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4465*9880d681SAndroid Build Coastguard Worker   if (cro.baseProtocols + n_value != 0)
4466*9880d681SAndroid Build Coastguard Worker     print_protocol_list64_t(cro.baseProtocols + n_value, info);
4467*9880d681SAndroid Build Coastguard Worker 
4468*9880d681SAndroid Build Coastguard Worker   outs() << "                    ivars ";
4469*9880d681SAndroid Build Coastguard Worker   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
4470*9880d681SAndroid Build Coastguard Worker                            info, n_value, cro.ivars);
4471*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4472*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4473*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4474*9880d681SAndroid Build Coastguard Worker     else
4475*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4476*9880d681SAndroid Build Coastguard Worker     if (cro.ivars != 0)
4477*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, cro.ivars);
4478*9880d681SAndroid Build Coastguard Worker   } else
4479*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, cro.ivars);
4480*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4481*9880d681SAndroid Build Coastguard Worker   if (cro.ivars + n_value != 0)
4482*9880d681SAndroid Build Coastguard Worker     print_ivar_list64_t(cro.ivars + n_value, info);
4483*9880d681SAndroid Build Coastguard Worker 
4484*9880d681SAndroid Build Coastguard Worker   outs() << "           weakIvarLayout ";
4485*9880d681SAndroid Build Coastguard Worker   sym_name =
4486*9880d681SAndroid Build Coastguard Worker       get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
4487*9880d681SAndroid Build Coastguard Worker                     info, n_value, cro.weakIvarLayout);
4488*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4489*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4490*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4491*9880d681SAndroid Build Coastguard Worker     else
4492*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4493*9880d681SAndroid Build Coastguard Worker     if (cro.weakIvarLayout != 0)
4494*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
4495*9880d681SAndroid Build Coastguard Worker   } else
4496*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, cro.weakIvarLayout);
4497*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4498*9880d681SAndroid Build Coastguard Worker   print_layout_map64(cro.weakIvarLayout + n_value, info);
4499*9880d681SAndroid Build Coastguard Worker 
4500*9880d681SAndroid Build Coastguard Worker   outs() << "           baseProperties ";
4501*9880d681SAndroid Build Coastguard Worker   sym_name =
4502*9880d681SAndroid Build Coastguard Worker       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
4503*9880d681SAndroid Build Coastguard Worker                     info, n_value, cro.baseProperties);
4504*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4505*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4506*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4507*9880d681SAndroid Build Coastguard Worker     else
4508*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4509*9880d681SAndroid Build Coastguard Worker     if (cro.baseProperties != 0)
4510*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
4511*9880d681SAndroid Build Coastguard Worker   } else
4512*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, cro.baseProperties);
4513*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4514*9880d681SAndroid Build Coastguard Worker   if (cro.baseProperties + n_value != 0)
4515*9880d681SAndroid Build Coastguard Worker     print_objc_property_list64(cro.baseProperties + n_value, info);
4516*9880d681SAndroid Build Coastguard Worker 
4517*9880d681SAndroid Build Coastguard Worker   is_meta_class = (cro.flags & RO_META) != 0;
4518*9880d681SAndroid Build Coastguard Worker   return true;
4519*9880d681SAndroid Build Coastguard Worker }
4520*9880d681SAndroid Build Coastguard Worker 
print_class_ro32_t(uint32_t p,struct DisassembleInfo * info,bool & is_meta_class)4521*9880d681SAndroid Build Coastguard Worker static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
4522*9880d681SAndroid Build Coastguard Worker                                bool &is_meta_class) {
4523*9880d681SAndroid Build Coastguard Worker   struct class_ro32_t cro;
4524*9880d681SAndroid Build Coastguard Worker   const char *r;
4525*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left;
4526*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
4527*9880d681SAndroid Build Coastguard Worker   const char *name;
4528*9880d681SAndroid Build Coastguard Worker 
4529*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
4530*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
4531*9880d681SAndroid Build Coastguard Worker     return false;
4532*9880d681SAndroid Build Coastguard Worker   memset(&cro, '\0', sizeof(struct class_ro32_t));
4533*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct class_ro32_t)) {
4534*9880d681SAndroid Build Coastguard Worker     memcpy(&cro, r, left);
4535*9880d681SAndroid Build Coastguard Worker     outs() << "   (class_ro_t entends past the end of the section)\n";
4536*9880d681SAndroid Build Coastguard Worker   } else
4537*9880d681SAndroid Build Coastguard Worker     memcpy(&cro, r, sizeof(struct class_ro32_t));
4538*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4539*9880d681SAndroid Build Coastguard Worker     swapStruct(cro);
4540*9880d681SAndroid Build Coastguard Worker   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
4541*9880d681SAndroid Build Coastguard Worker   if (cro.flags & RO_META)
4542*9880d681SAndroid Build Coastguard Worker     outs() << " RO_META";
4543*9880d681SAndroid Build Coastguard Worker   if (cro.flags & RO_ROOT)
4544*9880d681SAndroid Build Coastguard Worker     outs() << " RO_ROOT";
4545*9880d681SAndroid Build Coastguard Worker   if (cro.flags & RO_HAS_CXX_STRUCTORS)
4546*9880d681SAndroid Build Coastguard Worker     outs() << " RO_HAS_CXX_STRUCTORS";
4547*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4548*9880d681SAndroid Build Coastguard Worker   outs() << "            instanceStart " << cro.instanceStart << "\n";
4549*9880d681SAndroid Build Coastguard Worker   outs() << "             instanceSize " << cro.instanceSize << "\n";
4550*9880d681SAndroid Build Coastguard Worker   outs() << "               ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
4551*9880d681SAndroid Build Coastguard Worker          << "\n";
4552*9880d681SAndroid Build Coastguard Worker   print_layout_map32(cro.ivarLayout, info);
4553*9880d681SAndroid Build Coastguard Worker 
4554*9880d681SAndroid Build Coastguard Worker   outs() << "                     name " << format("0x%" PRIx32, cro.name);
4555*9880d681SAndroid Build Coastguard Worker   name = get_pointer_32(cro.name, xoffset, left, xS, info);
4556*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4557*9880d681SAndroid Build Coastguard Worker     outs() << format(" %.*s", left, name);
4558*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4559*9880d681SAndroid Build Coastguard Worker 
4560*9880d681SAndroid Build Coastguard Worker   outs() << "              baseMethods "
4561*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, cro.baseMethods)
4562*9880d681SAndroid Build Coastguard Worker          << " (struct method_list_t *)\n";
4563*9880d681SAndroid Build Coastguard Worker   if (cro.baseMethods != 0)
4564*9880d681SAndroid Build Coastguard Worker     print_method_list32_t(cro.baseMethods, info, "");
4565*9880d681SAndroid Build Coastguard Worker 
4566*9880d681SAndroid Build Coastguard Worker   outs() << "            baseProtocols "
4567*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, cro.baseProtocols) << "\n";
4568*9880d681SAndroid Build Coastguard Worker   if (cro.baseProtocols != 0)
4569*9880d681SAndroid Build Coastguard Worker     print_protocol_list32_t(cro.baseProtocols, info);
4570*9880d681SAndroid Build Coastguard Worker   outs() << "                    ivars " << format("0x%" PRIx32, cro.ivars)
4571*9880d681SAndroid Build Coastguard Worker          << "\n";
4572*9880d681SAndroid Build Coastguard Worker   if (cro.ivars != 0)
4573*9880d681SAndroid Build Coastguard Worker     print_ivar_list32_t(cro.ivars, info);
4574*9880d681SAndroid Build Coastguard Worker   outs() << "           weakIvarLayout "
4575*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
4576*9880d681SAndroid Build Coastguard Worker   print_layout_map32(cro.weakIvarLayout, info);
4577*9880d681SAndroid Build Coastguard Worker   outs() << "           baseProperties "
4578*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, cro.baseProperties) << "\n";
4579*9880d681SAndroid Build Coastguard Worker   if (cro.baseProperties != 0)
4580*9880d681SAndroid Build Coastguard Worker     print_objc_property_list32(cro.baseProperties, info);
4581*9880d681SAndroid Build Coastguard Worker   is_meta_class = (cro.flags & RO_META) != 0;
4582*9880d681SAndroid Build Coastguard Worker   return true;
4583*9880d681SAndroid Build Coastguard Worker }
4584*9880d681SAndroid Build Coastguard Worker 
print_class64_t(uint64_t p,struct DisassembleInfo * info)4585*9880d681SAndroid Build Coastguard Worker static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
4586*9880d681SAndroid Build Coastguard Worker   struct class64_t c;
4587*9880d681SAndroid Build Coastguard Worker   const char *r;
4588*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
4589*9880d681SAndroid Build Coastguard Worker   SectionRef S;
4590*9880d681SAndroid Build Coastguard Worker   const char *name;
4591*9880d681SAndroid Build Coastguard Worker   uint64_t isa_n_value, n_value;
4592*9880d681SAndroid Build Coastguard Worker 
4593*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(p, offset, left, S, info);
4594*9880d681SAndroid Build Coastguard Worker   if (r == nullptr || left < sizeof(struct class64_t))
4595*9880d681SAndroid Build Coastguard Worker     return;
4596*9880d681SAndroid Build Coastguard Worker   memset(&c, '\0', sizeof(struct class64_t));
4597*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct class64_t)) {
4598*9880d681SAndroid Build Coastguard Worker     memcpy(&c, r, left);
4599*9880d681SAndroid Build Coastguard Worker     outs() << "   (class_t entends past the end of the section)\n";
4600*9880d681SAndroid Build Coastguard Worker   } else
4601*9880d681SAndroid Build Coastguard Worker     memcpy(&c, r, sizeof(struct class64_t));
4602*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4603*9880d681SAndroid Build Coastguard Worker     swapStruct(c);
4604*9880d681SAndroid Build Coastguard Worker 
4605*9880d681SAndroid Build Coastguard Worker   outs() << "           isa " << format("0x%" PRIx64, c.isa);
4606*9880d681SAndroid Build Coastguard Worker   name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
4607*9880d681SAndroid Build Coastguard Worker                        isa_n_value, c.isa);
4608*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4609*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
4610*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4611*9880d681SAndroid Build Coastguard Worker 
4612*9880d681SAndroid Build Coastguard Worker   outs() << "    superclass " << format("0x%" PRIx64, c.superclass);
4613*9880d681SAndroid Build Coastguard Worker   name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
4614*9880d681SAndroid Build Coastguard Worker                        n_value, c.superclass);
4615*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4616*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
4617*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4618*9880d681SAndroid Build Coastguard Worker 
4619*9880d681SAndroid Build Coastguard Worker   outs() << "         cache " << format("0x%" PRIx64, c.cache);
4620*9880d681SAndroid Build Coastguard Worker   name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
4621*9880d681SAndroid Build Coastguard Worker                        n_value, c.cache);
4622*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4623*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
4624*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4625*9880d681SAndroid Build Coastguard Worker 
4626*9880d681SAndroid Build Coastguard Worker   outs() << "        vtable " << format("0x%" PRIx64, c.vtable);
4627*9880d681SAndroid Build Coastguard Worker   name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
4628*9880d681SAndroid Build Coastguard Worker                        n_value, c.vtable);
4629*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4630*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
4631*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4632*9880d681SAndroid Build Coastguard Worker 
4633*9880d681SAndroid Build Coastguard Worker   name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
4634*9880d681SAndroid Build Coastguard Worker                        n_value, c.data);
4635*9880d681SAndroid Build Coastguard Worker   outs() << "          data ";
4636*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4637*9880d681SAndroid Build Coastguard Worker     if (info->verbose && name != nullptr)
4638*9880d681SAndroid Build Coastguard Worker       outs() << name;
4639*9880d681SAndroid Build Coastguard Worker     else
4640*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4641*9880d681SAndroid Build Coastguard Worker     if (c.data != 0)
4642*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, c.data);
4643*9880d681SAndroid Build Coastguard Worker   } else
4644*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, c.data);
4645*9880d681SAndroid Build Coastguard Worker   outs() << " (struct class_ro_t *)";
4646*9880d681SAndroid Build Coastguard Worker 
4647*9880d681SAndroid Build Coastguard Worker   // This is a Swift class if some of the low bits of the pointer are set.
4648*9880d681SAndroid Build Coastguard Worker   if ((c.data + n_value) & 0x7)
4649*9880d681SAndroid Build Coastguard Worker     outs() << " Swift class";
4650*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4651*9880d681SAndroid Build Coastguard Worker   bool is_meta_class;
4652*9880d681SAndroid Build Coastguard Worker   if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
4653*9880d681SAndroid Build Coastguard Worker     return;
4654*9880d681SAndroid Build Coastguard Worker 
4655*9880d681SAndroid Build Coastguard Worker   if (!is_meta_class &&
4656*9880d681SAndroid Build Coastguard Worker       c.isa + isa_n_value != p &&
4657*9880d681SAndroid Build Coastguard Worker       c.isa + isa_n_value != 0 &&
4658*9880d681SAndroid Build Coastguard Worker       info->depth < 100) {
4659*9880d681SAndroid Build Coastguard Worker       info->depth++;
4660*9880d681SAndroid Build Coastguard Worker       outs() << "Meta Class\n";
4661*9880d681SAndroid Build Coastguard Worker       print_class64_t(c.isa + isa_n_value, info);
4662*9880d681SAndroid Build Coastguard Worker   }
4663*9880d681SAndroid Build Coastguard Worker }
4664*9880d681SAndroid Build Coastguard Worker 
print_class32_t(uint32_t p,struct DisassembleInfo * info)4665*9880d681SAndroid Build Coastguard Worker static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
4666*9880d681SAndroid Build Coastguard Worker   struct class32_t c;
4667*9880d681SAndroid Build Coastguard Worker   const char *r;
4668*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
4669*9880d681SAndroid Build Coastguard Worker   SectionRef S;
4670*9880d681SAndroid Build Coastguard Worker   const char *name;
4671*9880d681SAndroid Build Coastguard Worker 
4672*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
4673*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
4674*9880d681SAndroid Build Coastguard Worker     return;
4675*9880d681SAndroid Build Coastguard Worker   memset(&c, '\0', sizeof(struct class32_t));
4676*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct class32_t)) {
4677*9880d681SAndroid Build Coastguard Worker     memcpy(&c, r, left);
4678*9880d681SAndroid Build Coastguard Worker     outs() << "   (class_t entends past the end of the section)\n";
4679*9880d681SAndroid Build Coastguard Worker   } else
4680*9880d681SAndroid Build Coastguard Worker     memcpy(&c, r, sizeof(struct class32_t));
4681*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4682*9880d681SAndroid Build Coastguard Worker     swapStruct(c);
4683*9880d681SAndroid Build Coastguard Worker 
4684*9880d681SAndroid Build Coastguard Worker   outs() << "           isa " << format("0x%" PRIx32, c.isa);
4685*9880d681SAndroid Build Coastguard Worker   name =
4686*9880d681SAndroid Build Coastguard Worker       get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
4687*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4688*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
4689*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4690*9880d681SAndroid Build Coastguard Worker 
4691*9880d681SAndroid Build Coastguard Worker   outs() << "    superclass " << format("0x%" PRIx32, c.superclass);
4692*9880d681SAndroid Build Coastguard Worker   name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
4693*9880d681SAndroid Build Coastguard Worker                        c.superclass);
4694*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4695*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
4696*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4697*9880d681SAndroid Build Coastguard Worker 
4698*9880d681SAndroid Build Coastguard Worker   outs() << "         cache " << format("0x%" PRIx32, c.cache);
4699*9880d681SAndroid Build Coastguard Worker   name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
4700*9880d681SAndroid Build Coastguard Worker                        c.cache);
4701*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4702*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
4703*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4704*9880d681SAndroid Build Coastguard Worker 
4705*9880d681SAndroid Build Coastguard Worker   outs() << "        vtable " << format("0x%" PRIx32, c.vtable);
4706*9880d681SAndroid Build Coastguard Worker   name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
4707*9880d681SAndroid Build Coastguard Worker                        c.vtable);
4708*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4709*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
4710*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4711*9880d681SAndroid Build Coastguard Worker 
4712*9880d681SAndroid Build Coastguard Worker   name =
4713*9880d681SAndroid Build Coastguard Worker       get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
4714*9880d681SAndroid Build Coastguard Worker   outs() << "          data " << format("0x%" PRIx32, c.data)
4715*9880d681SAndroid Build Coastguard Worker          << " (struct class_ro_t *)";
4716*9880d681SAndroid Build Coastguard Worker 
4717*9880d681SAndroid Build Coastguard Worker   // This is a Swift class if some of the low bits of the pointer are set.
4718*9880d681SAndroid Build Coastguard Worker   if (c.data & 0x3)
4719*9880d681SAndroid Build Coastguard Worker     outs() << " Swift class";
4720*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4721*9880d681SAndroid Build Coastguard Worker   bool is_meta_class;
4722*9880d681SAndroid Build Coastguard Worker   if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
4723*9880d681SAndroid Build Coastguard Worker     return;
4724*9880d681SAndroid Build Coastguard Worker 
4725*9880d681SAndroid Build Coastguard Worker   if (!is_meta_class) {
4726*9880d681SAndroid Build Coastguard Worker     outs() << "Meta Class\n";
4727*9880d681SAndroid Build Coastguard Worker     print_class32_t(c.isa, info);
4728*9880d681SAndroid Build Coastguard Worker   }
4729*9880d681SAndroid Build Coastguard Worker }
4730*9880d681SAndroid Build Coastguard Worker 
print_objc_class_t(struct objc_class_t * objc_class,struct DisassembleInfo * info)4731*9880d681SAndroid Build Coastguard Worker static void print_objc_class_t(struct objc_class_t *objc_class,
4732*9880d681SAndroid Build Coastguard Worker                                struct DisassembleInfo *info) {
4733*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left, xleft;
4734*9880d681SAndroid Build Coastguard Worker   const char *name, *p, *ivar_list;
4735*9880d681SAndroid Build Coastguard Worker   SectionRef S;
4736*9880d681SAndroid Build Coastguard Worker   int32_t i;
4737*9880d681SAndroid Build Coastguard Worker   struct objc_ivar_list_t objc_ivar_list;
4738*9880d681SAndroid Build Coastguard Worker   struct objc_ivar_t ivar;
4739*9880d681SAndroid Build Coastguard Worker 
4740*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t      isa " << format("0x%08" PRIx32, objc_class->isa);
4741*9880d681SAndroid Build Coastguard Worker   if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
4742*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
4743*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4744*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4745*9880d681SAndroid Build Coastguard Worker     else
4746*9880d681SAndroid Build Coastguard Worker       outs() << " (not in an __OBJC section)";
4747*9880d681SAndroid Build Coastguard Worker   }
4748*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4749*9880d681SAndroid Build Coastguard Worker 
4750*9880d681SAndroid Build Coastguard Worker   outs() << "\t      super_class "
4751*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, objc_class->super_class);
4752*9880d681SAndroid Build Coastguard Worker   if (info->verbose) {
4753*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
4754*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4755*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4756*9880d681SAndroid Build Coastguard Worker     else
4757*9880d681SAndroid Build Coastguard Worker       outs() << " (not in an __OBJC section)";
4758*9880d681SAndroid Build Coastguard Worker   }
4759*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4760*9880d681SAndroid Build Coastguard Worker 
4761*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t     name " << format("0x%08" PRIx32, objc_class->name);
4762*9880d681SAndroid Build Coastguard Worker   if (info->verbose) {
4763*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(objc_class->name, offset, left, S, info, true);
4764*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4765*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4766*9880d681SAndroid Build Coastguard Worker     else
4767*9880d681SAndroid Build Coastguard Worker       outs() << " (not in an __OBJC section)";
4768*9880d681SAndroid Build Coastguard Worker   }
4769*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4770*9880d681SAndroid Build Coastguard Worker 
4771*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t  version " << format("0x%08" PRIx32, objc_class->version)
4772*9880d681SAndroid Build Coastguard Worker          << "\n";
4773*9880d681SAndroid Build Coastguard Worker 
4774*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t     info " << format("0x%08" PRIx32, objc_class->info);
4775*9880d681SAndroid Build Coastguard Worker   if (info->verbose) {
4776*9880d681SAndroid Build Coastguard Worker     if (CLS_GETINFO(objc_class, CLS_CLASS))
4777*9880d681SAndroid Build Coastguard Worker       outs() << " CLS_CLASS";
4778*9880d681SAndroid Build Coastguard Worker     else if (CLS_GETINFO(objc_class, CLS_META))
4779*9880d681SAndroid Build Coastguard Worker       outs() << " CLS_META";
4780*9880d681SAndroid Build Coastguard Worker   }
4781*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4782*9880d681SAndroid Build Coastguard Worker 
4783*9880d681SAndroid Build Coastguard Worker   outs() << "\t    instance_size "
4784*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
4785*9880d681SAndroid Build Coastguard Worker 
4786*9880d681SAndroid Build Coastguard Worker   p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
4787*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t    ivars " << format("0x%08" PRIx32, objc_class->ivars);
4788*9880d681SAndroid Build Coastguard Worker   if (p != nullptr) {
4789*9880d681SAndroid Build Coastguard Worker     if (left > sizeof(struct objc_ivar_list_t)) {
4790*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
4791*9880d681SAndroid Build Coastguard Worker       memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
4792*9880d681SAndroid Build Coastguard Worker     } else {
4793*9880d681SAndroid Build Coastguard Worker       outs() << " (entends past the end of the section)\n";
4794*9880d681SAndroid Build Coastguard Worker       memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
4795*9880d681SAndroid Build Coastguard Worker       memcpy(&objc_ivar_list, p, left);
4796*9880d681SAndroid Build Coastguard Worker     }
4797*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4798*9880d681SAndroid Build Coastguard Worker       swapStruct(objc_ivar_list);
4799*9880d681SAndroid Build Coastguard Worker     outs() << "\t\t       ivar_count " << objc_ivar_list.ivar_count << "\n";
4800*9880d681SAndroid Build Coastguard Worker     ivar_list = p + sizeof(struct objc_ivar_list_t);
4801*9880d681SAndroid Build Coastguard Worker     for (i = 0; i < objc_ivar_list.ivar_count; i++) {
4802*9880d681SAndroid Build Coastguard Worker       if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
4803*9880d681SAndroid Build Coastguard Worker         outs() << "\t\t remaining ivar's extend past the of the section\n";
4804*9880d681SAndroid Build Coastguard Worker         break;
4805*9880d681SAndroid Build Coastguard Worker       }
4806*9880d681SAndroid Build Coastguard Worker       memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
4807*9880d681SAndroid Build Coastguard Worker              sizeof(struct objc_ivar_t));
4808*9880d681SAndroid Build Coastguard Worker       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4809*9880d681SAndroid Build Coastguard Worker         swapStruct(ivar);
4810*9880d681SAndroid Build Coastguard Worker 
4811*9880d681SAndroid Build Coastguard Worker       outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
4812*9880d681SAndroid Build Coastguard Worker       if (info->verbose) {
4813*9880d681SAndroid Build Coastguard Worker         name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
4814*9880d681SAndroid Build Coastguard Worker         if (name != nullptr)
4815*9880d681SAndroid Build Coastguard Worker           outs() << format(" %.*s", xleft, name);
4816*9880d681SAndroid Build Coastguard Worker         else
4817*9880d681SAndroid Build Coastguard Worker           outs() << " (not in an __OBJC section)";
4818*9880d681SAndroid Build Coastguard Worker       }
4819*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
4820*9880d681SAndroid Build Coastguard Worker 
4821*9880d681SAndroid Build Coastguard Worker       outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
4822*9880d681SAndroid Build Coastguard Worker       if (info->verbose) {
4823*9880d681SAndroid Build Coastguard Worker         name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
4824*9880d681SAndroid Build Coastguard Worker         if (name != nullptr)
4825*9880d681SAndroid Build Coastguard Worker           outs() << format(" %.*s", xleft, name);
4826*9880d681SAndroid Build Coastguard Worker         else
4827*9880d681SAndroid Build Coastguard Worker           outs() << " (not in an __OBJC section)";
4828*9880d681SAndroid Build Coastguard Worker       }
4829*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
4830*9880d681SAndroid Build Coastguard Worker 
4831*9880d681SAndroid Build Coastguard Worker       outs() << "\t\t      ivar_offset "
4832*9880d681SAndroid Build Coastguard Worker              << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
4833*9880d681SAndroid Build Coastguard Worker     }
4834*9880d681SAndroid Build Coastguard Worker   } else {
4835*9880d681SAndroid Build Coastguard Worker     outs() << " (not in an __OBJC section)\n";
4836*9880d681SAndroid Build Coastguard Worker   }
4837*9880d681SAndroid Build Coastguard Worker 
4838*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t  methods " << format("0x%08" PRIx32, objc_class->methodLists);
4839*9880d681SAndroid Build Coastguard Worker   if (print_method_list(objc_class->methodLists, info))
4840*9880d681SAndroid Build Coastguard Worker     outs() << " (not in an __OBJC section)\n";
4841*9880d681SAndroid Build Coastguard Worker 
4842*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t    cache " << format("0x%08" PRIx32, objc_class->cache)
4843*9880d681SAndroid Build Coastguard Worker          << "\n";
4844*9880d681SAndroid Build Coastguard Worker 
4845*9880d681SAndroid Build Coastguard Worker   outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
4846*9880d681SAndroid Build Coastguard Worker   if (print_protocol_list(objc_class->protocols, 16, info))
4847*9880d681SAndroid Build Coastguard Worker     outs() << " (not in an __OBJC section)\n";
4848*9880d681SAndroid Build Coastguard Worker }
4849*9880d681SAndroid Build Coastguard Worker 
print_objc_objc_category_t(struct objc_category_t * objc_category,struct DisassembleInfo * info)4850*9880d681SAndroid Build Coastguard Worker static void print_objc_objc_category_t(struct objc_category_t *objc_category,
4851*9880d681SAndroid Build Coastguard Worker                                        struct DisassembleInfo *info) {
4852*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
4853*9880d681SAndroid Build Coastguard Worker   const char *name;
4854*9880d681SAndroid Build Coastguard Worker   SectionRef S;
4855*9880d681SAndroid Build Coastguard Worker 
4856*9880d681SAndroid Build Coastguard Worker   outs() << "\t       category name "
4857*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, objc_category->category_name);
4858*9880d681SAndroid Build Coastguard Worker   if (info->verbose) {
4859*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(objc_category->category_name, offset, left, S, info,
4860*9880d681SAndroid Build Coastguard Worker                           true);
4861*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4862*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4863*9880d681SAndroid Build Coastguard Worker     else
4864*9880d681SAndroid Build Coastguard Worker       outs() << " (not in an __OBJC section)";
4865*9880d681SAndroid Build Coastguard Worker   }
4866*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4867*9880d681SAndroid Build Coastguard Worker 
4868*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t  class name "
4869*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, objc_category->class_name);
4870*9880d681SAndroid Build Coastguard Worker   if (info->verbose) {
4871*9880d681SAndroid Build Coastguard Worker     name =
4872*9880d681SAndroid Build Coastguard Worker         get_pointer_32(objc_category->class_name, offset, left, S, info, true);
4873*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
4874*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
4875*9880d681SAndroid Build Coastguard Worker     else
4876*9880d681SAndroid Build Coastguard Worker       outs() << " (not in an __OBJC section)";
4877*9880d681SAndroid Build Coastguard Worker   }
4878*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4879*9880d681SAndroid Build Coastguard Worker 
4880*9880d681SAndroid Build Coastguard Worker   outs() << "\t    instance methods "
4881*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, objc_category->instance_methods);
4882*9880d681SAndroid Build Coastguard Worker   if (print_method_list(objc_category->instance_methods, info))
4883*9880d681SAndroid Build Coastguard Worker     outs() << " (not in an __OBJC section)\n";
4884*9880d681SAndroid Build Coastguard Worker 
4885*9880d681SAndroid Build Coastguard Worker   outs() << "\t       class methods "
4886*9880d681SAndroid Build Coastguard Worker          << format("0x%08" PRIx32, objc_category->class_methods);
4887*9880d681SAndroid Build Coastguard Worker   if (print_method_list(objc_category->class_methods, info))
4888*9880d681SAndroid Build Coastguard Worker     outs() << " (not in an __OBJC section)\n";
4889*9880d681SAndroid Build Coastguard Worker }
4890*9880d681SAndroid Build Coastguard Worker 
print_category64_t(uint64_t p,struct DisassembleInfo * info)4891*9880d681SAndroid Build Coastguard Worker static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
4892*9880d681SAndroid Build Coastguard Worker   struct category64_t c;
4893*9880d681SAndroid Build Coastguard Worker   const char *r;
4894*9880d681SAndroid Build Coastguard Worker   uint32_t offset, xoffset, left;
4895*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
4896*9880d681SAndroid Build Coastguard Worker   const char *name, *sym_name;
4897*9880d681SAndroid Build Coastguard Worker   uint64_t n_value;
4898*9880d681SAndroid Build Coastguard Worker 
4899*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(p, offset, left, S, info);
4900*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
4901*9880d681SAndroid Build Coastguard Worker     return;
4902*9880d681SAndroid Build Coastguard Worker   memset(&c, '\0', sizeof(struct category64_t));
4903*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct category64_t)) {
4904*9880d681SAndroid Build Coastguard Worker     memcpy(&c, r, left);
4905*9880d681SAndroid Build Coastguard Worker     outs() << "   (category_t entends past the end of the section)\n";
4906*9880d681SAndroid Build Coastguard Worker   } else
4907*9880d681SAndroid Build Coastguard Worker     memcpy(&c, r, sizeof(struct category64_t));
4908*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4909*9880d681SAndroid Build Coastguard Worker     swapStruct(c);
4910*9880d681SAndroid Build Coastguard Worker 
4911*9880d681SAndroid Build Coastguard Worker   outs() << "              name ";
4912*9880d681SAndroid Build Coastguard Worker   sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
4913*9880d681SAndroid Build Coastguard Worker                            info, n_value, c.name);
4914*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4915*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4916*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4917*9880d681SAndroid Build Coastguard Worker     else
4918*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4919*9880d681SAndroid Build Coastguard Worker     if (c.name != 0)
4920*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, c.name);
4921*9880d681SAndroid Build Coastguard Worker   } else
4922*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, c.name);
4923*9880d681SAndroid Build Coastguard Worker   name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
4924*9880d681SAndroid Build Coastguard Worker   if (name != nullptr)
4925*9880d681SAndroid Build Coastguard Worker     outs() << format(" %.*s", left, name);
4926*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4927*9880d681SAndroid Build Coastguard Worker 
4928*9880d681SAndroid Build Coastguard Worker   outs() << "               cls ";
4929*9880d681SAndroid Build Coastguard Worker   sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
4930*9880d681SAndroid Build Coastguard Worker                            n_value, c.cls);
4931*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4932*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4933*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4934*9880d681SAndroid Build Coastguard Worker     else
4935*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4936*9880d681SAndroid Build Coastguard Worker     if (c.cls != 0)
4937*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, c.cls);
4938*9880d681SAndroid Build Coastguard Worker   } else
4939*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, c.cls);
4940*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4941*9880d681SAndroid Build Coastguard Worker   if (c.cls + n_value != 0)
4942*9880d681SAndroid Build Coastguard Worker     print_class64_t(c.cls + n_value, info);
4943*9880d681SAndroid Build Coastguard Worker 
4944*9880d681SAndroid Build Coastguard Worker   outs() << "   instanceMethods ";
4945*9880d681SAndroid Build Coastguard Worker   sym_name =
4946*9880d681SAndroid Build Coastguard Worker       get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
4947*9880d681SAndroid Build Coastguard Worker                     info, n_value, c.instanceMethods);
4948*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4949*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4950*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4951*9880d681SAndroid Build Coastguard Worker     else
4952*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4953*9880d681SAndroid Build Coastguard Worker     if (c.instanceMethods != 0)
4954*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
4955*9880d681SAndroid Build Coastguard Worker   } else
4956*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, c.instanceMethods);
4957*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4958*9880d681SAndroid Build Coastguard Worker   if (c.instanceMethods + n_value != 0)
4959*9880d681SAndroid Build Coastguard Worker     print_method_list64_t(c.instanceMethods + n_value, info, "");
4960*9880d681SAndroid Build Coastguard Worker 
4961*9880d681SAndroid Build Coastguard Worker   outs() << "      classMethods ";
4962*9880d681SAndroid Build Coastguard Worker   sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
4963*9880d681SAndroid Build Coastguard Worker                            S, info, n_value, c.classMethods);
4964*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4965*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4966*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4967*9880d681SAndroid Build Coastguard Worker     else
4968*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4969*9880d681SAndroid Build Coastguard Worker     if (c.classMethods != 0)
4970*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, c.classMethods);
4971*9880d681SAndroid Build Coastguard Worker   } else
4972*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, c.classMethods);
4973*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4974*9880d681SAndroid Build Coastguard Worker   if (c.classMethods + n_value != 0)
4975*9880d681SAndroid Build Coastguard Worker     print_method_list64_t(c.classMethods + n_value, info, "");
4976*9880d681SAndroid Build Coastguard Worker 
4977*9880d681SAndroid Build Coastguard Worker   outs() << "         protocols ";
4978*9880d681SAndroid Build Coastguard Worker   sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
4979*9880d681SAndroid Build Coastguard Worker                            info, n_value, c.protocols);
4980*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4981*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4982*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
4983*9880d681SAndroid Build Coastguard Worker     else
4984*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
4985*9880d681SAndroid Build Coastguard Worker     if (c.protocols != 0)
4986*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, c.protocols);
4987*9880d681SAndroid Build Coastguard Worker   } else
4988*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, c.protocols);
4989*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
4990*9880d681SAndroid Build Coastguard Worker   if (c.protocols + n_value != 0)
4991*9880d681SAndroid Build Coastguard Worker     print_protocol_list64_t(c.protocols + n_value, info);
4992*9880d681SAndroid Build Coastguard Worker 
4993*9880d681SAndroid Build Coastguard Worker   outs() << "instanceProperties ";
4994*9880d681SAndroid Build Coastguard Worker   sym_name =
4995*9880d681SAndroid Build Coastguard Worker       get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
4996*9880d681SAndroid Build Coastguard Worker                     S, info, n_value, c.instanceProperties);
4997*9880d681SAndroid Build Coastguard Worker   if (n_value != 0) {
4998*9880d681SAndroid Build Coastguard Worker     if (info->verbose && sym_name != nullptr)
4999*9880d681SAndroid Build Coastguard Worker       outs() << sym_name;
5000*9880d681SAndroid Build Coastguard Worker     else
5001*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value);
5002*9880d681SAndroid Build Coastguard Worker     if (c.instanceProperties != 0)
5003*9880d681SAndroid Build Coastguard Worker       outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
5004*9880d681SAndroid Build Coastguard Worker   } else
5005*9880d681SAndroid Build Coastguard Worker     outs() << format("0x%" PRIx64, c.instanceProperties);
5006*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
5007*9880d681SAndroid Build Coastguard Worker   if (c.instanceProperties + n_value != 0)
5008*9880d681SAndroid Build Coastguard Worker     print_objc_property_list64(c.instanceProperties + n_value, info);
5009*9880d681SAndroid Build Coastguard Worker }
5010*9880d681SAndroid Build Coastguard Worker 
print_category32_t(uint32_t p,struct DisassembleInfo * info)5011*9880d681SAndroid Build Coastguard Worker static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
5012*9880d681SAndroid Build Coastguard Worker   struct category32_t c;
5013*9880d681SAndroid Build Coastguard Worker   const char *r;
5014*9880d681SAndroid Build Coastguard Worker   uint32_t offset, left;
5015*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
5016*9880d681SAndroid Build Coastguard Worker   const char *name;
5017*9880d681SAndroid Build Coastguard Worker 
5018*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
5019*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
5020*9880d681SAndroid Build Coastguard Worker     return;
5021*9880d681SAndroid Build Coastguard Worker   memset(&c, '\0', sizeof(struct category32_t));
5022*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct category32_t)) {
5023*9880d681SAndroid Build Coastguard Worker     memcpy(&c, r, left);
5024*9880d681SAndroid Build Coastguard Worker     outs() << "   (category_t entends past the end of the section)\n";
5025*9880d681SAndroid Build Coastguard Worker   } else
5026*9880d681SAndroid Build Coastguard Worker     memcpy(&c, r, sizeof(struct category32_t));
5027*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5028*9880d681SAndroid Build Coastguard Worker     swapStruct(c);
5029*9880d681SAndroid Build Coastguard Worker 
5030*9880d681SAndroid Build Coastguard Worker   outs() << "              name " << format("0x%" PRIx32, c.name);
5031*9880d681SAndroid Build Coastguard Worker   name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
5032*9880d681SAndroid Build Coastguard Worker                        c.name);
5033*9880d681SAndroid Build Coastguard Worker   if (name)
5034*9880d681SAndroid Build Coastguard Worker     outs() << " " << name;
5035*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
5036*9880d681SAndroid Build Coastguard Worker 
5037*9880d681SAndroid Build Coastguard Worker   outs() << "               cls " << format("0x%" PRIx32, c.cls) << "\n";
5038*9880d681SAndroid Build Coastguard Worker   if (c.cls != 0)
5039*9880d681SAndroid Build Coastguard Worker     print_class32_t(c.cls, info);
5040*9880d681SAndroid Build Coastguard Worker   outs() << "   instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
5041*9880d681SAndroid Build Coastguard Worker          << "\n";
5042*9880d681SAndroid Build Coastguard Worker   if (c.instanceMethods != 0)
5043*9880d681SAndroid Build Coastguard Worker     print_method_list32_t(c.instanceMethods, info, "");
5044*9880d681SAndroid Build Coastguard Worker   outs() << "      classMethods " << format("0x%" PRIx32, c.classMethods)
5045*9880d681SAndroid Build Coastguard Worker          << "\n";
5046*9880d681SAndroid Build Coastguard Worker   if (c.classMethods != 0)
5047*9880d681SAndroid Build Coastguard Worker     print_method_list32_t(c.classMethods, info, "");
5048*9880d681SAndroid Build Coastguard Worker   outs() << "         protocols " << format("0x%" PRIx32, c.protocols) << "\n";
5049*9880d681SAndroid Build Coastguard Worker   if (c.protocols != 0)
5050*9880d681SAndroid Build Coastguard Worker     print_protocol_list32_t(c.protocols, info);
5051*9880d681SAndroid Build Coastguard Worker   outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
5052*9880d681SAndroid Build Coastguard Worker          << "\n";
5053*9880d681SAndroid Build Coastguard Worker   if (c.instanceProperties != 0)
5054*9880d681SAndroid Build Coastguard Worker     print_objc_property_list32(c.instanceProperties, info);
5055*9880d681SAndroid Build Coastguard Worker }
5056*9880d681SAndroid Build Coastguard Worker 
print_message_refs64(SectionRef S,struct DisassembleInfo * info)5057*9880d681SAndroid Build Coastguard Worker static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
5058*9880d681SAndroid Build Coastguard Worker   uint32_t i, left, offset, xoffset;
5059*9880d681SAndroid Build Coastguard Worker   uint64_t p, n_value;
5060*9880d681SAndroid Build Coastguard Worker   struct message_ref64 mr;
5061*9880d681SAndroid Build Coastguard Worker   const char *name, *sym_name;
5062*9880d681SAndroid Build Coastguard Worker   const char *r;
5063*9880d681SAndroid Build Coastguard Worker   SectionRef xS;
5064*9880d681SAndroid Build Coastguard Worker 
5065*9880d681SAndroid Build Coastguard Worker   if (S == SectionRef())
5066*9880d681SAndroid Build Coastguard Worker     return;
5067*9880d681SAndroid Build Coastguard Worker 
5068*9880d681SAndroid Build Coastguard Worker   StringRef SectName;
5069*9880d681SAndroid Build Coastguard Worker   S.getName(SectName);
5070*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ref = S.getRawDataRefImpl();
5071*9880d681SAndroid Build Coastguard Worker   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5072*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5073*9880d681SAndroid Build Coastguard Worker   offset = 0;
5074*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5075*9880d681SAndroid Build Coastguard Worker     p = S.getAddress() + i;
5076*9880d681SAndroid Build Coastguard Worker     r = get_pointer_64(p, offset, left, S, info);
5077*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
5078*9880d681SAndroid Build Coastguard Worker       return;
5079*9880d681SAndroid Build Coastguard Worker     memset(&mr, '\0', sizeof(struct message_ref64));
5080*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct message_ref64)) {
5081*9880d681SAndroid Build Coastguard Worker       memcpy(&mr, r, left);
5082*9880d681SAndroid Build Coastguard Worker       outs() << "   (message_ref entends past the end of the section)\n";
5083*9880d681SAndroid Build Coastguard Worker     } else
5084*9880d681SAndroid Build Coastguard Worker       memcpy(&mr, r, sizeof(struct message_ref64));
5085*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5086*9880d681SAndroid Build Coastguard Worker       swapStruct(mr);
5087*9880d681SAndroid Build Coastguard Worker 
5088*9880d681SAndroid Build Coastguard Worker     outs() << "  imp ";
5089*9880d681SAndroid Build Coastguard Worker     name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
5090*9880d681SAndroid Build Coastguard Worker                          n_value, mr.imp);
5091*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
5092*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, n_value) << " ";
5093*9880d681SAndroid Build Coastguard Worker       if (mr.imp != 0)
5094*9880d681SAndroid Build Coastguard Worker         outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
5095*9880d681SAndroid Build Coastguard Worker     } else
5096*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, mr.imp) << " ";
5097*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
5098*9880d681SAndroid Build Coastguard Worker       outs() << " " << name;
5099*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
5100*9880d681SAndroid Build Coastguard Worker 
5101*9880d681SAndroid Build Coastguard Worker     outs() << "  sel ";
5102*9880d681SAndroid Build Coastguard Worker     sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
5103*9880d681SAndroid Build Coastguard Worker                              info, n_value, mr.sel);
5104*9880d681SAndroid Build Coastguard Worker     if (n_value != 0) {
5105*9880d681SAndroid Build Coastguard Worker       if (info->verbose && sym_name != nullptr)
5106*9880d681SAndroid Build Coastguard Worker         outs() << sym_name;
5107*9880d681SAndroid Build Coastguard Worker       else
5108*9880d681SAndroid Build Coastguard Worker         outs() << format("0x%" PRIx64, n_value);
5109*9880d681SAndroid Build Coastguard Worker       if (mr.sel != 0)
5110*9880d681SAndroid Build Coastguard Worker         outs() << " + " << format("0x%" PRIx64, mr.sel);
5111*9880d681SAndroid Build Coastguard Worker     } else
5112*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%" PRIx64, mr.sel);
5113*9880d681SAndroid Build Coastguard Worker     name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
5114*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
5115*9880d681SAndroid Build Coastguard Worker       outs() << format(" %.*s", left, name);
5116*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
5117*9880d681SAndroid Build Coastguard Worker 
5118*9880d681SAndroid Build Coastguard Worker     offset += sizeof(struct message_ref64);
5119*9880d681SAndroid Build Coastguard Worker   }
5120*9880d681SAndroid Build Coastguard Worker }
5121*9880d681SAndroid Build Coastguard Worker 
print_message_refs32(SectionRef S,struct DisassembleInfo * info)5122*9880d681SAndroid Build Coastguard Worker static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
5123*9880d681SAndroid Build Coastguard Worker   uint32_t i, left, offset, xoffset, p;
5124*9880d681SAndroid Build Coastguard Worker   struct message_ref32 mr;
5125*9880d681SAndroid Build Coastguard Worker   const char *name, *r;
5126*9880d681SAndroid Build Coastguard Worker   SectionRef xS;
5127*9880d681SAndroid Build Coastguard Worker 
5128*9880d681SAndroid Build Coastguard Worker   if (S == SectionRef())
5129*9880d681SAndroid Build Coastguard Worker     return;
5130*9880d681SAndroid Build Coastguard Worker 
5131*9880d681SAndroid Build Coastguard Worker   StringRef SectName;
5132*9880d681SAndroid Build Coastguard Worker   S.getName(SectName);
5133*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ref = S.getRawDataRefImpl();
5134*9880d681SAndroid Build Coastguard Worker   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5135*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5136*9880d681SAndroid Build Coastguard Worker   offset = 0;
5137*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5138*9880d681SAndroid Build Coastguard Worker     p = S.getAddress() + i;
5139*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(p, offset, left, S, info);
5140*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
5141*9880d681SAndroid Build Coastguard Worker       return;
5142*9880d681SAndroid Build Coastguard Worker     memset(&mr, '\0', sizeof(struct message_ref32));
5143*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct message_ref32)) {
5144*9880d681SAndroid Build Coastguard Worker       memcpy(&mr, r, left);
5145*9880d681SAndroid Build Coastguard Worker       outs() << "   (message_ref entends past the end of the section)\n";
5146*9880d681SAndroid Build Coastguard Worker     } else
5147*9880d681SAndroid Build Coastguard Worker       memcpy(&mr, r, sizeof(struct message_ref32));
5148*9880d681SAndroid Build Coastguard Worker     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5149*9880d681SAndroid Build Coastguard Worker       swapStruct(mr);
5150*9880d681SAndroid Build Coastguard Worker 
5151*9880d681SAndroid Build Coastguard Worker     outs() << "  imp " << format("0x%" PRIx32, mr.imp);
5152*9880d681SAndroid Build Coastguard Worker     name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
5153*9880d681SAndroid Build Coastguard Worker                          mr.imp);
5154*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
5155*9880d681SAndroid Build Coastguard Worker       outs() << " " << name;
5156*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
5157*9880d681SAndroid Build Coastguard Worker 
5158*9880d681SAndroid Build Coastguard Worker     outs() << "  sel " << format("0x%" PRIx32, mr.sel);
5159*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(mr.sel, xoffset, left, xS, info);
5160*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
5161*9880d681SAndroid Build Coastguard Worker       outs() << " " << name;
5162*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
5163*9880d681SAndroid Build Coastguard Worker 
5164*9880d681SAndroid Build Coastguard Worker     offset += sizeof(struct message_ref32);
5165*9880d681SAndroid Build Coastguard Worker   }
5166*9880d681SAndroid Build Coastguard Worker }
5167*9880d681SAndroid Build Coastguard Worker 
print_image_info64(SectionRef S,struct DisassembleInfo * info)5168*9880d681SAndroid Build Coastguard Worker static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
5169*9880d681SAndroid Build Coastguard Worker   uint32_t left, offset, swift_version;
5170*9880d681SAndroid Build Coastguard Worker   uint64_t p;
5171*9880d681SAndroid Build Coastguard Worker   struct objc_image_info64 o;
5172*9880d681SAndroid Build Coastguard Worker   const char *r;
5173*9880d681SAndroid Build Coastguard Worker 
5174*9880d681SAndroid Build Coastguard Worker   if (S == SectionRef())
5175*9880d681SAndroid Build Coastguard Worker     return;
5176*9880d681SAndroid Build Coastguard Worker 
5177*9880d681SAndroid Build Coastguard Worker   StringRef SectName;
5178*9880d681SAndroid Build Coastguard Worker   S.getName(SectName);
5179*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ref = S.getRawDataRefImpl();
5180*9880d681SAndroid Build Coastguard Worker   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5181*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5182*9880d681SAndroid Build Coastguard Worker   p = S.getAddress();
5183*9880d681SAndroid Build Coastguard Worker   r = get_pointer_64(p, offset, left, S, info);
5184*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
5185*9880d681SAndroid Build Coastguard Worker     return;
5186*9880d681SAndroid Build Coastguard Worker   memset(&o, '\0', sizeof(struct objc_image_info64));
5187*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct objc_image_info64)) {
5188*9880d681SAndroid Build Coastguard Worker     memcpy(&o, r, left);
5189*9880d681SAndroid Build Coastguard Worker     outs() << "   (objc_image_info entends past the end of the section)\n";
5190*9880d681SAndroid Build Coastguard Worker   } else
5191*9880d681SAndroid Build Coastguard Worker     memcpy(&o, r, sizeof(struct objc_image_info64));
5192*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5193*9880d681SAndroid Build Coastguard Worker     swapStruct(o);
5194*9880d681SAndroid Build Coastguard Worker   outs() << "  version " << o.version << "\n";
5195*9880d681SAndroid Build Coastguard Worker   outs() << "    flags " << format("0x%" PRIx32, o.flags);
5196*9880d681SAndroid Build Coastguard Worker   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
5197*9880d681SAndroid Build Coastguard Worker     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5198*9880d681SAndroid Build Coastguard Worker   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
5199*9880d681SAndroid Build Coastguard Worker     outs() << " OBJC_IMAGE_SUPPORTS_GC";
5200*9880d681SAndroid Build Coastguard Worker   swift_version = (o.flags >> 8) & 0xff;
5201*9880d681SAndroid Build Coastguard Worker   if (swift_version != 0) {
5202*9880d681SAndroid Build Coastguard Worker     if (swift_version == 1)
5203*9880d681SAndroid Build Coastguard Worker       outs() << " Swift 1.0";
5204*9880d681SAndroid Build Coastguard Worker     else if (swift_version == 2)
5205*9880d681SAndroid Build Coastguard Worker       outs() << " Swift 1.1";
5206*9880d681SAndroid Build Coastguard Worker     else
5207*9880d681SAndroid Build Coastguard Worker       outs() << " unknown future Swift version (" << swift_version << ")";
5208*9880d681SAndroid Build Coastguard Worker   }
5209*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
5210*9880d681SAndroid Build Coastguard Worker }
5211*9880d681SAndroid Build Coastguard Worker 
print_image_info32(SectionRef S,struct DisassembleInfo * info)5212*9880d681SAndroid Build Coastguard Worker static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
5213*9880d681SAndroid Build Coastguard Worker   uint32_t left, offset, swift_version, p;
5214*9880d681SAndroid Build Coastguard Worker   struct objc_image_info32 o;
5215*9880d681SAndroid Build Coastguard Worker   const char *r;
5216*9880d681SAndroid Build Coastguard Worker 
5217*9880d681SAndroid Build Coastguard Worker   if (S == SectionRef())
5218*9880d681SAndroid Build Coastguard Worker     return;
5219*9880d681SAndroid Build Coastguard Worker 
5220*9880d681SAndroid Build Coastguard Worker   StringRef SectName;
5221*9880d681SAndroid Build Coastguard Worker   S.getName(SectName);
5222*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ref = S.getRawDataRefImpl();
5223*9880d681SAndroid Build Coastguard Worker   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5224*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5225*9880d681SAndroid Build Coastguard Worker   p = S.getAddress();
5226*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
5227*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
5228*9880d681SAndroid Build Coastguard Worker     return;
5229*9880d681SAndroid Build Coastguard Worker   memset(&o, '\0', sizeof(struct objc_image_info32));
5230*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct objc_image_info32)) {
5231*9880d681SAndroid Build Coastguard Worker     memcpy(&o, r, left);
5232*9880d681SAndroid Build Coastguard Worker     outs() << "   (objc_image_info entends past the end of the section)\n";
5233*9880d681SAndroid Build Coastguard Worker   } else
5234*9880d681SAndroid Build Coastguard Worker     memcpy(&o, r, sizeof(struct objc_image_info32));
5235*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5236*9880d681SAndroid Build Coastguard Worker     swapStruct(o);
5237*9880d681SAndroid Build Coastguard Worker   outs() << "  version " << o.version << "\n";
5238*9880d681SAndroid Build Coastguard Worker   outs() << "    flags " << format("0x%" PRIx32, o.flags);
5239*9880d681SAndroid Build Coastguard Worker   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
5240*9880d681SAndroid Build Coastguard Worker     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5241*9880d681SAndroid Build Coastguard Worker   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
5242*9880d681SAndroid Build Coastguard Worker     outs() << " OBJC_IMAGE_SUPPORTS_GC";
5243*9880d681SAndroid Build Coastguard Worker   swift_version = (o.flags >> 8) & 0xff;
5244*9880d681SAndroid Build Coastguard Worker   if (swift_version != 0) {
5245*9880d681SAndroid Build Coastguard Worker     if (swift_version == 1)
5246*9880d681SAndroid Build Coastguard Worker       outs() << " Swift 1.0";
5247*9880d681SAndroid Build Coastguard Worker     else if (swift_version == 2)
5248*9880d681SAndroid Build Coastguard Worker       outs() << " Swift 1.1";
5249*9880d681SAndroid Build Coastguard Worker     else
5250*9880d681SAndroid Build Coastguard Worker       outs() << " unknown future Swift version (" << swift_version << ")";
5251*9880d681SAndroid Build Coastguard Worker   }
5252*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
5253*9880d681SAndroid Build Coastguard Worker }
5254*9880d681SAndroid Build Coastguard Worker 
print_image_info(SectionRef S,struct DisassembleInfo * info)5255*9880d681SAndroid Build Coastguard Worker static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
5256*9880d681SAndroid Build Coastguard Worker   uint32_t left, offset, p;
5257*9880d681SAndroid Build Coastguard Worker   struct imageInfo_t o;
5258*9880d681SAndroid Build Coastguard Worker   const char *r;
5259*9880d681SAndroid Build Coastguard Worker 
5260*9880d681SAndroid Build Coastguard Worker   StringRef SectName;
5261*9880d681SAndroid Build Coastguard Worker   S.getName(SectName);
5262*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ref = S.getRawDataRefImpl();
5263*9880d681SAndroid Build Coastguard Worker   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5264*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5265*9880d681SAndroid Build Coastguard Worker   p = S.getAddress();
5266*9880d681SAndroid Build Coastguard Worker   r = get_pointer_32(p, offset, left, S, info);
5267*9880d681SAndroid Build Coastguard Worker   if (r == nullptr)
5268*9880d681SAndroid Build Coastguard Worker     return;
5269*9880d681SAndroid Build Coastguard Worker   memset(&o, '\0', sizeof(struct imageInfo_t));
5270*9880d681SAndroid Build Coastguard Worker   if (left < sizeof(struct imageInfo_t)) {
5271*9880d681SAndroid Build Coastguard Worker     memcpy(&o, r, left);
5272*9880d681SAndroid Build Coastguard Worker     outs() << " (imageInfo entends past the end of the section)\n";
5273*9880d681SAndroid Build Coastguard Worker   } else
5274*9880d681SAndroid Build Coastguard Worker     memcpy(&o, r, sizeof(struct imageInfo_t));
5275*9880d681SAndroid Build Coastguard Worker   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5276*9880d681SAndroid Build Coastguard Worker     swapStruct(o);
5277*9880d681SAndroid Build Coastguard Worker   outs() << "  version " << o.version << "\n";
5278*9880d681SAndroid Build Coastguard Worker   outs() << "    flags " << format("0x%" PRIx32, o.flags);
5279*9880d681SAndroid Build Coastguard Worker   if (o.flags & 0x1)
5280*9880d681SAndroid Build Coastguard Worker     outs() << "  F&C";
5281*9880d681SAndroid Build Coastguard Worker   if (o.flags & 0x2)
5282*9880d681SAndroid Build Coastguard Worker     outs() << " GC";
5283*9880d681SAndroid Build Coastguard Worker   if (o.flags & 0x4)
5284*9880d681SAndroid Build Coastguard Worker     outs() << " GC-only";
5285*9880d681SAndroid Build Coastguard Worker   else
5286*9880d681SAndroid Build Coastguard Worker     outs() << " RR";
5287*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
5288*9880d681SAndroid Build Coastguard Worker }
5289*9880d681SAndroid Build Coastguard Worker 
printObjc2_64bit_MetaData(MachOObjectFile * O,bool verbose)5290*9880d681SAndroid Build Coastguard Worker static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
5291*9880d681SAndroid Build Coastguard Worker   SymbolAddressMap AddrMap;
5292*9880d681SAndroid Build Coastguard Worker   if (verbose)
5293*9880d681SAndroid Build Coastguard Worker     CreateSymbolAddressMap(O, &AddrMap);
5294*9880d681SAndroid Build Coastguard Worker 
5295*9880d681SAndroid Build Coastguard Worker   std::vector<SectionRef> Sections;
5296*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : O->sections()) {
5297*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
5298*9880d681SAndroid Build Coastguard Worker     Section.getName(SectName);
5299*9880d681SAndroid Build Coastguard Worker     Sections.push_back(Section);
5300*9880d681SAndroid Build Coastguard Worker   }
5301*9880d681SAndroid Build Coastguard Worker 
5302*9880d681SAndroid Build Coastguard Worker   struct DisassembleInfo info;
5303*9880d681SAndroid Build Coastguard Worker   // Set up the block of info used by the Symbolizer call backs.
5304*9880d681SAndroid Build Coastguard Worker   info.verbose = verbose;
5305*9880d681SAndroid Build Coastguard Worker   info.O = O;
5306*9880d681SAndroid Build Coastguard Worker   info.AddrMap = &AddrMap;
5307*9880d681SAndroid Build Coastguard Worker   info.Sections = &Sections;
5308*9880d681SAndroid Build Coastguard Worker   info.class_name = nullptr;
5309*9880d681SAndroid Build Coastguard Worker   info.selector_name = nullptr;
5310*9880d681SAndroid Build Coastguard Worker   info.method = nullptr;
5311*9880d681SAndroid Build Coastguard Worker   info.demangled_name = nullptr;
5312*9880d681SAndroid Build Coastguard Worker   info.bindtable = nullptr;
5313*9880d681SAndroid Build Coastguard Worker   info.adrp_addr = 0;
5314*9880d681SAndroid Build Coastguard Worker   info.adrp_inst = 0;
5315*9880d681SAndroid Build Coastguard Worker 
5316*9880d681SAndroid Build Coastguard Worker   info.depth = 0;
5317*9880d681SAndroid Build Coastguard Worker   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5318*9880d681SAndroid Build Coastguard Worker   if (CL == SectionRef())
5319*9880d681SAndroid Build Coastguard Worker     CL = get_section(O, "__DATA", "__objc_classlist");
5320*9880d681SAndroid Build Coastguard Worker   info.S = CL;
5321*9880d681SAndroid Build Coastguard Worker   walk_pointer_list_64("class", CL, O, &info, print_class64_t);
5322*9880d681SAndroid Build Coastguard Worker 
5323*9880d681SAndroid Build Coastguard Worker   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5324*9880d681SAndroid Build Coastguard Worker   if (CR == SectionRef())
5325*9880d681SAndroid Build Coastguard Worker     CR = get_section(O, "__DATA", "__objc_classrefs");
5326*9880d681SAndroid Build Coastguard Worker   info.S = CR;
5327*9880d681SAndroid Build Coastguard Worker   walk_pointer_list_64("class refs", CR, O, &info, nullptr);
5328*9880d681SAndroid Build Coastguard Worker 
5329*9880d681SAndroid Build Coastguard Worker   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5330*9880d681SAndroid Build Coastguard Worker   if (SR == SectionRef())
5331*9880d681SAndroid Build Coastguard Worker     SR = get_section(O, "__DATA", "__objc_superrefs");
5332*9880d681SAndroid Build Coastguard Worker   info.S = SR;
5333*9880d681SAndroid Build Coastguard Worker   walk_pointer_list_64("super refs", SR, O, &info, nullptr);
5334*9880d681SAndroid Build Coastguard Worker 
5335*9880d681SAndroid Build Coastguard Worker   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5336*9880d681SAndroid Build Coastguard Worker   if (CA == SectionRef())
5337*9880d681SAndroid Build Coastguard Worker     CA = get_section(O, "__DATA", "__objc_catlist");
5338*9880d681SAndroid Build Coastguard Worker   info.S = CA;
5339*9880d681SAndroid Build Coastguard Worker   walk_pointer_list_64("category", CA, O, &info, print_category64_t);
5340*9880d681SAndroid Build Coastguard Worker 
5341*9880d681SAndroid Build Coastguard Worker   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5342*9880d681SAndroid Build Coastguard Worker   if (PL == SectionRef())
5343*9880d681SAndroid Build Coastguard Worker     PL = get_section(O, "__DATA", "__objc_protolist");
5344*9880d681SAndroid Build Coastguard Worker   info.S = PL;
5345*9880d681SAndroid Build Coastguard Worker   walk_pointer_list_64("protocol", PL, O, &info, nullptr);
5346*9880d681SAndroid Build Coastguard Worker 
5347*9880d681SAndroid Build Coastguard Worker   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5348*9880d681SAndroid Build Coastguard Worker   if (MR == SectionRef())
5349*9880d681SAndroid Build Coastguard Worker     MR = get_section(O, "__DATA", "__objc_msgrefs");
5350*9880d681SAndroid Build Coastguard Worker   info.S = MR;
5351*9880d681SAndroid Build Coastguard Worker   print_message_refs64(MR, &info);
5352*9880d681SAndroid Build Coastguard Worker 
5353*9880d681SAndroid Build Coastguard Worker   SectionRef II = get_section(O, "__OBJC2", "__image_info");
5354*9880d681SAndroid Build Coastguard Worker   if (II == SectionRef())
5355*9880d681SAndroid Build Coastguard Worker     II = get_section(O, "__DATA", "__objc_imageinfo");
5356*9880d681SAndroid Build Coastguard Worker   info.S = II;
5357*9880d681SAndroid Build Coastguard Worker   print_image_info64(II, &info);
5358*9880d681SAndroid Build Coastguard Worker 
5359*9880d681SAndroid Build Coastguard Worker   if (info.bindtable != nullptr)
5360*9880d681SAndroid Build Coastguard Worker     delete info.bindtable;
5361*9880d681SAndroid Build Coastguard Worker }
5362*9880d681SAndroid Build Coastguard Worker 
printObjc2_32bit_MetaData(MachOObjectFile * O,bool verbose)5363*9880d681SAndroid Build Coastguard Worker static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5364*9880d681SAndroid Build Coastguard Worker   SymbolAddressMap AddrMap;
5365*9880d681SAndroid Build Coastguard Worker   if (verbose)
5366*9880d681SAndroid Build Coastguard Worker     CreateSymbolAddressMap(O, &AddrMap);
5367*9880d681SAndroid Build Coastguard Worker 
5368*9880d681SAndroid Build Coastguard Worker   std::vector<SectionRef> Sections;
5369*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : O->sections()) {
5370*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
5371*9880d681SAndroid Build Coastguard Worker     Section.getName(SectName);
5372*9880d681SAndroid Build Coastguard Worker     Sections.push_back(Section);
5373*9880d681SAndroid Build Coastguard Worker   }
5374*9880d681SAndroid Build Coastguard Worker 
5375*9880d681SAndroid Build Coastguard Worker   struct DisassembleInfo info;
5376*9880d681SAndroid Build Coastguard Worker   // Set up the block of info used by the Symbolizer call backs.
5377*9880d681SAndroid Build Coastguard Worker   info.verbose = verbose;
5378*9880d681SAndroid Build Coastguard Worker   info.O = O;
5379*9880d681SAndroid Build Coastguard Worker   info.AddrMap = &AddrMap;
5380*9880d681SAndroid Build Coastguard Worker   info.Sections = &Sections;
5381*9880d681SAndroid Build Coastguard Worker   info.class_name = nullptr;
5382*9880d681SAndroid Build Coastguard Worker   info.selector_name = nullptr;
5383*9880d681SAndroid Build Coastguard Worker   info.method = nullptr;
5384*9880d681SAndroid Build Coastguard Worker   info.demangled_name = nullptr;
5385*9880d681SAndroid Build Coastguard Worker   info.bindtable = nullptr;
5386*9880d681SAndroid Build Coastguard Worker   info.adrp_addr = 0;
5387*9880d681SAndroid Build Coastguard Worker   info.adrp_inst = 0;
5388*9880d681SAndroid Build Coastguard Worker 
5389*9880d681SAndroid Build Coastguard Worker   const SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5390*9880d681SAndroid Build Coastguard Worker   if (CL != SectionRef()) {
5391*9880d681SAndroid Build Coastguard Worker     info.S = CL;
5392*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("class", CL, O, &info, print_class32_t);
5393*9880d681SAndroid Build Coastguard Worker   } else {
5394*9880d681SAndroid Build Coastguard Worker     const SectionRef CL = get_section(O, "__DATA", "__objc_classlist");
5395*9880d681SAndroid Build Coastguard Worker     info.S = CL;
5396*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("class", CL, O, &info, print_class32_t);
5397*9880d681SAndroid Build Coastguard Worker   }
5398*9880d681SAndroid Build Coastguard Worker 
5399*9880d681SAndroid Build Coastguard Worker   const SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5400*9880d681SAndroid Build Coastguard Worker   if (CR != SectionRef()) {
5401*9880d681SAndroid Build Coastguard Worker     info.S = CR;
5402*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("class refs", CR, O, &info, nullptr);
5403*9880d681SAndroid Build Coastguard Worker   } else {
5404*9880d681SAndroid Build Coastguard Worker     const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs");
5405*9880d681SAndroid Build Coastguard Worker     info.S = CR;
5406*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("class refs", CR, O, &info, nullptr);
5407*9880d681SAndroid Build Coastguard Worker   }
5408*9880d681SAndroid Build Coastguard Worker 
5409*9880d681SAndroid Build Coastguard Worker   const SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5410*9880d681SAndroid Build Coastguard Worker   if (SR != SectionRef()) {
5411*9880d681SAndroid Build Coastguard Worker     info.S = SR;
5412*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("super refs", SR, O, &info, nullptr);
5413*9880d681SAndroid Build Coastguard Worker   } else {
5414*9880d681SAndroid Build Coastguard Worker     const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs");
5415*9880d681SAndroid Build Coastguard Worker     info.S = SR;
5416*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("super refs", SR, O, &info, nullptr);
5417*9880d681SAndroid Build Coastguard Worker   }
5418*9880d681SAndroid Build Coastguard Worker 
5419*9880d681SAndroid Build Coastguard Worker   const SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5420*9880d681SAndroid Build Coastguard Worker   if (CA != SectionRef()) {
5421*9880d681SAndroid Build Coastguard Worker     info.S = CA;
5422*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("category", CA, O, &info, print_category32_t);
5423*9880d681SAndroid Build Coastguard Worker   } else {
5424*9880d681SAndroid Build Coastguard Worker     const SectionRef CA = get_section(O, "__DATA", "__objc_catlist");
5425*9880d681SAndroid Build Coastguard Worker     info.S = CA;
5426*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("category", CA, O, &info, print_category32_t);
5427*9880d681SAndroid Build Coastguard Worker   }
5428*9880d681SAndroid Build Coastguard Worker 
5429*9880d681SAndroid Build Coastguard Worker   const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5430*9880d681SAndroid Build Coastguard Worker   if (PL != SectionRef()) {
5431*9880d681SAndroid Build Coastguard Worker     info.S = PL;
5432*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("protocol", PL, O, &info, nullptr);
5433*9880d681SAndroid Build Coastguard Worker   } else {
5434*9880d681SAndroid Build Coastguard Worker     const SectionRef PL = get_section(O, "__DATA", "__objc_protolist");
5435*9880d681SAndroid Build Coastguard Worker     info.S = PL;
5436*9880d681SAndroid Build Coastguard Worker     walk_pointer_list_32("protocol", PL, O, &info, nullptr);
5437*9880d681SAndroid Build Coastguard Worker   }
5438*9880d681SAndroid Build Coastguard Worker 
5439*9880d681SAndroid Build Coastguard Worker   const SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5440*9880d681SAndroid Build Coastguard Worker   if (MR != SectionRef()) {
5441*9880d681SAndroid Build Coastguard Worker     info.S = MR;
5442*9880d681SAndroid Build Coastguard Worker     print_message_refs32(MR, &info);
5443*9880d681SAndroid Build Coastguard Worker   } else {
5444*9880d681SAndroid Build Coastguard Worker     const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs");
5445*9880d681SAndroid Build Coastguard Worker     info.S = MR;
5446*9880d681SAndroid Build Coastguard Worker     print_message_refs32(MR, &info);
5447*9880d681SAndroid Build Coastguard Worker   }
5448*9880d681SAndroid Build Coastguard Worker 
5449*9880d681SAndroid Build Coastguard Worker   const SectionRef II = get_section(O, "__OBJC2", "__image_info");
5450*9880d681SAndroid Build Coastguard Worker   if (II != SectionRef()) {
5451*9880d681SAndroid Build Coastguard Worker     info.S = II;
5452*9880d681SAndroid Build Coastguard Worker     print_image_info32(II, &info);
5453*9880d681SAndroid Build Coastguard Worker   } else {
5454*9880d681SAndroid Build Coastguard Worker     const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo");
5455*9880d681SAndroid Build Coastguard Worker     info.S = II;
5456*9880d681SAndroid Build Coastguard Worker     print_image_info32(II, &info);
5457*9880d681SAndroid Build Coastguard Worker   }
5458*9880d681SAndroid Build Coastguard Worker }
5459*9880d681SAndroid Build Coastguard Worker 
printObjc1_32bit_MetaData(MachOObjectFile * O,bool verbose)5460*9880d681SAndroid Build Coastguard Worker static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5461*9880d681SAndroid Build Coastguard Worker   uint32_t i, j, p, offset, xoffset, left, defs_left, def;
5462*9880d681SAndroid Build Coastguard Worker   const char *r, *name, *defs;
5463*9880d681SAndroid Build Coastguard Worker   struct objc_module_t module;
5464*9880d681SAndroid Build Coastguard Worker   SectionRef S, xS;
5465*9880d681SAndroid Build Coastguard Worker   struct objc_symtab_t symtab;
5466*9880d681SAndroid Build Coastguard Worker   struct objc_class_t objc_class;
5467*9880d681SAndroid Build Coastguard Worker   struct objc_category_t objc_category;
5468*9880d681SAndroid Build Coastguard Worker 
5469*9880d681SAndroid Build Coastguard Worker   outs() << "Objective-C segment\n";
5470*9880d681SAndroid Build Coastguard Worker   S = get_section(O, "__OBJC", "__module_info");
5471*9880d681SAndroid Build Coastguard Worker   if (S == SectionRef())
5472*9880d681SAndroid Build Coastguard Worker     return false;
5473*9880d681SAndroid Build Coastguard Worker 
5474*9880d681SAndroid Build Coastguard Worker   SymbolAddressMap AddrMap;
5475*9880d681SAndroid Build Coastguard Worker   if (verbose)
5476*9880d681SAndroid Build Coastguard Worker     CreateSymbolAddressMap(O, &AddrMap);
5477*9880d681SAndroid Build Coastguard Worker 
5478*9880d681SAndroid Build Coastguard Worker   std::vector<SectionRef> Sections;
5479*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : O->sections()) {
5480*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
5481*9880d681SAndroid Build Coastguard Worker     Section.getName(SectName);
5482*9880d681SAndroid Build Coastguard Worker     Sections.push_back(Section);
5483*9880d681SAndroid Build Coastguard Worker   }
5484*9880d681SAndroid Build Coastguard Worker 
5485*9880d681SAndroid Build Coastguard Worker   struct DisassembleInfo info;
5486*9880d681SAndroid Build Coastguard Worker   // Set up the block of info used by the Symbolizer call backs.
5487*9880d681SAndroid Build Coastguard Worker   info.verbose = verbose;
5488*9880d681SAndroid Build Coastguard Worker   info.O = O;
5489*9880d681SAndroid Build Coastguard Worker   info.AddrMap = &AddrMap;
5490*9880d681SAndroid Build Coastguard Worker   info.Sections = &Sections;
5491*9880d681SAndroid Build Coastguard Worker   info.class_name = nullptr;
5492*9880d681SAndroid Build Coastguard Worker   info.selector_name = nullptr;
5493*9880d681SAndroid Build Coastguard Worker   info.method = nullptr;
5494*9880d681SAndroid Build Coastguard Worker   info.demangled_name = nullptr;
5495*9880d681SAndroid Build Coastguard Worker   info.bindtable = nullptr;
5496*9880d681SAndroid Build Coastguard Worker   info.adrp_addr = 0;
5497*9880d681SAndroid Build Coastguard Worker   info.adrp_inst = 0;
5498*9880d681SAndroid Build Coastguard Worker 
5499*9880d681SAndroid Build Coastguard Worker   for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
5500*9880d681SAndroid Build Coastguard Worker     p = S.getAddress() + i;
5501*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(p, offset, left, S, &info, true);
5502*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
5503*9880d681SAndroid Build Coastguard Worker       return true;
5504*9880d681SAndroid Build Coastguard Worker     memset(&module, '\0', sizeof(struct objc_module_t));
5505*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct objc_module_t)) {
5506*9880d681SAndroid Build Coastguard Worker       memcpy(&module, r, left);
5507*9880d681SAndroid Build Coastguard Worker       outs() << "   (module extends past end of __module_info section)\n";
5508*9880d681SAndroid Build Coastguard Worker     } else
5509*9880d681SAndroid Build Coastguard Worker       memcpy(&module, r, sizeof(struct objc_module_t));
5510*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost)
5511*9880d681SAndroid Build Coastguard Worker       swapStruct(module);
5512*9880d681SAndroid Build Coastguard Worker 
5513*9880d681SAndroid Build Coastguard Worker     outs() << "Module " << format("0x%" PRIx32, p) << "\n";
5514*9880d681SAndroid Build Coastguard Worker     outs() << "    version " << module.version << "\n";
5515*9880d681SAndroid Build Coastguard Worker     outs() << "       size " << module.size << "\n";
5516*9880d681SAndroid Build Coastguard Worker     outs() << "       name ";
5517*9880d681SAndroid Build Coastguard Worker     name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
5518*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
5519*9880d681SAndroid Build Coastguard Worker       outs() << format("%.*s", left, name);
5520*9880d681SAndroid Build Coastguard Worker     else
5521*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%08" PRIx32, module.name)
5522*9880d681SAndroid Build Coastguard Worker              << "(not in an __OBJC section)";
5523*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
5524*9880d681SAndroid Build Coastguard Worker 
5525*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
5526*9880d681SAndroid Build Coastguard Worker     if (module.symtab == 0 || r == nullptr) {
5527*9880d681SAndroid Build Coastguard Worker       outs() << "     symtab " << format("0x%08" PRIx32, module.symtab)
5528*9880d681SAndroid Build Coastguard Worker              << " (not in an __OBJC section)\n";
5529*9880d681SAndroid Build Coastguard Worker       continue;
5530*9880d681SAndroid Build Coastguard Worker     }
5531*9880d681SAndroid Build Coastguard Worker     outs() << "     symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
5532*9880d681SAndroid Build Coastguard Worker     memset(&symtab, '\0', sizeof(struct objc_symtab_t));
5533*9880d681SAndroid Build Coastguard Worker     defs_left = 0;
5534*9880d681SAndroid Build Coastguard Worker     defs = nullptr;
5535*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct objc_symtab_t)) {
5536*9880d681SAndroid Build Coastguard Worker       memcpy(&symtab, r, left);
5537*9880d681SAndroid Build Coastguard Worker       outs() << "\tsymtab extends past end of an __OBJC section)\n";
5538*9880d681SAndroid Build Coastguard Worker     } else {
5539*9880d681SAndroid Build Coastguard Worker       memcpy(&symtab, r, sizeof(struct objc_symtab_t));
5540*9880d681SAndroid Build Coastguard Worker       if (left > sizeof(struct objc_symtab_t)) {
5541*9880d681SAndroid Build Coastguard Worker         defs_left = left - sizeof(struct objc_symtab_t);
5542*9880d681SAndroid Build Coastguard Worker         defs = r + sizeof(struct objc_symtab_t);
5543*9880d681SAndroid Build Coastguard Worker       }
5544*9880d681SAndroid Build Coastguard Worker     }
5545*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost)
5546*9880d681SAndroid Build Coastguard Worker       swapStruct(symtab);
5547*9880d681SAndroid Build Coastguard Worker 
5548*9880d681SAndroid Build Coastguard Worker     outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
5549*9880d681SAndroid Build Coastguard Worker     r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
5550*9880d681SAndroid Build Coastguard Worker     outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
5551*9880d681SAndroid Build Coastguard Worker     if (r == nullptr)
5552*9880d681SAndroid Build Coastguard Worker       outs() << " (not in an __OBJC section)";
5553*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
5554*9880d681SAndroid Build Coastguard Worker     outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
5555*9880d681SAndroid Build Coastguard Worker     outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
5556*9880d681SAndroid Build Coastguard Worker     if (symtab.cls_def_cnt > 0)
5557*9880d681SAndroid Build Coastguard Worker       outs() << "\tClass Definitions\n";
5558*9880d681SAndroid Build Coastguard Worker     for (j = 0; j < symtab.cls_def_cnt; j++) {
5559*9880d681SAndroid Build Coastguard Worker       if ((j + 1) * sizeof(uint32_t) > defs_left) {
5560*9880d681SAndroid Build Coastguard Worker         outs() << "\t(remaining class defs entries entends past the end of the "
5561*9880d681SAndroid Build Coastguard Worker                << "section)\n";
5562*9880d681SAndroid Build Coastguard Worker         break;
5563*9880d681SAndroid Build Coastguard Worker       }
5564*9880d681SAndroid Build Coastguard Worker       memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
5565*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost)
5566*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(def);
5567*9880d681SAndroid Build Coastguard Worker 
5568*9880d681SAndroid Build Coastguard Worker       r = get_pointer_32(def, xoffset, left, xS, &info, true);
5569*9880d681SAndroid Build Coastguard Worker       outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
5570*9880d681SAndroid Build Coastguard Worker       if (r != nullptr) {
5571*9880d681SAndroid Build Coastguard Worker         if (left > sizeof(struct objc_class_t)) {
5572*9880d681SAndroid Build Coastguard Worker           outs() << "\n";
5573*9880d681SAndroid Build Coastguard Worker           memcpy(&objc_class, r, sizeof(struct objc_class_t));
5574*9880d681SAndroid Build Coastguard Worker         } else {
5575*9880d681SAndroid Build Coastguard Worker           outs() << " (entends past the end of the section)\n";
5576*9880d681SAndroid Build Coastguard Worker           memset(&objc_class, '\0', sizeof(struct objc_class_t));
5577*9880d681SAndroid Build Coastguard Worker           memcpy(&objc_class, r, left);
5578*9880d681SAndroid Build Coastguard Worker         }
5579*9880d681SAndroid Build Coastguard Worker         if (O->isLittleEndian() != sys::IsLittleEndianHost)
5580*9880d681SAndroid Build Coastguard Worker           swapStruct(objc_class);
5581*9880d681SAndroid Build Coastguard Worker         print_objc_class_t(&objc_class, &info);
5582*9880d681SAndroid Build Coastguard Worker       } else {
5583*9880d681SAndroid Build Coastguard Worker         outs() << "(not in an __OBJC section)\n";
5584*9880d681SAndroid Build Coastguard Worker       }
5585*9880d681SAndroid Build Coastguard Worker 
5586*9880d681SAndroid Build Coastguard Worker       if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
5587*9880d681SAndroid Build Coastguard Worker         outs() << "\tMeta Class";
5588*9880d681SAndroid Build Coastguard Worker         r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
5589*9880d681SAndroid Build Coastguard Worker         if (r != nullptr) {
5590*9880d681SAndroid Build Coastguard Worker           if (left > sizeof(struct objc_class_t)) {
5591*9880d681SAndroid Build Coastguard Worker             outs() << "\n";
5592*9880d681SAndroid Build Coastguard Worker             memcpy(&objc_class, r, sizeof(struct objc_class_t));
5593*9880d681SAndroid Build Coastguard Worker           } else {
5594*9880d681SAndroid Build Coastguard Worker             outs() << " (entends past the end of the section)\n";
5595*9880d681SAndroid Build Coastguard Worker             memset(&objc_class, '\0', sizeof(struct objc_class_t));
5596*9880d681SAndroid Build Coastguard Worker             memcpy(&objc_class, r, left);
5597*9880d681SAndroid Build Coastguard Worker           }
5598*9880d681SAndroid Build Coastguard Worker           if (O->isLittleEndian() != sys::IsLittleEndianHost)
5599*9880d681SAndroid Build Coastguard Worker             swapStruct(objc_class);
5600*9880d681SAndroid Build Coastguard Worker           print_objc_class_t(&objc_class, &info);
5601*9880d681SAndroid Build Coastguard Worker         } else {
5602*9880d681SAndroid Build Coastguard Worker           outs() << "(not in an __OBJC section)\n";
5603*9880d681SAndroid Build Coastguard Worker         }
5604*9880d681SAndroid Build Coastguard Worker       }
5605*9880d681SAndroid Build Coastguard Worker     }
5606*9880d681SAndroid Build Coastguard Worker     if (symtab.cat_def_cnt > 0)
5607*9880d681SAndroid Build Coastguard Worker       outs() << "\tCategory Definitions\n";
5608*9880d681SAndroid Build Coastguard Worker     for (j = 0; j < symtab.cat_def_cnt; j++) {
5609*9880d681SAndroid Build Coastguard Worker       if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
5610*9880d681SAndroid Build Coastguard Worker         outs() << "\t(remaining category defs entries entends past the end of "
5611*9880d681SAndroid Build Coastguard Worker                << "the section)\n";
5612*9880d681SAndroid Build Coastguard Worker         break;
5613*9880d681SAndroid Build Coastguard Worker       }
5614*9880d681SAndroid Build Coastguard Worker       memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
5615*9880d681SAndroid Build Coastguard Worker              sizeof(uint32_t));
5616*9880d681SAndroid Build Coastguard Worker       if (O->isLittleEndian() != sys::IsLittleEndianHost)
5617*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(def);
5618*9880d681SAndroid Build Coastguard Worker 
5619*9880d681SAndroid Build Coastguard Worker       r = get_pointer_32(def, xoffset, left, xS, &info, true);
5620*9880d681SAndroid Build Coastguard Worker       outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
5621*9880d681SAndroid Build Coastguard Worker              << format("0x%08" PRIx32, def);
5622*9880d681SAndroid Build Coastguard Worker       if (r != nullptr) {
5623*9880d681SAndroid Build Coastguard Worker         if (left > sizeof(struct objc_category_t)) {
5624*9880d681SAndroid Build Coastguard Worker           outs() << "\n";
5625*9880d681SAndroid Build Coastguard Worker           memcpy(&objc_category, r, sizeof(struct objc_category_t));
5626*9880d681SAndroid Build Coastguard Worker         } else {
5627*9880d681SAndroid Build Coastguard Worker           outs() << " (entends past the end of the section)\n";
5628*9880d681SAndroid Build Coastguard Worker           memset(&objc_category, '\0', sizeof(struct objc_category_t));
5629*9880d681SAndroid Build Coastguard Worker           memcpy(&objc_category, r, left);
5630*9880d681SAndroid Build Coastguard Worker         }
5631*9880d681SAndroid Build Coastguard Worker         if (O->isLittleEndian() != sys::IsLittleEndianHost)
5632*9880d681SAndroid Build Coastguard Worker           swapStruct(objc_category);
5633*9880d681SAndroid Build Coastguard Worker         print_objc_objc_category_t(&objc_category, &info);
5634*9880d681SAndroid Build Coastguard Worker       } else {
5635*9880d681SAndroid Build Coastguard Worker         outs() << "(not in an __OBJC section)\n";
5636*9880d681SAndroid Build Coastguard Worker       }
5637*9880d681SAndroid Build Coastguard Worker     }
5638*9880d681SAndroid Build Coastguard Worker   }
5639*9880d681SAndroid Build Coastguard Worker   const SectionRef II = get_section(O, "__OBJC", "__image_info");
5640*9880d681SAndroid Build Coastguard Worker   if (II != SectionRef())
5641*9880d681SAndroid Build Coastguard Worker     print_image_info(II, &info);
5642*9880d681SAndroid Build Coastguard Worker 
5643*9880d681SAndroid Build Coastguard Worker   return true;
5644*9880d681SAndroid Build Coastguard Worker }
5645*9880d681SAndroid Build Coastguard Worker 
DumpProtocolSection(MachOObjectFile * O,const char * sect,uint32_t size,uint32_t addr)5646*9880d681SAndroid Build Coastguard Worker static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
5647*9880d681SAndroid Build Coastguard Worker                                 uint32_t size, uint32_t addr) {
5648*9880d681SAndroid Build Coastguard Worker   SymbolAddressMap AddrMap;
5649*9880d681SAndroid Build Coastguard Worker   CreateSymbolAddressMap(O, &AddrMap);
5650*9880d681SAndroid Build Coastguard Worker 
5651*9880d681SAndroid Build Coastguard Worker   std::vector<SectionRef> Sections;
5652*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : O->sections()) {
5653*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
5654*9880d681SAndroid Build Coastguard Worker     Section.getName(SectName);
5655*9880d681SAndroid Build Coastguard Worker     Sections.push_back(Section);
5656*9880d681SAndroid Build Coastguard Worker   }
5657*9880d681SAndroid Build Coastguard Worker 
5658*9880d681SAndroid Build Coastguard Worker   struct DisassembleInfo info;
5659*9880d681SAndroid Build Coastguard Worker   // Set up the block of info used by the Symbolizer call backs.
5660*9880d681SAndroid Build Coastguard Worker   info.verbose = true;
5661*9880d681SAndroid Build Coastguard Worker   info.O = O;
5662*9880d681SAndroid Build Coastguard Worker   info.AddrMap = &AddrMap;
5663*9880d681SAndroid Build Coastguard Worker   info.Sections = &Sections;
5664*9880d681SAndroid Build Coastguard Worker   info.class_name = nullptr;
5665*9880d681SAndroid Build Coastguard Worker   info.selector_name = nullptr;
5666*9880d681SAndroid Build Coastguard Worker   info.method = nullptr;
5667*9880d681SAndroid Build Coastguard Worker   info.demangled_name = nullptr;
5668*9880d681SAndroid Build Coastguard Worker   info.bindtable = nullptr;
5669*9880d681SAndroid Build Coastguard Worker   info.adrp_addr = 0;
5670*9880d681SAndroid Build Coastguard Worker   info.adrp_inst = 0;
5671*9880d681SAndroid Build Coastguard Worker 
5672*9880d681SAndroid Build Coastguard Worker   const char *p;
5673*9880d681SAndroid Build Coastguard Worker   struct objc_protocol_t protocol;
5674*9880d681SAndroid Build Coastguard Worker   uint32_t left, paddr;
5675*9880d681SAndroid Build Coastguard Worker   for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
5676*9880d681SAndroid Build Coastguard Worker     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
5677*9880d681SAndroid Build Coastguard Worker     left = size - (p - sect);
5678*9880d681SAndroid Build Coastguard Worker     if (left < sizeof(struct objc_protocol_t)) {
5679*9880d681SAndroid Build Coastguard Worker       outs() << "Protocol extends past end of __protocol section\n";
5680*9880d681SAndroid Build Coastguard Worker       memcpy(&protocol, p, left);
5681*9880d681SAndroid Build Coastguard Worker     } else
5682*9880d681SAndroid Build Coastguard Worker       memcpy(&protocol, p, sizeof(struct objc_protocol_t));
5683*9880d681SAndroid Build Coastguard Worker     if (O->isLittleEndian() != sys::IsLittleEndianHost)
5684*9880d681SAndroid Build Coastguard Worker       swapStruct(protocol);
5685*9880d681SAndroid Build Coastguard Worker     paddr = addr + (p - sect);
5686*9880d681SAndroid Build Coastguard Worker     outs() << "Protocol " << format("0x%" PRIx32, paddr);
5687*9880d681SAndroid Build Coastguard Worker     if (print_protocol(paddr, 0, &info))
5688*9880d681SAndroid Build Coastguard Worker       outs() << "(not in an __OBJC section)\n";
5689*9880d681SAndroid Build Coastguard Worker   }
5690*9880d681SAndroid Build Coastguard Worker }
5691*9880d681SAndroid Build Coastguard Worker 
5692*9880d681SAndroid Build Coastguard Worker #ifdef HAVE_LIBXAR
swapStruct(struct xar_header & xar)5693*9880d681SAndroid Build Coastguard Worker inline void swapStruct(struct xar_header &xar) {
5694*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(xar.magic);
5695*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(xar.size);
5696*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(xar.version);
5697*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(xar.toc_length_compressed);
5698*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(xar.toc_length_uncompressed);
5699*9880d681SAndroid Build Coastguard Worker   sys::swapByteOrder(xar.cksum_alg);
5700*9880d681SAndroid Build Coastguard Worker }
5701*9880d681SAndroid Build Coastguard Worker 
PrintModeVerbose(uint32_t mode)5702*9880d681SAndroid Build Coastguard Worker static void PrintModeVerbose(uint32_t mode) {
5703*9880d681SAndroid Build Coastguard Worker   switch(mode & S_IFMT){
5704*9880d681SAndroid Build Coastguard Worker   case S_IFDIR:
5705*9880d681SAndroid Build Coastguard Worker     outs() << "d";
5706*9880d681SAndroid Build Coastguard Worker     break;
5707*9880d681SAndroid Build Coastguard Worker   case S_IFCHR:
5708*9880d681SAndroid Build Coastguard Worker     outs() << "c";
5709*9880d681SAndroid Build Coastguard Worker     break;
5710*9880d681SAndroid Build Coastguard Worker   case S_IFBLK:
5711*9880d681SAndroid Build Coastguard Worker     outs() << "b";
5712*9880d681SAndroid Build Coastguard Worker     break;
5713*9880d681SAndroid Build Coastguard Worker   case S_IFREG:
5714*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5715*9880d681SAndroid Build Coastguard Worker     break;
5716*9880d681SAndroid Build Coastguard Worker   case S_IFLNK:
5717*9880d681SAndroid Build Coastguard Worker     outs() << "l";
5718*9880d681SAndroid Build Coastguard Worker     break;
5719*9880d681SAndroid Build Coastguard Worker   case S_IFSOCK:
5720*9880d681SAndroid Build Coastguard Worker     outs() << "s";
5721*9880d681SAndroid Build Coastguard Worker     break;
5722*9880d681SAndroid Build Coastguard Worker   default:
5723*9880d681SAndroid Build Coastguard Worker     outs() << "?";
5724*9880d681SAndroid Build Coastguard Worker     break;
5725*9880d681SAndroid Build Coastguard Worker   }
5726*9880d681SAndroid Build Coastguard Worker 
5727*9880d681SAndroid Build Coastguard Worker   /* owner permissions */
5728*9880d681SAndroid Build Coastguard Worker   if(mode & S_IREAD)
5729*9880d681SAndroid Build Coastguard Worker     outs() << "r";
5730*9880d681SAndroid Build Coastguard Worker   else
5731*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5732*9880d681SAndroid Build Coastguard Worker   if(mode & S_IWRITE)
5733*9880d681SAndroid Build Coastguard Worker     outs() << "w";
5734*9880d681SAndroid Build Coastguard Worker   else
5735*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5736*9880d681SAndroid Build Coastguard Worker   if(mode & S_ISUID)
5737*9880d681SAndroid Build Coastguard Worker     outs() << "s";
5738*9880d681SAndroid Build Coastguard Worker   else if(mode & S_IEXEC)
5739*9880d681SAndroid Build Coastguard Worker     outs() << "x";
5740*9880d681SAndroid Build Coastguard Worker   else
5741*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5742*9880d681SAndroid Build Coastguard Worker 
5743*9880d681SAndroid Build Coastguard Worker   /* group permissions */
5744*9880d681SAndroid Build Coastguard Worker   if(mode & (S_IREAD >> 3))
5745*9880d681SAndroid Build Coastguard Worker     outs() << "r";
5746*9880d681SAndroid Build Coastguard Worker   else
5747*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5748*9880d681SAndroid Build Coastguard Worker   if(mode & (S_IWRITE >> 3))
5749*9880d681SAndroid Build Coastguard Worker     outs() << "w";
5750*9880d681SAndroid Build Coastguard Worker   else
5751*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5752*9880d681SAndroid Build Coastguard Worker   if(mode & S_ISGID)
5753*9880d681SAndroid Build Coastguard Worker     outs() << "s";
5754*9880d681SAndroid Build Coastguard Worker   else if(mode & (S_IEXEC >> 3))
5755*9880d681SAndroid Build Coastguard Worker     outs() << "x";
5756*9880d681SAndroid Build Coastguard Worker   else
5757*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5758*9880d681SAndroid Build Coastguard Worker 
5759*9880d681SAndroid Build Coastguard Worker   /* other permissions */
5760*9880d681SAndroid Build Coastguard Worker   if(mode & (S_IREAD >> 6))
5761*9880d681SAndroid Build Coastguard Worker     outs() << "r";
5762*9880d681SAndroid Build Coastguard Worker   else
5763*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5764*9880d681SAndroid Build Coastguard Worker   if(mode & (S_IWRITE >> 6))
5765*9880d681SAndroid Build Coastguard Worker     outs() << "w";
5766*9880d681SAndroid Build Coastguard Worker   else
5767*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5768*9880d681SAndroid Build Coastguard Worker   if(mode & S_ISVTX)
5769*9880d681SAndroid Build Coastguard Worker     outs() << "t";
5770*9880d681SAndroid Build Coastguard Worker   else if(mode & (S_IEXEC >> 6))
5771*9880d681SAndroid Build Coastguard Worker     outs() << "x";
5772*9880d681SAndroid Build Coastguard Worker   else
5773*9880d681SAndroid Build Coastguard Worker     outs() << "-";
5774*9880d681SAndroid Build Coastguard Worker }
5775*9880d681SAndroid Build Coastguard Worker 
PrintXarFilesSummary(const char * XarFilename,xar_t xar)5776*9880d681SAndroid Build Coastguard Worker static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
5777*9880d681SAndroid Build Coastguard Worker   xar_iter_t xi;
5778*9880d681SAndroid Build Coastguard Worker   xar_file_t xf;
5779*9880d681SAndroid Build Coastguard Worker   xar_iter_t xp;
5780*9880d681SAndroid Build Coastguard Worker   const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
5781*9880d681SAndroid Build Coastguard Worker   char *endp;
5782*9880d681SAndroid Build Coastguard Worker   uint32_t mode_value;
5783*9880d681SAndroid Build Coastguard Worker 
5784*9880d681SAndroid Build Coastguard Worker   xi = xar_iter_new();
5785*9880d681SAndroid Build Coastguard Worker   if (!xi) {
5786*9880d681SAndroid Build Coastguard Worker     errs() << "Can't obtain an xar iterator for xar archive "
5787*9880d681SAndroid Build Coastguard Worker            << XarFilename << "\n";
5788*9880d681SAndroid Build Coastguard Worker     return;
5789*9880d681SAndroid Build Coastguard Worker   }
5790*9880d681SAndroid Build Coastguard Worker 
5791*9880d681SAndroid Build Coastguard Worker   // Go through the xar's files.
5792*9880d681SAndroid Build Coastguard Worker   for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
5793*9880d681SAndroid Build Coastguard Worker     xp = xar_iter_new();
5794*9880d681SAndroid Build Coastguard Worker     if(!xp){
5795*9880d681SAndroid Build Coastguard Worker       errs() << "Can't obtain an xar iterator for xar archive "
5796*9880d681SAndroid Build Coastguard Worker              << XarFilename << "\n";
5797*9880d681SAndroid Build Coastguard Worker       return;
5798*9880d681SAndroid Build Coastguard Worker     }
5799*9880d681SAndroid Build Coastguard Worker     type = nullptr;
5800*9880d681SAndroid Build Coastguard Worker     mode = nullptr;
5801*9880d681SAndroid Build Coastguard Worker     user = nullptr;
5802*9880d681SAndroid Build Coastguard Worker     group = nullptr;
5803*9880d681SAndroid Build Coastguard Worker     size = nullptr;
5804*9880d681SAndroid Build Coastguard Worker     mtime = nullptr;
5805*9880d681SAndroid Build Coastguard Worker     name = nullptr;
5806*9880d681SAndroid Build Coastguard Worker     for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
5807*9880d681SAndroid Build Coastguard Worker       const char *val = nullptr;
5808*9880d681SAndroid Build Coastguard Worker       xar_prop_get(xf, key, &val);
5809*9880d681SAndroid Build Coastguard Worker #if 0 // Useful for debugging.
5810*9880d681SAndroid Build Coastguard Worker       outs() << "key: " << key << " value: " << val << "\n";
5811*9880d681SAndroid Build Coastguard Worker #endif
5812*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "type") == 0)
5813*9880d681SAndroid Build Coastguard Worker         type = val;
5814*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "mode") == 0)
5815*9880d681SAndroid Build Coastguard Worker         mode = val;
5816*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "user") == 0)
5817*9880d681SAndroid Build Coastguard Worker         user = val;
5818*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "group") == 0)
5819*9880d681SAndroid Build Coastguard Worker         group = val;
5820*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "data/size") == 0)
5821*9880d681SAndroid Build Coastguard Worker         size = val;
5822*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "mtime") == 0)
5823*9880d681SAndroid Build Coastguard Worker         mtime = val;
5824*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "name") == 0)
5825*9880d681SAndroid Build Coastguard Worker         name = val;
5826*9880d681SAndroid Build Coastguard Worker     }
5827*9880d681SAndroid Build Coastguard Worker     if(mode != nullptr){
5828*9880d681SAndroid Build Coastguard Worker       mode_value = strtoul(mode, &endp, 8);
5829*9880d681SAndroid Build Coastguard Worker       if(*endp != '\0')
5830*9880d681SAndroid Build Coastguard Worker         outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
5831*9880d681SAndroid Build Coastguard Worker       if(strcmp(type, "file") == 0)
5832*9880d681SAndroid Build Coastguard Worker         mode_value |= S_IFREG;
5833*9880d681SAndroid Build Coastguard Worker       PrintModeVerbose(mode_value);
5834*9880d681SAndroid Build Coastguard Worker       outs() << " ";
5835*9880d681SAndroid Build Coastguard Worker     }
5836*9880d681SAndroid Build Coastguard Worker     if(user != nullptr)
5837*9880d681SAndroid Build Coastguard Worker       outs() << format("%10s/", user);
5838*9880d681SAndroid Build Coastguard Worker     if(group != nullptr)
5839*9880d681SAndroid Build Coastguard Worker       outs() << format("%-10s ", group);
5840*9880d681SAndroid Build Coastguard Worker     if(size != nullptr)
5841*9880d681SAndroid Build Coastguard Worker       outs() << format("%7s ", size);
5842*9880d681SAndroid Build Coastguard Worker     if(mtime != nullptr){
5843*9880d681SAndroid Build Coastguard Worker       for(m = mtime; *m != 'T' && *m != '\0'; m++)
5844*9880d681SAndroid Build Coastguard Worker         outs() << *m;
5845*9880d681SAndroid Build Coastguard Worker       if(*m == 'T')
5846*9880d681SAndroid Build Coastguard Worker         m++;
5847*9880d681SAndroid Build Coastguard Worker       outs() << " ";
5848*9880d681SAndroid Build Coastguard Worker       for( ; *m != 'Z' && *m != '\0'; m++)
5849*9880d681SAndroid Build Coastguard Worker         outs() << *m;
5850*9880d681SAndroid Build Coastguard Worker       outs() << " ";
5851*9880d681SAndroid Build Coastguard Worker     }
5852*9880d681SAndroid Build Coastguard Worker     if(name != nullptr)
5853*9880d681SAndroid Build Coastguard Worker       outs() << name;
5854*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
5855*9880d681SAndroid Build Coastguard Worker   }
5856*9880d681SAndroid Build Coastguard Worker }
5857*9880d681SAndroid Build Coastguard Worker 
DumpBitcodeSection(MachOObjectFile * O,const char * sect,uint32_t size,bool verbose,bool PrintXarHeader,bool PrintXarFileHeaders,std::string XarMemberName)5858*9880d681SAndroid Build Coastguard Worker static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
5859*9880d681SAndroid Build Coastguard Worker                                 uint32_t size, bool verbose,
5860*9880d681SAndroid Build Coastguard Worker                                 bool PrintXarHeader, bool PrintXarFileHeaders,
5861*9880d681SAndroid Build Coastguard Worker                                 std::string XarMemberName) {
5862*9880d681SAndroid Build Coastguard Worker   if(size < sizeof(struct xar_header)) {
5863*9880d681SAndroid Build Coastguard Worker     outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
5864*9880d681SAndroid Build Coastguard Worker               "of struct xar_header)\n";
5865*9880d681SAndroid Build Coastguard Worker     return;
5866*9880d681SAndroid Build Coastguard Worker   }
5867*9880d681SAndroid Build Coastguard Worker   struct xar_header XarHeader;
5868*9880d681SAndroid Build Coastguard Worker   memcpy(&XarHeader, sect, sizeof(struct xar_header));
5869*9880d681SAndroid Build Coastguard Worker   if (sys::IsLittleEndianHost)
5870*9880d681SAndroid Build Coastguard Worker     swapStruct(XarHeader);
5871*9880d681SAndroid Build Coastguard Worker   if (PrintXarHeader) {
5872*9880d681SAndroid Build Coastguard Worker     if (!XarMemberName.empty())
5873*9880d681SAndroid Build Coastguard Worker       outs() << "In xar member " << XarMemberName << ": ";
5874*9880d681SAndroid Build Coastguard Worker     else
5875*9880d681SAndroid Build Coastguard Worker       outs() << "For (__LLVM,__bundle) section: ";
5876*9880d681SAndroid Build Coastguard Worker     outs() << "xar header\n";
5877*9880d681SAndroid Build Coastguard Worker     if (XarHeader.magic == XAR_HEADER_MAGIC)
5878*9880d681SAndroid Build Coastguard Worker       outs() << "                  magic XAR_HEADER_MAGIC\n";
5879*9880d681SAndroid Build Coastguard Worker     else
5880*9880d681SAndroid Build Coastguard Worker       outs() << "                  magic "
5881*9880d681SAndroid Build Coastguard Worker              << format_hex(XarHeader.magic, 10, true)
5882*9880d681SAndroid Build Coastguard Worker              << " (not XAR_HEADER_MAGIC)\n";
5883*9880d681SAndroid Build Coastguard Worker     outs() << "                   size " << XarHeader.size << "\n";
5884*9880d681SAndroid Build Coastguard Worker     outs() << "                version " << XarHeader.version << "\n";
5885*9880d681SAndroid Build Coastguard Worker     outs() << "  toc_length_compressed " << XarHeader.toc_length_compressed
5886*9880d681SAndroid Build Coastguard Worker            << "\n";
5887*9880d681SAndroid Build Coastguard Worker     outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
5888*9880d681SAndroid Build Coastguard Worker            << "\n";
5889*9880d681SAndroid Build Coastguard Worker     outs() << "              cksum_alg ";
5890*9880d681SAndroid Build Coastguard Worker     switch (XarHeader.cksum_alg) {
5891*9880d681SAndroid Build Coastguard Worker       case XAR_CKSUM_NONE:
5892*9880d681SAndroid Build Coastguard Worker         outs() << "XAR_CKSUM_NONE\n";
5893*9880d681SAndroid Build Coastguard Worker         break;
5894*9880d681SAndroid Build Coastguard Worker       case XAR_CKSUM_SHA1:
5895*9880d681SAndroid Build Coastguard Worker         outs() << "XAR_CKSUM_SHA1\n";
5896*9880d681SAndroid Build Coastguard Worker         break;
5897*9880d681SAndroid Build Coastguard Worker       case XAR_CKSUM_MD5:
5898*9880d681SAndroid Build Coastguard Worker         outs() << "XAR_CKSUM_MD5\n";
5899*9880d681SAndroid Build Coastguard Worker         break;
5900*9880d681SAndroid Build Coastguard Worker #ifdef XAR_CKSUM_SHA256
5901*9880d681SAndroid Build Coastguard Worker       case XAR_CKSUM_SHA256:
5902*9880d681SAndroid Build Coastguard Worker         outs() << "XAR_CKSUM_SHA256\n";
5903*9880d681SAndroid Build Coastguard Worker         break;
5904*9880d681SAndroid Build Coastguard Worker #endif
5905*9880d681SAndroid Build Coastguard Worker #ifdef XAR_CKSUM_SHA512
5906*9880d681SAndroid Build Coastguard Worker       case XAR_CKSUM_SHA512:
5907*9880d681SAndroid Build Coastguard Worker         outs() << "XAR_CKSUM_SHA512\n";
5908*9880d681SAndroid Build Coastguard Worker         break;
5909*9880d681SAndroid Build Coastguard Worker #endif
5910*9880d681SAndroid Build Coastguard Worker       default:
5911*9880d681SAndroid Build Coastguard Worker         outs() << XarHeader.cksum_alg << "\n";
5912*9880d681SAndroid Build Coastguard Worker     }
5913*9880d681SAndroid Build Coastguard Worker   }
5914*9880d681SAndroid Build Coastguard Worker 
5915*9880d681SAndroid Build Coastguard Worker   SmallString<128> XarFilename;
5916*9880d681SAndroid Build Coastguard Worker   int FD;
5917*9880d681SAndroid Build Coastguard Worker   std::error_code XarEC =
5918*9880d681SAndroid Build Coastguard Worker       sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
5919*9880d681SAndroid Build Coastguard Worker   if (XarEC) {
5920*9880d681SAndroid Build Coastguard Worker     errs() << XarEC.message() << "\n";
5921*9880d681SAndroid Build Coastguard Worker     return;
5922*9880d681SAndroid Build Coastguard Worker   }
5923*9880d681SAndroid Build Coastguard Worker   tool_output_file XarFile(XarFilename, FD);
5924*9880d681SAndroid Build Coastguard Worker   raw_fd_ostream &XarOut = XarFile.os();
5925*9880d681SAndroid Build Coastguard Worker   StringRef XarContents(sect, size);
5926*9880d681SAndroid Build Coastguard Worker   XarOut << XarContents;
5927*9880d681SAndroid Build Coastguard Worker   XarOut.close();
5928*9880d681SAndroid Build Coastguard Worker   if (XarOut.has_error())
5929*9880d681SAndroid Build Coastguard Worker     return;
5930*9880d681SAndroid Build Coastguard Worker 
5931*9880d681SAndroid Build Coastguard Worker   xar_t xar = xar_open(XarFilename.c_str(), READ);
5932*9880d681SAndroid Build Coastguard Worker   if (!xar) {
5933*9880d681SAndroid Build Coastguard Worker     errs() << "Can't create temporary xar archive " << XarFilename << "\n";
5934*9880d681SAndroid Build Coastguard Worker     return;
5935*9880d681SAndroid Build Coastguard Worker   }
5936*9880d681SAndroid Build Coastguard Worker 
5937*9880d681SAndroid Build Coastguard Worker   SmallString<128> TocFilename;
5938*9880d681SAndroid Build Coastguard Worker   std::error_code TocEC =
5939*9880d681SAndroid Build Coastguard Worker       sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
5940*9880d681SAndroid Build Coastguard Worker   if (TocEC) {
5941*9880d681SAndroid Build Coastguard Worker     errs() << TocEC.message() << "\n";
5942*9880d681SAndroid Build Coastguard Worker     return;
5943*9880d681SAndroid Build Coastguard Worker   }
5944*9880d681SAndroid Build Coastguard Worker   xar_serialize(xar, TocFilename.c_str());
5945*9880d681SAndroid Build Coastguard Worker 
5946*9880d681SAndroid Build Coastguard Worker   if (PrintXarFileHeaders) {
5947*9880d681SAndroid Build Coastguard Worker     if (!XarMemberName.empty())
5948*9880d681SAndroid Build Coastguard Worker       outs() << "In xar member " << XarMemberName << ": ";
5949*9880d681SAndroid Build Coastguard Worker     else
5950*9880d681SAndroid Build Coastguard Worker       outs() << "For (__LLVM,__bundle) section: ";
5951*9880d681SAndroid Build Coastguard Worker     outs() << "xar archive files:\n";
5952*9880d681SAndroid Build Coastguard Worker     PrintXarFilesSummary(XarFilename.c_str(), xar);
5953*9880d681SAndroid Build Coastguard Worker   }
5954*9880d681SAndroid Build Coastguard Worker 
5955*9880d681SAndroid Build Coastguard Worker   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
5956*9880d681SAndroid Build Coastguard Worker     MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
5957*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = FileOrErr.getError()) {
5958*9880d681SAndroid Build Coastguard Worker     errs() << EC.message() << "\n";
5959*9880d681SAndroid Build Coastguard Worker     return;
5960*9880d681SAndroid Build Coastguard Worker   }
5961*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
5962*9880d681SAndroid Build Coastguard Worker 
5963*9880d681SAndroid Build Coastguard Worker   if (!XarMemberName.empty())
5964*9880d681SAndroid Build Coastguard Worker     outs() << "In xar member " << XarMemberName << ": ";
5965*9880d681SAndroid Build Coastguard Worker   else
5966*9880d681SAndroid Build Coastguard Worker     outs() << "For (__LLVM,__bundle) section: ";
5967*9880d681SAndroid Build Coastguard Worker   outs() << "xar table of contents:\n";
5968*9880d681SAndroid Build Coastguard Worker   outs() << Buffer->getBuffer() << "\n";
5969*9880d681SAndroid Build Coastguard Worker 
5970*9880d681SAndroid Build Coastguard Worker   // TODO: Go through the xar's files.
5971*9880d681SAndroid Build Coastguard Worker   xar_iter_t xi = xar_iter_new();
5972*9880d681SAndroid Build Coastguard Worker   if(!xi){
5973*9880d681SAndroid Build Coastguard Worker     errs() << "Can't obtain an xar iterator for xar archive "
5974*9880d681SAndroid Build Coastguard Worker            << XarFilename.c_str() << "\n";
5975*9880d681SAndroid Build Coastguard Worker     xar_close(xar);
5976*9880d681SAndroid Build Coastguard Worker     return;
5977*9880d681SAndroid Build Coastguard Worker   }
5978*9880d681SAndroid Build Coastguard Worker   for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
5979*9880d681SAndroid Build Coastguard Worker     const char *key;
5980*9880d681SAndroid Build Coastguard Worker     xar_iter_t xp;
5981*9880d681SAndroid Build Coastguard Worker     const char *member_name, *member_type, *member_size_string;
5982*9880d681SAndroid Build Coastguard Worker     size_t member_size;
5983*9880d681SAndroid Build Coastguard Worker 
5984*9880d681SAndroid Build Coastguard Worker     xp = xar_iter_new();
5985*9880d681SAndroid Build Coastguard Worker     if(!xp){
5986*9880d681SAndroid Build Coastguard Worker       errs() << "Can't obtain an xar iterator for xar archive "
5987*9880d681SAndroid Build Coastguard Worker 	     << XarFilename.c_str() << "\n";
5988*9880d681SAndroid Build Coastguard Worker       xar_close(xar);
5989*9880d681SAndroid Build Coastguard Worker       return;
5990*9880d681SAndroid Build Coastguard Worker     }
5991*9880d681SAndroid Build Coastguard Worker     member_name = NULL;
5992*9880d681SAndroid Build Coastguard Worker     member_type = NULL;
5993*9880d681SAndroid Build Coastguard Worker     member_size_string = NULL;
5994*9880d681SAndroid Build Coastguard Worker     for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
5995*9880d681SAndroid Build Coastguard Worker       const char *val = nullptr;
5996*9880d681SAndroid Build Coastguard Worker       xar_prop_get(xf, key, &val);
5997*9880d681SAndroid Build Coastguard Worker #if 0 // Useful for debugging.
5998*9880d681SAndroid Build Coastguard Worker       outs() << "key: " << key << " value: " << val << "\n";
5999*9880d681SAndroid Build Coastguard Worker #endif
6000*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "name") == 0)
6001*9880d681SAndroid Build Coastguard Worker 	member_name = val;
6002*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "type") == 0)
6003*9880d681SAndroid Build Coastguard Worker 	member_type = val;
6004*9880d681SAndroid Build Coastguard Worker       if(strcmp(key, "data/size") == 0)
6005*9880d681SAndroid Build Coastguard Worker 	member_size_string = val;
6006*9880d681SAndroid Build Coastguard Worker     }
6007*9880d681SAndroid Build Coastguard Worker     /*
6008*9880d681SAndroid Build Coastguard Worker      * If we find a file with a name, date/size and type properties
6009*9880d681SAndroid Build Coastguard Worker      * and with the type being "file" see if that is a xar file.
6010*9880d681SAndroid Build Coastguard Worker      */
6011*9880d681SAndroid Build Coastguard Worker     if (member_name != NULL && member_type != NULL &&
6012*9880d681SAndroid Build Coastguard Worker         strcmp(member_type, "file") == 0 &&
6013*9880d681SAndroid Build Coastguard Worker         member_size_string != NULL){
6014*9880d681SAndroid Build Coastguard Worker       // Extract the file into a buffer.
6015*9880d681SAndroid Build Coastguard Worker       char *endptr;
6016*9880d681SAndroid Build Coastguard Worker       member_size = strtoul(member_size_string, &endptr, 10);
6017*9880d681SAndroid Build Coastguard Worker       if (*endptr == '\0' && member_size != 0) {
6018*9880d681SAndroid Build Coastguard Worker 	char *buffer = (char *) ::operator new (member_size);
6019*9880d681SAndroid Build Coastguard Worker 	if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
6020*9880d681SAndroid Build Coastguard Worker #if 0 // Useful for debugging.
6021*9880d681SAndroid Build Coastguard Worker 	  outs() << "xar member: " << member_name << " extracted\n";
6022*9880d681SAndroid Build Coastguard Worker #endif
6023*9880d681SAndroid Build Coastguard Worker           // Set the XarMemberName we want to see printed in the header.
6024*9880d681SAndroid Build Coastguard Worker 	  std::string OldXarMemberName;
6025*9880d681SAndroid Build Coastguard Worker 	  // If XarMemberName is already set this is nested. So
6026*9880d681SAndroid Build Coastguard Worker 	  // save the old name and create the nested name.
6027*9880d681SAndroid Build Coastguard Worker 	  if (!XarMemberName.empty()) {
6028*9880d681SAndroid Build Coastguard Worker 	    OldXarMemberName = XarMemberName;
6029*9880d681SAndroid Build Coastguard Worker             XarMemberName =
6030*9880d681SAndroid Build Coastguard Worker              (Twine("[") + XarMemberName + "]" + member_name).str();
6031*9880d681SAndroid Build Coastguard Worker 	  } else {
6032*9880d681SAndroid Build Coastguard Worker 	    OldXarMemberName = "";
6033*9880d681SAndroid Build Coastguard Worker 	    XarMemberName = member_name;
6034*9880d681SAndroid Build Coastguard Worker 	  }
6035*9880d681SAndroid Build Coastguard Worker 	  // See if this is could be a xar file (nested).
6036*9880d681SAndroid Build Coastguard Worker 	  if (member_size >= sizeof(struct xar_header)) {
6037*9880d681SAndroid Build Coastguard Worker #if 0 // Useful for debugging.
6038*9880d681SAndroid Build Coastguard Worker 	    outs() << "could be a xar file: " << member_name << "\n";
6039*9880d681SAndroid Build Coastguard Worker #endif
6040*9880d681SAndroid Build Coastguard Worker 	    memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
6041*9880d681SAndroid Build Coastguard Worker             if (sys::IsLittleEndianHost)
6042*9880d681SAndroid Build Coastguard Worker 	      swapStruct(XarHeader);
6043*9880d681SAndroid Build Coastguard Worker 	    if(XarHeader.magic == XAR_HEADER_MAGIC)
6044*9880d681SAndroid Build Coastguard Worker 	      DumpBitcodeSection(O, buffer, member_size, verbose,
6045*9880d681SAndroid Build Coastguard Worker                                  PrintXarHeader, PrintXarFileHeaders,
6046*9880d681SAndroid Build Coastguard Worker 		                 XarMemberName);
6047*9880d681SAndroid Build Coastguard Worker 	  }
6048*9880d681SAndroid Build Coastguard Worker 	  XarMemberName = OldXarMemberName;
6049*9880d681SAndroid Build Coastguard Worker 	}
6050*9880d681SAndroid Build Coastguard Worker         delete buffer;
6051*9880d681SAndroid Build Coastguard Worker       }
6052*9880d681SAndroid Build Coastguard Worker     }
6053*9880d681SAndroid Build Coastguard Worker     xar_iter_free(xp);
6054*9880d681SAndroid Build Coastguard Worker   }
6055*9880d681SAndroid Build Coastguard Worker   xar_close(xar);
6056*9880d681SAndroid Build Coastguard Worker }
6057*9880d681SAndroid Build Coastguard Worker #endif // defined(HAVE_LIBXAR)
6058*9880d681SAndroid Build Coastguard Worker 
printObjcMetaData(MachOObjectFile * O,bool verbose)6059*9880d681SAndroid Build Coastguard Worker static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6060*9880d681SAndroid Build Coastguard Worker   if (O->is64Bit())
6061*9880d681SAndroid Build Coastguard Worker     printObjc2_64bit_MetaData(O, verbose);
6062*9880d681SAndroid Build Coastguard Worker   else {
6063*9880d681SAndroid Build Coastguard Worker     MachO::mach_header H;
6064*9880d681SAndroid Build Coastguard Worker     H = O->getHeader();
6065*9880d681SAndroid Build Coastguard Worker     if (H.cputype == MachO::CPU_TYPE_ARM)
6066*9880d681SAndroid Build Coastguard Worker       printObjc2_32bit_MetaData(O, verbose);
6067*9880d681SAndroid Build Coastguard Worker     else {
6068*9880d681SAndroid Build Coastguard Worker       // This is the 32-bit non-arm cputype case.  Which is normally
6069*9880d681SAndroid Build Coastguard Worker       // the first Objective-C ABI.  But it may be the case of a
6070*9880d681SAndroid Build Coastguard Worker       // binary for the iOS simulator which is the second Objective-C
6071*9880d681SAndroid Build Coastguard Worker       // ABI.  In that case printObjc1_32bit_MetaData() will determine that
6072*9880d681SAndroid Build Coastguard Worker       // and return false.
6073*9880d681SAndroid Build Coastguard Worker       if (!printObjc1_32bit_MetaData(O, verbose))
6074*9880d681SAndroid Build Coastguard Worker         printObjc2_32bit_MetaData(O, verbose);
6075*9880d681SAndroid Build Coastguard Worker     }
6076*9880d681SAndroid Build Coastguard Worker   }
6077*9880d681SAndroid Build Coastguard Worker }
6078*9880d681SAndroid Build Coastguard Worker 
6079*9880d681SAndroid Build Coastguard Worker // GuessLiteralPointer returns a string which for the item in the Mach-O file
6080*9880d681SAndroid Build Coastguard Worker // for the address passed in as ReferenceValue for printing as a comment with
6081*9880d681SAndroid Build Coastguard Worker // the instruction and also returns the corresponding type of that item
6082*9880d681SAndroid Build Coastguard Worker // indirectly through ReferenceType.
6083*9880d681SAndroid Build Coastguard Worker //
6084*9880d681SAndroid Build Coastguard Worker // If ReferenceValue is an address of literal cstring then a pointer to the
6085*9880d681SAndroid Build Coastguard Worker // cstring is returned and ReferenceType is set to
6086*9880d681SAndroid Build Coastguard Worker // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6087*9880d681SAndroid Build Coastguard Worker //
6088*9880d681SAndroid Build Coastguard Worker // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6089*9880d681SAndroid Build Coastguard Worker // Class ref that name is returned and the ReferenceType is set accordingly.
6090*9880d681SAndroid Build Coastguard Worker //
6091*9880d681SAndroid Build Coastguard Worker // Lastly, literals which are Symbol address in a literal pool are looked for
6092*9880d681SAndroid Build Coastguard Worker // and if found the symbol name is returned and ReferenceType is set to
6093*9880d681SAndroid Build Coastguard Worker // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6094*9880d681SAndroid Build Coastguard Worker //
6095*9880d681SAndroid Build Coastguard Worker // If there is no item in the Mach-O file for the address passed in as
6096*9880d681SAndroid Build Coastguard Worker // ReferenceValue nullptr is returned and ReferenceType is unchanged.
GuessLiteralPointer(uint64_t ReferenceValue,uint64_t ReferencePC,uint64_t * ReferenceType,struct DisassembleInfo * info)6097*9880d681SAndroid Build Coastguard Worker static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6098*9880d681SAndroid Build Coastguard Worker                                        uint64_t ReferencePC,
6099*9880d681SAndroid Build Coastguard Worker                                        uint64_t *ReferenceType,
6100*9880d681SAndroid Build Coastguard Worker                                        struct DisassembleInfo *info) {
6101*9880d681SAndroid Build Coastguard Worker   // First see if there is an external relocation entry at the ReferencePC.
6102*9880d681SAndroid Build Coastguard Worker   if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6103*9880d681SAndroid Build Coastguard Worker     uint64_t sect_addr = info->S.getAddress();
6104*9880d681SAndroid Build Coastguard Worker     uint64_t sect_offset = ReferencePC - sect_addr;
6105*9880d681SAndroid Build Coastguard Worker     bool reloc_found = false;
6106*9880d681SAndroid Build Coastguard Worker     DataRefImpl Rel;
6107*9880d681SAndroid Build Coastguard Worker     MachO::any_relocation_info RE;
6108*9880d681SAndroid Build Coastguard Worker     bool isExtern = false;
6109*9880d681SAndroid Build Coastguard Worker     SymbolRef Symbol;
6110*9880d681SAndroid Build Coastguard Worker     for (const RelocationRef &Reloc : info->S.relocations()) {
6111*9880d681SAndroid Build Coastguard Worker       uint64_t RelocOffset = Reloc.getOffset();
6112*9880d681SAndroid Build Coastguard Worker       if (RelocOffset == sect_offset) {
6113*9880d681SAndroid Build Coastguard Worker         Rel = Reloc.getRawDataRefImpl();
6114*9880d681SAndroid Build Coastguard Worker         RE = info->O->getRelocation(Rel);
6115*9880d681SAndroid Build Coastguard Worker         if (info->O->isRelocationScattered(RE))
6116*9880d681SAndroid Build Coastguard Worker           continue;
6117*9880d681SAndroid Build Coastguard Worker         isExtern = info->O->getPlainRelocationExternal(RE);
6118*9880d681SAndroid Build Coastguard Worker         if (isExtern) {
6119*9880d681SAndroid Build Coastguard Worker           symbol_iterator RelocSym = Reloc.getSymbol();
6120*9880d681SAndroid Build Coastguard Worker           Symbol = *RelocSym;
6121*9880d681SAndroid Build Coastguard Worker         }
6122*9880d681SAndroid Build Coastguard Worker         reloc_found = true;
6123*9880d681SAndroid Build Coastguard Worker         break;
6124*9880d681SAndroid Build Coastguard Worker       }
6125*9880d681SAndroid Build Coastguard Worker     }
6126*9880d681SAndroid Build Coastguard Worker     // If there is an external relocation entry for a symbol in a section
6127*9880d681SAndroid Build Coastguard Worker     // then used that symbol's value for the value of the reference.
6128*9880d681SAndroid Build Coastguard Worker     if (reloc_found && isExtern) {
6129*9880d681SAndroid Build Coastguard Worker       if (info->O->getAnyRelocationPCRel(RE)) {
6130*9880d681SAndroid Build Coastguard Worker         unsigned Type = info->O->getAnyRelocationType(RE);
6131*9880d681SAndroid Build Coastguard Worker         if (Type == MachO::X86_64_RELOC_SIGNED) {
6132*9880d681SAndroid Build Coastguard Worker           ReferenceValue = Symbol.getValue();
6133*9880d681SAndroid Build Coastguard Worker         }
6134*9880d681SAndroid Build Coastguard Worker       }
6135*9880d681SAndroid Build Coastguard Worker     }
6136*9880d681SAndroid Build Coastguard Worker   }
6137*9880d681SAndroid Build Coastguard Worker 
6138*9880d681SAndroid Build Coastguard Worker   // Look for literals such as Objective-C CFStrings refs, Selector refs,
6139*9880d681SAndroid Build Coastguard Worker   // Message refs and Class refs.
6140*9880d681SAndroid Build Coastguard Worker   bool classref, selref, msgref, cfstring;
6141*9880d681SAndroid Build Coastguard Worker   uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6142*9880d681SAndroid Build Coastguard Worker                                                selref, msgref, cfstring);
6143*9880d681SAndroid Build Coastguard Worker   if (classref && pointer_value == 0) {
6144*9880d681SAndroid Build Coastguard Worker     // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6145*9880d681SAndroid Build Coastguard Worker     // And the pointer_value in that section is typically zero as it will be
6146*9880d681SAndroid Build Coastguard Worker     // set by dyld as part of the "bind information".
6147*9880d681SAndroid Build Coastguard Worker     const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6148*9880d681SAndroid Build Coastguard Worker     if (name != nullptr) {
6149*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6150*9880d681SAndroid Build Coastguard Worker       const char *class_name = strrchr(name, '$');
6151*9880d681SAndroid Build Coastguard Worker       if (class_name != nullptr && class_name[1] == '_' &&
6152*9880d681SAndroid Build Coastguard Worker           class_name[2] != '\0') {
6153*9880d681SAndroid Build Coastguard Worker         info->class_name = class_name + 2;
6154*9880d681SAndroid Build Coastguard Worker         return name;
6155*9880d681SAndroid Build Coastguard Worker       }
6156*9880d681SAndroid Build Coastguard Worker     }
6157*9880d681SAndroid Build Coastguard Worker   }
6158*9880d681SAndroid Build Coastguard Worker 
6159*9880d681SAndroid Build Coastguard Worker   if (classref) {
6160*9880d681SAndroid Build Coastguard Worker     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6161*9880d681SAndroid Build Coastguard Worker     const char *name =
6162*9880d681SAndroid Build Coastguard Worker         get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6163*9880d681SAndroid Build Coastguard Worker     if (name != nullptr)
6164*9880d681SAndroid Build Coastguard Worker       info->class_name = name;
6165*9880d681SAndroid Build Coastguard Worker     else
6166*9880d681SAndroid Build Coastguard Worker       name = "bad class ref";
6167*9880d681SAndroid Build Coastguard Worker     return name;
6168*9880d681SAndroid Build Coastguard Worker   }
6169*9880d681SAndroid Build Coastguard Worker 
6170*9880d681SAndroid Build Coastguard Worker   if (cfstring) {
6171*9880d681SAndroid Build Coastguard Worker     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
6172*9880d681SAndroid Build Coastguard Worker     const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6173*9880d681SAndroid Build Coastguard Worker     return name;
6174*9880d681SAndroid Build Coastguard Worker   }
6175*9880d681SAndroid Build Coastguard Worker 
6176*9880d681SAndroid Build Coastguard Worker   if (selref && pointer_value == 0)
6177*9880d681SAndroid Build Coastguard Worker     pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6178*9880d681SAndroid Build Coastguard Worker 
6179*9880d681SAndroid Build Coastguard Worker   if (pointer_value != 0)
6180*9880d681SAndroid Build Coastguard Worker     ReferenceValue = pointer_value;
6181*9880d681SAndroid Build Coastguard Worker 
6182*9880d681SAndroid Build Coastguard Worker   const char *name = GuessCstringPointer(ReferenceValue, info);
6183*9880d681SAndroid Build Coastguard Worker   if (name) {
6184*9880d681SAndroid Build Coastguard Worker     if (pointer_value != 0 && selref) {
6185*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
6186*9880d681SAndroid Build Coastguard Worker       info->selector_name = name;
6187*9880d681SAndroid Build Coastguard Worker     } else if (pointer_value != 0 && msgref) {
6188*9880d681SAndroid Build Coastguard Worker       info->class_name = nullptr;
6189*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
6190*9880d681SAndroid Build Coastguard Worker       info->selector_name = name;
6191*9880d681SAndroid Build Coastguard Worker     } else
6192*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
6193*9880d681SAndroid Build Coastguard Worker     return name;
6194*9880d681SAndroid Build Coastguard Worker   }
6195*9880d681SAndroid Build Coastguard Worker 
6196*9880d681SAndroid Build Coastguard Worker   // Lastly look for an indirect symbol with this ReferenceValue which is in
6197*9880d681SAndroid Build Coastguard Worker   // a literal pool.  If found return that symbol name.
6198*9880d681SAndroid Build Coastguard Worker   name = GuessIndirectSymbol(ReferenceValue, info);
6199*9880d681SAndroid Build Coastguard Worker   if (name) {
6200*9880d681SAndroid Build Coastguard Worker     *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
6201*9880d681SAndroid Build Coastguard Worker     return name;
6202*9880d681SAndroid Build Coastguard Worker   }
6203*9880d681SAndroid Build Coastguard Worker 
6204*9880d681SAndroid Build Coastguard Worker   return nullptr;
6205*9880d681SAndroid Build Coastguard Worker }
6206*9880d681SAndroid Build Coastguard Worker 
6207*9880d681SAndroid Build Coastguard Worker // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6208*9880d681SAndroid Build Coastguard Worker // the Symbolizer.  It looks up the ReferenceValue using the info passed via the
6209*9880d681SAndroid Build Coastguard Worker // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6210*9880d681SAndroid Build Coastguard Worker // is created and returns the symbol name that matches the ReferenceValue or
6211*9880d681SAndroid Build Coastguard Worker // nullptr if none.  The ReferenceType is passed in for the IN type of
6212*9880d681SAndroid Build Coastguard Worker // reference the instruction is making from the values in defined in the header
6213*9880d681SAndroid Build Coastguard Worker // "llvm-c/Disassembler.h".  On return the ReferenceType can set to a specific
6214*9880d681SAndroid Build Coastguard Worker // Out type and the ReferenceName will also be set which is added as a comment
6215*9880d681SAndroid Build Coastguard Worker // to the disassembled instruction.
6216*9880d681SAndroid Build Coastguard Worker //
6217*9880d681SAndroid Build Coastguard Worker #if HAVE_CXXABI_H
6218*9880d681SAndroid Build Coastguard Worker // If the symbol name is a C++ mangled name then the demangled name is
6219*9880d681SAndroid Build Coastguard Worker // returned through ReferenceName and ReferenceType is set to
6220*9880d681SAndroid Build Coastguard Worker // LLVMDisassembler_ReferenceType_DeMangled_Name .
6221*9880d681SAndroid Build Coastguard Worker #endif
6222*9880d681SAndroid Build Coastguard Worker //
6223*9880d681SAndroid Build Coastguard Worker // When this is called to get a symbol name for a branch target then the
6224*9880d681SAndroid Build Coastguard Worker // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6225*9880d681SAndroid Build Coastguard Worker // SymbolValue will be looked for in the indirect symbol table to determine if
6226*9880d681SAndroid Build Coastguard Worker // it is an address for a symbol stub.  If so then the symbol name for that
6227*9880d681SAndroid Build Coastguard Worker // stub is returned indirectly through ReferenceName and then ReferenceType is
6228*9880d681SAndroid Build Coastguard Worker // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6229*9880d681SAndroid Build Coastguard Worker //
6230*9880d681SAndroid Build Coastguard Worker // When this is called with an value loaded via a PC relative load then
6231*9880d681SAndroid Build Coastguard Worker // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6232*9880d681SAndroid Build Coastguard Worker // SymbolValue is checked to be an address of literal pointer, symbol pointer,
6233*9880d681SAndroid Build Coastguard Worker // or an Objective-C meta data reference.  If so the output ReferenceType is
6234*9880d681SAndroid Build Coastguard Worker // set to correspond to that as well as setting the ReferenceName.
SymbolizerSymbolLookUp(void * DisInfo,uint64_t ReferenceValue,uint64_t * ReferenceType,uint64_t ReferencePC,const char ** ReferenceName)6235*9880d681SAndroid Build Coastguard Worker static const char *SymbolizerSymbolLookUp(void *DisInfo,
6236*9880d681SAndroid Build Coastguard Worker                                           uint64_t ReferenceValue,
6237*9880d681SAndroid Build Coastguard Worker                                           uint64_t *ReferenceType,
6238*9880d681SAndroid Build Coastguard Worker                                           uint64_t ReferencePC,
6239*9880d681SAndroid Build Coastguard Worker                                           const char **ReferenceName) {
6240*9880d681SAndroid Build Coastguard Worker   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6241*9880d681SAndroid Build Coastguard Worker   // If no verbose symbolic information is wanted then just return nullptr.
6242*9880d681SAndroid Build Coastguard Worker   if (!info->verbose) {
6243*9880d681SAndroid Build Coastguard Worker     *ReferenceName = nullptr;
6244*9880d681SAndroid Build Coastguard Worker     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6245*9880d681SAndroid Build Coastguard Worker     return nullptr;
6246*9880d681SAndroid Build Coastguard Worker   }
6247*9880d681SAndroid Build Coastguard Worker 
6248*9880d681SAndroid Build Coastguard Worker   const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6249*9880d681SAndroid Build Coastguard Worker 
6250*9880d681SAndroid Build Coastguard Worker   if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
6251*9880d681SAndroid Build Coastguard Worker     *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6252*9880d681SAndroid Build Coastguard Worker     if (*ReferenceName != nullptr) {
6253*9880d681SAndroid Build Coastguard Worker       method_reference(info, ReferenceType, ReferenceName);
6254*9880d681SAndroid Build Coastguard Worker       if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
6255*9880d681SAndroid Build Coastguard Worker         *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
6256*9880d681SAndroid Build Coastguard Worker     } else
6257*9880d681SAndroid Build Coastguard Worker #if HAVE_CXXABI_H
6258*9880d681SAndroid Build Coastguard Worker         if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6259*9880d681SAndroid Build Coastguard Worker       if (info->demangled_name != nullptr)
6260*9880d681SAndroid Build Coastguard Worker         free(info->demangled_name);
6261*9880d681SAndroid Build Coastguard Worker       int status;
6262*9880d681SAndroid Build Coastguard Worker       info->demangled_name =
6263*9880d681SAndroid Build Coastguard Worker           abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status);
6264*9880d681SAndroid Build Coastguard Worker       if (info->demangled_name != nullptr) {
6265*9880d681SAndroid Build Coastguard Worker         *ReferenceName = info->demangled_name;
6266*9880d681SAndroid Build Coastguard Worker         *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6267*9880d681SAndroid Build Coastguard Worker       } else
6268*9880d681SAndroid Build Coastguard Worker         *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6269*9880d681SAndroid Build Coastguard Worker     } else
6270*9880d681SAndroid Build Coastguard Worker #endif
6271*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6272*9880d681SAndroid Build Coastguard Worker   } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
6273*9880d681SAndroid Build Coastguard Worker     *ReferenceName =
6274*9880d681SAndroid Build Coastguard Worker         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6275*9880d681SAndroid Build Coastguard Worker     if (*ReferenceName)
6276*9880d681SAndroid Build Coastguard Worker       method_reference(info, ReferenceType, ReferenceName);
6277*9880d681SAndroid Build Coastguard Worker     else
6278*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6279*9880d681SAndroid Build Coastguard Worker     // If this is arm64 and the reference is an adrp instruction save the
6280*9880d681SAndroid Build Coastguard Worker     // instruction, passed in ReferenceValue and the address of the instruction
6281*9880d681SAndroid Build Coastguard Worker     // for use later if we see and add immediate instruction.
6282*9880d681SAndroid Build Coastguard Worker   } else if (info->O->getArch() == Triple::aarch64 &&
6283*9880d681SAndroid Build Coastguard Worker              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
6284*9880d681SAndroid Build Coastguard Worker     info->adrp_inst = ReferenceValue;
6285*9880d681SAndroid Build Coastguard Worker     info->adrp_addr = ReferencePC;
6286*9880d681SAndroid Build Coastguard Worker     SymbolName = nullptr;
6287*9880d681SAndroid Build Coastguard Worker     *ReferenceName = nullptr;
6288*9880d681SAndroid Build Coastguard Worker     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6289*9880d681SAndroid Build Coastguard Worker     // If this is arm64 and reference is an add immediate instruction and we
6290*9880d681SAndroid Build Coastguard Worker     // have
6291*9880d681SAndroid Build Coastguard Worker     // seen an adrp instruction just before it and the adrp's Xd register
6292*9880d681SAndroid Build Coastguard Worker     // matches
6293*9880d681SAndroid Build Coastguard Worker     // this add's Xn register reconstruct the value being referenced and look to
6294*9880d681SAndroid Build Coastguard Worker     // see if it is a literal pointer.  Note the add immediate instruction is
6295*9880d681SAndroid Build Coastguard Worker     // passed in ReferenceValue.
6296*9880d681SAndroid Build Coastguard Worker   } else if (info->O->getArch() == Triple::aarch64 &&
6297*9880d681SAndroid Build Coastguard Worker              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
6298*9880d681SAndroid Build Coastguard Worker              ReferencePC - 4 == info->adrp_addr &&
6299*9880d681SAndroid Build Coastguard Worker              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6300*9880d681SAndroid Build Coastguard Worker              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6301*9880d681SAndroid Build Coastguard Worker     uint32_t addxri_inst;
6302*9880d681SAndroid Build Coastguard Worker     uint64_t adrp_imm, addxri_imm;
6303*9880d681SAndroid Build Coastguard Worker 
6304*9880d681SAndroid Build Coastguard Worker     adrp_imm =
6305*9880d681SAndroid Build Coastguard Worker         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6306*9880d681SAndroid Build Coastguard Worker     if (info->adrp_inst & 0x0200000)
6307*9880d681SAndroid Build Coastguard Worker       adrp_imm |= 0xfffffffffc000000LL;
6308*9880d681SAndroid Build Coastguard Worker 
6309*9880d681SAndroid Build Coastguard Worker     addxri_inst = ReferenceValue;
6310*9880d681SAndroid Build Coastguard Worker     addxri_imm = (addxri_inst >> 10) & 0xfff;
6311*9880d681SAndroid Build Coastguard Worker     if (((addxri_inst >> 22) & 0x3) == 1)
6312*9880d681SAndroid Build Coastguard Worker       addxri_imm <<= 12;
6313*9880d681SAndroid Build Coastguard Worker 
6314*9880d681SAndroid Build Coastguard Worker     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6315*9880d681SAndroid Build Coastguard Worker                      (adrp_imm << 12) + addxri_imm;
6316*9880d681SAndroid Build Coastguard Worker 
6317*9880d681SAndroid Build Coastguard Worker     *ReferenceName =
6318*9880d681SAndroid Build Coastguard Worker         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6319*9880d681SAndroid Build Coastguard Worker     if (*ReferenceName == nullptr)
6320*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6321*9880d681SAndroid Build Coastguard Worker     // If this is arm64 and the reference is a load register instruction and we
6322*9880d681SAndroid Build Coastguard Worker     // have seen an adrp instruction just before it and the adrp's Xd register
6323*9880d681SAndroid Build Coastguard Worker     // matches this add's Xn register reconstruct the value being referenced and
6324*9880d681SAndroid Build Coastguard Worker     // look to see if it is a literal pointer.  Note the load register
6325*9880d681SAndroid Build Coastguard Worker     // instruction is passed in ReferenceValue.
6326*9880d681SAndroid Build Coastguard Worker   } else if (info->O->getArch() == Triple::aarch64 &&
6327*9880d681SAndroid Build Coastguard Worker              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
6328*9880d681SAndroid Build Coastguard Worker              ReferencePC - 4 == info->adrp_addr &&
6329*9880d681SAndroid Build Coastguard Worker              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6330*9880d681SAndroid Build Coastguard Worker              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6331*9880d681SAndroid Build Coastguard Worker     uint32_t ldrxui_inst;
6332*9880d681SAndroid Build Coastguard Worker     uint64_t adrp_imm, ldrxui_imm;
6333*9880d681SAndroid Build Coastguard Worker 
6334*9880d681SAndroid Build Coastguard Worker     adrp_imm =
6335*9880d681SAndroid Build Coastguard Worker         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6336*9880d681SAndroid Build Coastguard Worker     if (info->adrp_inst & 0x0200000)
6337*9880d681SAndroid Build Coastguard Worker       adrp_imm |= 0xfffffffffc000000LL;
6338*9880d681SAndroid Build Coastguard Worker 
6339*9880d681SAndroid Build Coastguard Worker     ldrxui_inst = ReferenceValue;
6340*9880d681SAndroid Build Coastguard Worker     ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
6341*9880d681SAndroid Build Coastguard Worker 
6342*9880d681SAndroid Build Coastguard Worker     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6343*9880d681SAndroid Build Coastguard Worker                      (adrp_imm << 12) + (ldrxui_imm << 3);
6344*9880d681SAndroid Build Coastguard Worker 
6345*9880d681SAndroid Build Coastguard Worker     *ReferenceName =
6346*9880d681SAndroid Build Coastguard Worker         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6347*9880d681SAndroid Build Coastguard Worker     if (*ReferenceName == nullptr)
6348*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6349*9880d681SAndroid Build Coastguard Worker   }
6350*9880d681SAndroid Build Coastguard Worker   // If this arm64 and is an load register (PC-relative) instruction the
6351*9880d681SAndroid Build Coastguard Worker   // ReferenceValue is the PC plus the immediate value.
6352*9880d681SAndroid Build Coastguard Worker   else if (info->O->getArch() == Triple::aarch64 &&
6353*9880d681SAndroid Build Coastguard Worker            (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
6354*9880d681SAndroid Build Coastguard Worker             *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
6355*9880d681SAndroid Build Coastguard Worker     *ReferenceName =
6356*9880d681SAndroid Build Coastguard Worker         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6357*9880d681SAndroid Build Coastguard Worker     if (*ReferenceName == nullptr)
6358*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6359*9880d681SAndroid Build Coastguard Worker   }
6360*9880d681SAndroid Build Coastguard Worker #if HAVE_CXXABI_H
6361*9880d681SAndroid Build Coastguard Worker   else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6362*9880d681SAndroid Build Coastguard Worker     if (info->demangled_name != nullptr)
6363*9880d681SAndroid Build Coastguard Worker       free(info->demangled_name);
6364*9880d681SAndroid Build Coastguard Worker     int status;
6365*9880d681SAndroid Build Coastguard Worker     info->demangled_name =
6366*9880d681SAndroid Build Coastguard Worker         abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status);
6367*9880d681SAndroid Build Coastguard Worker     if (info->demangled_name != nullptr) {
6368*9880d681SAndroid Build Coastguard Worker       *ReferenceName = info->demangled_name;
6369*9880d681SAndroid Build Coastguard Worker       *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6370*9880d681SAndroid Build Coastguard Worker     }
6371*9880d681SAndroid Build Coastguard Worker   }
6372*9880d681SAndroid Build Coastguard Worker #endif
6373*9880d681SAndroid Build Coastguard Worker   else {
6374*9880d681SAndroid Build Coastguard Worker     *ReferenceName = nullptr;
6375*9880d681SAndroid Build Coastguard Worker     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6376*9880d681SAndroid Build Coastguard Worker   }
6377*9880d681SAndroid Build Coastguard Worker 
6378*9880d681SAndroid Build Coastguard Worker   return SymbolName;
6379*9880d681SAndroid Build Coastguard Worker }
6380*9880d681SAndroid Build Coastguard Worker 
6381*9880d681SAndroid Build Coastguard Worker /// \brief Emits the comments that are stored in the CommentStream.
6382*9880d681SAndroid Build Coastguard Worker /// Each comment in the CommentStream must end with a newline.
emitComments(raw_svector_ostream & CommentStream,SmallString<128> & CommentsToEmit,formatted_raw_ostream & FormattedOS,const MCAsmInfo & MAI)6383*9880d681SAndroid Build Coastguard Worker static void emitComments(raw_svector_ostream &CommentStream,
6384*9880d681SAndroid Build Coastguard Worker                          SmallString<128> &CommentsToEmit,
6385*9880d681SAndroid Build Coastguard Worker                          formatted_raw_ostream &FormattedOS,
6386*9880d681SAndroid Build Coastguard Worker                          const MCAsmInfo &MAI) {
6387*9880d681SAndroid Build Coastguard Worker   // Flush the stream before taking its content.
6388*9880d681SAndroid Build Coastguard Worker   StringRef Comments = CommentsToEmit.str();
6389*9880d681SAndroid Build Coastguard Worker   // Get the default information for printing a comment.
6390*9880d681SAndroid Build Coastguard Worker   const char *CommentBegin = MAI.getCommentString();
6391*9880d681SAndroid Build Coastguard Worker   unsigned CommentColumn = MAI.getCommentColumn();
6392*9880d681SAndroid Build Coastguard Worker   bool IsFirst = true;
6393*9880d681SAndroid Build Coastguard Worker   while (!Comments.empty()) {
6394*9880d681SAndroid Build Coastguard Worker     if (!IsFirst)
6395*9880d681SAndroid Build Coastguard Worker       FormattedOS << '\n';
6396*9880d681SAndroid Build Coastguard Worker     // Emit a line of comments.
6397*9880d681SAndroid Build Coastguard Worker     FormattedOS.PadToColumn(CommentColumn);
6398*9880d681SAndroid Build Coastguard Worker     size_t Position = Comments.find('\n');
6399*9880d681SAndroid Build Coastguard Worker     FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
6400*9880d681SAndroid Build Coastguard Worker     // Move after the newline character.
6401*9880d681SAndroid Build Coastguard Worker     Comments = Comments.substr(Position + 1);
6402*9880d681SAndroid Build Coastguard Worker     IsFirst = false;
6403*9880d681SAndroid Build Coastguard Worker   }
6404*9880d681SAndroid Build Coastguard Worker   FormattedOS.flush();
6405*9880d681SAndroid Build Coastguard Worker 
6406*9880d681SAndroid Build Coastguard Worker   // Tell the comment stream that the vector changed underneath it.
6407*9880d681SAndroid Build Coastguard Worker   CommentsToEmit.clear();
6408*9880d681SAndroid Build Coastguard Worker }
6409*9880d681SAndroid Build Coastguard Worker 
DisassembleMachO(StringRef Filename,MachOObjectFile * MachOOF,StringRef DisSegName,StringRef DisSectName)6410*9880d681SAndroid Build Coastguard Worker static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
6411*9880d681SAndroid Build Coastguard Worker                              StringRef DisSegName, StringRef DisSectName) {
6412*9880d681SAndroid Build Coastguard Worker   const char *McpuDefault = nullptr;
6413*9880d681SAndroid Build Coastguard Worker   const Target *ThumbTarget = nullptr;
6414*9880d681SAndroid Build Coastguard Worker   const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
6415*9880d681SAndroid Build Coastguard Worker   if (!TheTarget) {
6416*9880d681SAndroid Build Coastguard Worker     // GetTarget prints out stuff.
6417*9880d681SAndroid Build Coastguard Worker     return;
6418*9880d681SAndroid Build Coastguard Worker   }
6419*9880d681SAndroid Build Coastguard Worker   if (MCPU.empty() && McpuDefault)
6420*9880d681SAndroid Build Coastguard Worker     MCPU = McpuDefault;
6421*9880d681SAndroid Build Coastguard Worker 
6422*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
6423*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
6424*9880d681SAndroid Build Coastguard Worker   if (ThumbTarget)
6425*9880d681SAndroid Build Coastguard Worker     ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
6426*9880d681SAndroid Build Coastguard Worker 
6427*9880d681SAndroid Build Coastguard Worker   // Package up features to be passed to target/subtarget
6428*9880d681SAndroid Build Coastguard Worker   std::string FeaturesStr;
6429*9880d681SAndroid Build Coastguard Worker   if (MAttrs.size()) {
6430*9880d681SAndroid Build Coastguard Worker     SubtargetFeatures Features;
6431*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i != MAttrs.size(); ++i)
6432*9880d681SAndroid Build Coastguard Worker       Features.AddFeature(MAttrs[i]);
6433*9880d681SAndroid Build Coastguard Worker     FeaturesStr = Features.getString();
6434*9880d681SAndroid Build Coastguard Worker   }
6435*9880d681SAndroid Build Coastguard Worker 
6436*9880d681SAndroid Build Coastguard Worker   // Set up disassembler.
6437*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<const MCRegisterInfo> MRI(
6438*9880d681SAndroid Build Coastguard Worker       TheTarget->createMCRegInfo(TripleName));
6439*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<const MCAsmInfo> AsmInfo(
6440*9880d681SAndroid Build Coastguard Worker       TheTarget->createMCAsmInfo(*MRI, TripleName));
6441*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<const MCSubtargetInfo> STI(
6442*9880d681SAndroid Build Coastguard Worker       TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
6443*9880d681SAndroid Build Coastguard Worker   MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
6444*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCDisassembler> DisAsm(
6445*9880d681SAndroid Build Coastguard Worker       TheTarget->createMCDisassembler(*STI, Ctx));
6446*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCSymbolizer> Symbolizer;
6447*9880d681SAndroid Build Coastguard Worker   struct DisassembleInfo SymbolizerInfo;
6448*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCRelocationInfo> RelInfo(
6449*9880d681SAndroid Build Coastguard Worker       TheTarget->createMCRelocationInfo(TripleName, Ctx));
6450*9880d681SAndroid Build Coastguard Worker   if (RelInfo) {
6451*9880d681SAndroid Build Coastguard Worker     Symbolizer.reset(TheTarget->createMCSymbolizer(
6452*9880d681SAndroid Build Coastguard Worker         TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6453*9880d681SAndroid Build Coastguard Worker         &SymbolizerInfo, &Ctx, std::move(RelInfo)));
6454*9880d681SAndroid Build Coastguard Worker     DisAsm->setSymbolizer(std::move(Symbolizer));
6455*9880d681SAndroid Build Coastguard Worker   }
6456*9880d681SAndroid Build Coastguard Worker   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
6457*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
6458*9880d681SAndroid Build Coastguard Worker       Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
6459*9880d681SAndroid Build Coastguard Worker   // Set the display preference for hex vs. decimal immediates.
6460*9880d681SAndroid Build Coastguard Worker   IP->setPrintImmHex(PrintImmHex);
6461*9880d681SAndroid Build Coastguard Worker   // Comment stream and backing vector.
6462*9880d681SAndroid Build Coastguard Worker   SmallString<128> CommentsToEmit;
6463*9880d681SAndroid Build Coastguard Worker   raw_svector_ostream CommentStream(CommentsToEmit);
6464*9880d681SAndroid Build Coastguard Worker   // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
6465*9880d681SAndroid Build Coastguard Worker   // if it is done then arm64 comments for string literals don't get printed
6466*9880d681SAndroid Build Coastguard Worker   // and some constant get printed instead and not setting it causes intel
6467*9880d681SAndroid Build Coastguard Worker   // (32-bit and 64-bit) comments printed with different spacing before the
6468*9880d681SAndroid Build Coastguard Worker   // comment causing different diffs with the 'C' disassembler library API.
6469*9880d681SAndroid Build Coastguard Worker   // IP->setCommentStream(CommentStream);
6470*9880d681SAndroid Build Coastguard Worker 
6471*9880d681SAndroid Build Coastguard Worker   if (!AsmInfo || !STI || !DisAsm || !IP) {
6472*9880d681SAndroid Build Coastguard Worker     errs() << "error: couldn't initialize disassembler for target "
6473*9880d681SAndroid Build Coastguard Worker            << TripleName << '\n';
6474*9880d681SAndroid Build Coastguard Worker     return;
6475*9880d681SAndroid Build Coastguard Worker   }
6476*9880d681SAndroid Build Coastguard Worker 
6477*9880d681SAndroid Build Coastguard Worker   // Set up separate thumb disassembler if needed.
6478*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<const MCRegisterInfo> ThumbMRI;
6479*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
6480*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
6481*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCDisassembler> ThumbDisAsm;
6482*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCInstPrinter> ThumbIP;
6483*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCContext> ThumbCtx;
6484*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
6485*9880d681SAndroid Build Coastguard Worker   struct DisassembleInfo ThumbSymbolizerInfo;
6486*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
6487*9880d681SAndroid Build Coastguard Worker   if (ThumbTarget) {
6488*9880d681SAndroid Build Coastguard Worker     ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
6489*9880d681SAndroid Build Coastguard Worker     ThumbAsmInfo.reset(
6490*9880d681SAndroid Build Coastguard Worker         ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName));
6491*9880d681SAndroid Build Coastguard Worker     ThumbSTI.reset(
6492*9880d681SAndroid Build Coastguard Worker         ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MCPU, FeaturesStr));
6493*9880d681SAndroid Build Coastguard Worker     ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
6494*9880d681SAndroid Build Coastguard Worker     ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
6495*9880d681SAndroid Build Coastguard Worker     MCContext *PtrThumbCtx = ThumbCtx.get();
6496*9880d681SAndroid Build Coastguard Worker     ThumbRelInfo.reset(
6497*9880d681SAndroid Build Coastguard Worker         ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
6498*9880d681SAndroid Build Coastguard Worker     if (ThumbRelInfo) {
6499*9880d681SAndroid Build Coastguard Worker       ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
6500*9880d681SAndroid Build Coastguard Worker           ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6501*9880d681SAndroid Build Coastguard Worker           &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
6502*9880d681SAndroid Build Coastguard Worker       ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
6503*9880d681SAndroid Build Coastguard Worker     }
6504*9880d681SAndroid Build Coastguard Worker     int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
6505*9880d681SAndroid Build Coastguard Worker     ThumbIP.reset(ThumbTarget->createMCInstPrinter(
6506*9880d681SAndroid Build Coastguard Worker         Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
6507*9880d681SAndroid Build Coastguard Worker         *ThumbInstrInfo, *ThumbMRI));
6508*9880d681SAndroid Build Coastguard Worker     // Set the display preference for hex vs. decimal immediates.
6509*9880d681SAndroid Build Coastguard Worker     ThumbIP->setPrintImmHex(PrintImmHex);
6510*9880d681SAndroid Build Coastguard Worker   }
6511*9880d681SAndroid Build Coastguard Worker 
6512*9880d681SAndroid Build Coastguard Worker   if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) {
6513*9880d681SAndroid Build Coastguard Worker     errs() << "error: couldn't initialize disassembler for target "
6514*9880d681SAndroid Build Coastguard Worker            << ThumbTripleName << '\n';
6515*9880d681SAndroid Build Coastguard Worker     return;
6516*9880d681SAndroid Build Coastguard Worker   }
6517*9880d681SAndroid Build Coastguard Worker 
6518*9880d681SAndroid Build Coastguard Worker   MachO::mach_header Header = MachOOF->getHeader();
6519*9880d681SAndroid Build Coastguard Worker 
6520*9880d681SAndroid Build Coastguard Worker   // FIXME: Using the -cfg command line option, this code used to be able to
6521*9880d681SAndroid Build Coastguard Worker   // annotate relocations with the referenced symbol's name, and if this was
6522*9880d681SAndroid Build Coastguard Worker   // inside a __[cf]string section, the data it points to. This is now replaced
6523*9880d681SAndroid Build Coastguard Worker   // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
6524*9880d681SAndroid Build Coastguard Worker   std::vector<SectionRef> Sections;
6525*9880d681SAndroid Build Coastguard Worker   std::vector<SymbolRef> Symbols;
6526*9880d681SAndroid Build Coastguard Worker   SmallVector<uint64_t, 8> FoundFns;
6527*9880d681SAndroid Build Coastguard Worker   uint64_t BaseSegmentAddress;
6528*9880d681SAndroid Build Coastguard Worker 
6529*9880d681SAndroid Build Coastguard Worker   getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
6530*9880d681SAndroid Build Coastguard Worker                         BaseSegmentAddress);
6531*9880d681SAndroid Build Coastguard Worker 
6532*9880d681SAndroid Build Coastguard Worker   // Sort the symbols by address, just in case they didn't come in that way.
6533*9880d681SAndroid Build Coastguard Worker   std::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
6534*9880d681SAndroid Build Coastguard Worker 
6535*9880d681SAndroid Build Coastguard Worker   // Build a data in code table that is sorted on by the address of each entry.
6536*9880d681SAndroid Build Coastguard Worker   uint64_t BaseAddress = 0;
6537*9880d681SAndroid Build Coastguard Worker   if (Header.filetype == MachO::MH_OBJECT)
6538*9880d681SAndroid Build Coastguard Worker     BaseAddress = Sections[0].getAddress();
6539*9880d681SAndroid Build Coastguard Worker   else
6540*9880d681SAndroid Build Coastguard Worker     BaseAddress = BaseSegmentAddress;
6541*9880d681SAndroid Build Coastguard Worker   DiceTable Dices;
6542*9880d681SAndroid Build Coastguard Worker   for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
6543*9880d681SAndroid Build Coastguard Worker        DI != DE; ++DI) {
6544*9880d681SAndroid Build Coastguard Worker     uint32_t Offset;
6545*9880d681SAndroid Build Coastguard Worker     DI->getOffset(Offset);
6546*9880d681SAndroid Build Coastguard Worker     Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
6547*9880d681SAndroid Build Coastguard Worker   }
6548*9880d681SAndroid Build Coastguard Worker   array_pod_sort(Dices.begin(), Dices.end());
6549*9880d681SAndroid Build Coastguard Worker 
6550*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
6551*9880d681SAndroid Build Coastguard Worker   raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
6552*9880d681SAndroid Build Coastguard Worker #else
6553*9880d681SAndroid Build Coastguard Worker   raw_ostream &DebugOut = nulls();
6554*9880d681SAndroid Build Coastguard Worker #endif
6555*9880d681SAndroid Build Coastguard Worker 
6556*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<DIContext> diContext;
6557*9880d681SAndroid Build Coastguard Worker   ObjectFile *DbgObj = MachOOF;
6558*9880d681SAndroid Build Coastguard Worker   // Try to find debug info and set up the DIContext for it.
6559*9880d681SAndroid Build Coastguard Worker   if (UseDbg) {
6560*9880d681SAndroid Build Coastguard Worker     // A separate DSym file path was specified, parse it as a macho file,
6561*9880d681SAndroid Build Coastguard Worker     // get the sections and supply it to the section name parsing machinery.
6562*9880d681SAndroid Build Coastguard Worker     if (!DSYMFile.empty()) {
6563*9880d681SAndroid Build Coastguard Worker       ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
6564*9880d681SAndroid Build Coastguard Worker           MemoryBuffer::getFileOrSTDIN(DSYMFile);
6565*9880d681SAndroid Build Coastguard Worker       if (std::error_code EC = BufOrErr.getError()) {
6566*9880d681SAndroid Build Coastguard Worker         errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
6567*9880d681SAndroid Build Coastguard Worker         return;
6568*9880d681SAndroid Build Coastguard Worker       }
6569*9880d681SAndroid Build Coastguard Worker       DbgObj =
6570*9880d681SAndroid Build Coastguard Worker           ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef())
6571*9880d681SAndroid Build Coastguard Worker               .get()
6572*9880d681SAndroid Build Coastguard Worker               .release();
6573*9880d681SAndroid Build Coastguard Worker     }
6574*9880d681SAndroid Build Coastguard Worker 
6575*9880d681SAndroid Build Coastguard Worker     // Setup the DIContext
6576*9880d681SAndroid Build Coastguard Worker     diContext.reset(new DWARFContextInMemory(*DbgObj));
6577*9880d681SAndroid Build Coastguard Worker   }
6578*9880d681SAndroid Build Coastguard Worker 
6579*9880d681SAndroid Build Coastguard Worker   if (FilterSections.size() == 0)
6580*9880d681SAndroid Build Coastguard Worker     outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
6581*9880d681SAndroid Build Coastguard Worker 
6582*9880d681SAndroid Build Coastguard Worker   for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
6583*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
6584*9880d681SAndroid Build Coastguard Worker     if (Sections[SectIdx].getName(SectName) || SectName != DisSectName)
6585*9880d681SAndroid Build Coastguard Worker       continue;
6586*9880d681SAndroid Build Coastguard Worker 
6587*9880d681SAndroid Build Coastguard Worker     DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
6588*9880d681SAndroid Build Coastguard Worker 
6589*9880d681SAndroid Build Coastguard Worker     StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
6590*9880d681SAndroid Build Coastguard Worker     if (SegmentName != DisSegName)
6591*9880d681SAndroid Build Coastguard Worker       continue;
6592*9880d681SAndroid Build Coastguard Worker 
6593*9880d681SAndroid Build Coastguard Worker     StringRef BytesStr;
6594*9880d681SAndroid Build Coastguard Worker     Sections[SectIdx].getContents(BytesStr);
6595*9880d681SAndroid Build Coastguard Worker     ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
6596*9880d681SAndroid Build Coastguard Worker                             BytesStr.size());
6597*9880d681SAndroid Build Coastguard Worker     uint64_t SectAddress = Sections[SectIdx].getAddress();
6598*9880d681SAndroid Build Coastguard Worker 
6599*9880d681SAndroid Build Coastguard Worker     bool symbolTableWorked = false;
6600*9880d681SAndroid Build Coastguard Worker 
6601*9880d681SAndroid Build Coastguard Worker     // Create a map of symbol addresses to symbol names for use by
6602*9880d681SAndroid Build Coastguard Worker     // the SymbolizerSymbolLookUp() routine.
6603*9880d681SAndroid Build Coastguard Worker     SymbolAddressMap AddrMap;
6604*9880d681SAndroid Build Coastguard Worker     bool DisSymNameFound = false;
6605*9880d681SAndroid Build Coastguard Worker     for (const SymbolRef &Symbol : MachOOF->symbols()) {
6606*9880d681SAndroid Build Coastguard Worker       Expected<SymbolRef::Type> STOrErr = Symbol.getType();
6607*9880d681SAndroid Build Coastguard Worker       if (!STOrErr) {
6608*9880d681SAndroid Build Coastguard Worker         std::string Buf;
6609*9880d681SAndroid Build Coastguard Worker         raw_string_ostream OS(Buf);
6610*9880d681SAndroid Build Coastguard Worker         logAllUnhandledErrors(STOrErr.takeError(), OS, "");
6611*9880d681SAndroid Build Coastguard Worker         OS.flush();
6612*9880d681SAndroid Build Coastguard Worker         report_fatal_error(Buf);
6613*9880d681SAndroid Build Coastguard Worker       }
6614*9880d681SAndroid Build Coastguard Worker       SymbolRef::Type ST = *STOrErr;
6615*9880d681SAndroid Build Coastguard Worker       if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
6616*9880d681SAndroid Build Coastguard Worker           ST == SymbolRef::ST_Other) {
6617*9880d681SAndroid Build Coastguard Worker         uint64_t Address = Symbol.getValue();
6618*9880d681SAndroid Build Coastguard Worker         Expected<StringRef> SymNameOrErr = Symbol.getName();
6619*9880d681SAndroid Build Coastguard Worker         if (!SymNameOrErr) {
6620*9880d681SAndroid Build Coastguard Worker           std::string Buf;
6621*9880d681SAndroid Build Coastguard Worker           raw_string_ostream OS(Buf);
6622*9880d681SAndroid Build Coastguard Worker           logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
6623*9880d681SAndroid Build Coastguard Worker           OS.flush();
6624*9880d681SAndroid Build Coastguard Worker           report_fatal_error(Buf);
6625*9880d681SAndroid Build Coastguard Worker         }
6626*9880d681SAndroid Build Coastguard Worker         StringRef SymName = *SymNameOrErr;
6627*9880d681SAndroid Build Coastguard Worker         AddrMap[Address] = SymName;
6628*9880d681SAndroid Build Coastguard Worker         if (!DisSymName.empty() && DisSymName == SymName)
6629*9880d681SAndroid Build Coastguard Worker           DisSymNameFound = true;
6630*9880d681SAndroid Build Coastguard Worker       }
6631*9880d681SAndroid Build Coastguard Worker     }
6632*9880d681SAndroid Build Coastguard Worker     if (!DisSymName.empty() && !DisSymNameFound) {
6633*9880d681SAndroid Build Coastguard Worker       outs() << "Can't find -dis-symname: " << DisSymName << "\n";
6634*9880d681SAndroid Build Coastguard Worker       return;
6635*9880d681SAndroid Build Coastguard Worker     }
6636*9880d681SAndroid Build Coastguard Worker     // Set up the block of info used by the Symbolizer call backs.
6637*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.verbose = !NoSymbolicOperands;
6638*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.O = MachOOF;
6639*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.S = Sections[SectIdx];
6640*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.AddrMap = &AddrMap;
6641*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.Sections = &Sections;
6642*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.class_name = nullptr;
6643*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.selector_name = nullptr;
6644*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.method = nullptr;
6645*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.demangled_name = nullptr;
6646*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.bindtable = nullptr;
6647*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.adrp_addr = 0;
6648*9880d681SAndroid Build Coastguard Worker     SymbolizerInfo.adrp_inst = 0;
6649*9880d681SAndroid Build Coastguard Worker     // Same for the ThumbSymbolizer
6650*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
6651*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.O = MachOOF;
6652*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.S = Sections[SectIdx];
6653*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.AddrMap = &AddrMap;
6654*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.Sections = &Sections;
6655*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.class_name = nullptr;
6656*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.selector_name = nullptr;
6657*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.method = nullptr;
6658*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.demangled_name = nullptr;
6659*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.bindtable = nullptr;
6660*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.adrp_addr = 0;
6661*9880d681SAndroid Build Coastguard Worker     ThumbSymbolizerInfo.adrp_inst = 0;
6662*9880d681SAndroid Build Coastguard Worker 
6663*9880d681SAndroid Build Coastguard Worker     unsigned int Arch = MachOOF->getArch();
6664*9880d681SAndroid Build Coastguard Worker 
6665*9880d681SAndroid Build Coastguard Worker     // Disassemble symbol by symbol.
6666*9880d681SAndroid Build Coastguard Worker     for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
6667*9880d681SAndroid Build Coastguard Worker       Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
6668*9880d681SAndroid Build Coastguard Worker       if (!SymNameOrErr) {
6669*9880d681SAndroid Build Coastguard Worker         std::string Buf;
6670*9880d681SAndroid Build Coastguard Worker         raw_string_ostream OS(Buf);
6671*9880d681SAndroid Build Coastguard Worker         logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
6672*9880d681SAndroid Build Coastguard Worker         OS.flush();
6673*9880d681SAndroid Build Coastguard Worker         report_fatal_error(Buf);
6674*9880d681SAndroid Build Coastguard Worker       }
6675*9880d681SAndroid Build Coastguard Worker       StringRef SymName = *SymNameOrErr;
6676*9880d681SAndroid Build Coastguard Worker 
6677*9880d681SAndroid Build Coastguard Worker       Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
6678*9880d681SAndroid Build Coastguard Worker       if (!STOrErr) {
6679*9880d681SAndroid Build Coastguard Worker         std::string Buf;
6680*9880d681SAndroid Build Coastguard Worker         raw_string_ostream OS(Buf);
6681*9880d681SAndroid Build Coastguard Worker         logAllUnhandledErrors(STOrErr.takeError(), OS, "");
6682*9880d681SAndroid Build Coastguard Worker         OS.flush();
6683*9880d681SAndroid Build Coastguard Worker         report_fatal_error(Buf);
6684*9880d681SAndroid Build Coastguard Worker       }
6685*9880d681SAndroid Build Coastguard Worker       SymbolRef::Type ST = *STOrErr;
6686*9880d681SAndroid Build Coastguard Worker       if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
6687*9880d681SAndroid Build Coastguard Worker         continue;
6688*9880d681SAndroid Build Coastguard Worker 
6689*9880d681SAndroid Build Coastguard Worker       // Make sure the symbol is defined in this section.
6690*9880d681SAndroid Build Coastguard Worker       bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
6691*9880d681SAndroid Build Coastguard Worker       if (!containsSym) {
6692*9880d681SAndroid Build Coastguard Worker         if (!DisSymName.empty() && DisSymName == SymName) {
6693*9880d681SAndroid Build Coastguard Worker           outs() << "-dis-symname: " << DisSymName << " not in the section\n";
6694*9880d681SAndroid Build Coastguard Worker           return;
6695*9880d681SAndroid Build Coastguard Worker 	}
6696*9880d681SAndroid Build Coastguard Worker         continue;
6697*9880d681SAndroid Build Coastguard Worker       }
6698*9880d681SAndroid Build Coastguard Worker       // The __mh_execute_header is special and we need to deal with that fact
6699*9880d681SAndroid Build Coastguard Worker       // this symbol is before the start of the (__TEXT,__text) section and at the
6700*9880d681SAndroid Build Coastguard Worker       // address of the start of the __TEXT segment.  This is because this symbol
6701*9880d681SAndroid Build Coastguard Worker       // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
6702*9880d681SAndroid Build Coastguard Worker       // start of the section in a standard MH_EXECUTE filetype.
6703*9880d681SAndroid Build Coastguard Worker       if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
6704*9880d681SAndroid Build Coastguard Worker         outs() << "-dis-symname: __mh_execute_header not in any section\n";
6705*9880d681SAndroid Build Coastguard Worker         return;
6706*9880d681SAndroid Build Coastguard Worker       }
6707*9880d681SAndroid Build Coastguard Worker       // When this code is trying to disassemble a symbol at a time and in the case
6708*9880d681SAndroid Build Coastguard Worker       // there is only the __mh_execute_header symbol left as in a stripped
6709*9880d681SAndroid Build Coastguard Worker       // executable, we need to deal with this by ignoring this symbol so the whole
6710*9880d681SAndroid Build Coastguard Worker       // section is disassembled and this symbol is then not displayed.
6711*9880d681SAndroid Build Coastguard Worker       if (SymName == "__mh_execute_header")
6712*9880d681SAndroid Build Coastguard Worker         continue;
6713*9880d681SAndroid Build Coastguard Worker 
6714*9880d681SAndroid Build Coastguard Worker       // If we are only disassembling one symbol see if this is that symbol.
6715*9880d681SAndroid Build Coastguard Worker       if (!DisSymName.empty() && DisSymName != SymName)
6716*9880d681SAndroid Build Coastguard Worker         continue;
6717*9880d681SAndroid Build Coastguard Worker 
6718*9880d681SAndroid Build Coastguard Worker       // Start at the address of the symbol relative to the section's address.
6719*9880d681SAndroid Build Coastguard Worker       uint64_t Start = Symbols[SymIdx].getValue();
6720*9880d681SAndroid Build Coastguard Worker       uint64_t SectionAddress = Sections[SectIdx].getAddress();
6721*9880d681SAndroid Build Coastguard Worker       Start -= SectionAddress;
6722*9880d681SAndroid Build Coastguard Worker 
6723*9880d681SAndroid Build Coastguard Worker       // Stop disassembling either at the beginning of the next symbol or at
6724*9880d681SAndroid Build Coastguard Worker       // the end of the section.
6725*9880d681SAndroid Build Coastguard Worker       bool containsNextSym = false;
6726*9880d681SAndroid Build Coastguard Worker       uint64_t NextSym = 0;
6727*9880d681SAndroid Build Coastguard Worker       uint64_t NextSymIdx = SymIdx + 1;
6728*9880d681SAndroid Build Coastguard Worker       while (Symbols.size() > NextSymIdx) {
6729*9880d681SAndroid Build Coastguard Worker         Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
6730*9880d681SAndroid Build Coastguard Worker         if (!STOrErr) {
6731*9880d681SAndroid Build Coastguard Worker           std::string Buf;
6732*9880d681SAndroid Build Coastguard Worker           raw_string_ostream OS(Buf);
6733*9880d681SAndroid Build Coastguard Worker           logAllUnhandledErrors(STOrErr.takeError(), OS, "");
6734*9880d681SAndroid Build Coastguard Worker           OS.flush();
6735*9880d681SAndroid Build Coastguard Worker           report_fatal_error(Buf);
6736*9880d681SAndroid Build Coastguard Worker         }
6737*9880d681SAndroid Build Coastguard Worker         SymbolRef::Type NextSymType = *STOrErr;
6738*9880d681SAndroid Build Coastguard Worker         if (NextSymType == SymbolRef::ST_Function) {
6739*9880d681SAndroid Build Coastguard Worker           containsNextSym =
6740*9880d681SAndroid Build Coastguard Worker               Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
6741*9880d681SAndroid Build Coastguard Worker           NextSym = Symbols[NextSymIdx].getValue();
6742*9880d681SAndroid Build Coastguard Worker           NextSym -= SectionAddress;
6743*9880d681SAndroid Build Coastguard Worker           break;
6744*9880d681SAndroid Build Coastguard Worker         }
6745*9880d681SAndroid Build Coastguard Worker         ++NextSymIdx;
6746*9880d681SAndroid Build Coastguard Worker       }
6747*9880d681SAndroid Build Coastguard Worker 
6748*9880d681SAndroid Build Coastguard Worker       uint64_t SectSize = Sections[SectIdx].getSize();
6749*9880d681SAndroid Build Coastguard Worker       uint64_t End = containsNextSym ? NextSym : SectSize;
6750*9880d681SAndroid Build Coastguard Worker       uint64_t Size;
6751*9880d681SAndroid Build Coastguard Worker 
6752*9880d681SAndroid Build Coastguard Worker       symbolTableWorked = true;
6753*9880d681SAndroid Build Coastguard Worker 
6754*9880d681SAndroid Build Coastguard Worker       DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
6755*9880d681SAndroid Build Coastguard Worker       bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb;
6756*9880d681SAndroid Build Coastguard Worker 
6757*9880d681SAndroid Build Coastguard Worker       // We only need the dedicated Thumb target if there's a real choice
6758*9880d681SAndroid Build Coastguard Worker       // (i.e. we're not targeting M-class) and the function is Thumb.
6759*9880d681SAndroid Build Coastguard Worker       bool UseThumbTarget = IsThumb && ThumbTarget;
6760*9880d681SAndroid Build Coastguard Worker 
6761*9880d681SAndroid Build Coastguard Worker       outs() << SymName << ":\n";
6762*9880d681SAndroid Build Coastguard Worker       DILineInfo lastLine;
6763*9880d681SAndroid Build Coastguard Worker       for (uint64_t Index = Start; Index < End; Index += Size) {
6764*9880d681SAndroid Build Coastguard Worker         MCInst Inst;
6765*9880d681SAndroid Build Coastguard Worker 
6766*9880d681SAndroid Build Coastguard Worker         uint64_t PC = SectAddress + Index;
6767*9880d681SAndroid Build Coastguard Worker         if (!NoLeadingAddr) {
6768*9880d681SAndroid Build Coastguard Worker           if (FullLeadingAddr) {
6769*9880d681SAndroid Build Coastguard Worker             if (MachOOF->is64Bit())
6770*9880d681SAndroid Build Coastguard Worker               outs() << format("%016" PRIx64, PC);
6771*9880d681SAndroid Build Coastguard Worker             else
6772*9880d681SAndroid Build Coastguard Worker               outs() << format("%08" PRIx64, PC);
6773*9880d681SAndroid Build Coastguard Worker           } else {
6774*9880d681SAndroid Build Coastguard Worker             outs() << format("%8" PRIx64 ":", PC);
6775*9880d681SAndroid Build Coastguard Worker           }
6776*9880d681SAndroid Build Coastguard Worker         }
6777*9880d681SAndroid Build Coastguard Worker         if (!NoShowRawInsn || Arch == Triple::arm)
6778*9880d681SAndroid Build Coastguard Worker           outs() << "\t";
6779*9880d681SAndroid Build Coastguard Worker 
6780*9880d681SAndroid Build Coastguard Worker         // Check the data in code table here to see if this is data not an
6781*9880d681SAndroid Build Coastguard Worker         // instruction to be disassembled.
6782*9880d681SAndroid Build Coastguard Worker         DiceTable Dice;
6783*9880d681SAndroid Build Coastguard Worker         Dice.push_back(std::make_pair(PC, DiceRef()));
6784*9880d681SAndroid Build Coastguard Worker         dice_table_iterator DTI =
6785*9880d681SAndroid Build Coastguard Worker             std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
6786*9880d681SAndroid Build Coastguard Worker                         compareDiceTableEntries);
6787*9880d681SAndroid Build Coastguard Worker         if (DTI != Dices.end()) {
6788*9880d681SAndroid Build Coastguard Worker           uint16_t Length;
6789*9880d681SAndroid Build Coastguard Worker           DTI->second.getLength(Length);
6790*9880d681SAndroid Build Coastguard Worker           uint16_t Kind;
6791*9880d681SAndroid Build Coastguard Worker           DTI->second.getKind(Kind);
6792*9880d681SAndroid Build Coastguard Worker           Size = DumpDataInCode(Bytes.data() + Index, Length, Kind);
6793*9880d681SAndroid Build Coastguard Worker           if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
6794*9880d681SAndroid Build Coastguard Worker               (PC == (DTI->first + Length - 1)) && (Length & 1))
6795*9880d681SAndroid Build Coastguard Worker             Size++;
6796*9880d681SAndroid Build Coastguard Worker           continue;
6797*9880d681SAndroid Build Coastguard Worker         }
6798*9880d681SAndroid Build Coastguard Worker 
6799*9880d681SAndroid Build Coastguard Worker         SmallVector<char, 64> AnnotationsBytes;
6800*9880d681SAndroid Build Coastguard Worker         raw_svector_ostream Annotations(AnnotationsBytes);
6801*9880d681SAndroid Build Coastguard Worker 
6802*9880d681SAndroid Build Coastguard Worker         bool gotInst;
6803*9880d681SAndroid Build Coastguard Worker         if (UseThumbTarget)
6804*9880d681SAndroid Build Coastguard Worker           gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
6805*9880d681SAndroid Build Coastguard Worker                                                 PC, DebugOut, Annotations);
6806*9880d681SAndroid Build Coastguard Worker         else
6807*9880d681SAndroid Build Coastguard Worker           gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
6808*9880d681SAndroid Build Coastguard Worker                                            DebugOut, Annotations);
6809*9880d681SAndroid Build Coastguard Worker         if (gotInst) {
6810*9880d681SAndroid Build Coastguard Worker           if (!NoShowRawInsn || Arch == Triple::arm) {
6811*9880d681SAndroid Build Coastguard Worker             dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
6812*9880d681SAndroid Build Coastguard Worker           }
6813*9880d681SAndroid Build Coastguard Worker           formatted_raw_ostream FormattedOS(outs());
6814*9880d681SAndroid Build Coastguard Worker           StringRef AnnotationsStr = Annotations.str();
6815*9880d681SAndroid Build Coastguard Worker           if (UseThumbTarget)
6816*9880d681SAndroid Build Coastguard Worker             ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
6817*9880d681SAndroid Build Coastguard Worker           else
6818*9880d681SAndroid Build Coastguard Worker             IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
6819*9880d681SAndroid Build Coastguard Worker           emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
6820*9880d681SAndroid Build Coastguard Worker 
6821*9880d681SAndroid Build Coastguard Worker           // Print debug info.
6822*9880d681SAndroid Build Coastguard Worker           if (diContext) {
6823*9880d681SAndroid Build Coastguard Worker             DILineInfo dli = diContext->getLineInfoForAddress(PC);
6824*9880d681SAndroid Build Coastguard Worker             // Print valid line info if it changed.
6825*9880d681SAndroid Build Coastguard Worker             if (dli != lastLine && dli.Line != 0)
6826*9880d681SAndroid Build Coastguard Worker               outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
6827*9880d681SAndroid Build Coastguard Worker                      << dli.Column;
6828*9880d681SAndroid Build Coastguard Worker             lastLine = dli;
6829*9880d681SAndroid Build Coastguard Worker           }
6830*9880d681SAndroid Build Coastguard Worker           outs() << "\n";
6831*9880d681SAndroid Build Coastguard Worker         } else {
6832*9880d681SAndroid Build Coastguard Worker           unsigned int Arch = MachOOF->getArch();
6833*9880d681SAndroid Build Coastguard Worker           if (Arch == Triple::x86_64 || Arch == Triple::x86) {
6834*9880d681SAndroid Build Coastguard Worker             outs() << format("\t.byte 0x%02x #bad opcode\n",
6835*9880d681SAndroid Build Coastguard Worker                              *(Bytes.data() + Index) & 0xff);
6836*9880d681SAndroid Build Coastguard Worker             Size = 1; // skip exactly one illegible byte and move on.
6837*9880d681SAndroid Build Coastguard Worker           } else if (Arch == Triple::aarch64 ||
6838*9880d681SAndroid Build Coastguard Worker                      (Arch == Triple::arm && !IsThumb)) {
6839*9880d681SAndroid Build Coastguard Worker             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
6840*9880d681SAndroid Build Coastguard Worker                               (*(Bytes.data() + Index + 1) & 0xff) << 8 |
6841*9880d681SAndroid Build Coastguard Worker                               (*(Bytes.data() + Index + 2) & 0xff) << 16 |
6842*9880d681SAndroid Build Coastguard Worker                               (*(Bytes.data() + Index + 3) & 0xff) << 24;
6843*9880d681SAndroid Build Coastguard Worker             outs() << format("\t.long\t0x%08x\n", opcode);
6844*9880d681SAndroid Build Coastguard Worker             Size = 4;
6845*9880d681SAndroid Build Coastguard Worker           } else if (Arch == Triple::arm) {
6846*9880d681SAndroid Build Coastguard Worker             assert(IsThumb && "ARM mode should have been dealt with above");
6847*9880d681SAndroid Build Coastguard Worker             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
6848*9880d681SAndroid Build Coastguard Worker                               (*(Bytes.data() + Index + 1) & 0xff) << 8;
6849*9880d681SAndroid Build Coastguard Worker             outs() << format("\t.short\t0x%04x\n", opcode);
6850*9880d681SAndroid Build Coastguard Worker             Size = 2;
6851*9880d681SAndroid Build Coastguard Worker           } else{
6852*9880d681SAndroid Build Coastguard Worker             errs() << "llvm-objdump: warning: invalid instruction encoding\n";
6853*9880d681SAndroid Build Coastguard Worker             if (Size == 0)
6854*9880d681SAndroid Build Coastguard Worker               Size = 1; // skip illegible bytes
6855*9880d681SAndroid Build Coastguard Worker           }
6856*9880d681SAndroid Build Coastguard Worker         }
6857*9880d681SAndroid Build Coastguard Worker       }
6858*9880d681SAndroid Build Coastguard Worker     }
6859*9880d681SAndroid Build Coastguard Worker     if (!symbolTableWorked) {
6860*9880d681SAndroid Build Coastguard Worker       // Reading the symbol table didn't work, disassemble the whole section.
6861*9880d681SAndroid Build Coastguard Worker       uint64_t SectAddress = Sections[SectIdx].getAddress();
6862*9880d681SAndroid Build Coastguard Worker       uint64_t SectSize = Sections[SectIdx].getSize();
6863*9880d681SAndroid Build Coastguard Worker       uint64_t InstSize;
6864*9880d681SAndroid Build Coastguard Worker       for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
6865*9880d681SAndroid Build Coastguard Worker         MCInst Inst;
6866*9880d681SAndroid Build Coastguard Worker 
6867*9880d681SAndroid Build Coastguard Worker         uint64_t PC = SectAddress + Index;
6868*9880d681SAndroid Build Coastguard Worker         if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
6869*9880d681SAndroid Build Coastguard Worker                                    DebugOut, nulls())) {
6870*9880d681SAndroid Build Coastguard Worker           if (!NoLeadingAddr) {
6871*9880d681SAndroid Build Coastguard Worker             if (FullLeadingAddr) {
6872*9880d681SAndroid Build Coastguard Worker               if (MachOOF->is64Bit())
6873*9880d681SAndroid Build Coastguard Worker                 outs() << format("%016" PRIx64, PC);
6874*9880d681SAndroid Build Coastguard Worker               else
6875*9880d681SAndroid Build Coastguard Worker                 outs() << format("%08" PRIx64, PC);
6876*9880d681SAndroid Build Coastguard Worker             } else {
6877*9880d681SAndroid Build Coastguard Worker               outs() << format("%8" PRIx64 ":", PC);
6878*9880d681SAndroid Build Coastguard Worker             }
6879*9880d681SAndroid Build Coastguard Worker           }
6880*9880d681SAndroid Build Coastguard Worker           if (!NoShowRawInsn || Arch == Triple::arm) {
6881*9880d681SAndroid Build Coastguard Worker             outs() << "\t";
6882*9880d681SAndroid Build Coastguard Worker             dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
6883*9880d681SAndroid Build Coastguard Worker           }
6884*9880d681SAndroid Build Coastguard Worker           IP->printInst(&Inst, outs(), "", *STI);
6885*9880d681SAndroid Build Coastguard Worker           outs() << "\n";
6886*9880d681SAndroid Build Coastguard Worker         } else {
6887*9880d681SAndroid Build Coastguard Worker           unsigned int Arch = MachOOF->getArch();
6888*9880d681SAndroid Build Coastguard Worker           if (Arch == Triple::x86_64 || Arch == Triple::x86) {
6889*9880d681SAndroid Build Coastguard Worker             outs() << format("\t.byte 0x%02x #bad opcode\n",
6890*9880d681SAndroid Build Coastguard Worker                              *(Bytes.data() + Index) & 0xff);
6891*9880d681SAndroid Build Coastguard Worker             InstSize = 1; // skip exactly one illegible byte and move on.
6892*9880d681SAndroid Build Coastguard Worker           } else {
6893*9880d681SAndroid Build Coastguard Worker             errs() << "llvm-objdump: warning: invalid instruction encoding\n";
6894*9880d681SAndroid Build Coastguard Worker             if (InstSize == 0)
6895*9880d681SAndroid Build Coastguard Worker               InstSize = 1; // skip illegible bytes
6896*9880d681SAndroid Build Coastguard Worker           }
6897*9880d681SAndroid Build Coastguard Worker         }
6898*9880d681SAndroid Build Coastguard Worker       }
6899*9880d681SAndroid Build Coastguard Worker     }
6900*9880d681SAndroid Build Coastguard Worker     // The TripleName's need to be reset if we are called again for a different
6901*9880d681SAndroid Build Coastguard Worker     // archtecture.
6902*9880d681SAndroid Build Coastguard Worker     TripleName = "";
6903*9880d681SAndroid Build Coastguard Worker     ThumbTripleName = "";
6904*9880d681SAndroid Build Coastguard Worker 
6905*9880d681SAndroid Build Coastguard Worker     if (SymbolizerInfo.method != nullptr)
6906*9880d681SAndroid Build Coastguard Worker       free(SymbolizerInfo.method);
6907*9880d681SAndroid Build Coastguard Worker     if (SymbolizerInfo.demangled_name != nullptr)
6908*9880d681SAndroid Build Coastguard Worker       free(SymbolizerInfo.demangled_name);
6909*9880d681SAndroid Build Coastguard Worker     if (SymbolizerInfo.bindtable != nullptr)
6910*9880d681SAndroid Build Coastguard Worker       delete SymbolizerInfo.bindtable;
6911*9880d681SAndroid Build Coastguard Worker     if (ThumbSymbolizerInfo.method != nullptr)
6912*9880d681SAndroid Build Coastguard Worker       free(ThumbSymbolizerInfo.method);
6913*9880d681SAndroid Build Coastguard Worker     if (ThumbSymbolizerInfo.demangled_name != nullptr)
6914*9880d681SAndroid Build Coastguard Worker       free(ThumbSymbolizerInfo.demangled_name);
6915*9880d681SAndroid Build Coastguard Worker     if (ThumbSymbolizerInfo.bindtable != nullptr)
6916*9880d681SAndroid Build Coastguard Worker       delete ThumbSymbolizerInfo.bindtable;
6917*9880d681SAndroid Build Coastguard Worker   }
6918*9880d681SAndroid Build Coastguard Worker }
6919*9880d681SAndroid Build Coastguard Worker 
6920*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
6921*9880d681SAndroid Build Coastguard Worker // __compact_unwind section dumping
6922*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
6923*9880d681SAndroid Build Coastguard Worker 
6924*9880d681SAndroid Build Coastguard Worker namespace {
6925*9880d681SAndroid Build Coastguard Worker 
readNext(const char * & Buf)6926*9880d681SAndroid Build Coastguard Worker template <typename T> static uint64_t readNext(const char *&Buf) {
6927*9880d681SAndroid Build Coastguard Worker   using llvm::support::little;
6928*9880d681SAndroid Build Coastguard Worker   using llvm::support::unaligned;
6929*9880d681SAndroid Build Coastguard Worker 
6930*9880d681SAndroid Build Coastguard Worker   uint64_t Val = support::endian::read<T, little, unaligned>(Buf);
6931*9880d681SAndroid Build Coastguard Worker   Buf += sizeof(T);
6932*9880d681SAndroid Build Coastguard Worker   return Val;
6933*9880d681SAndroid Build Coastguard Worker }
6934*9880d681SAndroid Build Coastguard Worker 
6935*9880d681SAndroid Build Coastguard Worker struct CompactUnwindEntry {
6936*9880d681SAndroid Build Coastguard Worker   uint32_t OffsetInSection;
6937*9880d681SAndroid Build Coastguard Worker 
6938*9880d681SAndroid Build Coastguard Worker   uint64_t FunctionAddr;
6939*9880d681SAndroid Build Coastguard Worker   uint32_t Length;
6940*9880d681SAndroid Build Coastguard Worker   uint32_t CompactEncoding;
6941*9880d681SAndroid Build Coastguard Worker   uint64_t PersonalityAddr;
6942*9880d681SAndroid Build Coastguard Worker   uint64_t LSDAAddr;
6943*9880d681SAndroid Build Coastguard Worker 
6944*9880d681SAndroid Build Coastguard Worker   RelocationRef FunctionReloc;
6945*9880d681SAndroid Build Coastguard Worker   RelocationRef PersonalityReloc;
6946*9880d681SAndroid Build Coastguard Worker   RelocationRef LSDAReloc;
6947*9880d681SAndroid Build Coastguard Worker 
CompactUnwindEntry__anon18b79a880511::CompactUnwindEntry6948*9880d681SAndroid Build Coastguard Worker   CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
6949*9880d681SAndroid Build Coastguard Worker       : OffsetInSection(Offset) {
6950*9880d681SAndroid Build Coastguard Worker     if (Is64)
6951*9880d681SAndroid Build Coastguard Worker       read<uint64_t>(Contents.data() + Offset);
6952*9880d681SAndroid Build Coastguard Worker     else
6953*9880d681SAndroid Build Coastguard Worker       read<uint32_t>(Contents.data() + Offset);
6954*9880d681SAndroid Build Coastguard Worker   }
6955*9880d681SAndroid Build Coastguard Worker 
6956*9880d681SAndroid Build Coastguard Worker private:
read__anon18b79a880511::CompactUnwindEntry6957*9880d681SAndroid Build Coastguard Worker   template <typename UIntPtr> void read(const char *Buf) {
6958*9880d681SAndroid Build Coastguard Worker     FunctionAddr = readNext<UIntPtr>(Buf);
6959*9880d681SAndroid Build Coastguard Worker     Length = readNext<uint32_t>(Buf);
6960*9880d681SAndroid Build Coastguard Worker     CompactEncoding = readNext<uint32_t>(Buf);
6961*9880d681SAndroid Build Coastguard Worker     PersonalityAddr = readNext<UIntPtr>(Buf);
6962*9880d681SAndroid Build Coastguard Worker     LSDAAddr = readNext<UIntPtr>(Buf);
6963*9880d681SAndroid Build Coastguard Worker   }
6964*9880d681SAndroid Build Coastguard Worker };
6965*9880d681SAndroid Build Coastguard Worker }
6966*9880d681SAndroid Build Coastguard Worker 
6967*9880d681SAndroid Build Coastguard Worker /// Given a relocation from __compact_unwind, consisting of the RelocationRef
6968*9880d681SAndroid Build Coastguard Worker /// and data being relocated, determine the best base Name and Addend to use for
6969*9880d681SAndroid Build Coastguard Worker /// display purposes.
6970*9880d681SAndroid Build Coastguard Worker ///
6971*9880d681SAndroid Build Coastguard Worker /// 1. An Extern relocation will directly reference a symbol (and the data is
6972*9880d681SAndroid Build Coastguard Worker ///    then already an addend), so use that.
6973*9880d681SAndroid Build Coastguard Worker /// 2. Otherwise the data is an offset in the object file's layout; try to find
6974*9880d681SAndroid Build Coastguard Worker //     a symbol before it in the same section, and use the offset from there.
6975*9880d681SAndroid Build Coastguard Worker /// 3. Finally, if all that fails, fall back to an offset from the start of the
6976*9880d681SAndroid Build Coastguard Worker ///    referenced section.
findUnwindRelocNameAddend(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr,StringRef & Name,uint64_t & Addend)6977*9880d681SAndroid Build Coastguard Worker static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
6978*9880d681SAndroid Build Coastguard Worker                                       std::map<uint64_t, SymbolRef> &Symbols,
6979*9880d681SAndroid Build Coastguard Worker                                       const RelocationRef &Reloc, uint64_t Addr,
6980*9880d681SAndroid Build Coastguard Worker                                       StringRef &Name, uint64_t &Addend) {
6981*9880d681SAndroid Build Coastguard Worker   if (Reloc.getSymbol() != Obj->symbol_end()) {
6982*9880d681SAndroid Build Coastguard Worker     Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
6983*9880d681SAndroid Build Coastguard Worker     if (!NameOrErr) {
6984*9880d681SAndroid Build Coastguard Worker       std::string Buf;
6985*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Buf);
6986*9880d681SAndroid Build Coastguard Worker       logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
6987*9880d681SAndroid Build Coastguard Worker       OS.flush();
6988*9880d681SAndroid Build Coastguard Worker       report_fatal_error(Buf);
6989*9880d681SAndroid Build Coastguard Worker     }
6990*9880d681SAndroid Build Coastguard Worker     Name = *NameOrErr;
6991*9880d681SAndroid Build Coastguard Worker     Addend = Addr;
6992*9880d681SAndroid Build Coastguard Worker     return;
6993*9880d681SAndroid Build Coastguard Worker   }
6994*9880d681SAndroid Build Coastguard Worker 
6995*9880d681SAndroid Build Coastguard Worker   auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
6996*9880d681SAndroid Build Coastguard Worker   SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
6997*9880d681SAndroid Build Coastguard Worker 
6998*9880d681SAndroid Build Coastguard Worker   uint64_t SectionAddr = RelocSection.getAddress();
6999*9880d681SAndroid Build Coastguard Worker 
7000*9880d681SAndroid Build Coastguard Worker   auto Sym = Symbols.upper_bound(Addr);
7001*9880d681SAndroid Build Coastguard Worker   if (Sym == Symbols.begin()) {
7002*9880d681SAndroid Build Coastguard Worker     // The first symbol in the object is after this reference, the best we can
7003*9880d681SAndroid Build Coastguard Worker     // do is section-relative notation.
7004*9880d681SAndroid Build Coastguard Worker     RelocSection.getName(Name);
7005*9880d681SAndroid Build Coastguard Worker     Addend = Addr - SectionAddr;
7006*9880d681SAndroid Build Coastguard Worker     return;
7007*9880d681SAndroid Build Coastguard Worker   }
7008*9880d681SAndroid Build Coastguard Worker 
7009*9880d681SAndroid Build Coastguard Worker   // Go back one so that SymbolAddress <= Addr.
7010*9880d681SAndroid Build Coastguard Worker   --Sym;
7011*9880d681SAndroid Build Coastguard Worker 
7012*9880d681SAndroid Build Coastguard Worker   auto SectOrErr = Sym->second.getSection();
7013*9880d681SAndroid Build Coastguard Worker   if (!SectOrErr) {
7014*9880d681SAndroid Build Coastguard Worker     std::string Buf;
7015*9880d681SAndroid Build Coastguard Worker     raw_string_ostream OS(Buf);
7016*9880d681SAndroid Build Coastguard Worker     logAllUnhandledErrors(SectOrErr.takeError(), OS, "");
7017*9880d681SAndroid Build Coastguard Worker     OS.flush();
7018*9880d681SAndroid Build Coastguard Worker     report_fatal_error(Buf);
7019*9880d681SAndroid Build Coastguard Worker   }
7020*9880d681SAndroid Build Coastguard Worker   section_iterator SymSection = *SectOrErr;
7021*9880d681SAndroid Build Coastguard Worker   if (RelocSection == *SymSection) {
7022*9880d681SAndroid Build Coastguard Worker     // There's a valid symbol in the same section before this reference.
7023*9880d681SAndroid Build Coastguard Worker     Expected<StringRef> NameOrErr = Sym->second.getName();
7024*9880d681SAndroid Build Coastguard Worker     if (!NameOrErr) {
7025*9880d681SAndroid Build Coastguard Worker       std::string Buf;
7026*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Buf);
7027*9880d681SAndroid Build Coastguard Worker       logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
7028*9880d681SAndroid Build Coastguard Worker       OS.flush();
7029*9880d681SAndroid Build Coastguard Worker       report_fatal_error(Buf);
7030*9880d681SAndroid Build Coastguard Worker     }
7031*9880d681SAndroid Build Coastguard Worker     Name = *NameOrErr;
7032*9880d681SAndroid Build Coastguard Worker     Addend = Addr - Sym->first;
7033*9880d681SAndroid Build Coastguard Worker     return;
7034*9880d681SAndroid Build Coastguard Worker   }
7035*9880d681SAndroid Build Coastguard Worker 
7036*9880d681SAndroid Build Coastguard Worker   // There is a symbol before this reference, but it's in a different
7037*9880d681SAndroid Build Coastguard Worker   // section. Probably not helpful to mention it, so use the section name.
7038*9880d681SAndroid Build Coastguard Worker   RelocSection.getName(Name);
7039*9880d681SAndroid Build Coastguard Worker   Addend = Addr - SectionAddr;
7040*9880d681SAndroid Build Coastguard Worker }
7041*9880d681SAndroid Build Coastguard Worker 
printUnwindRelocDest(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr)7042*9880d681SAndroid Build Coastguard Worker static void printUnwindRelocDest(const MachOObjectFile *Obj,
7043*9880d681SAndroid Build Coastguard Worker                                  std::map<uint64_t, SymbolRef> &Symbols,
7044*9880d681SAndroid Build Coastguard Worker                                  const RelocationRef &Reloc, uint64_t Addr) {
7045*9880d681SAndroid Build Coastguard Worker   StringRef Name;
7046*9880d681SAndroid Build Coastguard Worker   uint64_t Addend;
7047*9880d681SAndroid Build Coastguard Worker 
7048*9880d681SAndroid Build Coastguard Worker   if (!Reloc.getObject())
7049*9880d681SAndroid Build Coastguard Worker     return;
7050*9880d681SAndroid Build Coastguard Worker 
7051*9880d681SAndroid Build Coastguard Worker   findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7052*9880d681SAndroid Build Coastguard Worker 
7053*9880d681SAndroid Build Coastguard Worker   outs() << Name;
7054*9880d681SAndroid Build Coastguard Worker   if (Addend)
7055*9880d681SAndroid Build Coastguard Worker     outs() << " + " << format("0x%" PRIx64, Addend);
7056*9880d681SAndroid Build Coastguard Worker }
7057*9880d681SAndroid Build Coastguard Worker 
7058*9880d681SAndroid Build Coastguard Worker static void
printMachOCompactUnwindSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & CompactUnwind)7059*9880d681SAndroid Build Coastguard Worker printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7060*9880d681SAndroid Build Coastguard Worker                                std::map<uint64_t, SymbolRef> &Symbols,
7061*9880d681SAndroid Build Coastguard Worker                                const SectionRef &CompactUnwind) {
7062*9880d681SAndroid Build Coastguard Worker 
7063*9880d681SAndroid Build Coastguard Worker   assert(Obj->isLittleEndian() &&
7064*9880d681SAndroid Build Coastguard Worker          "There should not be a big-endian .o with __compact_unwind");
7065*9880d681SAndroid Build Coastguard Worker 
7066*9880d681SAndroid Build Coastguard Worker   bool Is64 = Obj->is64Bit();
7067*9880d681SAndroid Build Coastguard Worker   uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7068*9880d681SAndroid Build Coastguard Worker   uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7069*9880d681SAndroid Build Coastguard Worker 
7070*9880d681SAndroid Build Coastguard Worker   StringRef Contents;
7071*9880d681SAndroid Build Coastguard Worker   CompactUnwind.getContents(Contents);
7072*9880d681SAndroid Build Coastguard Worker 
7073*9880d681SAndroid Build Coastguard Worker   SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7074*9880d681SAndroid Build Coastguard Worker 
7075*9880d681SAndroid Build Coastguard Worker   // First populate the initial raw offsets, encodings and so on from the entry.
7076*9880d681SAndroid Build Coastguard Worker   for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7077*9880d681SAndroid Build Coastguard Worker     CompactUnwindEntry Entry(Contents.data(), Offset, Is64);
7078*9880d681SAndroid Build Coastguard Worker     CompactUnwinds.push_back(Entry);
7079*9880d681SAndroid Build Coastguard Worker   }
7080*9880d681SAndroid Build Coastguard Worker 
7081*9880d681SAndroid Build Coastguard Worker   // Next we need to look at the relocations to find out what objects are
7082*9880d681SAndroid Build Coastguard Worker   // actually being referred to.
7083*9880d681SAndroid Build Coastguard Worker   for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7084*9880d681SAndroid Build Coastguard Worker     uint64_t RelocAddress = Reloc.getOffset();
7085*9880d681SAndroid Build Coastguard Worker 
7086*9880d681SAndroid Build Coastguard Worker     uint32_t EntryIdx = RelocAddress / EntrySize;
7087*9880d681SAndroid Build Coastguard Worker     uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7088*9880d681SAndroid Build Coastguard Worker     CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7089*9880d681SAndroid Build Coastguard Worker 
7090*9880d681SAndroid Build Coastguard Worker     if (OffsetInEntry == 0)
7091*9880d681SAndroid Build Coastguard Worker       Entry.FunctionReloc = Reloc;
7092*9880d681SAndroid Build Coastguard Worker     else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7093*9880d681SAndroid Build Coastguard Worker       Entry.PersonalityReloc = Reloc;
7094*9880d681SAndroid Build Coastguard Worker     else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7095*9880d681SAndroid Build Coastguard Worker       Entry.LSDAReloc = Reloc;
7096*9880d681SAndroid Build Coastguard Worker     else
7097*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Unexpected relocation in __compact_unwind section");
7098*9880d681SAndroid Build Coastguard Worker   }
7099*9880d681SAndroid Build Coastguard Worker 
7100*9880d681SAndroid Build Coastguard Worker   // Finally, we're ready to print the data we've gathered.
7101*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of __compact_unwind section:\n";
7102*9880d681SAndroid Build Coastguard Worker   for (auto &Entry : CompactUnwinds) {
7103*9880d681SAndroid Build Coastguard Worker     outs() << "  Entry at offset "
7104*9880d681SAndroid Build Coastguard Worker            << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
7105*9880d681SAndroid Build Coastguard Worker 
7106*9880d681SAndroid Build Coastguard Worker     // 1. Start of the region this entry applies to.
7107*9880d681SAndroid Build Coastguard Worker     outs() << "    start:                " << format("0x%" PRIx64,
7108*9880d681SAndroid Build Coastguard Worker                                                      Entry.FunctionAddr) << ' ';
7109*9880d681SAndroid Build Coastguard Worker     printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
7110*9880d681SAndroid Build Coastguard Worker     outs() << '\n';
7111*9880d681SAndroid Build Coastguard Worker 
7112*9880d681SAndroid Build Coastguard Worker     // 2. Length of the region this entry applies to.
7113*9880d681SAndroid Build Coastguard Worker     outs() << "    length:               " << format("0x%" PRIx32, Entry.Length)
7114*9880d681SAndroid Build Coastguard Worker            << '\n';
7115*9880d681SAndroid Build Coastguard Worker     // 3. The 32-bit compact encoding.
7116*9880d681SAndroid Build Coastguard Worker     outs() << "    compact encoding:     "
7117*9880d681SAndroid Build Coastguard Worker            << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
7118*9880d681SAndroid Build Coastguard Worker 
7119*9880d681SAndroid Build Coastguard Worker     // 4. The personality function, if present.
7120*9880d681SAndroid Build Coastguard Worker     if (Entry.PersonalityReloc.getObject()) {
7121*9880d681SAndroid Build Coastguard Worker       outs() << "    personality function: "
7122*9880d681SAndroid Build Coastguard Worker              << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
7123*9880d681SAndroid Build Coastguard Worker       printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
7124*9880d681SAndroid Build Coastguard Worker                            Entry.PersonalityAddr);
7125*9880d681SAndroid Build Coastguard Worker       outs() << '\n';
7126*9880d681SAndroid Build Coastguard Worker     }
7127*9880d681SAndroid Build Coastguard Worker 
7128*9880d681SAndroid Build Coastguard Worker     // 5. This entry's language-specific data area.
7129*9880d681SAndroid Build Coastguard Worker     if (Entry.LSDAReloc.getObject()) {
7130*9880d681SAndroid Build Coastguard Worker       outs() << "    LSDA:                 " << format("0x%" PRIx64,
7131*9880d681SAndroid Build Coastguard Worker                                                        Entry.LSDAAddr) << ' ';
7132*9880d681SAndroid Build Coastguard Worker       printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
7133*9880d681SAndroid Build Coastguard Worker       outs() << '\n';
7134*9880d681SAndroid Build Coastguard Worker     }
7135*9880d681SAndroid Build Coastguard Worker   }
7136*9880d681SAndroid Build Coastguard Worker }
7137*9880d681SAndroid Build Coastguard Worker 
7138*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
7139*9880d681SAndroid Build Coastguard Worker // __unwind_info section dumping
7140*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
7141*9880d681SAndroid Build Coastguard Worker 
printRegularSecondLevelUnwindPage(const char * PageStart)7142*9880d681SAndroid Build Coastguard Worker static void printRegularSecondLevelUnwindPage(const char *PageStart) {
7143*9880d681SAndroid Build Coastguard Worker   const char *Pos = PageStart;
7144*9880d681SAndroid Build Coastguard Worker   uint32_t Kind = readNext<uint32_t>(Pos);
7145*9880d681SAndroid Build Coastguard Worker   (void)Kind;
7146*9880d681SAndroid Build Coastguard Worker   assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
7147*9880d681SAndroid Build Coastguard Worker 
7148*9880d681SAndroid Build Coastguard Worker   uint16_t EntriesStart = readNext<uint16_t>(Pos);
7149*9880d681SAndroid Build Coastguard Worker   uint16_t NumEntries = readNext<uint16_t>(Pos);
7150*9880d681SAndroid Build Coastguard Worker 
7151*9880d681SAndroid Build Coastguard Worker   Pos = PageStart + EntriesStart;
7152*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumEntries; ++i) {
7153*9880d681SAndroid Build Coastguard Worker     uint32_t FunctionOffset = readNext<uint32_t>(Pos);
7154*9880d681SAndroid Build Coastguard Worker     uint32_t Encoding = readNext<uint32_t>(Pos);
7155*9880d681SAndroid Build Coastguard Worker 
7156*9880d681SAndroid Build Coastguard Worker     outs() << "      [" << i << "]: "
7157*9880d681SAndroid Build Coastguard Worker            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7158*9880d681SAndroid Build Coastguard Worker            << ", "
7159*9880d681SAndroid Build Coastguard Worker            << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
7160*9880d681SAndroid Build Coastguard Worker   }
7161*9880d681SAndroid Build Coastguard Worker }
7162*9880d681SAndroid Build Coastguard Worker 
printCompressedSecondLevelUnwindPage(const char * PageStart,uint32_t FunctionBase,const SmallVectorImpl<uint32_t> & CommonEncodings)7163*9880d681SAndroid Build Coastguard Worker static void printCompressedSecondLevelUnwindPage(
7164*9880d681SAndroid Build Coastguard Worker     const char *PageStart, uint32_t FunctionBase,
7165*9880d681SAndroid Build Coastguard Worker     const SmallVectorImpl<uint32_t> &CommonEncodings) {
7166*9880d681SAndroid Build Coastguard Worker   const char *Pos = PageStart;
7167*9880d681SAndroid Build Coastguard Worker   uint32_t Kind = readNext<uint32_t>(Pos);
7168*9880d681SAndroid Build Coastguard Worker   (void)Kind;
7169*9880d681SAndroid Build Coastguard Worker   assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
7170*9880d681SAndroid Build Coastguard Worker 
7171*9880d681SAndroid Build Coastguard Worker   uint16_t EntriesStart = readNext<uint16_t>(Pos);
7172*9880d681SAndroid Build Coastguard Worker   uint16_t NumEntries = readNext<uint16_t>(Pos);
7173*9880d681SAndroid Build Coastguard Worker 
7174*9880d681SAndroid Build Coastguard Worker   uint16_t EncodingsStart = readNext<uint16_t>(Pos);
7175*9880d681SAndroid Build Coastguard Worker   readNext<uint16_t>(Pos);
7176*9880d681SAndroid Build Coastguard Worker   const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>(
7177*9880d681SAndroid Build Coastguard Worker       PageStart + EncodingsStart);
7178*9880d681SAndroid Build Coastguard Worker 
7179*9880d681SAndroid Build Coastguard Worker   Pos = PageStart + EntriesStart;
7180*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumEntries; ++i) {
7181*9880d681SAndroid Build Coastguard Worker     uint32_t Entry = readNext<uint32_t>(Pos);
7182*9880d681SAndroid Build Coastguard Worker     uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
7183*9880d681SAndroid Build Coastguard Worker     uint32_t EncodingIdx = Entry >> 24;
7184*9880d681SAndroid Build Coastguard Worker 
7185*9880d681SAndroid Build Coastguard Worker     uint32_t Encoding;
7186*9880d681SAndroid Build Coastguard Worker     if (EncodingIdx < CommonEncodings.size())
7187*9880d681SAndroid Build Coastguard Worker       Encoding = CommonEncodings[EncodingIdx];
7188*9880d681SAndroid Build Coastguard Worker     else
7189*9880d681SAndroid Build Coastguard Worker       Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()];
7190*9880d681SAndroid Build Coastguard Worker 
7191*9880d681SAndroid Build Coastguard Worker     outs() << "      [" << i << "]: "
7192*9880d681SAndroid Build Coastguard Worker            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7193*9880d681SAndroid Build Coastguard Worker            << ", "
7194*9880d681SAndroid Build Coastguard Worker            << "encoding[" << EncodingIdx
7195*9880d681SAndroid Build Coastguard Worker            << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
7196*9880d681SAndroid Build Coastguard Worker   }
7197*9880d681SAndroid Build Coastguard Worker }
7198*9880d681SAndroid Build Coastguard Worker 
printMachOUnwindInfoSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & UnwindInfo)7199*9880d681SAndroid Build Coastguard Worker static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
7200*9880d681SAndroid Build Coastguard Worker                                         std::map<uint64_t, SymbolRef> &Symbols,
7201*9880d681SAndroid Build Coastguard Worker                                         const SectionRef &UnwindInfo) {
7202*9880d681SAndroid Build Coastguard Worker 
7203*9880d681SAndroid Build Coastguard Worker   assert(Obj->isLittleEndian() &&
7204*9880d681SAndroid Build Coastguard Worker          "There should not be a big-endian .o with __unwind_info");
7205*9880d681SAndroid Build Coastguard Worker 
7206*9880d681SAndroid Build Coastguard Worker   outs() << "Contents of __unwind_info section:\n";
7207*9880d681SAndroid Build Coastguard Worker 
7208*9880d681SAndroid Build Coastguard Worker   StringRef Contents;
7209*9880d681SAndroid Build Coastguard Worker   UnwindInfo.getContents(Contents);
7210*9880d681SAndroid Build Coastguard Worker   const char *Pos = Contents.data();
7211*9880d681SAndroid Build Coastguard Worker 
7212*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7213*9880d681SAndroid Build Coastguard Worker   // Section header
7214*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7215*9880d681SAndroid Build Coastguard Worker 
7216*9880d681SAndroid Build Coastguard Worker   uint32_t Version = readNext<uint32_t>(Pos);
7217*9880d681SAndroid Build Coastguard Worker   outs() << "  Version:                                   "
7218*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, Version) << '\n';
7219*9880d681SAndroid Build Coastguard Worker   assert(Version == 1 && "only understand version 1");
7220*9880d681SAndroid Build Coastguard Worker 
7221*9880d681SAndroid Build Coastguard Worker   uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos);
7222*9880d681SAndroid Build Coastguard Worker   outs() << "  Common encodings array section offset:     "
7223*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
7224*9880d681SAndroid Build Coastguard Worker   uint32_t NumCommonEncodings = readNext<uint32_t>(Pos);
7225*9880d681SAndroid Build Coastguard Worker   outs() << "  Number of common encodings in array:       "
7226*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, NumCommonEncodings) << '\n';
7227*9880d681SAndroid Build Coastguard Worker 
7228*9880d681SAndroid Build Coastguard Worker   uint32_t PersonalitiesStart = readNext<uint32_t>(Pos);
7229*9880d681SAndroid Build Coastguard Worker   outs() << "  Personality function array section offset: "
7230*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, PersonalitiesStart) << '\n';
7231*9880d681SAndroid Build Coastguard Worker   uint32_t NumPersonalities = readNext<uint32_t>(Pos);
7232*9880d681SAndroid Build Coastguard Worker   outs() << "  Number of personality functions in array:  "
7233*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, NumPersonalities) << '\n';
7234*9880d681SAndroid Build Coastguard Worker 
7235*9880d681SAndroid Build Coastguard Worker   uint32_t IndicesStart = readNext<uint32_t>(Pos);
7236*9880d681SAndroid Build Coastguard Worker   outs() << "  Index array section offset:                "
7237*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, IndicesStart) << '\n';
7238*9880d681SAndroid Build Coastguard Worker   uint32_t NumIndices = readNext<uint32_t>(Pos);
7239*9880d681SAndroid Build Coastguard Worker   outs() << "  Number of indices in array:                "
7240*9880d681SAndroid Build Coastguard Worker          << format("0x%" PRIx32, NumIndices) << '\n';
7241*9880d681SAndroid Build Coastguard Worker 
7242*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7243*9880d681SAndroid Build Coastguard Worker   // A shared list of common encodings
7244*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7245*9880d681SAndroid Build Coastguard Worker 
7246*9880d681SAndroid Build Coastguard Worker   // These occupy indices in the range [0, N] whenever an encoding is referenced
7247*9880d681SAndroid Build Coastguard Worker   // from a compressed 2nd level index table. In practice the linker only
7248*9880d681SAndroid Build Coastguard Worker   // creates ~128 of these, so that indices are available to embed encodings in
7249*9880d681SAndroid Build Coastguard Worker   // the 2nd level index.
7250*9880d681SAndroid Build Coastguard Worker 
7251*9880d681SAndroid Build Coastguard Worker   SmallVector<uint32_t, 64> CommonEncodings;
7252*9880d681SAndroid Build Coastguard Worker   outs() << "  Common encodings: (count = " << NumCommonEncodings << ")\n";
7253*9880d681SAndroid Build Coastguard Worker   Pos = Contents.data() + CommonEncodingsStart;
7254*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumCommonEncodings; ++i) {
7255*9880d681SAndroid Build Coastguard Worker     uint32_t Encoding = readNext<uint32_t>(Pos);
7256*9880d681SAndroid Build Coastguard Worker     CommonEncodings.push_back(Encoding);
7257*9880d681SAndroid Build Coastguard Worker 
7258*9880d681SAndroid Build Coastguard Worker     outs() << "    encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
7259*9880d681SAndroid Build Coastguard Worker            << '\n';
7260*9880d681SAndroid Build Coastguard Worker   }
7261*9880d681SAndroid Build Coastguard Worker 
7262*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7263*9880d681SAndroid Build Coastguard Worker   // Personality functions used in this executable
7264*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7265*9880d681SAndroid Build Coastguard Worker 
7266*9880d681SAndroid Build Coastguard Worker   // There should be only a handful of these (one per source language,
7267*9880d681SAndroid Build Coastguard Worker   // roughly). Particularly since they only get 2 bits in the compact encoding.
7268*9880d681SAndroid Build Coastguard Worker 
7269*9880d681SAndroid Build Coastguard Worker   outs() << "  Personality functions: (count = " << NumPersonalities << ")\n";
7270*9880d681SAndroid Build Coastguard Worker   Pos = Contents.data() + PersonalitiesStart;
7271*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumPersonalities; ++i) {
7272*9880d681SAndroid Build Coastguard Worker     uint32_t PersonalityFn = readNext<uint32_t>(Pos);
7273*9880d681SAndroid Build Coastguard Worker     outs() << "    personality[" << i + 1
7274*9880d681SAndroid Build Coastguard Worker            << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
7275*9880d681SAndroid Build Coastguard Worker   }
7276*9880d681SAndroid Build Coastguard Worker 
7277*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7278*9880d681SAndroid Build Coastguard Worker   // The level 1 index entries
7279*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7280*9880d681SAndroid Build Coastguard Worker 
7281*9880d681SAndroid Build Coastguard Worker   // These specify an approximate place to start searching for the more detailed
7282*9880d681SAndroid Build Coastguard Worker   // information, sorted by PC.
7283*9880d681SAndroid Build Coastguard Worker 
7284*9880d681SAndroid Build Coastguard Worker   struct IndexEntry {
7285*9880d681SAndroid Build Coastguard Worker     uint32_t FunctionOffset;
7286*9880d681SAndroid Build Coastguard Worker     uint32_t SecondLevelPageStart;
7287*9880d681SAndroid Build Coastguard Worker     uint32_t LSDAStart;
7288*9880d681SAndroid Build Coastguard Worker   };
7289*9880d681SAndroid Build Coastguard Worker 
7290*9880d681SAndroid Build Coastguard Worker   SmallVector<IndexEntry, 4> IndexEntries;
7291*9880d681SAndroid Build Coastguard Worker 
7292*9880d681SAndroid Build Coastguard Worker   outs() << "  Top level indices: (count = " << NumIndices << ")\n";
7293*9880d681SAndroid Build Coastguard Worker   Pos = Contents.data() + IndicesStart;
7294*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumIndices; ++i) {
7295*9880d681SAndroid Build Coastguard Worker     IndexEntry Entry;
7296*9880d681SAndroid Build Coastguard Worker 
7297*9880d681SAndroid Build Coastguard Worker     Entry.FunctionOffset = readNext<uint32_t>(Pos);
7298*9880d681SAndroid Build Coastguard Worker     Entry.SecondLevelPageStart = readNext<uint32_t>(Pos);
7299*9880d681SAndroid Build Coastguard Worker     Entry.LSDAStart = readNext<uint32_t>(Pos);
7300*9880d681SAndroid Build Coastguard Worker     IndexEntries.push_back(Entry);
7301*9880d681SAndroid Build Coastguard Worker 
7302*9880d681SAndroid Build Coastguard Worker     outs() << "    [" << i << "]: "
7303*9880d681SAndroid Build Coastguard Worker            << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
7304*9880d681SAndroid Build Coastguard Worker            << ", "
7305*9880d681SAndroid Build Coastguard Worker            << "2nd level page offset="
7306*9880d681SAndroid Build Coastguard Worker            << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
7307*9880d681SAndroid Build Coastguard Worker            << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
7308*9880d681SAndroid Build Coastguard Worker   }
7309*9880d681SAndroid Build Coastguard Worker 
7310*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7311*9880d681SAndroid Build Coastguard Worker   // Next come the LSDA tables
7312*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7313*9880d681SAndroid Build Coastguard Worker 
7314*9880d681SAndroid Build Coastguard Worker   // The LSDA layout is rather implicit: it's a contiguous array of entries from
7315*9880d681SAndroid Build Coastguard Worker   // the first top-level index's LSDAOffset to the last (sentinel).
7316*9880d681SAndroid Build Coastguard Worker 
7317*9880d681SAndroid Build Coastguard Worker   outs() << "  LSDA descriptors:\n";
7318*9880d681SAndroid Build Coastguard Worker   Pos = Contents.data() + IndexEntries[0].LSDAStart;
7319*9880d681SAndroid Build Coastguard Worker   int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) /
7320*9880d681SAndroid Build Coastguard Worker                  (2 * sizeof(uint32_t));
7321*9880d681SAndroid Build Coastguard Worker   for (int i = 0; i < NumLSDAs; ++i) {
7322*9880d681SAndroid Build Coastguard Worker     uint32_t FunctionOffset = readNext<uint32_t>(Pos);
7323*9880d681SAndroid Build Coastguard Worker     uint32_t LSDAOffset = readNext<uint32_t>(Pos);
7324*9880d681SAndroid Build Coastguard Worker     outs() << "    [" << i << "]: "
7325*9880d681SAndroid Build Coastguard Worker            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7326*9880d681SAndroid Build Coastguard Worker            << ", "
7327*9880d681SAndroid Build Coastguard Worker            << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
7328*9880d681SAndroid Build Coastguard Worker   }
7329*9880d681SAndroid Build Coastguard Worker 
7330*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7331*9880d681SAndroid Build Coastguard Worker   // Finally, the 2nd level indices
7332*9880d681SAndroid Build Coastguard Worker   //===----------------------------------
7333*9880d681SAndroid Build Coastguard Worker 
7334*9880d681SAndroid Build Coastguard Worker   // Generally these are 4K in size, and have 2 possible forms:
7335*9880d681SAndroid Build Coastguard Worker   //   + Regular stores up to 511 entries with disparate encodings
7336*9880d681SAndroid Build Coastguard Worker   //   + Compressed stores up to 1021 entries if few enough compact encoding
7337*9880d681SAndroid Build Coastguard Worker   //     values are used.
7338*9880d681SAndroid Build Coastguard Worker   outs() << "  Second level indices:\n";
7339*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
7340*9880d681SAndroid Build Coastguard Worker     // The final sentinel top-level index has no associated 2nd level page
7341*9880d681SAndroid Build Coastguard Worker     if (IndexEntries[i].SecondLevelPageStart == 0)
7342*9880d681SAndroid Build Coastguard Worker       break;
7343*9880d681SAndroid Build Coastguard Worker 
7344*9880d681SAndroid Build Coastguard Worker     outs() << "    Second level index[" << i << "]: "
7345*9880d681SAndroid Build Coastguard Worker            << "offset in section="
7346*9880d681SAndroid Build Coastguard Worker            << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
7347*9880d681SAndroid Build Coastguard Worker            << ", "
7348*9880d681SAndroid Build Coastguard Worker            << "base function offset="
7349*9880d681SAndroid Build Coastguard Worker            << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
7350*9880d681SAndroid Build Coastguard Worker 
7351*9880d681SAndroid Build Coastguard Worker     Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart;
7352*9880d681SAndroid Build Coastguard Worker     uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos);
7353*9880d681SAndroid Build Coastguard Worker     if (Kind == 2)
7354*9880d681SAndroid Build Coastguard Worker       printRegularSecondLevelUnwindPage(Pos);
7355*9880d681SAndroid Build Coastguard Worker     else if (Kind == 3)
7356*9880d681SAndroid Build Coastguard Worker       printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset,
7357*9880d681SAndroid Build Coastguard Worker                                            CommonEncodings);
7358*9880d681SAndroid Build Coastguard Worker     else
7359*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Do not know how to print this kind of 2nd level page");
7360*9880d681SAndroid Build Coastguard Worker   }
7361*9880d681SAndroid Build Coastguard Worker }
7362*9880d681SAndroid Build Coastguard Worker 
printMachOUnwindInfo(const MachOObjectFile * Obj)7363*9880d681SAndroid Build Coastguard Worker void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
7364*9880d681SAndroid Build Coastguard Worker   std::map<uint64_t, SymbolRef> Symbols;
7365*9880d681SAndroid Build Coastguard Worker   for (const SymbolRef &SymRef : Obj->symbols()) {
7366*9880d681SAndroid Build Coastguard Worker     // Discard any undefined or absolute symbols. They're not going to take part
7367*9880d681SAndroid Build Coastguard Worker     // in the convenience lookup for unwind info and just take up resources.
7368*9880d681SAndroid Build Coastguard Worker     auto SectOrErr = SymRef.getSection();
7369*9880d681SAndroid Build Coastguard Worker     if (!SectOrErr) {
7370*9880d681SAndroid Build Coastguard Worker       // TODO: Actually report errors helpfully.
7371*9880d681SAndroid Build Coastguard Worker       consumeError(SectOrErr.takeError());
7372*9880d681SAndroid Build Coastguard Worker       continue;
7373*9880d681SAndroid Build Coastguard Worker     }
7374*9880d681SAndroid Build Coastguard Worker     section_iterator Section = *SectOrErr;
7375*9880d681SAndroid Build Coastguard Worker     if (Section == Obj->section_end())
7376*9880d681SAndroid Build Coastguard Worker       continue;
7377*9880d681SAndroid Build Coastguard Worker 
7378*9880d681SAndroid Build Coastguard Worker     uint64_t Addr = SymRef.getValue();
7379*9880d681SAndroid Build Coastguard Worker     Symbols.insert(std::make_pair(Addr, SymRef));
7380*9880d681SAndroid Build Coastguard Worker   }
7381*9880d681SAndroid Build Coastguard Worker 
7382*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : Obj->sections()) {
7383*9880d681SAndroid Build Coastguard Worker     StringRef SectName;
7384*9880d681SAndroid Build Coastguard Worker     Section.getName(SectName);
7385*9880d681SAndroid Build Coastguard Worker     if (SectName == "__compact_unwind")
7386*9880d681SAndroid Build Coastguard Worker       printMachOCompactUnwindSection(Obj, Symbols, Section);
7387*9880d681SAndroid Build Coastguard Worker     else if (SectName == "__unwind_info")
7388*9880d681SAndroid Build Coastguard Worker       printMachOUnwindInfoSection(Obj, Symbols, Section);
7389*9880d681SAndroid Build Coastguard Worker   }
7390*9880d681SAndroid Build Coastguard Worker }
7391*9880d681SAndroid Build Coastguard Worker 
PrintMachHeader(uint32_t magic,uint32_t cputype,uint32_t cpusubtype,uint32_t filetype,uint32_t ncmds,uint32_t sizeofcmds,uint32_t flags,bool verbose)7392*9880d681SAndroid Build Coastguard Worker static void PrintMachHeader(uint32_t magic, uint32_t cputype,
7393*9880d681SAndroid Build Coastguard Worker                             uint32_t cpusubtype, uint32_t filetype,
7394*9880d681SAndroid Build Coastguard Worker                             uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
7395*9880d681SAndroid Build Coastguard Worker                             bool verbose) {
7396*9880d681SAndroid Build Coastguard Worker   outs() << "Mach header\n";
7397*9880d681SAndroid Build Coastguard Worker   outs() << "      magic cputype cpusubtype  caps    filetype ncmds "
7398*9880d681SAndroid Build Coastguard Worker             "sizeofcmds      flags\n";
7399*9880d681SAndroid Build Coastguard Worker   if (verbose) {
7400*9880d681SAndroid Build Coastguard Worker     if (magic == MachO::MH_MAGIC)
7401*9880d681SAndroid Build Coastguard Worker       outs() << "   MH_MAGIC";
7402*9880d681SAndroid Build Coastguard Worker     else if (magic == MachO::MH_MAGIC_64)
7403*9880d681SAndroid Build Coastguard Worker       outs() << "MH_MAGIC_64";
7404*9880d681SAndroid Build Coastguard Worker     else
7405*9880d681SAndroid Build Coastguard Worker       outs() << format(" 0x%08" PRIx32, magic);
7406*9880d681SAndroid Build Coastguard Worker     switch (cputype) {
7407*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_TYPE_I386:
7408*9880d681SAndroid Build Coastguard Worker       outs() << "    I386";
7409*9880d681SAndroid Build Coastguard Worker       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7410*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_I386_ALL:
7411*9880d681SAndroid Build Coastguard Worker         outs() << "        ALL";
7412*9880d681SAndroid Build Coastguard Worker         break;
7413*9880d681SAndroid Build Coastguard Worker       default:
7414*9880d681SAndroid Build Coastguard Worker         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7415*9880d681SAndroid Build Coastguard Worker         break;
7416*9880d681SAndroid Build Coastguard Worker       }
7417*9880d681SAndroid Build Coastguard Worker       break;
7418*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_TYPE_X86_64:
7419*9880d681SAndroid Build Coastguard Worker       outs() << "  X86_64";
7420*9880d681SAndroid Build Coastguard Worker       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7421*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_X86_64_ALL:
7422*9880d681SAndroid Build Coastguard Worker         outs() << "        ALL";
7423*9880d681SAndroid Build Coastguard Worker         break;
7424*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_X86_64_H:
7425*9880d681SAndroid Build Coastguard Worker         outs() << "    Haswell";
7426*9880d681SAndroid Build Coastguard Worker         break;
7427*9880d681SAndroid Build Coastguard Worker       default:
7428*9880d681SAndroid Build Coastguard Worker         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7429*9880d681SAndroid Build Coastguard Worker         break;
7430*9880d681SAndroid Build Coastguard Worker       }
7431*9880d681SAndroid Build Coastguard Worker       break;
7432*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_TYPE_ARM:
7433*9880d681SAndroid Build Coastguard Worker       outs() << "     ARM";
7434*9880d681SAndroid Build Coastguard Worker       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7435*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_ALL:
7436*9880d681SAndroid Build Coastguard Worker         outs() << "        ALL";
7437*9880d681SAndroid Build Coastguard Worker         break;
7438*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V4T:
7439*9880d681SAndroid Build Coastguard Worker         outs() << "        V4T";
7440*9880d681SAndroid Build Coastguard Worker         break;
7441*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V5TEJ:
7442*9880d681SAndroid Build Coastguard Worker         outs() << "      V5TEJ";
7443*9880d681SAndroid Build Coastguard Worker         break;
7444*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_XSCALE:
7445*9880d681SAndroid Build Coastguard Worker         outs() << "     XSCALE";
7446*9880d681SAndroid Build Coastguard Worker         break;
7447*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V6:
7448*9880d681SAndroid Build Coastguard Worker         outs() << "         V6";
7449*9880d681SAndroid Build Coastguard Worker         break;
7450*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V6M:
7451*9880d681SAndroid Build Coastguard Worker         outs() << "        V6M";
7452*9880d681SAndroid Build Coastguard Worker         break;
7453*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V7:
7454*9880d681SAndroid Build Coastguard Worker         outs() << "         V7";
7455*9880d681SAndroid Build Coastguard Worker         break;
7456*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V7EM:
7457*9880d681SAndroid Build Coastguard Worker         outs() << "       V7EM";
7458*9880d681SAndroid Build Coastguard Worker         break;
7459*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V7K:
7460*9880d681SAndroid Build Coastguard Worker         outs() << "        V7K";
7461*9880d681SAndroid Build Coastguard Worker         break;
7462*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V7M:
7463*9880d681SAndroid Build Coastguard Worker         outs() << "        V7M";
7464*9880d681SAndroid Build Coastguard Worker         break;
7465*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM_V7S:
7466*9880d681SAndroid Build Coastguard Worker         outs() << "        V7S";
7467*9880d681SAndroid Build Coastguard Worker         break;
7468*9880d681SAndroid Build Coastguard Worker       default:
7469*9880d681SAndroid Build Coastguard Worker         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7470*9880d681SAndroid Build Coastguard Worker         break;
7471*9880d681SAndroid Build Coastguard Worker       }
7472*9880d681SAndroid Build Coastguard Worker       break;
7473*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_TYPE_ARM64:
7474*9880d681SAndroid Build Coastguard Worker       outs() << "   ARM64";
7475*9880d681SAndroid Build Coastguard Worker       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7476*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_ARM64_ALL:
7477*9880d681SAndroid Build Coastguard Worker         outs() << "        ALL";
7478*9880d681SAndroid Build Coastguard Worker         break;
7479*9880d681SAndroid Build Coastguard Worker       default:
7480*9880d681SAndroid Build Coastguard Worker         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7481*9880d681SAndroid Build Coastguard Worker         break;
7482*9880d681SAndroid Build Coastguard Worker       }
7483*9880d681SAndroid Build Coastguard Worker       break;
7484*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_TYPE_POWERPC:
7485*9880d681SAndroid Build Coastguard Worker       outs() << "     PPC";
7486*9880d681SAndroid Build Coastguard Worker       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7487*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_POWERPC_ALL:
7488*9880d681SAndroid Build Coastguard Worker         outs() << "        ALL";
7489*9880d681SAndroid Build Coastguard Worker         break;
7490*9880d681SAndroid Build Coastguard Worker       default:
7491*9880d681SAndroid Build Coastguard Worker         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7492*9880d681SAndroid Build Coastguard Worker         break;
7493*9880d681SAndroid Build Coastguard Worker       }
7494*9880d681SAndroid Build Coastguard Worker       break;
7495*9880d681SAndroid Build Coastguard Worker     case MachO::CPU_TYPE_POWERPC64:
7496*9880d681SAndroid Build Coastguard Worker       outs() << "   PPC64";
7497*9880d681SAndroid Build Coastguard Worker       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7498*9880d681SAndroid Build Coastguard Worker       case MachO::CPU_SUBTYPE_POWERPC_ALL:
7499*9880d681SAndroid Build Coastguard Worker         outs() << "        ALL";
7500*9880d681SAndroid Build Coastguard Worker         break;
7501*9880d681SAndroid Build Coastguard Worker       default:
7502*9880d681SAndroid Build Coastguard Worker         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7503*9880d681SAndroid Build Coastguard Worker         break;
7504*9880d681SAndroid Build Coastguard Worker       }
7505*9880d681SAndroid Build Coastguard Worker       break;
7506*9880d681SAndroid Build Coastguard Worker     default:
7507*9880d681SAndroid Build Coastguard Worker       outs() << format(" %7d", cputype);
7508*9880d681SAndroid Build Coastguard Worker       outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7509*9880d681SAndroid Build Coastguard Worker       break;
7510*9880d681SAndroid Build Coastguard Worker     }
7511*9880d681SAndroid Build Coastguard Worker     if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
7512*9880d681SAndroid Build Coastguard Worker       outs() << " LIB64";
7513*9880d681SAndroid Build Coastguard Worker     } else {
7514*9880d681SAndroid Build Coastguard Worker       outs() << format("  0x%02" PRIx32,
7515*9880d681SAndroid Build Coastguard Worker                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
7516*9880d681SAndroid Build Coastguard Worker     }
7517*9880d681SAndroid Build Coastguard Worker     switch (filetype) {
7518*9880d681SAndroid Build Coastguard Worker     case MachO::MH_OBJECT:
7519*9880d681SAndroid Build Coastguard Worker       outs() << "      OBJECT";
7520*9880d681SAndroid Build Coastguard Worker       break;
7521*9880d681SAndroid Build Coastguard Worker     case MachO::MH_EXECUTE:
7522*9880d681SAndroid Build Coastguard Worker       outs() << "     EXECUTE";
7523*9880d681SAndroid Build Coastguard Worker       break;
7524*9880d681SAndroid Build Coastguard Worker     case MachO::MH_FVMLIB:
7525*9880d681SAndroid Build Coastguard Worker       outs() << "      FVMLIB";
7526*9880d681SAndroid Build Coastguard Worker       break;
7527*9880d681SAndroid Build Coastguard Worker     case MachO::MH_CORE:
7528*9880d681SAndroid Build Coastguard Worker       outs() << "        CORE";
7529*9880d681SAndroid Build Coastguard Worker       break;
7530*9880d681SAndroid Build Coastguard Worker     case MachO::MH_PRELOAD:
7531*9880d681SAndroid Build Coastguard Worker       outs() << "     PRELOAD";
7532*9880d681SAndroid Build Coastguard Worker       break;
7533*9880d681SAndroid Build Coastguard Worker     case MachO::MH_DYLIB:
7534*9880d681SAndroid Build Coastguard Worker       outs() << "       DYLIB";
7535*9880d681SAndroid Build Coastguard Worker       break;
7536*9880d681SAndroid Build Coastguard Worker     case MachO::MH_DYLIB_STUB:
7537*9880d681SAndroid Build Coastguard Worker       outs() << "  DYLIB_STUB";
7538*9880d681SAndroid Build Coastguard Worker       break;
7539*9880d681SAndroid Build Coastguard Worker     case MachO::MH_DYLINKER:
7540*9880d681SAndroid Build Coastguard Worker       outs() << "    DYLINKER";
7541*9880d681SAndroid Build Coastguard Worker       break;
7542*9880d681SAndroid Build Coastguard Worker     case MachO::MH_BUNDLE:
7543*9880d681SAndroid Build Coastguard Worker       outs() << "      BUNDLE";
7544*9880d681SAndroid Build Coastguard Worker       break;
7545*9880d681SAndroid Build Coastguard Worker     case MachO::MH_DSYM:
7546*9880d681SAndroid Build Coastguard Worker       outs() << "        DSYM";
7547*9880d681SAndroid Build Coastguard Worker       break;
7548*9880d681SAndroid Build Coastguard Worker     case MachO::MH_KEXT_BUNDLE:
7549*9880d681SAndroid Build Coastguard Worker       outs() << "  KEXTBUNDLE";
7550*9880d681SAndroid Build Coastguard Worker       break;
7551*9880d681SAndroid Build Coastguard Worker     default:
7552*9880d681SAndroid Build Coastguard Worker       outs() << format("  %10u", filetype);
7553*9880d681SAndroid Build Coastguard Worker       break;
7554*9880d681SAndroid Build Coastguard Worker     }
7555*9880d681SAndroid Build Coastguard Worker     outs() << format(" %5u", ncmds);
7556*9880d681SAndroid Build Coastguard Worker     outs() << format(" %10u", sizeofcmds);
7557*9880d681SAndroid Build Coastguard Worker     uint32_t f = flags;
7558*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_NOUNDEFS) {
7559*9880d681SAndroid Build Coastguard Worker       outs() << "   NOUNDEFS";
7560*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_NOUNDEFS;
7561*9880d681SAndroid Build Coastguard Worker     }
7562*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_INCRLINK) {
7563*9880d681SAndroid Build Coastguard Worker       outs() << " INCRLINK";
7564*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_INCRLINK;
7565*9880d681SAndroid Build Coastguard Worker     }
7566*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_DYLDLINK) {
7567*9880d681SAndroid Build Coastguard Worker       outs() << " DYLDLINK";
7568*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_DYLDLINK;
7569*9880d681SAndroid Build Coastguard Worker     }
7570*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_BINDATLOAD) {
7571*9880d681SAndroid Build Coastguard Worker       outs() << " BINDATLOAD";
7572*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_BINDATLOAD;
7573*9880d681SAndroid Build Coastguard Worker     }
7574*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_PREBOUND) {
7575*9880d681SAndroid Build Coastguard Worker       outs() << " PREBOUND";
7576*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_PREBOUND;
7577*9880d681SAndroid Build Coastguard Worker     }
7578*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_SPLIT_SEGS) {
7579*9880d681SAndroid Build Coastguard Worker       outs() << " SPLIT_SEGS";
7580*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_SPLIT_SEGS;
7581*9880d681SAndroid Build Coastguard Worker     }
7582*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_LAZY_INIT) {
7583*9880d681SAndroid Build Coastguard Worker       outs() << " LAZY_INIT";
7584*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_LAZY_INIT;
7585*9880d681SAndroid Build Coastguard Worker     }
7586*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_TWOLEVEL) {
7587*9880d681SAndroid Build Coastguard Worker       outs() << " TWOLEVEL";
7588*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_TWOLEVEL;
7589*9880d681SAndroid Build Coastguard Worker     }
7590*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_FORCE_FLAT) {
7591*9880d681SAndroid Build Coastguard Worker       outs() << " FORCE_FLAT";
7592*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_FORCE_FLAT;
7593*9880d681SAndroid Build Coastguard Worker     }
7594*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_NOMULTIDEFS) {
7595*9880d681SAndroid Build Coastguard Worker       outs() << " NOMULTIDEFS";
7596*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_NOMULTIDEFS;
7597*9880d681SAndroid Build Coastguard Worker     }
7598*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_NOFIXPREBINDING) {
7599*9880d681SAndroid Build Coastguard Worker       outs() << " NOFIXPREBINDING";
7600*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_NOFIXPREBINDING;
7601*9880d681SAndroid Build Coastguard Worker     }
7602*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_PREBINDABLE) {
7603*9880d681SAndroid Build Coastguard Worker       outs() << " PREBINDABLE";
7604*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_PREBINDABLE;
7605*9880d681SAndroid Build Coastguard Worker     }
7606*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_ALLMODSBOUND) {
7607*9880d681SAndroid Build Coastguard Worker       outs() << " ALLMODSBOUND";
7608*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_ALLMODSBOUND;
7609*9880d681SAndroid Build Coastguard Worker     }
7610*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
7611*9880d681SAndroid Build Coastguard Worker       outs() << " SUBSECTIONS_VIA_SYMBOLS";
7612*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
7613*9880d681SAndroid Build Coastguard Worker     }
7614*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_CANONICAL) {
7615*9880d681SAndroid Build Coastguard Worker       outs() << " CANONICAL";
7616*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_CANONICAL;
7617*9880d681SAndroid Build Coastguard Worker     }
7618*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_WEAK_DEFINES) {
7619*9880d681SAndroid Build Coastguard Worker       outs() << " WEAK_DEFINES";
7620*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_WEAK_DEFINES;
7621*9880d681SAndroid Build Coastguard Worker     }
7622*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_BINDS_TO_WEAK) {
7623*9880d681SAndroid Build Coastguard Worker       outs() << " BINDS_TO_WEAK";
7624*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_BINDS_TO_WEAK;
7625*9880d681SAndroid Build Coastguard Worker     }
7626*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
7627*9880d681SAndroid Build Coastguard Worker       outs() << " ALLOW_STACK_EXECUTION";
7628*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
7629*9880d681SAndroid Build Coastguard Worker     }
7630*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
7631*9880d681SAndroid Build Coastguard Worker       outs() << " DEAD_STRIPPABLE_DYLIB";
7632*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
7633*9880d681SAndroid Build Coastguard Worker     }
7634*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_PIE) {
7635*9880d681SAndroid Build Coastguard Worker       outs() << " PIE";
7636*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_PIE;
7637*9880d681SAndroid Build Coastguard Worker     }
7638*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
7639*9880d681SAndroid Build Coastguard Worker       outs() << " NO_REEXPORTED_DYLIBS";
7640*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
7641*9880d681SAndroid Build Coastguard Worker     }
7642*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
7643*9880d681SAndroid Build Coastguard Worker       outs() << " MH_HAS_TLV_DESCRIPTORS";
7644*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
7645*9880d681SAndroid Build Coastguard Worker     }
7646*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_NO_HEAP_EXECUTION) {
7647*9880d681SAndroid Build Coastguard Worker       outs() << " MH_NO_HEAP_EXECUTION";
7648*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_NO_HEAP_EXECUTION;
7649*9880d681SAndroid Build Coastguard Worker     }
7650*9880d681SAndroid Build Coastguard Worker     if (f & MachO::MH_APP_EXTENSION_SAFE) {
7651*9880d681SAndroid Build Coastguard Worker       outs() << " APP_EXTENSION_SAFE";
7652*9880d681SAndroid Build Coastguard Worker       f &= ~MachO::MH_APP_EXTENSION_SAFE;
7653*9880d681SAndroid Build Coastguard Worker     }
7654*9880d681SAndroid Build Coastguard Worker     if (f != 0 || flags == 0)
7655*9880d681SAndroid Build Coastguard Worker       outs() << format(" 0x%08" PRIx32, f);
7656*9880d681SAndroid Build Coastguard Worker   } else {
7657*9880d681SAndroid Build Coastguard Worker     outs() << format(" 0x%08" PRIx32, magic);
7658*9880d681SAndroid Build Coastguard Worker     outs() << format(" %7d", cputype);
7659*9880d681SAndroid Build Coastguard Worker     outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7660*9880d681SAndroid Build Coastguard Worker     outs() << format("  0x%02" PRIx32,
7661*9880d681SAndroid Build Coastguard Worker                      (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
7662*9880d681SAndroid Build Coastguard Worker     outs() << format("  %10u", filetype);
7663*9880d681SAndroid Build Coastguard Worker     outs() << format(" %5u", ncmds);
7664*9880d681SAndroid Build Coastguard Worker     outs() << format(" %10u", sizeofcmds);
7665*9880d681SAndroid Build Coastguard Worker     outs() << format(" 0x%08" PRIx32, flags);
7666*9880d681SAndroid Build Coastguard Worker   }
7667*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
7668*9880d681SAndroid Build Coastguard Worker }
7669*9880d681SAndroid Build Coastguard Worker 
PrintSegmentCommand(uint32_t cmd,uint32_t cmdsize,StringRef SegName,uint64_t vmaddr,uint64_t vmsize,uint64_t fileoff,uint64_t filesize,uint32_t maxprot,uint32_t initprot,uint32_t nsects,uint32_t flags,uint32_t object_size,bool verbose)7670*9880d681SAndroid Build Coastguard Worker static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
7671*9880d681SAndroid Build Coastguard Worker                                 StringRef SegName, uint64_t vmaddr,
7672*9880d681SAndroid Build Coastguard Worker                                 uint64_t vmsize, uint64_t fileoff,
7673*9880d681SAndroid Build Coastguard Worker                                 uint64_t filesize, uint32_t maxprot,
7674*9880d681SAndroid Build Coastguard Worker                                 uint32_t initprot, uint32_t nsects,
7675*9880d681SAndroid Build Coastguard Worker                                 uint32_t flags, uint32_t object_size,
7676*9880d681SAndroid Build Coastguard Worker                                 bool verbose) {
7677*9880d681SAndroid Build Coastguard Worker   uint64_t expected_cmdsize;
7678*9880d681SAndroid Build Coastguard Worker   if (cmd == MachO::LC_SEGMENT) {
7679*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd LC_SEGMENT\n";
7680*9880d681SAndroid Build Coastguard Worker     expected_cmdsize = nsects;
7681*9880d681SAndroid Build Coastguard Worker     expected_cmdsize *= sizeof(struct MachO::section);
7682*9880d681SAndroid Build Coastguard Worker     expected_cmdsize += sizeof(struct MachO::segment_command);
7683*9880d681SAndroid Build Coastguard Worker   } else {
7684*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd LC_SEGMENT_64\n";
7685*9880d681SAndroid Build Coastguard Worker     expected_cmdsize = nsects;
7686*9880d681SAndroid Build Coastguard Worker     expected_cmdsize *= sizeof(struct MachO::section_64);
7687*9880d681SAndroid Build Coastguard Worker     expected_cmdsize += sizeof(struct MachO::segment_command_64);
7688*9880d681SAndroid Build Coastguard Worker   }
7689*9880d681SAndroid Build Coastguard Worker   outs() << "  cmdsize " << cmdsize;
7690*9880d681SAndroid Build Coastguard Worker   if (cmdsize != expected_cmdsize)
7691*9880d681SAndroid Build Coastguard Worker     outs() << " Inconsistent size\n";
7692*9880d681SAndroid Build Coastguard Worker   else
7693*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7694*9880d681SAndroid Build Coastguard Worker   outs() << "  segname " << SegName << "\n";
7695*9880d681SAndroid Build Coastguard Worker   if (cmd == MachO::LC_SEGMENT_64) {
7696*9880d681SAndroid Build Coastguard Worker     outs() << "   vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
7697*9880d681SAndroid Build Coastguard Worker     outs() << "   vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
7698*9880d681SAndroid Build Coastguard Worker   } else {
7699*9880d681SAndroid Build Coastguard Worker     outs() << "   vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
7700*9880d681SAndroid Build Coastguard Worker     outs() << "   vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
7701*9880d681SAndroid Build Coastguard Worker   }
7702*9880d681SAndroid Build Coastguard Worker   outs() << "  fileoff " << fileoff;
7703*9880d681SAndroid Build Coastguard Worker   if (fileoff > object_size)
7704*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7705*9880d681SAndroid Build Coastguard Worker   else
7706*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7707*9880d681SAndroid Build Coastguard Worker   outs() << " filesize " << filesize;
7708*9880d681SAndroid Build Coastguard Worker   if (fileoff + filesize > object_size)
7709*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7710*9880d681SAndroid Build Coastguard Worker   else
7711*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7712*9880d681SAndroid Build Coastguard Worker   if (verbose) {
7713*9880d681SAndroid Build Coastguard Worker     if ((maxprot &
7714*9880d681SAndroid Build Coastguard Worker          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
7715*9880d681SAndroid Build Coastguard Worker            MachO::VM_PROT_EXECUTE)) != 0)
7716*9880d681SAndroid Build Coastguard Worker       outs() << "  maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
7717*9880d681SAndroid Build Coastguard Worker     else {
7718*9880d681SAndroid Build Coastguard Worker       outs() << "  maxprot ";
7719*9880d681SAndroid Build Coastguard Worker       outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
7720*9880d681SAndroid Build Coastguard Worker       outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
7721*9880d681SAndroid Build Coastguard Worker       outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
7722*9880d681SAndroid Build Coastguard Worker     }
7723*9880d681SAndroid Build Coastguard Worker     if ((initprot &
7724*9880d681SAndroid Build Coastguard Worker          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
7725*9880d681SAndroid Build Coastguard Worker            MachO::VM_PROT_EXECUTE)) != 0)
7726*9880d681SAndroid Build Coastguard Worker       outs() << "  initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
7727*9880d681SAndroid Build Coastguard Worker     else {
7728*9880d681SAndroid Build Coastguard Worker       outs() << "  initprot ";
7729*9880d681SAndroid Build Coastguard Worker       outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
7730*9880d681SAndroid Build Coastguard Worker       outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
7731*9880d681SAndroid Build Coastguard Worker       outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
7732*9880d681SAndroid Build Coastguard Worker     }
7733*9880d681SAndroid Build Coastguard Worker   } else {
7734*9880d681SAndroid Build Coastguard Worker     outs() << "  maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
7735*9880d681SAndroid Build Coastguard Worker     outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
7736*9880d681SAndroid Build Coastguard Worker   }
7737*9880d681SAndroid Build Coastguard Worker   outs() << "   nsects " << nsects << "\n";
7738*9880d681SAndroid Build Coastguard Worker   if (verbose) {
7739*9880d681SAndroid Build Coastguard Worker     outs() << "    flags";
7740*9880d681SAndroid Build Coastguard Worker     if (flags == 0)
7741*9880d681SAndroid Build Coastguard Worker       outs() << " (none)\n";
7742*9880d681SAndroid Build Coastguard Worker     else {
7743*9880d681SAndroid Build Coastguard Worker       if (flags & MachO::SG_HIGHVM) {
7744*9880d681SAndroid Build Coastguard Worker         outs() << " HIGHVM";
7745*9880d681SAndroid Build Coastguard Worker         flags &= ~MachO::SG_HIGHVM;
7746*9880d681SAndroid Build Coastguard Worker       }
7747*9880d681SAndroid Build Coastguard Worker       if (flags & MachO::SG_FVMLIB) {
7748*9880d681SAndroid Build Coastguard Worker         outs() << " FVMLIB";
7749*9880d681SAndroid Build Coastguard Worker         flags &= ~MachO::SG_FVMLIB;
7750*9880d681SAndroid Build Coastguard Worker       }
7751*9880d681SAndroid Build Coastguard Worker       if (flags & MachO::SG_NORELOC) {
7752*9880d681SAndroid Build Coastguard Worker         outs() << " NORELOC";
7753*9880d681SAndroid Build Coastguard Worker         flags &= ~MachO::SG_NORELOC;
7754*9880d681SAndroid Build Coastguard Worker       }
7755*9880d681SAndroid Build Coastguard Worker       if (flags & MachO::SG_PROTECTED_VERSION_1) {
7756*9880d681SAndroid Build Coastguard Worker         outs() << " PROTECTED_VERSION_1";
7757*9880d681SAndroid Build Coastguard Worker         flags &= ~MachO::SG_PROTECTED_VERSION_1;
7758*9880d681SAndroid Build Coastguard Worker       }
7759*9880d681SAndroid Build Coastguard Worker       if (flags)
7760*9880d681SAndroid Build Coastguard Worker         outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
7761*9880d681SAndroid Build Coastguard Worker       else
7762*9880d681SAndroid Build Coastguard Worker         outs() << "\n";
7763*9880d681SAndroid Build Coastguard Worker     }
7764*9880d681SAndroid Build Coastguard Worker   } else {
7765*9880d681SAndroid Build Coastguard Worker     outs() << "    flags " << format("0x%" PRIx32, flags) << "\n";
7766*9880d681SAndroid Build Coastguard Worker   }
7767*9880d681SAndroid Build Coastguard Worker }
7768*9880d681SAndroid Build Coastguard Worker 
PrintSection(const char * sectname,const char * segname,uint64_t addr,uint64_t size,uint32_t offset,uint32_t align,uint32_t reloff,uint32_t nreloc,uint32_t flags,uint32_t reserved1,uint32_t reserved2,uint32_t cmd,const char * sg_segname,uint32_t filetype,uint32_t object_size,bool verbose)7769*9880d681SAndroid Build Coastguard Worker static void PrintSection(const char *sectname, const char *segname,
7770*9880d681SAndroid Build Coastguard Worker                          uint64_t addr, uint64_t size, uint32_t offset,
7771*9880d681SAndroid Build Coastguard Worker                          uint32_t align, uint32_t reloff, uint32_t nreloc,
7772*9880d681SAndroid Build Coastguard Worker                          uint32_t flags, uint32_t reserved1, uint32_t reserved2,
7773*9880d681SAndroid Build Coastguard Worker                          uint32_t cmd, const char *sg_segname,
7774*9880d681SAndroid Build Coastguard Worker                          uint32_t filetype, uint32_t object_size,
7775*9880d681SAndroid Build Coastguard Worker                          bool verbose) {
7776*9880d681SAndroid Build Coastguard Worker   outs() << "Section\n";
7777*9880d681SAndroid Build Coastguard Worker   outs() << "  sectname " << format("%.16s\n", sectname);
7778*9880d681SAndroid Build Coastguard Worker   outs() << "   segname " << format("%.16s", segname);
7779*9880d681SAndroid Build Coastguard Worker   if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
7780*9880d681SAndroid Build Coastguard Worker     outs() << " (does not match segment)\n";
7781*9880d681SAndroid Build Coastguard Worker   else
7782*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7783*9880d681SAndroid Build Coastguard Worker   if (cmd == MachO::LC_SEGMENT_64) {
7784*9880d681SAndroid Build Coastguard Worker     outs() << "      addr " << format("0x%016" PRIx64, addr) << "\n";
7785*9880d681SAndroid Build Coastguard Worker     outs() << "      size " << format("0x%016" PRIx64, size);
7786*9880d681SAndroid Build Coastguard Worker   } else {
7787*9880d681SAndroid Build Coastguard Worker     outs() << "      addr " << format("0x%08" PRIx64, addr) << "\n";
7788*9880d681SAndroid Build Coastguard Worker     outs() << "      size " << format("0x%08" PRIx64, size);
7789*9880d681SAndroid Build Coastguard Worker   }
7790*9880d681SAndroid Build Coastguard Worker   if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
7791*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7792*9880d681SAndroid Build Coastguard Worker   else
7793*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7794*9880d681SAndroid Build Coastguard Worker   outs() << "    offset " << offset;
7795*9880d681SAndroid Build Coastguard Worker   if (offset > object_size)
7796*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7797*9880d681SAndroid Build Coastguard Worker   else
7798*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7799*9880d681SAndroid Build Coastguard Worker   uint32_t align_shifted = 1 << align;
7800*9880d681SAndroid Build Coastguard Worker   outs() << "     align 2^" << align << " (" << align_shifted << ")\n";
7801*9880d681SAndroid Build Coastguard Worker   outs() << "    reloff " << reloff;
7802*9880d681SAndroid Build Coastguard Worker   if (reloff > object_size)
7803*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7804*9880d681SAndroid Build Coastguard Worker   else
7805*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7806*9880d681SAndroid Build Coastguard Worker   outs() << "    nreloc " << nreloc;
7807*9880d681SAndroid Build Coastguard Worker   if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
7808*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7809*9880d681SAndroid Build Coastguard Worker   else
7810*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7811*9880d681SAndroid Build Coastguard Worker   uint32_t section_type = flags & MachO::SECTION_TYPE;
7812*9880d681SAndroid Build Coastguard Worker   if (verbose) {
7813*9880d681SAndroid Build Coastguard Worker     outs() << "      type";
7814*9880d681SAndroid Build Coastguard Worker     if (section_type == MachO::S_REGULAR)
7815*9880d681SAndroid Build Coastguard Worker       outs() << " S_REGULAR\n";
7816*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_ZEROFILL)
7817*9880d681SAndroid Build Coastguard Worker       outs() << " S_ZEROFILL\n";
7818*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_CSTRING_LITERALS)
7819*9880d681SAndroid Build Coastguard Worker       outs() << " S_CSTRING_LITERALS\n";
7820*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_4BYTE_LITERALS)
7821*9880d681SAndroid Build Coastguard Worker       outs() << " S_4BYTE_LITERALS\n";
7822*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_8BYTE_LITERALS)
7823*9880d681SAndroid Build Coastguard Worker       outs() << " S_8BYTE_LITERALS\n";
7824*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_16BYTE_LITERALS)
7825*9880d681SAndroid Build Coastguard Worker       outs() << " S_16BYTE_LITERALS\n";
7826*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_LITERAL_POINTERS)
7827*9880d681SAndroid Build Coastguard Worker       outs() << " S_LITERAL_POINTERS\n";
7828*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
7829*9880d681SAndroid Build Coastguard Worker       outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
7830*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
7831*9880d681SAndroid Build Coastguard Worker       outs() << " S_LAZY_SYMBOL_POINTERS\n";
7832*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_SYMBOL_STUBS)
7833*9880d681SAndroid Build Coastguard Worker       outs() << " S_SYMBOL_STUBS\n";
7834*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
7835*9880d681SAndroid Build Coastguard Worker       outs() << " S_MOD_INIT_FUNC_POINTERS\n";
7836*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
7837*9880d681SAndroid Build Coastguard Worker       outs() << " S_MOD_TERM_FUNC_POINTERS\n";
7838*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_COALESCED)
7839*9880d681SAndroid Build Coastguard Worker       outs() << " S_COALESCED\n";
7840*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_INTERPOSING)
7841*9880d681SAndroid Build Coastguard Worker       outs() << " S_INTERPOSING\n";
7842*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_DTRACE_DOF)
7843*9880d681SAndroid Build Coastguard Worker       outs() << " S_DTRACE_DOF\n";
7844*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
7845*9880d681SAndroid Build Coastguard Worker       outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
7846*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
7847*9880d681SAndroid Build Coastguard Worker       outs() << " S_THREAD_LOCAL_REGULAR\n";
7848*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
7849*9880d681SAndroid Build Coastguard Worker       outs() << " S_THREAD_LOCAL_ZEROFILL\n";
7850*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
7851*9880d681SAndroid Build Coastguard Worker       outs() << " S_THREAD_LOCAL_VARIABLES\n";
7852*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
7853*9880d681SAndroid Build Coastguard Worker       outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
7854*9880d681SAndroid Build Coastguard Worker     else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
7855*9880d681SAndroid Build Coastguard Worker       outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
7856*9880d681SAndroid Build Coastguard Worker     else
7857*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%08" PRIx32, section_type) << "\n";
7858*9880d681SAndroid Build Coastguard Worker     outs() << "attributes";
7859*9880d681SAndroid Build Coastguard Worker     uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
7860*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
7861*9880d681SAndroid Build Coastguard Worker       outs() << " PURE_INSTRUCTIONS";
7862*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_NO_TOC)
7863*9880d681SAndroid Build Coastguard Worker       outs() << " NO_TOC";
7864*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
7865*9880d681SAndroid Build Coastguard Worker       outs() << " STRIP_STATIC_SYMS";
7866*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
7867*9880d681SAndroid Build Coastguard Worker       outs() << " NO_DEAD_STRIP";
7868*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
7869*9880d681SAndroid Build Coastguard Worker       outs() << " LIVE_SUPPORT";
7870*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
7871*9880d681SAndroid Build Coastguard Worker       outs() << " SELF_MODIFYING_CODE";
7872*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_DEBUG)
7873*9880d681SAndroid Build Coastguard Worker       outs() << " DEBUG";
7874*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
7875*9880d681SAndroid Build Coastguard Worker       outs() << " SOME_INSTRUCTIONS";
7876*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_EXT_RELOC)
7877*9880d681SAndroid Build Coastguard Worker       outs() << " EXT_RELOC";
7878*9880d681SAndroid Build Coastguard Worker     if (section_attributes & MachO::S_ATTR_LOC_RELOC)
7879*9880d681SAndroid Build Coastguard Worker       outs() << " LOC_RELOC";
7880*9880d681SAndroid Build Coastguard Worker     if (section_attributes == 0)
7881*9880d681SAndroid Build Coastguard Worker       outs() << " (none)";
7882*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7883*9880d681SAndroid Build Coastguard Worker   } else
7884*9880d681SAndroid Build Coastguard Worker     outs() << "     flags " << format("0x%08" PRIx32, flags) << "\n";
7885*9880d681SAndroid Build Coastguard Worker   outs() << " reserved1 " << reserved1;
7886*9880d681SAndroid Build Coastguard Worker   if (section_type == MachO::S_SYMBOL_STUBS ||
7887*9880d681SAndroid Build Coastguard Worker       section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
7888*9880d681SAndroid Build Coastguard Worker       section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
7889*9880d681SAndroid Build Coastguard Worker       section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
7890*9880d681SAndroid Build Coastguard Worker       section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
7891*9880d681SAndroid Build Coastguard Worker     outs() << " (index into indirect symbol table)\n";
7892*9880d681SAndroid Build Coastguard Worker   else
7893*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7894*9880d681SAndroid Build Coastguard Worker   outs() << " reserved2 " << reserved2;
7895*9880d681SAndroid Build Coastguard Worker   if (section_type == MachO::S_SYMBOL_STUBS)
7896*9880d681SAndroid Build Coastguard Worker     outs() << " (size of stubs)\n";
7897*9880d681SAndroid Build Coastguard Worker   else
7898*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7899*9880d681SAndroid Build Coastguard Worker }
7900*9880d681SAndroid Build Coastguard Worker 
PrintSymtabLoadCommand(MachO::symtab_command st,bool Is64Bit,uint32_t object_size)7901*9880d681SAndroid Build Coastguard Worker static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
7902*9880d681SAndroid Build Coastguard Worker                                    uint32_t object_size) {
7903*9880d681SAndroid Build Coastguard Worker   outs() << "     cmd LC_SYMTAB\n";
7904*9880d681SAndroid Build Coastguard Worker   outs() << " cmdsize " << st.cmdsize;
7905*9880d681SAndroid Build Coastguard Worker   if (st.cmdsize != sizeof(struct MachO::symtab_command))
7906*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
7907*9880d681SAndroid Build Coastguard Worker   else
7908*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7909*9880d681SAndroid Build Coastguard Worker   outs() << "  symoff " << st.symoff;
7910*9880d681SAndroid Build Coastguard Worker   if (st.symoff > object_size)
7911*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7912*9880d681SAndroid Build Coastguard Worker   else
7913*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7914*9880d681SAndroid Build Coastguard Worker   outs() << "   nsyms " << st.nsyms;
7915*9880d681SAndroid Build Coastguard Worker   uint64_t big_size;
7916*9880d681SAndroid Build Coastguard Worker   if (Is64Bit) {
7917*9880d681SAndroid Build Coastguard Worker     big_size = st.nsyms;
7918*9880d681SAndroid Build Coastguard Worker     big_size *= sizeof(struct MachO::nlist_64);
7919*9880d681SAndroid Build Coastguard Worker     big_size += st.symoff;
7920*9880d681SAndroid Build Coastguard Worker     if (big_size > object_size)
7921*9880d681SAndroid Build Coastguard Worker       outs() << " (past end of file)\n";
7922*9880d681SAndroid Build Coastguard Worker     else
7923*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
7924*9880d681SAndroid Build Coastguard Worker   } else {
7925*9880d681SAndroid Build Coastguard Worker     big_size = st.nsyms;
7926*9880d681SAndroid Build Coastguard Worker     big_size *= sizeof(struct MachO::nlist);
7927*9880d681SAndroid Build Coastguard Worker     big_size += st.symoff;
7928*9880d681SAndroid Build Coastguard Worker     if (big_size > object_size)
7929*9880d681SAndroid Build Coastguard Worker       outs() << " (past end of file)\n";
7930*9880d681SAndroid Build Coastguard Worker     else
7931*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
7932*9880d681SAndroid Build Coastguard Worker   }
7933*9880d681SAndroid Build Coastguard Worker   outs() << "  stroff " << st.stroff;
7934*9880d681SAndroid Build Coastguard Worker   if (st.stroff > object_size)
7935*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7936*9880d681SAndroid Build Coastguard Worker   else
7937*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7938*9880d681SAndroid Build Coastguard Worker   outs() << " strsize " << st.strsize;
7939*9880d681SAndroid Build Coastguard Worker   big_size = st.stroff;
7940*9880d681SAndroid Build Coastguard Worker   big_size += st.strsize;
7941*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
7942*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7943*9880d681SAndroid Build Coastguard Worker   else
7944*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7945*9880d681SAndroid Build Coastguard Worker }
7946*9880d681SAndroid Build Coastguard Worker 
PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,uint32_t nsyms,uint32_t object_size,bool Is64Bit)7947*9880d681SAndroid Build Coastguard Worker static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
7948*9880d681SAndroid Build Coastguard Worker                                      uint32_t nsyms, uint32_t object_size,
7949*9880d681SAndroid Build Coastguard Worker                                      bool Is64Bit) {
7950*9880d681SAndroid Build Coastguard Worker   outs() << "            cmd LC_DYSYMTAB\n";
7951*9880d681SAndroid Build Coastguard Worker   outs() << "        cmdsize " << dyst.cmdsize;
7952*9880d681SAndroid Build Coastguard Worker   if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
7953*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
7954*9880d681SAndroid Build Coastguard Worker   else
7955*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7956*9880d681SAndroid Build Coastguard Worker   outs() << "      ilocalsym " << dyst.ilocalsym;
7957*9880d681SAndroid Build Coastguard Worker   if (dyst.ilocalsym > nsyms)
7958*9880d681SAndroid Build Coastguard Worker     outs() << " (greater than the number of symbols)\n";
7959*9880d681SAndroid Build Coastguard Worker   else
7960*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7961*9880d681SAndroid Build Coastguard Worker   outs() << "      nlocalsym " << dyst.nlocalsym;
7962*9880d681SAndroid Build Coastguard Worker   uint64_t big_size;
7963*9880d681SAndroid Build Coastguard Worker   big_size = dyst.ilocalsym;
7964*9880d681SAndroid Build Coastguard Worker   big_size += dyst.nlocalsym;
7965*9880d681SAndroid Build Coastguard Worker   if (big_size > nsyms)
7966*9880d681SAndroid Build Coastguard Worker     outs() << " (past the end of the symbol table)\n";
7967*9880d681SAndroid Build Coastguard Worker   else
7968*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7969*9880d681SAndroid Build Coastguard Worker   outs() << "     iextdefsym " << dyst.iextdefsym;
7970*9880d681SAndroid Build Coastguard Worker   if (dyst.iextdefsym > nsyms)
7971*9880d681SAndroid Build Coastguard Worker     outs() << " (greater than the number of symbols)\n";
7972*9880d681SAndroid Build Coastguard Worker   else
7973*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7974*9880d681SAndroid Build Coastguard Worker   outs() << "     nextdefsym " << dyst.nextdefsym;
7975*9880d681SAndroid Build Coastguard Worker   big_size = dyst.iextdefsym;
7976*9880d681SAndroid Build Coastguard Worker   big_size += dyst.nextdefsym;
7977*9880d681SAndroid Build Coastguard Worker   if (big_size > nsyms)
7978*9880d681SAndroid Build Coastguard Worker     outs() << " (past the end of the symbol table)\n";
7979*9880d681SAndroid Build Coastguard Worker   else
7980*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7981*9880d681SAndroid Build Coastguard Worker   outs() << "      iundefsym " << dyst.iundefsym;
7982*9880d681SAndroid Build Coastguard Worker   if (dyst.iundefsym > nsyms)
7983*9880d681SAndroid Build Coastguard Worker     outs() << " (greater than the number of symbols)\n";
7984*9880d681SAndroid Build Coastguard Worker   else
7985*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7986*9880d681SAndroid Build Coastguard Worker   outs() << "      nundefsym " << dyst.nundefsym;
7987*9880d681SAndroid Build Coastguard Worker   big_size = dyst.iundefsym;
7988*9880d681SAndroid Build Coastguard Worker   big_size += dyst.nundefsym;
7989*9880d681SAndroid Build Coastguard Worker   if (big_size > nsyms)
7990*9880d681SAndroid Build Coastguard Worker     outs() << " (past the end of the symbol table)\n";
7991*9880d681SAndroid Build Coastguard Worker   else
7992*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7993*9880d681SAndroid Build Coastguard Worker   outs() << "         tocoff " << dyst.tocoff;
7994*9880d681SAndroid Build Coastguard Worker   if (dyst.tocoff > object_size)
7995*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
7996*9880d681SAndroid Build Coastguard Worker   else
7997*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
7998*9880d681SAndroid Build Coastguard Worker   outs() << "           ntoc " << dyst.ntoc;
7999*9880d681SAndroid Build Coastguard Worker   big_size = dyst.ntoc;
8000*9880d681SAndroid Build Coastguard Worker   big_size *= sizeof(struct MachO::dylib_table_of_contents);
8001*9880d681SAndroid Build Coastguard Worker   big_size += dyst.tocoff;
8002*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8003*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8004*9880d681SAndroid Build Coastguard Worker   else
8005*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8006*9880d681SAndroid Build Coastguard Worker   outs() << "      modtaboff " << dyst.modtaboff;
8007*9880d681SAndroid Build Coastguard Worker   if (dyst.modtaboff > object_size)
8008*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8009*9880d681SAndroid Build Coastguard Worker   else
8010*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8011*9880d681SAndroid Build Coastguard Worker   outs() << "        nmodtab " << dyst.nmodtab;
8012*9880d681SAndroid Build Coastguard Worker   uint64_t modtabend;
8013*9880d681SAndroid Build Coastguard Worker   if (Is64Bit) {
8014*9880d681SAndroid Build Coastguard Worker     modtabend = dyst.nmodtab;
8015*9880d681SAndroid Build Coastguard Worker     modtabend *= sizeof(struct MachO::dylib_module_64);
8016*9880d681SAndroid Build Coastguard Worker     modtabend += dyst.modtaboff;
8017*9880d681SAndroid Build Coastguard Worker   } else {
8018*9880d681SAndroid Build Coastguard Worker     modtabend = dyst.nmodtab;
8019*9880d681SAndroid Build Coastguard Worker     modtabend *= sizeof(struct MachO::dylib_module);
8020*9880d681SAndroid Build Coastguard Worker     modtabend += dyst.modtaboff;
8021*9880d681SAndroid Build Coastguard Worker   }
8022*9880d681SAndroid Build Coastguard Worker   if (modtabend > object_size)
8023*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8024*9880d681SAndroid Build Coastguard Worker   else
8025*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8026*9880d681SAndroid Build Coastguard Worker   outs() << "   extrefsymoff " << dyst.extrefsymoff;
8027*9880d681SAndroid Build Coastguard Worker   if (dyst.extrefsymoff > object_size)
8028*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8029*9880d681SAndroid Build Coastguard Worker   else
8030*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8031*9880d681SAndroid Build Coastguard Worker   outs() << "    nextrefsyms " << dyst.nextrefsyms;
8032*9880d681SAndroid Build Coastguard Worker   big_size = dyst.nextrefsyms;
8033*9880d681SAndroid Build Coastguard Worker   big_size *= sizeof(struct MachO::dylib_reference);
8034*9880d681SAndroid Build Coastguard Worker   big_size += dyst.extrefsymoff;
8035*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8036*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8037*9880d681SAndroid Build Coastguard Worker   else
8038*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8039*9880d681SAndroid Build Coastguard Worker   outs() << " indirectsymoff " << dyst.indirectsymoff;
8040*9880d681SAndroid Build Coastguard Worker   if (dyst.indirectsymoff > object_size)
8041*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8042*9880d681SAndroid Build Coastguard Worker   else
8043*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8044*9880d681SAndroid Build Coastguard Worker   outs() << "  nindirectsyms " << dyst.nindirectsyms;
8045*9880d681SAndroid Build Coastguard Worker   big_size = dyst.nindirectsyms;
8046*9880d681SAndroid Build Coastguard Worker   big_size *= sizeof(uint32_t);
8047*9880d681SAndroid Build Coastguard Worker   big_size += dyst.indirectsymoff;
8048*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8049*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8050*9880d681SAndroid Build Coastguard Worker   else
8051*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8052*9880d681SAndroid Build Coastguard Worker   outs() << "      extreloff " << dyst.extreloff;
8053*9880d681SAndroid Build Coastguard Worker   if (dyst.extreloff > object_size)
8054*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8055*9880d681SAndroid Build Coastguard Worker   else
8056*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8057*9880d681SAndroid Build Coastguard Worker   outs() << "        nextrel " << dyst.nextrel;
8058*9880d681SAndroid Build Coastguard Worker   big_size = dyst.nextrel;
8059*9880d681SAndroid Build Coastguard Worker   big_size *= sizeof(struct MachO::relocation_info);
8060*9880d681SAndroid Build Coastguard Worker   big_size += dyst.extreloff;
8061*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8062*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8063*9880d681SAndroid Build Coastguard Worker   else
8064*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8065*9880d681SAndroid Build Coastguard Worker   outs() << "      locreloff " << dyst.locreloff;
8066*9880d681SAndroid Build Coastguard Worker   if (dyst.locreloff > object_size)
8067*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8068*9880d681SAndroid Build Coastguard Worker   else
8069*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8070*9880d681SAndroid Build Coastguard Worker   outs() << "        nlocrel " << dyst.nlocrel;
8071*9880d681SAndroid Build Coastguard Worker   big_size = dyst.nlocrel;
8072*9880d681SAndroid Build Coastguard Worker   big_size *= sizeof(struct MachO::relocation_info);
8073*9880d681SAndroid Build Coastguard Worker   big_size += dyst.locreloff;
8074*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8075*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8076*9880d681SAndroid Build Coastguard Worker   else
8077*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8078*9880d681SAndroid Build Coastguard Worker }
8079*9880d681SAndroid Build Coastguard Worker 
PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,uint32_t object_size)8080*9880d681SAndroid Build Coastguard Worker static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
8081*9880d681SAndroid Build Coastguard Worker                                      uint32_t object_size) {
8082*9880d681SAndroid Build Coastguard Worker   if (dc.cmd == MachO::LC_DYLD_INFO)
8083*9880d681SAndroid Build Coastguard Worker     outs() << "            cmd LC_DYLD_INFO\n";
8084*9880d681SAndroid Build Coastguard Worker   else
8085*9880d681SAndroid Build Coastguard Worker     outs() << "            cmd LC_DYLD_INFO_ONLY\n";
8086*9880d681SAndroid Build Coastguard Worker   outs() << "        cmdsize " << dc.cmdsize;
8087*9880d681SAndroid Build Coastguard Worker   if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
8088*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8089*9880d681SAndroid Build Coastguard Worker   else
8090*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8091*9880d681SAndroid Build Coastguard Worker   outs() << "     rebase_off " << dc.rebase_off;
8092*9880d681SAndroid Build Coastguard Worker   if (dc.rebase_off > object_size)
8093*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8094*9880d681SAndroid Build Coastguard Worker   else
8095*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8096*9880d681SAndroid Build Coastguard Worker   outs() << "    rebase_size " << dc.rebase_size;
8097*9880d681SAndroid Build Coastguard Worker   uint64_t big_size;
8098*9880d681SAndroid Build Coastguard Worker   big_size = dc.rebase_off;
8099*9880d681SAndroid Build Coastguard Worker   big_size += dc.rebase_size;
8100*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8101*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8102*9880d681SAndroid Build Coastguard Worker   else
8103*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8104*9880d681SAndroid Build Coastguard Worker   outs() << "       bind_off " << dc.bind_off;
8105*9880d681SAndroid Build Coastguard Worker   if (dc.bind_off > object_size)
8106*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8107*9880d681SAndroid Build Coastguard Worker   else
8108*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8109*9880d681SAndroid Build Coastguard Worker   outs() << "      bind_size " << dc.bind_size;
8110*9880d681SAndroid Build Coastguard Worker   big_size = dc.bind_off;
8111*9880d681SAndroid Build Coastguard Worker   big_size += dc.bind_size;
8112*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8113*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8114*9880d681SAndroid Build Coastguard Worker   else
8115*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8116*9880d681SAndroid Build Coastguard Worker   outs() << "  weak_bind_off " << dc.weak_bind_off;
8117*9880d681SAndroid Build Coastguard Worker   if (dc.weak_bind_off > object_size)
8118*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8119*9880d681SAndroid Build Coastguard Worker   else
8120*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8121*9880d681SAndroid Build Coastguard Worker   outs() << " weak_bind_size " << dc.weak_bind_size;
8122*9880d681SAndroid Build Coastguard Worker   big_size = dc.weak_bind_off;
8123*9880d681SAndroid Build Coastguard Worker   big_size += dc.weak_bind_size;
8124*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8125*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8126*9880d681SAndroid Build Coastguard Worker   else
8127*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8128*9880d681SAndroid Build Coastguard Worker   outs() << "  lazy_bind_off " << dc.lazy_bind_off;
8129*9880d681SAndroid Build Coastguard Worker   if (dc.lazy_bind_off > object_size)
8130*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8131*9880d681SAndroid Build Coastguard Worker   else
8132*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8133*9880d681SAndroid Build Coastguard Worker   outs() << " lazy_bind_size " << dc.lazy_bind_size;
8134*9880d681SAndroid Build Coastguard Worker   big_size = dc.lazy_bind_off;
8135*9880d681SAndroid Build Coastguard Worker   big_size += dc.lazy_bind_size;
8136*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8137*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8138*9880d681SAndroid Build Coastguard Worker   else
8139*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8140*9880d681SAndroid Build Coastguard Worker   outs() << "     export_off " << dc.export_off;
8141*9880d681SAndroid Build Coastguard Worker   if (dc.export_off > object_size)
8142*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8143*9880d681SAndroid Build Coastguard Worker   else
8144*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8145*9880d681SAndroid Build Coastguard Worker   outs() << "    export_size " << dc.export_size;
8146*9880d681SAndroid Build Coastguard Worker   big_size = dc.export_off;
8147*9880d681SAndroid Build Coastguard Worker   big_size += dc.export_size;
8148*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8149*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8150*9880d681SAndroid Build Coastguard Worker   else
8151*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8152*9880d681SAndroid Build Coastguard Worker }
8153*9880d681SAndroid Build Coastguard Worker 
PrintDyldLoadCommand(MachO::dylinker_command dyld,const char * Ptr)8154*9880d681SAndroid Build Coastguard Worker static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
8155*9880d681SAndroid Build Coastguard Worker                                  const char *Ptr) {
8156*9880d681SAndroid Build Coastguard Worker   if (dyld.cmd == MachO::LC_ID_DYLINKER)
8157*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_ID_DYLINKER\n";
8158*9880d681SAndroid Build Coastguard Worker   else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
8159*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_LOAD_DYLINKER\n";
8160*9880d681SAndroid Build Coastguard Worker   else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
8161*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_DYLD_ENVIRONMENT\n";
8162*9880d681SAndroid Build Coastguard Worker   else
8163*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd ?(" << dyld.cmd << ")\n";
8164*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << dyld.cmdsize;
8165*9880d681SAndroid Build Coastguard Worker   if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
8166*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8167*9880d681SAndroid Build Coastguard Worker   else
8168*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8169*9880d681SAndroid Build Coastguard Worker   if (dyld.name >= dyld.cmdsize)
8170*9880d681SAndroid Build Coastguard Worker     outs() << "         name ?(bad offset " << dyld.name << ")\n";
8171*9880d681SAndroid Build Coastguard Worker   else {
8172*9880d681SAndroid Build Coastguard Worker     const char *P = (const char *)(Ptr) + dyld.name;
8173*9880d681SAndroid Build Coastguard Worker     outs() << "         name " << P << " (offset " << dyld.name << ")\n";
8174*9880d681SAndroid Build Coastguard Worker   }
8175*9880d681SAndroid Build Coastguard Worker }
8176*9880d681SAndroid Build Coastguard Worker 
PrintUuidLoadCommand(MachO::uuid_command uuid)8177*9880d681SAndroid Build Coastguard Worker static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
8178*9880d681SAndroid Build Coastguard Worker   outs() << "     cmd LC_UUID\n";
8179*9880d681SAndroid Build Coastguard Worker   outs() << " cmdsize " << uuid.cmdsize;
8180*9880d681SAndroid Build Coastguard Worker   if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
8181*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8182*9880d681SAndroid Build Coastguard Worker   else
8183*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8184*9880d681SAndroid Build Coastguard Worker   outs() << "    uuid ";
8185*9880d681SAndroid Build Coastguard Worker   for (int i = 0; i < 16; ++i) {
8186*9880d681SAndroid Build Coastguard Worker     outs() << format("%02" PRIX32, uuid.uuid[i]);
8187*9880d681SAndroid Build Coastguard Worker     if (i == 3 || i == 5 || i == 7 || i == 9)
8188*9880d681SAndroid Build Coastguard Worker       outs() << "-";
8189*9880d681SAndroid Build Coastguard Worker   }
8190*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8191*9880d681SAndroid Build Coastguard Worker }
8192*9880d681SAndroid Build Coastguard Worker 
PrintRpathLoadCommand(MachO::rpath_command rpath,const char * Ptr)8193*9880d681SAndroid Build Coastguard Worker static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
8194*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_RPATH\n";
8195*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << rpath.cmdsize;
8196*9880d681SAndroid Build Coastguard Worker   if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
8197*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8198*9880d681SAndroid Build Coastguard Worker   else
8199*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8200*9880d681SAndroid Build Coastguard Worker   if (rpath.path >= rpath.cmdsize)
8201*9880d681SAndroid Build Coastguard Worker     outs() << "         path ?(bad offset " << rpath.path << ")\n";
8202*9880d681SAndroid Build Coastguard Worker   else {
8203*9880d681SAndroid Build Coastguard Worker     const char *P = (const char *)(Ptr) + rpath.path;
8204*9880d681SAndroid Build Coastguard Worker     outs() << "         path " << P << " (offset " << rpath.path << ")\n";
8205*9880d681SAndroid Build Coastguard Worker   }
8206*9880d681SAndroid Build Coastguard Worker }
8207*9880d681SAndroid Build Coastguard Worker 
PrintVersionMinLoadCommand(MachO::version_min_command vd)8208*9880d681SAndroid Build Coastguard Worker static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
8209*9880d681SAndroid Build Coastguard Worker   StringRef LoadCmdName;
8210*9880d681SAndroid Build Coastguard Worker   switch (vd.cmd) {
8211*9880d681SAndroid Build Coastguard Worker   case MachO::LC_VERSION_MIN_MACOSX:
8212*9880d681SAndroid Build Coastguard Worker     LoadCmdName = "LC_VERSION_MIN_MACOSX";
8213*9880d681SAndroid Build Coastguard Worker     break;
8214*9880d681SAndroid Build Coastguard Worker   case MachO::LC_VERSION_MIN_IPHONEOS:
8215*9880d681SAndroid Build Coastguard Worker     LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
8216*9880d681SAndroid Build Coastguard Worker     break;
8217*9880d681SAndroid Build Coastguard Worker   case MachO::LC_VERSION_MIN_TVOS:
8218*9880d681SAndroid Build Coastguard Worker     LoadCmdName = "LC_VERSION_MIN_TVOS";
8219*9880d681SAndroid Build Coastguard Worker     break;
8220*9880d681SAndroid Build Coastguard Worker   case MachO::LC_VERSION_MIN_WATCHOS:
8221*9880d681SAndroid Build Coastguard Worker     LoadCmdName = "LC_VERSION_MIN_WATCHOS";
8222*9880d681SAndroid Build Coastguard Worker     break;
8223*9880d681SAndroid Build Coastguard Worker   default:
8224*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Unknown version min load command");
8225*9880d681SAndroid Build Coastguard Worker   }
8226*9880d681SAndroid Build Coastguard Worker 
8227*9880d681SAndroid Build Coastguard Worker   outs() << "      cmd " << LoadCmdName << '\n';
8228*9880d681SAndroid Build Coastguard Worker   outs() << "  cmdsize " << vd.cmdsize;
8229*9880d681SAndroid Build Coastguard Worker   if (vd.cmdsize != sizeof(struct MachO::version_min_command))
8230*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8231*9880d681SAndroid Build Coastguard Worker   else
8232*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8233*9880d681SAndroid Build Coastguard Worker   outs() << "  version "
8234*9880d681SAndroid Build Coastguard Worker          << MachOObjectFile::getVersionMinMajor(vd, false) << "."
8235*9880d681SAndroid Build Coastguard Worker          << MachOObjectFile::getVersionMinMinor(vd, false);
8236*9880d681SAndroid Build Coastguard Worker   uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
8237*9880d681SAndroid Build Coastguard Worker   if (Update != 0)
8238*9880d681SAndroid Build Coastguard Worker     outs() << "." << Update;
8239*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8240*9880d681SAndroid Build Coastguard Worker   if (vd.sdk == 0)
8241*9880d681SAndroid Build Coastguard Worker     outs() << "      sdk n/a";
8242*9880d681SAndroid Build Coastguard Worker   else {
8243*9880d681SAndroid Build Coastguard Worker     outs() << "      sdk "
8244*9880d681SAndroid Build Coastguard Worker            << MachOObjectFile::getVersionMinMajor(vd, true) << "."
8245*9880d681SAndroid Build Coastguard Worker            << MachOObjectFile::getVersionMinMinor(vd, true);
8246*9880d681SAndroid Build Coastguard Worker   }
8247*9880d681SAndroid Build Coastguard Worker   Update = MachOObjectFile::getVersionMinUpdate(vd, true);
8248*9880d681SAndroid Build Coastguard Worker   if (Update != 0)
8249*9880d681SAndroid Build Coastguard Worker     outs() << "." << Update;
8250*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8251*9880d681SAndroid Build Coastguard Worker }
8252*9880d681SAndroid Build Coastguard Worker 
PrintSourceVersionCommand(MachO::source_version_command sd)8253*9880d681SAndroid Build Coastguard Worker static void PrintSourceVersionCommand(MachO::source_version_command sd) {
8254*9880d681SAndroid Build Coastguard Worker   outs() << "      cmd LC_SOURCE_VERSION\n";
8255*9880d681SAndroid Build Coastguard Worker   outs() << "  cmdsize " << sd.cmdsize;
8256*9880d681SAndroid Build Coastguard Worker   if (sd.cmdsize != sizeof(struct MachO::source_version_command))
8257*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8258*9880d681SAndroid Build Coastguard Worker   else
8259*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8260*9880d681SAndroid Build Coastguard Worker   uint64_t a = (sd.version >> 40) & 0xffffff;
8261*9880d681SAndroid Build Coastguard Worker   uint64_t b = (sd.version >> 30) & 0x3ff;
8262*9880d681SAndroid Build Coastguard Worker   uint64_t c = (sd.version >> 20) & 0x3ff;
8263*9880d681SAndroid Build Coastguard Worker   uint64_t d = (sd.version >> 10) & 0x3ff;
8264*9880d681SAndroid Build Coastguard Worker   uint64_t e = sd.version & 0x3ff;
8265*9880d681SAndroid Build Coastguard Worker   outs() << "  version " << a << "." << b;
8266*9880d681SAndroid Build Coastguard Worker   if (e != 0)
8267*9880d681SAndroid Build Coastguard Worker     outs() << "." << c << "." << d << "." << e;
8268*9880d681SAndroid Build Coastguard Worker   else if (d != 0)
8269*9880d681SAndroid Build Coastguard Worker     outs() << "." << c << "." << d;
8270*9880d681SAndroid Build Coastguard Worker   else if (c != 0)
8271*9880d681SAndroid Build Coastguard Worker     outs() << "." << c;
8272*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8273*9880d681SAndroid Build Coastguard Worker }
8274*9880d681SAndroid Build Coastguard Worker 
PrintEntryPointCommand(MachO::entry_point_command ep)8275*9880d681SAndroid Build Coastguard Worker static void PrintEntryPointCommand(MachO::entry_point_command ep) {
8276*9880d681SAndroid Build Coastguard Worker   outs() << "       cmd LC_MAIN\n";
8277*9880d681SAndroid Build Coastguard Worker   outs() << "   cmdsize " << ep.cmdsize;
8278*9880d681SAndroid Build Coastguard Worker   if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
8279*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8280*9880d681SAndroid Build Coastguard Worker   else
8281*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8282*9880d681SAndroid Build Coastguard Worker   outs() << "  entryoff " << ep.entryoff << "\n";
8283*9880d681SAndroid Build Coastguard Worker   outs() << " stacksize " << ep.stacksize << "\n";
8284*9880d681SAndroid Build Coastguard Worker }
8285*9880d681SAndroid Build Coastguard Worker 
PrintEncryptionInfoCommand(MachO::encryption_info_command ec,uint32_t object_size)8286*9880d681SAndroid Build Coastguard Worker static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
8287*9880d681SAndroid Build Coastguard Worker                                        uint32_t object_size) {
8288*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_ENCRYPTION_INFO\n";
8289*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << ec.cmdsize;
8290*9880d681SAndroid Build Coastguard Worker   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
8291*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8292*9880d681SAndroid Build Coastguard Worker   else
8293*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8294*9880d681SAndroid Build Coastguard Worker   outs() << "     cryptoff " << ec.cryptoff;
8295*9880d681SAndroid Build Coastguard Worker   if (ec.cryptoff > object_size)
8296*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8297*9880d681SAndroid Build Coastguard Worker   else
8298*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8299*9880d681SAndroid Build Coastguard Worker   outs() << "    cryptsize " << ec.cryptsize;
8300*9880d681SAndroid Build Coastguard Worker   if (ec.cryptsize > object_size)
8301*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8302*9880d681SAndroid Build Coastguard Worker   else
8303*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8304*9880d681SAndroid Build Coastguard Worker   outs() << "      cryptid " << ec.cryptid << "\n";
8305*9880d681SAndroid Build Coastguard Worker }
8306*9880d681SAndroid Build Coastguard Worker 
PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,uint32_t object_size)8307*9880d681SAndroid Build Coastguard Worker static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
8308*9880d681SAndroid Build Coastguard Worker                                          uint32_t object_size) {
8309*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_ENCRYPTION_INFO_64\n";
8310*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << ec.cmdsize;
8311*9880d681SAndroid Build Coastguard Worker   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
8312*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8313*9880d681SAndroid Build Coastguard Worker   else
8314*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8315*9880d681SAndroid Build Coastguard Worker   outs() << "     cryptoff " << ec.cryptoff;
8316*9880d681SAndroid Build Coastguard Worker   if (ec.cryptoff > object_size)
8317*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8318*9880d681SAndroid Build Coastguard Worker   else
8319*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8320*9880d681SAndroid Build Coastguard Worker   outs() << "    cryptsize " << ec.cryptsize;
8321*9880d681SAndroid Build Coastguard Worker   if (ec.cryptsize > object_size)
8322*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8323*9880d681SAndroid Build Coastguard Worker   else
8324*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8325*9880d681SAndroid Build Coastguard Worker   outs() << "      cryptid " << ec.cryptid << "\n";
8326*9880d681SAndroid Build Coastguard Worker   outs() << "          pad " << ec.pad << "\n";
8327*9880d681SAndroid Build Coastguard Worker }
8328*9880d681SAndroid Build Coastguard Worker 
PrintLinkerOptionCommand(MachO::linker_option_command lo,const char * Ptr)8329*9880d681SAndroid Build Coastguard Worker static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
8330*9880d681SAndroid Build Coastguard Worker                                      const char *Ptr) {
8331*9880d681SAndroid Build Coastguard Worker   outs() << "     cmd LC_LINKER_OPTION\n";
8332*9880d681SAndroid Build Coastguard Worker   outs() << " cmdsize " << lo.cmdsize;
8333*9880d681SAndroid Build Coastguard Worker   if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
8334*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8335*9880d681SAndroid Build Coastguard Worker   else
8336*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8337*9880d681SAndroid Build Coastguard Worker   outs() << "   count " << lo.count << "\n";
8338*9880d681SAndroid Build Coastguard Worker   const char *string = Ptr + sizeof(struct MachO::linker_option_command);
8339*9880d681SAndroid Build Coastguard Worker   uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
8340*9880d681SAndroid Build Coastguard Worker   uint32_t i = 0;
8341*9880d681SAndroid Build Coastguard Worker   while (left > 0) {
8342*9880d681SAndroid Build Coastguard Worker     while (*string == '\0' && left > 0) {
8343*9880d681SAndroid Build Coastguard Worker       string++;
8344*9880d681SAndroid Build Coastguard Worker       left--;
8345*9880d681SAndroid Build Coastguard Worker     }
8346*9880d681SAndroid Build Coastguard Worker     if (left > 0) {
8347*9880d681SAndroid Build Coastguard Worker       i++;
8348*9880d681SAndroid Build Coastguard Worker       outs() << "  string #" << i << " " << format("%.*s\n", left, string);
8349*9880d681SAndroid Build Coastguard Worker       uint32_t NullPos = StringRef(string, left).find('\0');
8350*9880d681SAndroid Build Coastguard Worker       uint32_t len = std::min(NullPos, left) + 1;
8351*9880d681SAndroid Build Coastguard Worker       string += len;
8352*9880d681SAndroid Build Coastguard Worker       left -= len;
8353*9880d681SAndroid Build Coastguard Worker     }
8354*9880d681SAndroid Build Coastguard Worker   }
8355*9880d681SAndroid Build Coastguard Worker   if (lo.count != i)
8356*9880d681SAndroid Build Coastguard Worker     outs() << "   count " << lo.count << " does not match number of strings "
8357*9880d681SAndroid Build Coastguard Worker            << i << "\n";
8358*9880d681SAndroid Build Coastguard Worker }
8359*9880d681SAndroid Build Coastguard Worker 
PrintSubFrameworkCommand(MachO::sub_framework_command sub,const char * Ptr)8360*9880d681SAndroid Build Coastguard Worker static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
8361*9880d681SAndroid Build Coastguard Worker                                      const char *Ptr) {
8362*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_SUB_FRAMEWORK\n";
8363*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << sub.cmdsize;
8364*9880d681SAndroid Build Coastguard Worker   if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
8365*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8366*9880d681SAndroid Build Coastguard Worker   else
8367*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8368*9880d681SAndroid Build Coastguard Worker   if (sub.umbrella < sub.cmdsize) {
8369*9880d681SAndroid Build Coastguard Worker     const char *P = Ptr + sub.umbrella;
8370*9880d681SAndroid Build Coastguard Worker     outs() << "     umbrella " << P << " (offset " << sub.umbrella << ")\n";
8371*9880d681SAndroid Build Coastguard Worker   } else {
8372*9880d681SAndroid Build Coastguard Worker     outs() << "     umbrella ?(bad offset " << sub.umbrella << ")\n";
8373*9880d681SAndroid Build Coastguard Worker   }
8374*9880d681SAndroid Build Coastguard Worker }
8375*9880d681SAndroid Build Coastguard Worker 
PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,const char * Ptr)8376*9880d681SAndroid Build Coastguard Worker static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
8377*9880d681SAndroid Build Coastguard Worker                                     const char *Ptr) {
8378*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_SUB_UMBRELLA\n";
8379*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << sub.cmdsize;
8380*9880d681SAndroid Build Coastguard Worker   if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
8381*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8382*9880d681SAndroid Build Coastguard Worker   else
8383*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8384*9880d681SAndroid Build Coastguard Worker   if (sub.sub_umbrella < sub.cmdsize) {
8385*9880d681SAndroid Build Coastguard Worker     const char *P = Ptr + sub.sub_umbrella;
8386*9880d681SAndroid Build Coastguard Worker     outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
8387*9880d681SAndroid Build Coastguard Worker   } else {
8388*9880d681SAndroid Build Coastguard Worker     outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
8389*9880d681SAndroid Build Coastguard Worker   }
8390*9880d681SAndroid Build Coastguard Worker }
8391*9880d681SAndroid Build Coastguard Worker 
PrintSubLibraryCommand(MachO::sub_library_command sub,const char * Ptr)8392*9880d681SAndroid Build Coastguard Worker static void PrintSubLibraryCommand(MachO::sub_library_command sub,
8393*9880d681SAndroid Build Coastguard Worker                                    const char *Ptr) {
8394*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_SUB_LIBRARY\n";
8395*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << sub.cmdsize;
8396*9880d681SAndroid Build Coastguard Worker   if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
8397*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8398*9880d681SAndroid Build Coastguard Worker   else
8399*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8400*9880d681SAndroid Build Coastguard Worker   if (sub.sub_library < sub.cmdsize) {
8401*9880d681SAndroid Build Coastguard Worker     const char *P = Ptr + sub.sub_library;
8402*9880d681SAndroid Build Coastguard Worker     outs() << "  sub_library " << P << " (offset " << sub.sub_library << ")\n";
8403*9880d681SAndroid Build Coastguard Worker   } else {
8404*9880d681SAndroid Build Coastguard Worker     outs() << "  sub_library ?(bad offset " << sub.sub_library << ")\n";
8405*9880d681SAndroid Build Coastguard Worker   }
8406*9880d681SAndroid Build Coastguard Worker }
8407*9880d681SAndroid Build Coastguard Worker 
PrintSubClientCommand(MachO::sub_client_command sub,const char * Ptr)8408*9880d681SAndroid Build Coastguard Worker static void PrintSubClientCommand(MachO::sub_client_command sub,
8409*9880d681SAndroid Build Coastguard Worker                                   const char *Ptr) {
8410*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_SUB_CLIENT\n";
8411*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << sub.cmdsize;
8412*9880d681SAndroid Build Coastguard Worker   if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
8413*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8414*9880d681SAndroid Build Coastguard Worker   else
8415*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8416*9880d681SAndroid Build Coastguard Worker   if (sub.client < sub.cmdsize) {
8417*9880d681SAndroid Build Coastguard Worker     const char *P = Ptr + sub.client;
8418*9880d681SAndroid Build Coastguard Worker     outs() << "       client " << P << " (offset " << sub.client << ")\n";
8419*9880d681SAndroid Build Coastguard Worker   } else {
8420*9880d681SAndroid Build Coastguard Worker     outs() << "       client ?(bad offset " << sub.client << ")\n";
8421*9880d681SAndroid Build Coastguard Worker   }
8422*9880d681SAndroid Build Coastguard Worker }
8423*9880d681SAndroid Build Coastguard Worker 
PrintRoutinesCommand(MachO::routines_command r)8424*9880d681SAndroid Build Coastguard Worker static void PrintRoutinesCommand(MachO::routines_command r) {
8425*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_ROUTINES\n";
8426*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << r.cmdsize;
8427*9880d681SAndroid Build Coastguard Worker   if (r.cmdsize != sizeof(struct MachO::routines_command))
8428*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8429*9880d681SAndroid Build Coastguard Worker   else
8430*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8431*9880d681SAndroid Build Coastguard Worker   outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
8432*9880d681SAndroid Build Coastguard Worker   outs() << "  init_module " << r.init_module << "\n";
8433*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved1 " << r.reserved1 << "\n";
8434*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved2 " << r.reserved2 << "\n";
8435*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved3 " << r.reserved3 << "\n";
8436*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved4 " << r.reserved4 << "\n";
8437*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved5 " << r.reserved5 << "\n";
8438*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved6 " << r.reserved6 << "\n";
8439*9880d681SAndroid Build Coastguard Worker }
8440*9880d681SAndroid Build Coastguard Worker 
PrintRoutinesCommand64(MachO::routines_command_64 r)8441*9880d681SAndroid Build Coastguard Worker static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
8442*9880d681SAndroid Build Coastguard Worker   outs() << "          cmd LC_ROUTINES_64\n";
8443*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << r.cmdsize;
8444*9880d681SAndroid Build Coastguard Worker   if (r.cmdsize != sizeof(struct MachO::routines_command_64))
8445*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8446*9880d681SAndroid Build Coastguard Worker   else
8447*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8448*9880d681SAndroid Build Coastguard Worker   outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
8449*9880d681SAndroid Build Coastguard Worker   outs() << "  init_module " << r.init_module << "\n";
8450*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved1 " << r.reserved1 << "\n";
8451*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved2 " << r.reserved2 << "\n";
8452*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved3 " << r.reserved3 << "\n";
8453*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved4 " << r.reserved4 << "\n";
8454*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved5 " << r.reserved5 << "\n";
8455*9880d681SAndroid Build Coastguard Worker   outs() << "    reserved6 " << r.reserved6 << "\n";
8456*9880d681SAndroid Build Coastguard Worker }
8457*9880d681SAndroid Build Coastguard Worker 
Print_x86_thread_state64_t(MachO::x86_thread_state64_t & cpu64)8458*9880d681SAndroid Build Coastguard Worker static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
8459*9880d681SAndroid Build Coastguard Worker   outs() << "   rax  " << format("0x%016" PRIx64, cpu64.rax);
8460*9880d681SAndroid Build Coastguard Worker   outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
8461*9880d681SAndroid Build Coastguard Worker   outs() << " rcx  " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
8462*9880d681SAndroid Build Coastguard Worker   outs() << "   rdx  " << format("0x%016" PRIx64, cpu64.rdx);
8463*9880d681SAndroid Build Coastguard Worker   outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
8464*9880d681SAndroid Build Coastguard Worker   outs() << " rsi  " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
8465*9880d681SAndroid Build Coastguard Worker   outs() << "   rbp  " << format("0x%016" PRIx64, cpu64.rbp);
8466*9880d681SAndroid Build Coastguard Worker   outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
8467*9880d681SAndroid Build Coastguard Worker   outs() << " r8   " << format("0x%016" PRIx64, cpu64.r8) << "\n";
8468*9880d681SAndroid Build Coastguard Worker   outs() << "    r9  " << format("0x%016" PRIx64, cpu64.r9);
8469*9880d681SAndroid Build Coastguard Worker   outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
8470*9880d681SAndroid Build Coastguard Worker   outs() << " r11  " << format("0x%016" PRIx64, cpu64.r11) << "\n";
8471*9880d681SAndroid Build Coastguard Worker   outs() << "   r12  " << format("0x%016" PRIx64, cpu64.r12);
8472*9880d681SAndroid Build Coastguard Worker   outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
8473*9880d681SAndroid Build Coastguard Worker   outs() << " r14  " << format("0x%016" PRIx64, cpu64.r14) << "\n";
8474*9880d681SAndroid Build Coastguard Worker   outs() << "   r15  " << format("0x%016" PRIx64, cpu64.r15);
8475*9880d681SAndroid Build Coastguard Worker   outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
8476*9880d681SAndroid Build Coastguard Worker   outs() << "rflags  " << format("0x%016" PRIx64, cpu64.rflags);
8477*9880d681SAndroid Build Coastguard Worker   outs() << " cs  " << format("0x%016" PRIx64, cpu64.cs);
8478*9880d681SAndroid Build Coastguard Worker   outs() << " fs   " << format("0x%016" PRIx64, cpu64.fs) << "\n";
8479*9880d681SAndroid Build Coastguard Worker   outs() << "    gs  " << format("0x%016" PRIx64, cpu64.gs) << "\n";
8480*9880d681SAndroid Build Coastguard Worker }
8481*9880d681SAndroid Build Coastguard Worker 
Print_mmst_reg(MachO::mmst_reg_t & r)8482*9880d681SAndroid Build Coastguard Worker static void Print_mmst_reg(MachO::mmst_reg_t &r) {
8483*9880d681SAndroid Build Coastguard Worker   uint32_t f;
8484*9880d681SAndroid Build Coastguard Worker   outs() << "\t      mmst_reg  ";
8485*9880d681SAndroid Build Coastguard Worker   for (f = 0; f < 10; f++)
8486*9880d681SAndroid Build Coastguard Worker     outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
8487*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8488*9880d681SAndroid Build Coastguard Worker   outs() << "\t      mmst_rsrv ";
8489*9880d681SAndroid Build Coastguard Worker   for (f = 0; f < 6; f++)
8490*9880d681SAndroid Build Coastguard Worker     outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
8491*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8492*9880d681SAndroid Build Coastguard Worker }
8493*9880d681SAndroid Build Coastguard Worker 
Print_xmm_reg(MachO::xmm_reg_t & r)8494*9880d681SAndroid Build Coastguard Worker static void Print_xmm_reg(MachO::xmm_reg_t &r) {
8495*9880d681SAndroid Build Coastguard Worker   uint32_t f;
8496*9880d681SAndroid Build Coastguard Worker   outs() << "\t      xmm_reg ";
8497*9880d681SAndroid Build Coastguard Worker   for (f = 0; f < 16; f++)
8498*9880d681SAndroid Build Coastguard Worker     outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
8499*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8500*9880d681SAndroid Build Coastguard Worker }
8501*9880d681SAndroid Build Coastguard Worker 
Print_x86_float_state_t(MachO::x86_float_state64_t & fpu)8502*9880d681SAndroid Build Coastguard Worker static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
8503*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_reserved[0] " << fpu.fpu_reserved[0];
8504*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
8505*9880d681SAndroid Build Coastguard Worker   outs() << "\t    control: invalid " << fpu.fpu_fcw.invalid;
8506*9880d681SAndroid Build Coastguard Worker   outs() << " denorm " << fpu.fpu_fcw.denorm;
8507*9880d681SAndroid Build Coastguard Worker   outs() << " zdiv " << fpu.fpu_fcw.zdiv;
8508*9880d681SAndroid Build Coastguard Worker   outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
8509*9880d681SAndroid Build Coastguard Worker   outs() << " undfl " << fpu.fpu_fcw.undfl;
8510*9880d681SAndroid Build Coastguard Worker   outs() << " precis " << fpu.fpu_fcw.precis << "\n";
8511*9880d681SAndroid Build Coastguard Worker   outs() << "\t\t     pc ";
8512*9880d681SAndroid Build Coastguard Worker   if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
8513*9880d681SAndroid Build Coastguard Worker     outs() << "FP_PREC_24B ";
8514*9880d681SAndroid Build Coastguard Worker   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
8515*9880d681SAndroid Build Coastguard Worker     outs() << "FP_PREC_53B ";
8516*9880d681SAndroid Build Coastguard Worker   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
8517*9880d681SAndroid Build Coastguard Worker     outs() << "FP_PREC_64B ";
8518*9880d681SAndroid Build Coastguard Worker   else
8519*9880d681SAndroid Build Coastguard Worker     outs() << fpu.fpu_fcw.pc << " ";
8520*9880d681SAndroid Build Coastguard Worker   outs() << "rc ";
8521*9880d681SAndroid Build Coastguard Worker   if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
8522*9880d681SAndroid Build Coastguard Worker     outs() << "FP_RND_NEAR ";
8523*9880d681SAndroid Build Coastguard Worker   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
8524*9880d681SAndroid Build Coastguard Worker     outs() << "FP_RND_DOWN ";
8525*9880d681SAndroid Build Coastguard Worker   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
8526*9880d681SAndroid Build Coastguard Worker     outs() << "FP_RND_UP ";
8527*9880d681SAndroid Build Coastguard Worker   else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
8528*9880d681SAndroid Build Coastguard Worker     outs() << "FP_CHOP ";
8529*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8530*9880d681SAndroid Build Coastguard Worker   outs() << "\t    status: invalid " << fpu.fpu_fsw.invalid;
8531*9880d681SAndroid Build Coastguard Worker   outs() << " denorm " << fpu.fpu_fsw.denorm;
8532*9880d681SAndroid Build Coastguard Worker   outs() << " zdiv " << fpu.fpu_fsw.zdiv;
8533*9880d681SAndroid Build Coastguard Worker   outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
8534*9880d681SAndroid Build Coastguard Worker   outs() << " undfl " << fpu.fpu_fsw.undfl;
8535*9880d681SAndroid Build Coastguard Worker   outs() << " precis " << fpu.fpu_fsw.precis;
8536*9880d681SAndroid Build Coastguard Worker   outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
8537*9880d681SAndroid Build Coastguard Worker   outs() << "\t            errsumm " << fpu.fpu_fsw.errsumm;
8538*9880d681SAndroid Build Coastguard Worker   outs() << " c0 " << fpu.fpu_fsw.c0;
8539*9880d681SAndroid Build Coastguard Worker   outs() << " c1 " << fpu.fpu_fsw.c1;
8540*9880d681SAndroid Build Coastguard Worker   outs() << " c2 " << fpu.fpu_fsw.c2;
8541*9880d681SAndroid Build Coastguard Worker   outs() << " tos " << fpu.fpu_fsw.tos;
8542*9880d681SAndroid Build Coastguard Worker   outs() << " c3 " << fpu.fpu_fsw.c3;
8543*9880d681SAndroid Build Coastguard Worker   outs() << " busy " << fpu.fpu_fsw.busy << "\n";
8544*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
8545*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
8546*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
8547*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
8548*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
8549*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
8550*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
8551*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
8552*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
8553*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
8554*9880d681SAndroid Build Coastguard Worker   outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
8555*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8556*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_stmm0:\n";
8557*9880d681SAndroid Build Coastguard Worker   Print_mmst_reg(fpu.fpu_stmm0);
8558*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_stmm1:\n";
8559*9880d681SAndroid Build Coastguard Worker   Print_mmst_reg(fpu.fpu_stmm1);
8560*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_stmm2:\n";
8561*9880d681SAndroid Build Coastguard Worker   Print_mmst_reg(fpu.fpu_stmm2);
8562*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_stmm3:\n";
8563*9880d681SAndroid Build Coastguard Worker   Print_mmst_reg(fpu.fpu_stmm3);
8564*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_stmm4:\n";
8565*9880d681SAndroid Build Coastguard Worker   Print_mmst_reg(fpu.fpu_stmm4);
8566*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_stmm5:\n";
8567*9880d681SAndroid Build Coastguard Worker   Print_mmst_reg(fpu.fpu_stmm5);
8568*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_stmm6:\n";
8569*9880d681SAndroid Build Coastguard Worker   Print_mmst_reg(fpu.fpu_stmm6);
8570*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_stmm7:\n";
8571*9880d681SAndroid Build Coastguard Worker   Print_mmst_reg(fpu.fpu_stmm7);
8572*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm0:\n";
8573*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm0);
8574*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm1:\n";
8575*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm1);
8576*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm2:\n";
8577*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm2);
8578*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm3:\n";
8579*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm3);
8580*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm4:\n";
8581*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm4);
8582*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm5:\n";
8583*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm5);
8584*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm6:\n";
8585*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm6);
8586*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm7:\n";
8587*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm7);
8588*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm8:\n";
8589*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm8);
8590*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm9:\n";
8591*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm9);
8592*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm10:\n";
8593*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm10);
8594*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm11:\n";
8595*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm11);
8596*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm12:\n";
8597*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm12);
8598*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm13:\n";
8599*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm13);
8600*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm14:\n";
8601*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm14);
8602*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_xmm15:\n";
8603*9880d681SAndroid Build Coastguard Worker   Print_xmm_reg(fpu.fpu_xmm15);
8604*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_rsrv4:\n";
8605*9880d681SAndroid Build Coastguard Worker   for (uint32_t f = 0; f < 6; f++) {
8606*9880d681SAndroid Build Coastguard Worker     outs() << "\t            ";
8607*9880d681SAndroid Build Coastguard Worker     for (uint32_t g = 0; g < 16; g++)
8608*9880d681SAndroid Build Coastguard Worker       outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
8609*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8610*9880d681SAndroid Build Coastguard Worker   }
8611*9880d681SAndroid Build Coastguard Worker   outs() << "\t    fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
8612*9880d681SAndroid Build Coastguard Worker   outs() << "\n";
8613*9880d681SAndroid Build Coastguard Worker }
8614*9880d681SAndroid Build Coastguard Worker 
Print_x86_exception_state_t(MachO::x86_exception_state64_t & exc64)8615*9880d681SAndroid Build Coastguard Worker static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
8616*9880d681SAndroid Build Coastguard Worker   outs() << "\t    trapno " << format("0x%08" PRIx32, exc64.trapno);
8617*9880d681SAndroid Build Coastguard Worker   outs() << " err " << format("0x%08" PRIx32, exc64.err);
8618*9880d681SAndroid Build Coastguard Worker   outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
8619*9880d681SAndroid Build Coastguard Worker }
8620*9880d681SAndroid Build Coastguard Worker 
PrintThreadCommand(MachO::thread_command t,const char * Ptr,bool isLittleEndian,uint32_t cputype)8621*9880d681SAndroid Build Coastguard Worker static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
8622*9880d681SAndroid Build Coastguard Worker                                bool isLittleEndian, uint32_t cputype) {
8623*9880d681SAndroid Build Coastguard Worker   if (t.cmd == MachO::LC_THREAD)
8624*9880d681SAndroid Build Coastguard Worker     outs() << "        cmd LC_THREAD\n";
8625*9880d681SAndroid Build Coastguard Worker   else if (t.cmd == MachO::LC_UNIXTHREAD)
8626*9880d681SAndroid Build Coastguard Worker     outs() << "        cmd LC_UNIXTHREAD\n";
8627*9880d681SAndroid Build Coastguard Worker   else
8628*9880d681SAndroid Build Coastguard Worker     outs() << "        cmd " << t.cmd << " (unknown)\n";
8629*9880d681SAndroid Build Coastguard Worker   outs() << "    cmdsize " << t.cmdsize;
8630*9880d681SAndroid Build Coastguard Worker   if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
8631*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8632*9880d681SAndroid Build Coastguard Worker   else
8633*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8634*9880d681SAndroid Build Coastguard Worker 
8635*9880d681SAndroid Build Coastguard Worker   const char *begin = Ptr + sizeof(struct MachO::thread_command);
8636*9880d681SAndroid Build Coastguard Worker   const char *end = Ptr + t.cmdsize;
8637*9880d681SAndroid Build Coastguard Worker   uint32_t flavor, count, left;
8638*9880d681SAndroid Build Coastguard Worker   if (cputype == MachO::CPU_TYPE_X86_64) {
8639*9880d681SAndroid Build Coastguard Worker     while (begin < end) {
8640*9880d681SAndroid Build Coastguard Worker       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
8641*9880d681SAndroid Build Coastguard Worker         memcpy((char *)&flavor, begin, sizeof(uint32_t));
8642*9880d681SAndroid Build Coastguard Worker         begin += sizeof(uint32_t);
8643*9880d681SAndroid Build Coastguard Worker       } else {
8644*9880d681SAndroid Build Coastguard Worker         flavor = 0;
8645*9880d681SAndroid Build Coastguard Worker         begin = end;
8646*9880d681SAndroid Build Coastguard Worker       }
8647*9880d681SAndroid Build Coastguard Worker       if (isLittleEndian != sys::IsLittleEndianHost)
8648*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(flavor);
8649*9880d681SAndroid Build Coastguard Worker       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
8650*9880d681SAndroid Build Coastguard Worker         memcpy((char *)&count, begin, sizeof(uint32_t));
8651*9880d681SAndroid Build Coastguard Worker         begin += sizeof(uint32_t);
8652*9880d681SAndroid Build Coastguard Worker       } else {
8653*9880d681SAndroid Build Coastguard Worker         count = 0;
8654*9880d681SAndroid Build Coastguard Worker         begin = end;
8655*9880d681SAndroid Build Coastguard Worker       }
8656*9880d681SAndroid Build Coastguard Worker       if (isLittleEndian != sys::IsLittleEndianHost)
8657*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(count);
8658*9880d681SAndroid Build Coastguard Worker       if (flavor == MachO::x86_THREAD_STATE64) {
8659*9880d681SAndroid Build Coastguard Worker         outs() << "     flavor x86_THREAD_STATE64\n";
8660*9880d681SAndroid Build Coastguard Worker         if (count == MachO::x86_THREAD_STATE64_COUNT)
8661*9880d681SAndroid Build Coastguard Worker           outs() << "      count x86_THREAD_STATE64_COUNT\n";
8662*9880d681SAndroid Build Coastguard Worker         else
8663*9880d681SAndroid Build Coastguard Worker           outs() << "      count " << count
8664*9880d681SAndroid Build Coastguard Worker                  << " (not x86_THREAD_STATE64_COUNT)\n";
8665*9880d681SAndroid Build Coastguard Worker         MachO::x86_thread_state64_t cpu64;
8666*9880d681SAndroid Build Coastguard Worker         left = end - begin;
8667*9880d681SAndroid Build Coastguard Worker         if (left >= sizeof(MachO::x86_thread_state64_t)) {
8668*9880d681SAndroid Build Coastguard Worker           memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
8669*9880d681SAndroid Build Coastguard Worker           begin += sizeof(MachO::x86_thread_state64_t);
8670*9880d681SAndroid Build Coastguard Worker         } else {
8671*9880d681SAndroid Build Coastguard Worker           memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
8672*9880d681SAndroid Build Coastguard Worker           memcpy(&cpu64, begin, left);
8673*9880d681SAndroid Build Coastguard Worker           begin += left;
8674*9880d681SAndroid Build Coastguard Worker         }
8675*9880d681SAndroid Build Coastguard Worker         if (isLittleEndian != sys::IsLittleEndianHost)
8676*9880d681SAndroid Build Coastguard Worker           swapStruct(cpu64);
8677*9880d681SAndroid Build Coastguard Worker         Print_x86_thread_state64_t(cpu64);
8678*9880d681SAndroid Build Coastguard Worker       } else if (flavor == MachO::x86_THREAD_STATE) {
8679*9880d681SAndroid Build Coastguard Worker         outs() << "     flavor x86_THREAD_STATE\n";
8680*9880d681SAndroid Build Coastguard Worker         if (count == MachO::x86_THREAD_STATE_COUNT)
8681*9880d681SAndroid Build Coastguard Worker           outs() << "      count x86_THREAD_STATE_COUNT\n";
8682*9880d681SAndroid Build Coastguard Worker         else
8683*9880d681SAndroid Build Coastguard Worker           outs() << "      count " << count
8684*9880d681SAndroid Build Coastguard Worker                  << " (not x86_THREAD_STATE_COUNT)\n";
8685*9880d681SAndroid Build Coastguard Worker         struct MachO::x86_thread_state_t ts;
8686*9880d681SAndroid Build Coastguard Worker         left = end - begin;
8687*9880d681SAndroid Build Coastguard Worker         if (left >= sizeof(MachO::x86_thread_state_t)) {
8688*9880d681SAndroid Build Coastguard Worker           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
8689*9880d681SAndroid Build Coastguard Worker           begin += sizeof(MachO::x86_thread_state_t);
8690*9880d681SAndroid Build Coastguard Worker         } else {
8691*9880d681SAndroid Build Coastguard Worker           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
8692*9880d681SAndroid Build Coastguard Worker           memcpy(&ts, begin, left);
8693*9880d681SAndroid Build Coastguard Worker           begin += left;
8694*9880d681SAndroid Build Coastguard Worker         }
8695*9880d681SAndroid Build Coastguard Worker         if (isLittleEndian != sys::IsLittleEndianHost)
8696*9880d681SAndroid Build Coastguard Worker           swapStruct(ts);
8697*9880d681SAndroid Build Coastguard Worker         if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
8698*9880d681SAndroid Build Coastguard Worker           outs() << "\t    tsh.flavor x86_THREAD_STATE64 ";
8699*9880d681SAndroid Build Coastguard Worker           if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
8700*9880d681SAndroid Build Coastguard Worker             outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
8701*9880d681SAndroid Build Coastguard Worker           else
8702*9880d681SAndroid Build Coastguard Worker             outs() << "tsh.count " << ts.tsh.count
8703*9880d681SAndroid Build Coastguard Worker                    << " (not x86_THREAD_STATE64_COUNT\n";
8704*9880d681SAndroid Build Coastguard Worker           Print_x86_thread_state64_t(ts.uts.ts64);
8705*9880d681SAndroid Build Coastguard Worker         } else {
8706*9880d681SAndroid Build Coastguard Worker           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
8707*9880d681SAndroid Build Coastguard Worker                  << ts.tsh.count << "\n";
8708*9880d681SAndroid Build Coastguard Worker         }
8709*9880d681SAndroid Build Coastguard Worker       } else if (flavor == MachO::x86_FLOAT_STATE) {
8710*9880d681SAndroid Build Coastguard Worker         outs() << "     flavor x86_FLOAT_STATE\n";
8711*9880d681SAndroid Build Coastguard Worker         if (count == MachO::x86_FLOAT_STATE_COUNT)
8712*9880d681SAndroid Build Coastguard Worker           outs() << "      count x86_FLOAT_STATE_COUNT\n";
8713*9880d681SAndroid Build Coastguard Worker         else
8714*9880d681SAndroid Build Coastguard Worker           outs() << "      count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
8715*9880d681SAndroid Build Coastguard Worker         struct MachO::x86_float_state_t fs;
8716*9880d681SAndroid Build Coastguard Worker         left = end - begin;
8717*9880d681SAndroid Build Coastguard Worker         if (left >= sizeof(MachO::x86_float_state_t)) {
8718*9880d681SAndroid Build Coastguard Worker           memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
8719*9880d681SAndroid Build Coastguard Worker           begin += sizeof(MachO::x86_float_state_t);
8720*9880d681SAndroid Build Coastguard Worker         } else {
8721*9880d681SAndroid Build Coastguard Worker           memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
8722*9880d681SAndroid Build Coastguard Worker           memcpy(&fs, begin, left);
8723*9880d681SAndroid Build Coastguard Worker           begin += left;
8724*9880d681SAndroid Build Coastguard Worker         }
8725*9880d681SAndroid Build Coastguard Worker         if (isLittleEndian != sys::IsLittleEndianHost)
8726*9880d681SAndroid Build Coastguard Worker           swapStruct(fs);
8727*9880d681SAndroid Build Coastguard Worker         if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
8728*9880d681SAndroid Build Coastguard Worker           outs() << "\t    fsh.flavor x86_FLOAT_STATE64 ";
8729*9880d681SAndroid Build Coastguard Worker           if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
8730*9880d681SAndroid Build Coastguard Worker             outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
8731*9880d681SAndroid Build Coastguard Worker           else
8732*9880d681SAndroid Build Coastguard Worker             outs() << "fsh.count " << fs.fsh.count
8733*9880d681SAndroid Build Coastguard Worker                    << " (not x86_FLOAT_STATE64_COUNT\n";
8734*9880d681SAndroid Build Coastguard Worker           Print_x86_float_state_t(fs.ufs.fs64);
8735*9880d681SAndroid Build Coastguard Worker         } else {
8736*9880d681SAndroid Build Coastguard Worker           outs() << "\t    fsh.flavor " << fs.fsh.flavor << "  fsh.count "
8737*9880d681SAndroid Build Coastguard Worker                  << fs.fsh.count << "\n";
8738*9880d681SAndroid Build Coastguard Worker         }
8739*9880d681SAndroid Build Coastguard Worker       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
8740*9880d681SAndroid Build Coastguard Worker         outs() << "     flavor x86_EXCEPTION_STATE\n";
8741*9880d681SAndroid Build Coastguard Worker         if (count == MachO::x86_EXCEPTION_STATE_COUNT)
8742*9880d681SAndroid Build Coastguard Worker           outs() << "      count x86_EXCEPTION_STATE_COUNT\n";
8743*9880d681SAndroid Build Coastguard Worker         else
8744*9880d681SAndroid Build Coastguard Worker           outs() << "      count " << count
8745*9880d681SAndroid Build Coastguard Worker                  << " (not x86_EXCEPTION_STATE_COUNT)\n";
8746*9880d681SAndroid Build Coastguard Worker         struct MachO::x86_exception_state_t es;
8747*9880d681SAndroid Build Coastguard Worker         left = end - begin;
8748*9880d681SAndroid Build Coastguard Worker         if (left >= sizeof(MachO::x86_exception_state_t)) {
8749*9880d681SAndroid Build Coastguard Worker           memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
8750*9880d681SAndroid Build Coastguard Worker           begin += sizeof(MachO::x86_exception_state_t);
8751*9880d681SAndroid Build Coastguard Worker         } else {
8752*9880d681SAndroid Build Coastguard Worker           memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
8753*9880d681SAndroid Build Coastguard Worker           memcpy(&es, begin, left);
8754*9880d681SAndroid Build Coastguard Worker           begin += left;
8755*9880d681SAndroid Build Coastguard Worker         }
8756*9880d681SAndroid Build Coastguard Worker         if (isLittleEndian != sys::IsLittleEndianHost)
8757*9880d681SAndroid Build Coastguard Worker           swapStruct(es);
8758*9880d681SAndroid Build Coastguard Worker         if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
8759*9880d681SAndroid Build Coastguard Worker           outs() << "\t    esh.flavor x86_EXCEPTION_STATE64\n";
8760*9880d681SAndroid Build Coastguard Worker           if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
8761*9880d681SAndroid Build Coastguard Worker             outs() << "\t    esh.count x86_EXCEPTION_STATE64_COUNT\n";
8762*9880d681SAndroid Build Coastguard Worker           else
8763*9880d681SAndroid Build Coastguard Worker             outs() << "\t    esh.count " << es.esh.count
8764*9880d681SAndroid Build Coastguard Worker                    << " (not x86_EXCEPTION_STATE64_COUNT\n";
8765*9880d681SAndroid Build Coastguard Worker           Print_x86_exception_state_t(es.ues.es64);
8766*9880d681SAndroid Build Coastguard Worker         } else {
8767*9880d681SAndroid Build Coastguard Worker           outs() << "\t    esh.flavor " << es.esh.flavor << "  esh.count "
8768*9880d681SAndroid Build Coastguard Worker                  << es.esh.count << "\n";
8769*9880d681SAndroid Build Coastguard Worker         }
8770*9880d681SAndroid Build Coastguard Worker       } else {
8771*9880d681SAndroid Build Coastguard Worker         outs() << "     flavor " << flavor << " (unknown)\n";
8772*9880d681SAndroid Build Coastguard Worker         outs() << "      count " << count << "\n";
8773*9880d681SAndroid Build Coastguard Worker         outs() << "      state (unknown)\n";
8774*9880d681SAndroid Build Coastguard Worker         begin += count * sizeof(uint32_t);
8775*9880d681SAndroid Build Coastguard Worker       }
8776*9880d681SAndroid Build Coastguard Worker     }
8777*9880d681SAndroid Build Coastguard Worker   } else {
8778*9880d681SAndroid Build Coastguard Worker     while (begin < end) {
8779*9880d681SAndroid Build Coastguard Worker       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
8780*9880d681SAndroid Build Coastguard Worker         memcpy((char *)&flavor, begin, sizeof(uint32_t));
8781*9880d681SAndroid Build Coastguard Worker         begin += sizeof(uint32_t);
8782*9880d681SAndroid Build Coastguard Worker       } else {
8783*9880d681SAndroid Build Coastguard Worker         flavor = 0;
8784*9880d681SAndroid Build Coastguard Worker         begin = end;
8785*9880d681SAndroid Build Coastguard Worker       }
8786*9880d681SAndroid Build Coastguard Worker       if (isLittleEndian != sys::IsLittleEndianHost)
8787*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(flavor);
8788*9880d681SAndroid Build Coastguard Worker       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
8789*9880d681SAndroid Build Coastguard Worker         memcpy((char *)&count, begin, sizeof(uint32_t));
8790*9880d681SAndroid Build Coastguard Worker         begin += sizeof(uint32_t);
8791*9880d681SAndroid Build Coastguard Worker       } else {
8792*9880d681SAndroid Build Coastguard Worker         count = 0;
8793*9880d681SAndroid Build Coastguard Worker         begin = end;
8794*9880d681SAndroid Build Coastguard Worker       }
8795*9880d681SAndroid Build Coastguard Worker       if (isLittleEndian != sys::IsLittleEndianHost)
8796*9880d681SAndroid Build Coastguard Worker         sys::swapByteOrder(count);
8797*9880d681SAndroid Build Coastguard Worker       outs() << "     flavor " << flavor << "\n";
8798*9880d681SAndroid Build Coastguard Worker       outs() << "      count " << count << "\n";
8799*9880d681SAndroid Build Coastguard Worker       outs() << "      state (Unknown cputype/cpusubtype)\n";
8800*9880d681SAndroid Build Coastguard Worker       begin += count * sizeof(uint32_t);
8801*9880d681SAndroid Build Coastguard Worker     }
8802*9880d681SAndroid Build Coastguard Worker   }
8803*9880d681SAndroid Build Coastguard Worker }
8804*9880d681SAndroid Build Coastguard Worker 
PrintDylibCommand(MachO::dylib_command dl,const char * Ptr)8805*9880d681SAndroid Build Coastguard Worker static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
8806*9880d681SAndroid Build Coastguard Worker   if (dl.cmd == MachO::LC_ID_DYLIB)
8807*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_ID_DYLIB\n";
8808*9880d681SAndroid Build Coastguard Worker   else if (dl.cmd == MachO::LC_LOAD_DYLIB)
8809*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_LOAD_DYLIB\n";
8810*9880d681SAndroid Build Coastguard Worker   else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
8811*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_LOAD_WEAK_DYLIB\n";
8812*9880d681SAndroid Build Coastguard Worker   else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
8813*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_REEXPORT_DYLIB\n";
8814*9880d681SAndroid Build Coastguard Worker   else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
8815*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_LAZY_LOAD_DYLIB\n";
8816*9880d681SAndroid Build Coastguard Worker   else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
8817*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd LC_LOAD_UPWARD_DYLIB\n";
8818*9880d681SAndroid Build Coastguard Worker   else
8819*9880d681SAndroid Build Coastguard Worker     outs() << "          cmd " << dl.cmd << " (unknown)\n";
8820*9880d681SAndroid Build Coastguard Worker   outs() << "      cmdsize " << dl.cmdsize;
8821*9880d681SAndroid Build Coastguard Worker   if (dl.cmdsize < sizeof(struct MachO::dylib_command))
8822*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8823*9880d681SAndroid Build Coastguard Worker   else
8824*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8825*9880d681SAndroid Build Coastguard Worker   if (dl.dylib.name < dl.cmdsize) {
8826*9880d681SAndroid Build Coastguard Worker     const char *P = (const char *)(Ptr) + dl.dylib.name;
8827*9880d681SAndroid Build Coastguard Worker     outs() << "         name " << P << " (offset " << dl.dylib.name << ")\n";
8828*9880d681SAndroid Build Coastguard Worker   } else {
8829*9880d681SAndroid Build Coastguard Worker     outs() << "         name ?(bad offset " << dl.dylib.name << ")\n";
8830*9880d681SAndroid Build Coastguard Worker   }
8831*9880d681SAndroid Build Coastguard Worker   outs() << "   time stamp " << dl.dylib.timestamp << " ";
8832*9880d681SAndroid Build Coastguard Worker   time_t t = dl.dylib.timestamp;
8833*9880d681SAndroid Build Coastguard Worker   outs() << ctime(&t);
8834*9880d681SAndroid Build Coastguard Worker   outs() << "      current version ";
8835*9880d681SAndroid Build Coastguard Worker   if (dl.dylib.current_version == 0xffffffff)
8836*9880d681SAndroid Build Coastguard Worker     outs() << "n/a\n";
8837*9880d681SAndroid Build Coastguard Worker   else
8838*9880d681SAndroid Build Coastguard Worker     outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
8839*9880d681SAndroid Build Coastguard Worker            << ((dl.dylib.current_version >> 8) & 0xff) << "."
8840*9880d681SAndroid Build Coastguard Worker            << (dl.dylib.current_version & 0xff) << "\n";
8841*9880d681SAndroid Build Coastguard Worker   outs() << "compatibility version ";
8842*9880d681SAndroid Build Coastguard Worker   if (dl.dylib.compatibility_version == 0xffffffff)
8843*9880d681SAndroid Build Coastguard Worker     outs() << "n/a\n";
8844*9880d681SAndroid Build Coastguard Worker   else
8845*9880d681SAndroid Build Coastguard Worker     outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
8846*9880d681SAndroid Build Coastguard Worker            << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
8847*9880d681SAndroid Build Coastguard Worker            << (dl.dylib.compatibility_version & 0xff) << "\n";
8848*9880d681SAndroid Build Coastguard Worker }
8849*9880d681SAndroid Build Coastguard Worker 
PrintLinkEditDataCommand(MachO::linkedit_data_command ld,uint32_t object_size)8850*9880d681SAndroid Build Coastguard Worker static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
8851*9880d681SAndroid Build Coastguard Worker                                      uint32_t object_size) {
8852*9880d681SAndroid Build Coastguard Worker   if (ld.cmd == MachO::LC_CODE_SIGNATURE)
8853*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd LC_CODE_SIGNATURE\n";
8854*9880d681SAndroid Build Coastguard Worker   else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
8855*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd LC_SEGMENT_SPLIT_INFO\n";
8856*9880d681SAndroid Build Coastguard Worker   else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
8857*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd LC_FUNCTION_STARTS\n";
8858*9880d681SAndroid Build Coastguard Worker   else if (ld.cmd == MachO::LC_DATA_IN_CODE)
8859*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd LC_DATA_IN_CODE\n";
8860*9880d681SAndroid Build Coastguard Worker   else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
8861*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd LC_DYLIB_CODE_SIGN_DRS\n";
8862*9880d681SAndroid Build Coastguard Worker   else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
8863*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd LC_LINKER_OPTIMIZATION_HINT\n";
8864*9880d681SAndroid Build Coastguard Worker   else
8865*9880d681SAndroid Build Coastguard Worker     outs() << "      cmd " << ld.cmd << " (?)\n";
8866*9880d681SAndroid Build Coastguard Worker   outs() << "  cmdsize " << ld.cmdsize;
8867*9880d681SAndroid Build Coastguard Worker   if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
8868*9880d681SAndroid Build Coastguard Worker     outs() << " Incorrect size\n";
8869*9880d681SAndroid Build Coastguard Worker   else
8870*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8871*9880d681SAndroid Build Coastguard Worker   outs() << "  dataoff " << ld.dataoff;
8872*9880d681SAndroid Build Coastguard Worker   if (ld.dataoff > object_size)
8873*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8874*9880d681SAndroid Build Coastguard Worker   else
8875*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8876*9880d681SAndroid Build Coastguard Worker   outs() << " datasize " << ld.datasize;
8877*9880d681SAndroid Build Coastguard Worker   uint64_t big_size = ld.dataoff;
8878*9880d681SAndroid Build Coastguard Worker   big_size += ld.datasize;
8879*9880d681SAndroid Build Coastguard Worker   if (big_size > object_size)
8880*9880d681SAndroid Build Coastguard Worker     outs() << " (past end of file)\n";
8881*9880d681SAndroid Build Coastguard Worker   else
8882*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
8883*9880d681SAndroid Build Coastguard Worker }
8884*9880d681SAndroid Build Coastguard Worker 
PrintLoadCommands(const MachOObjectFile * Obj,uint32_t filetype,uint32_t cputype,bool verbose)8885*9880d681SAndroid Build Coastguard Worker static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
8886*9880d681SAndroid Build Coastguard Worker                               uint32_t cputype, bool verbose) {
8887*9880d681SAndroid Build Coastguard Worker   StringRef Buf = Obj->getData();
8888*9880d681SAndroid Build Coastguard Worker   unsigned Index = 0;
8889*9880d681SAndroid Build Coastguard Worker   for (const auto &Command : Obj->load_commands()) {
8890*9880d681SAndroid Build Coastguard Worker     outs() << "Load command " << Index++ << "\n";
8891*9880d681SAndroid Build Coastguard Worker     if (Command.C.cmd == MachO::LC_SEGMENT) {
8892*9880d681SAndroid Build Coastguard Worker       MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
8893*9880d681SAndroid Build Coastguard Worker       const char *sg_segname = SLC.segname;
8894*9880d681SAndroid Build Coastguard Worker       PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
8895*9880d681SAndroid Build Coastguard Worker                           SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
8896*9880d681SAndroid Build Coastguard Worker                           SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
8897*9880d681SAndroid Build Coastguard Worker                           verbose);
8898*9880d681SAndroid Build Coastguard Worker       for (unsigned j = 0; j < SLC.nsects; j++) {
8899*9880d681SAndroid Build Coastguard Worker         MachO::section S = Obj->getSection(Command, j);
8900*9880d681SAndroid Build Coastguard Worker         PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
8901*9880d681SAndroid Build Coastguard Worker                      S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
8902*9880d681SAndroid Build Coastguard Worker                      SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
8903*9880d681SAndroid Build Coastguard Worker       }
8904*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
8905*9880d681SAndroid Build Coastguard Worker       MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
8906*9880d681SAndroid Build Coastguard Worker       const char *sg_segname = SLC_64.segname;
8907*9880d681SAndroid Build Coastguard Worker       PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
8908*9880d681SAndroid Build Coastguard Worker                           SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
8909*9880d681SAndroid Build Coastguard Worker                           SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
8910*9880d681SAndroid Build Coastguard Worker                           SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
8911*9880d681SAndroid Build Coastguard Worker       for (unsigned j = 0; j < SLC_64.nsects; j++) {
8912*9880d681SAndroid Build Coastguard Worker         MachO::section_64 S_64 = Obj->getSection64(Command, j);
8913*9880d681SAndroid Build Coastguard Worker         PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
8914*9880d681SAndroid Build Coastguard Worker                      S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
8915*9880d681SAndroid Build Coastguard Worker                      S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
8916*9880d681SAndroid Build Coastguard Worker                      sg_segname, filetype, Buf.size(), verbose);
8917*9880d681SAndroid Build Coastguard Worker       }
8918*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_SYMTAB) {
8919*9880d681SAndroid Build Coastguard Worker       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
8920*9880d681SAndroid Build Coastguard Worker       PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
8921*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
8922*9880d681SAndroid Build Coastguard Worker       MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
8923*9880d681SAndroid Build Coastguard Worker       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
8924*9880d681SAndroid Build Coastguard Worker       PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
8925*9880d681SAndroid Build Coastguard Worker                                Obj->is64Bit());
8926*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
8927*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
8928*9880d681SAndroid Build Coastguard Worker       MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
8929*9880d681SAndroid Build Coastguard Worker       PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
8930*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
8931*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_ID_DYLINKER ||
8932*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
8933*9880d681SAndroid Build Coastguard Worker       MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
8934*9880d681SAndroid Build Coastguard Worker       PrintDyldLoadCommand(Dyld, Command.Ptr);
8935*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_UUID) {
8936*9880d681SAndroid Build Coastguard Worker       MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
8937*9880d681SAndroid Build Coastguard Worker       PrintUuidLoadCommand(Uuid);
8938*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_RPATH) {
8939*9880d681SAndroid Build Coastguard Worker       MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
8940*9880d681SAndroid Build Coastguard Worker       PrintRpathLoadCommand(Rpath, Command.Ptr);
8941*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
8942*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
8943*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
8944*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
8945*9880d681SAndroid Build Coastguard Worker       MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
8946*9880d681SAndroid Build Coastguard Worker       PrintVersionMinLoadCommand(Vd);
8947*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
8948*9880d681SAndroid Build Coastguard Worker       MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
8949*9880d681SAndroid Build Coastguard Worker       PrintSourceVersionCommand(Sd);
8950*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_MAIN) {
8951*9880d681SAndroid Build Coastguard Worker       MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
8952*9880d681SAndroid Build Coastguard Worker       PrintEntryPointCommand(Ep);
8953*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
8954*9880d681SAndroid Build Coastguard Worker       MachO::encryption_info_command Ei =
8955*9880d681SAndroid Build Coastguard Worker           Obj->getEncryptionInfoCommand(Command);
8956*9880d681SAndroid Build Coastguard Worker       PrintEncryptionInfoCommand(Ei, Buf.size());
8957*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
8958*9880d681SAndroid Build Coastguard Worker       MachO::encryption_info_command_64 Ei =
8959*9880d681SAndroid Build Coastguard Worker           Obj->getEncryptionInfoCommand64(Command);
8960*9880d681SAndroid Build Coastguard Worker       PrintEncryptionInfoCommand64(Ei, Buf.size());
8961*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
8962*9880d681SAndroid Build Coastguard Worker       MachO::linker_option_command Lo =
8963*9880d681SAndroid Build Coastguard Worker           Obj->getLinkerOptionLoadCommand(Command);
8964*9880d681SAndroid Build Coastguard Worker       PrintLinkerOptionCommand(Lo, Command.Ptr);
8965*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
8966*9880d681SAndroid Build Coastguard Worker       MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
8967*9880d681SAndroid Build Coastguard Worker       PrintSubFrameworkCommand(Sf, Command.Ptr);
8968*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
8969*9880d681SAndroid Build Coastguard Worker       MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
8970*9880d681SAndroid Build Coastguard Worker       PrintSubUmbrellaCommand(Sf, Command.Ptr);
8971*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
8972*9880d681SAndroid Build Coastguard Worker       MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
8973*9880d681SAndroid Build Coastguard Worker       PrintSubLibraryCommand(Sl, Command.Ptr);
8974*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
8975*9880d681SAndroid Build Coastguard Worker       MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
8976*9880d681SAndroid Build Coastguard Worker       PrintSubClientCommand(Sc, Command.Ptr);
8977*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_ROUTINES) {
8978*9880d681SAndroid Build Coastguard Worker       MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
8979*9880d681SAndroid Build Coastguard Worker       PrintRoutinesCommand(Rc);
8980*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
8981*9880d681SAndroid Build Coastguard Worker       MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
8982*9880d681SAndroid Build Coastguard Worker       PrintRoutinesCommand64(Rc);
8983*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_THREAD ||
8984*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_UNIXTHREAD) {
8985*9880d681SAndroid Build Coastguard Worker       MachO::thread_command Tc = Obj->getThreadCommand(Command);
8986*9880d681SAndroid Build Coastguard Worker       PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
8987*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
8988*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_ID_DYLIB ||
8989*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
8990*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
8991*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
8992*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
8993*9880d681SAndroid Build Coastguard Worker       MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
8994*9880d681SAndroid Build Coastguard Worker       PrintDylibCommand(Dl, Command.Ptr);
8995*9880d681SAndroid Build Coastguard Worker     } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
8996*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
8997*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
8998*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_DATA_IN_CODE ||
8999*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
9000*9880d681SAndroid Build Coastguard Worker                Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
9001*9880d681SAndroid Build Coastguard Worker       MachO::linkedit_data_command Ld =
9002*9880d681SAndroid Build Coastguard Worker           Obj->getLinkeditDataLoadCommand(Command);
9003*9880d681SAndroid Build Coastguard Worker       PrintLinkEditDataCommand(Ld, Buf.size());
9004*9880d681SAndroid Build Coastguard Worker     } else {
9005*9880d681SAndroid Build Coastguard Worker       outs() << "      cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
9006*9880d681SAndroid Build Coastguard Worker              << ")\n";
9007*9880d681SAndroid Build Coastguard Worker       outs() << "  cmdsize " << Command.C.cmdsize << "\n";
9008*9880d681SAndroid Build Coastguard Worker       // TODO: get and print the raw bytes of the load command.
9009*9880d681SAndroid Build Coastguard Worker     }
9010*9880d681SAndroid Build Coastguard Worker     // TODO: print all the other kinds of load commands.
9011*9880d681SAndroid Build Coastguard Worker   }
9012*9880d681SAndroid Build Coastguard Worker }
9013*9880d681SAndroid Build Coastguard Worker 
PrintMachHeader(const MachOObjectFile * Obj,bool verbose)9014*9880d681SAndroid Build Coastguard Worker static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
9015*9880d681SAndroid Build Coastguard Worker   if (Obj->is64Bit()) {
9016*9880d681SAndroid Build Coastguard Worker     MachO::mach_header_64 H_64;
9017*9880d681SAndroid Build Coastguard Worker     H_64 = Obj->getHeader64();
9018*9880d681SAndroid Build Coastguard Worker     PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
9019*9880d681SAndroid Build Coastguard Worker                     H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
9020*9880d681SAndroid Build Coastguard Worker   } else {
9021*9880d681SAndroid Build Coastguard Worker     MachO::mach_header H;
9022*9880d681SAndroid Build Coastguard Worker     H = Obj->getHeader();
9023*9880d681SAndroid Build Coastguard Worker     PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
9024*9880d681SAndroid Build Coastguard Worker                     H.sizeofcmds, H.flags, verbose);
9025*9880d681SAndroid Build Coastguard Worker   }
9026*9880d681SAndroid Build Coastguard Worker }
9027*9880d681SAndroid Build Coastguard Worker 
printMachOFileHeader(const object::ObjectFile * Obj)9028*9880d681SAndroid Build Coastguard Worker void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
9029*9880d681SAndroid Build Coastguard Worker   const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
9030*9880d681SAndroid Build Coastguard Worker   PrintMachHeader(file, !NonVerbose);
9031*9880d681SAndroid Build Coastguard Worker }
9032*9880d681SAndroid Build Coastguard Worker 
printMachOLoadCommands(const object::ObjectFile * Obj)9033*9880d681SAndroid Build Coastguard Worker void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) {
9034*9880d681SAndroid Build Coastguard Worker   const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
9035*9880d681SAndroid Build Coastguard Worker   uint32_t filetype = 0;
9036*9880d681SAndroid Build Coastguard Worker   uint32_t cputype = 0;
9037*9880d681SAndroid Build Coastguard Worker   if (file->is64Bit()) {
9038*9880d681SAndroid Build Coastguard Worker     MachO::mach_header_64 H_64;
9039*9880d681SAndroid Build Coastguard Worker     H_64 = file->getHeader64();
9040*9880d681SAndroid Build Coastguard Worker     filetype = H_64.filetype;
9041*9880d681SAndroid Build Coastguard Worker     cputype = H_64.cputype;
9042*9880d681SAndroid Build Coastguard Worker   } else {
9043*9880d681SAndroid Build Coastguard Worker     MachO::mach_header H;
9044*9880d681SAndroid Build Coastguard Worker     H = file->getHeader();
9045*9880d681SAndroid Build Coastguard Worker     filetype = H.filetype;
9046*9880d681SAndroid Build Coastguard Worker     cputype = H.cputype;
9047*9880d681SAndroid Build Coastguard Worker   }
9048*9880d681SAndroid Build Coastguard Worker   PrintLoadCommands(file, filetype, cputype, !NonVerbose);
9049*9880d681SAndroid Build Coastguard Worker }
9050*9880d681SAndroid Build Coastguard Worker 
9051*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9052*9880d681SAndroid Build Coastguard Worker // export trie dumping
9053*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9054*9880d681SAndroid Build Coastguard Worker 
printMachOExportsTrie(const object::MachOObjectFile * Obj)9055*9880d681SAndroid Build Coastguard Worker void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) {
9056*9880d681SAndroid Build Coastguard Worker   for (const llvm::object::ExportEntry &Entry : Obj->exports()) {
9057*9880d681SAndroid Build Coastguard Worker     uint64_t Flags = Entry.flags();
9058*9880d681SAndroid Build Coastguard Worker     bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
9059*9880d681SAndroid Build Coastguard Worker     bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
9060*9880d681SAndroid Build Coastguard Worker     bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
9061*9880d681SAndroid Build Coastguard Worker                         MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
9062*9880d681SAndroid Build Coastguard Worker     bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
9063*9880d681SAndroid Build Coastguard Worker                 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
9064*9880d681SAndroid Build Coastguard Worker     bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
9065*9880d681SAndroid Build Coastguard Worker     if (ReExport)
9066*9880d681SAndroid Build Coastguard Worker       outs() << "[re-export] ";
9067*9880d681SAndroid Build Coastguard Worker     else
9068*9880d681SAndroid Build Coastguard Worker       outs() << format("0x%08llX  ",
9069*9880d681SAndroid Build Coastguard Worker                        Entry.address()); // FIXME:add in base address
9070*9880d681SAndroid Build Coastguard Worker     outs() << Entry.name();
9071*9880d681SAndroid Build Coastguard Worker     if (WeakDef || ThreadLocal || Resolver || Abs) {
9072*9880d681SAndroid Build Coastguard Worker       bool NeedsComma = false;
9073*9880d681SAndroid Build Coastguard Worker       outs() << " [";
9074*9880d681SAndroid Build Coastguard Worker       if (WeakDef) {
9075*9880d681SAndroid Build Coastguard Worker         outs() << "weak_def";
9076*9880d681SAndroid Build Coastguard Worker         NeedsComma = true;
9077*9880d681SAndroid Build Coastguard Worker       }
9078*9880d681SAndroid Build Coastguard Worker       if (ThreadLocal) {
9079*9880d681SAndroid Build Coastguard Worker         if (NeedsComma)
9080*9880d681SAndroid Build Coastguard Worker           outs() << ", ";
9081*9880d681SAndroid Build Coastguard Worker         outs() << "per-thread";
9082*9880d681SAndroid Build Coastguard Worker         NeedsComma = true;
9083*9880d681SAndroid Build Coastguard Worker       }
9084*9880d681SAndroid Build Coastguard Worker       if (Abs) {
9085*9880d681SAndroid Build Coastguard Worker         if (NeedsComma)
9086*9880d681SAndroid Build Coastguard Worker           outs() << ", ";
9087*9880d681SAndroid Build Coastguard Worker         outs() << "absolute";
9088*9880d681SAndroid Build Coastguard Worker         NeedsComma = true;
9089*9880d681SAndroid Build Coastguard Worker       }
9090*9880d681SAndroid Build Coastguard Worker       if (Resolver) {
9091*9880d681SAndroid Build Coastguard Worker         if (NeedsComma)
9092*9880d681SAndroid Build Coastguard Worker           outs() << ", ";
9093*9880d681SAndroid Build Coastguard Worker         outs() << format("resolver=0x%08llX", Entry.other());
9094*9880d681SAndroid Build Coastguard Worker         NeedsComma = true;
9095*9880d681SAndroid Build Coastguard Worker       }
9096*9880d681SAndroid Build Coastguard Worker       outs() << "]";
9097*9880d681SAndroid Build Coastguard Worker     }
9098*9880d681SAndroid Build Coastguard Worker     if (ReExport) {
9099*9880d681SAndroid Build Coastguard Worker       StringRef DylibName = "unknown";
9100*9880d681SAndroid Build Coastguard Worker       int Ordinal = Entry.other() - 1;
9101*9880d681SAndroid Build Coastguard Worker       Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
9102*9880d681SAndroid Build Coastguard Worker       if (Entry.otherName().empty())
9103*9880d681SAndroid Build Coastguard Worker         outs() << " (from " << DylibName << ")";
9104*9880d681SAndroid Build Coastguard Worker       else
9105*9880d681SAndroid Build Coastguard Worker         outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
9106*9880d681SAndroid Build Coastguard Worker     }
9107*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
9108*9880d681SAndroid Build Coastguard Worker   }
9109*9880d681SAndroid Build Coastguard Worker }
9110*9880d681SAndroid Build Coastguard Worker 
9111*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9112*9880d681SAndroid Build Coastguard Worker // rebase table dumping
9113*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9114*9880d681SAndroid Build Coastguard Worker 
9115*9880d681SAndroid Build Coastguard Worker namespace {
9116*9880d681SAndroid Build Coastguard Worker class SegInfo {
9117*9880d681SAndroid Build Coastguard Worker public:
9118*9880d681SAndroid Build Coastguard Worker   SegInfo(const object::MachOObjectFile *Obj);
9119*9880d681SAndroid Build Coastguard Worker 
9120*9880d681SAndroid Build Coastguard Worker   StringRef segmentName(uint32_t SegIndex);
9121*9880d681SAndroid Build Coastguard Worker   StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset);
9122*9880d681SAndroid Build Coastguard Worker   uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
9123*9880d681SAndroid Build Coastguard Worker   bool isValidSegIndexAndOffset(uint32_t SegIndex, uint64_t SegOffset);
9124*9880d681SAndroid Build Coastguard Worker 
9125*9880d681SAndroid Build Coastguard Worker private:
9126*9880d681SAndroid Build Coastguard Worker   struct SectionInfo {
9127*9880d681SAndroid Build Coastguard Worker     uint64_t Address;
9128*9880d681SAndroid Build Coastguard Worker     uint64_t Size;
9129*9880d681SAndroid Build Coastguard Worker     StringRef SectionName;
9130*9880d681SAndroid Build Coastguard Worker     StringRef SegmentName;
9131*9880d681SAndroid Build Coastguard Worker     uint64_t OffsetInSegment;
9132*9880d681SAndroid Build Coastguard Worker     uint64_t SegmentStartAddress;
9133*9880d681SAndroid Build Coastguard Worker     uint32_t SegmentIndex;
9134*9880d681SAndroid Build Coastguard Worker   };
9135*9880d681SAndroid Build Coastguard Worker   const SectionInfo &findSection(uint32_t SegIndex, uint64_t SegOffset);
9136*9880d681SAndroid Build Coastguard Worker   SmallVector<SectionInfo, 32> Sections;
9137*9880d681SAndroid Build Coastguard Worker };
9138*9880d681SAndroid Build Coastguard Worker }
9139*9880d681SAndroid Build Coastguard Worker 
SegInfo(const object::MachOObjectFile * Obj)9140*9880d681SAndroid Build Coastguard Worker SegInfo::SegInfo(const object::MachOObjectFile *Obj) {
9141*9880d681SAndroid Build Coastguard Worker   // Build table of sections so segIndex/offset pairs can be translated.
9142*9880d681SAndroid Build Coastguard Worker   uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
9143*9880d681SAndroid Build Coastguard Worker   StringRef CurSegName;
9144*9880d681SAndroid Build Coastguard Worker   uint64_t CurSegAddress;
9145*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Section : Obj->sections()) {
9146*9880d681SAndroid Build Coastguard Worker     SectionInfo Info;
9147*9880d681SAndroid Build Coastguard Worker     error(Section.getName(Info.SectionName));
9148*9880d681SAndroid Build Coastguard Worker     Info.Address = Section.getAddress();
9149*9880d681SAndroid Build Coastguard Worker     Info.Size = Section.getSize();
9150*9880d681SAndroid Build Coastguard Worker     Info.SegmentName =
9151*9880d681SAndroid Build Coastguard Worker         Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
9152*9880d681SAndroid Build Coastguard Worker     if (!Info.SegmentName.equals(CurSegName)) {
9153*9880d681SAndroid Build Coastguard Worker       ++CurSegIndex;
9154*9880d681SAndroid Build Coastguard Worker       CurSegName = Info.SegmentName;
9155*9880d681SAndroid Build Coastguard Worker       CurSegAddress = Info.Address;
9156*9880d681SAndroid Build Coastguard Worker     }
9157*9880d681SAndroid Build Coastguard Worker     Info.SegmentIndex = CurSegIndex - 1;
9158*9880d681SAndroid Build Coastguard Worker     Info.OffsetInSegment = Info.Address - CurSegAddress;
9159*9880d681SAndroid Build Coastguard Worker     Info.SegmentStartAddress = CurSegAddress;
9160*9880d681SAndroid Build Coastguard Worker     Sections.push_back(Info);
9161*9880d681SAndroid Build Coastguard Worker   }
9162*9880d681SAndroid Build Coastguard Worker }
9163*9880d681SAndroid Build Coastguard Worker 
segmentName(uint32_t SegIndex)9164*9880d681SAndroid Build Coastguard Worker StringRef SegInfo::segmentName(uint32_t SegIndex) {
9165*9880d681SAndroid Build Coastguard Worker   for (const SectionInfo &SI : Sections) {
9166*9880d681SAndroid Build Coastguard Worker     if (SI.SegmentIndex == SegIndex)
9167*9880d681SAndroid Build Coastguard Worker       return SI.SegmentName;
9168*9880d681SAndroid Build Coastguard Worker   }
9169*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("invalid segIndex");
9170*9880d681SAndroid Build Coastguard Worker }
9171*9880d681SAndroid Build Coastguard Worker 
isValidSegIndexAndOffset(uint32_t SegIndex,uint64_t OffsetInSeg)9172*9880d681SAndroid Build Coastguard Worker bool SegInfo::isValidSegIndexAndOffset(uint32_t SegIndex,
9173*9880d681SAndroid Build Coastguard Worker                                        uint64_t OffsetInSeg) {
9174*9880d681SAndroid Build Coastguard Worker   for (const SectionInfo &SI : Sections) {
9175*9880d681SAndroid Build Coastguard Worker     if (SI.SegmentIndex != SegIndex)
9176*9880d681SAndroid Build Coastguard Worker       continue;
9177*9880d681SAndroid Build Coastguard Worker     if (SI.OffsetInSegment > OffsetInSeg)
9178*9880d681SAndroid Build Coastguard Worker       continue;
9179*9880d681SAndroid Build Coastguard Worker     if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
9180*9880d681SAndroid Build Coastguard Worker       continue;
9181*9880d681SAndroid Build Coastguard Worker     return true;
9182*9880d681SAndroid Build Coastguard Worker   }
9183*9880d681SAndroid Build Coastguard Worker   return false;
9184*9880d681SAndroid Build Coastguard Worker }
9185*9880d681SAndroid Build Coastguard Worker 
findSection(uint32_t SegIndex,uint64_t OffsetInSeg)9186*9880d681SAndroid Build Coastguard Worker const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex,
9187*9880d681SAndroid Build Coastguard Worker                                                  uint64_t OffsetInSeg) {
9188*9880d681SAndroid Build Coastguard Worker   for (const SectionInfo &SI : Sections) {
9189*9880d681SAndroid Build Coastguard Worker     if (SI.SegmentIndex != SegIndex)
9190*9880d681SAndroid Build Coastguard Worker       continue;
9191*9880d681SAndroid Build Coastguard Worker     if (SI.OffsetInSegment > OffsetInSeg)
9192*9880d681SAndroid Build Coastguard Worker       continue;
9193*9880d681SAndroid Build Coastguard Worker     if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
9194*9880d681SAndroid Build Coastguard Worker       continue;
9195*9880d681SAndroid Build Coastguard Worker     return SI;
9196*9880d681SAndroid Build Coastguard Worker   }
9197*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("segIndex and offset not in any section");
9198*9880d681SAndroid Build Coastguard Worker }
9199*9880d681SAndroid Build Coastguard Worker 
sectionName(uint32_t SegIndex,uint64_t OffsetInSeg)9200*9880d681SAndroid Build Coastguard Worker StringRef SegInfo::sectionName(uint32_t SegIndex, uint64_t OffsetInSeg) {
9201*9880d681SAndroid Build Coastguard Worker   return findSection(SegIndex, OffsetInSeg).SectionName;
9202*9880d681SAndroid Build Coastguard Worker }
9203*9880d681SAndroid Build Coastguard Worker 
address(uint32_t SegIndex,uint64_t OffsetInSeg)9204*9880d681SAndroid Build Coastguard Worker uint64_t SegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
9205*9880d681SAndroid Build Coastguard Worker   const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
9206*9880d681SAndroid Build Coastguard Worker   return SI.SegmentStartAddress + OffsetInSeg;
9207*9880d681SAndroid Build Coastguard Worker }
9208*9880d681SAndroid Build Coastguard Worker 
printMachORebaseTable(const object::MachOObjectFile * Obj)9209*9880d681SAndroid Build Coastguard Worker void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) {
9210*9880d681SAndroid Build Coastguard Worker   // Build table of sections so names can used in final output.
9211*9880d681SAndroid Build Coastguard Worker   SegInfo sectionTable(Obj);
9212*9880d681SAndroid Build Coastguard Worker 
9213*9880d681SAndroid Build Coastguard Worker   outs() << "segment  section            address     type\n";
9214*9880d681SAndroid Build Coastguard Worker   for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) {
9215*9880d681SAndroid Build Coastguard Worker     uint32_t SegIndex = Entry.segmentIndex();
9216*9880d681SAndroid Build Coastguard Worker     uint64_t OffsetInSeg = Entry.segmentOffset();
9217*9880d681SAndroid Build Coastguard Worker     StringRef SegmentName = sectionTable.segmentName(SegIndex);
9218*9880d681SAndroid Build Coastguard Worker     StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
9219*9880d681SAndroid Build Coastguard Worker     uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
9220*9880d681SAndroid Build Coastguard Worker 
9221*9880d681SAndroid Build Coastguard Worker     // Table lines look like: __DATA  __nl_symbol_ptr  0x0000F00C  pointer
9222*9880d681SAndroid Build Coastguard Worker     outs() << format("%-8s %-18s 0x%08" PRIX64 "  %s\n",
9223*9880d681SAndroid Build Coastguard Worker                      SegmentName.str().c_str(), SectionName.str().c_str(),
9224*9880d681SAndroid Build Coastguard Worker                      Address, Entry.typeName().str().c_str());
9225*9880d681SAndroid Build Coastguard Worker   }
9226*9880d681SAndroid Build Coastguard Worker }
9227*9880d681SAndroid Build Coastguard Worker 
ordinalName(const object::MachOObjectFile * Obj,int Ordinal)9228*9880d681SAndroid Build Coastguard Worker static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
9229*9880d681SAndroid Build Coastguard Worker   StringRef DylibName;
9230*9880d681SAndroid Build Coastguard Worker   switch (Ordinal) {
9231*9880d681SAndroid Build Coastguard Worker   case MachO::BIND_SPECIAL_DYLIB_SELF:
9232*9880d681SAndroid Build Coastguard Worker     return "this-image";
9233*9880d681SAndroid Build Coastguard Worker   case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
9234*9880d681SAndroid Build Coastguard Worker     return "main-executable";
9235*9880d681SAndroid Build Coastguard Worker   case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
9236*9880d681SAndroid Build Coastguard Worker     return "flat-namespace";
9237*9880d681SAndroid Build Coastguard Worker   default:
9238*9880d681SAndroid Build Coastguard Worker     if (Ordinal > 0) {
9239*9880d681SAndroid Build Coastguard Worker       std::error_code EC =
9240*9880d681SAndroid Build Coastguard Worker           Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
9241*9880d681SAndroid Build Coastguard Worker       if (EC)
9242*9880d681SAndroid Build Coastguard Worker         return "<<bad library ordinal>>";
9243*9880d681SAndroid Build Coastguard Worker       return DylibName;
9244*9880d681SAndroid Build Coastguard Worker     }
9245*9880d681SAndroid Build Coastguard Worker   }
9246*9880d681SAndroid Build Coastguard Worker   return "<<unknown special ordinal>>";
9247*9880d681SAndroid Build Coastguard Worker }
9248*9880d681SAndroid Build Coastguard Worker 
9249*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9250*9880d681SAndroid Build Coastguard Worker // bind table dumping
9251*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9252*9880d681SAndroid Build Coastguard Worker 
printMachOBindTable(const object::MachOObjectFile * Obj)9253*9880d681SAndroid Build Coastguard Worker void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) {
9254*9880d681SAndroid Build Coastguard Worker   // Build table of sections so names can used in final output.
9255*9880d681SAndroid Build Coastguard Worker   SegInfo sectionTable(Obj);
9256*9880d681SAndroid Build Coastguard Worker 
9257*9880d681SAndroid Build Coastguard Worker   outs() << "segment  section            address    type       "
9258*9880d681SAndroid Build Coastguard Worker             "addend dylib            symbol\n";
9259*9880d681SAndroid Build Coastguard Worker   for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) {
9260*9880d681SAndroid Build Coastguard Worker     uint32_t SegIndex = Entry.segmentIndex();
9261*9880d681SAndroid Build Coastguard Worker     uint64_t OffsetInSeg = Entry.segmentOffset();
9262*9880d681SAndroid Build Coastguard Worker     StringRef SegmentName = sectionTable.segmentName(SegIndex);
9263*9880d681SAndroid Build Coastguard Worker     StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
9264*9880d681SAndroid Build Coastguard Worker     uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
9265*9880d681SAndroid Build Coastguard Worker 
9266*9880d681SAndroid Build Coastguard Worker     // Table lines look like:
9267*9880d681SAndroid Build Coastguard Worker     //  __DATA  __got  0x00012010    pointer   0 libSystem ___stack_chk_guard
9268*9880d681SAndroid Build Coastguard Worker     StringRef Attr;
9269*9880d681SAndroid Build Coastguard Worker     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
9270*9880d681SAndroid Build Coastguard Worker       Attr = " (weak_import)";
9271*9880d681SAndroid Build Coastguard Worker     outs() << left_justify(SegmentName, 8) << " "
9272*9880d681SAndroid Build Coastguard Worker            << left_justify(SectionName, 18) << " "
9273*9880d681SAndroid Build Coastguard Worker            << format_hex(Address, 10, true) << " "
9274*9880d681SAndroid Build Coastguard Worker            << left_justify(Entry.typeName(), 8) << " "
9275*9880d681SAndroid Build Coastguard Worker            << format_decimal(Entry.addend(), 8) << " "
9276*9880d681SAndroid Build Coastguard Worker            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
9277*9880d681SAndroid Build Coastguard Worker            << Entry.symbolName() << Attr << "\n";
9278*9880d681SAndroid Build Coastguard Worker   }
9279*9880d681SAndroid Build Coastguard Worker }
9280*9880d681SAndroid Build Coastguard Worker 
9281*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9282*9880d681SAndroid Build Coastguard Worker // lazy bind table dumping
9283*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9284*9880d681SAndroid Build Coastguard Worker 
printMachOLazyBindTable(const object::MachOObjectFile * Obj)9285*9880d681SAndroid Build Coastguard Worker void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) {
9286*9880d681SAndroid Build Coastguard Worker   // Build table of sections so names can used in final output.
9287*9880d681SAndroid Build Coastguard Worker   SegInfo sectionTable(Obj);
9288*9880d681SAndroid Build Coastguard Worker 
9289*9880d681SAndroid Build Coastguard Worker   outs() << "segment  section            address     "
9290*9880d681SAndroid Build Coastguard Worker             "dylib            symbol\n";
9291*9880d681SAndroid Build Coastguard Worker   for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable()) {
9292*9880d681SAndroid Build Coastguard Worker     uint32_t SegIndex = Entry.segmentIndex();
9293*9880d681SAndroid Build Coastguard Worker     uint64_t OffsetInSeg = Entry.segmentOffset();
9294*9880d681SAndroid Build Coastguard Worker     StringRef SegmentName = sectionTable.segmentName(SegIndex);
9295*9880d681SAndroid Build Coastguard Worker     StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
9296*9880d681SAndroid Build Coastguard Worker     uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
9297*9880d681SAndroid Build Coastguard Worker 
9298*9880d681SAndroid Build Coastguard Worker     // Table lines look like:
9299*9880d681SAndroid Build Coastguard Worker     //  __DATA  __got  0x00012010 libSystem ___stack_chk_guard
9300*9880d681SAndroid Build Coastguard Worker     outs() << left_justify(SegmentName, 8) << " "
9301*9880d681SAndroid Build Coastguard Worker            << left_justify(SectionName, 18) << " "
9302*9880d681SAndroid Build Coastguard Worker            << format_hex(Address, 10, true) << " "
9303*9880d681SAndroid Build Coastguard Worker            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
9304*9880d681SAndroid Build Coastguard Worker            << Entry.symbolName() << "\n";
9305*9880d681SAndroid Build Coastguard Worker   }
9306*9880d681SAndroid Build Coastguard Worker }
9307*9880d681SAndroid Build Coastguard Worker 
9308*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9309*9880d681SAndroid Build Coastguard Worker // weak bind table dumping
9310*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9311*9880d681SAndroid Build Coastguard Worker 
printMachOWeakBindTable(const object::MachOObjectFile * Obj)9312*9880d681SAndroid Build Coastguard Worker void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) {
9313*9880d681SAndroid Build Coastguard Worker   // Build table of sections so names can used in final output.
9314*9880d681SAndroid Build Coastguard Worker   SegInfo sectionTable(Obj);
9315*9880d681SAndroid Build Coastguard Worker 
9316*9880d681SAndroid Build Coastguard Worker   outs() << "segment  section            address     "
9317*9880d681SAndroid Build Coastguard Worker             "type       addend   symbol\n";
9318*9880d681SAndroid Build Coastguard Worker   for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) {
9319*9880d681SAndroid Build Coastguard Worker     // Strong symbols don't have a location to update.
9320*9880d681SAndroid Build Coastguard Worker     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
9321*9880d681SAndroid Build Coastguard Worker       outs() << "                                        strong              "
9322*9880d681SAndroid Build Coastguard Worker              << Entry.symbolName() << "\n";
9323*9880d681SAndroid Build Coastguard Worker       continue;
9324*9880d681SAndroid Build Coastguard Worker     }
9325*9880d681SAndroid Build Coastguard Worker     uint32_t SegIndex = Entry.segmentIndex();
9326*9880d681SAndroid Build Coastguard Worker     uint64_t OffsetInSeg = Entry.segmentOffset();
9327*9880d681SAndroid Build Coastguard Worker     StringRef SegmentName = sectionTable.segmentName(SegIndex);
9328*9880d681SAndroid Build Coastguard Worker     StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
9329*9880d681SAndroid Build Coastguard Worker     uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
9330*9880d681SAndroid Build Coastguard Worker 
9331*9880d681SAndroid Build Coastguard Worker     // Table lines look like:
9332*9880d681SAndroid Build Coastguard Worker     // __DATA  __data  0x00001000  pointer    0   _foo
9333*9880d681SAndroid Build Coastguard Worker     outs() << left_justify(SegmentName, 8) << " "
9334*9880d681SAndroid Build Coastguard Worker            << left_justify(SectionName, 18) << " "
9335*9880d681SAndroid Build Coastguard Worker            << format_hex(Address, 10, true) << " "
9336*9880d681SAndroid Build Coastguard Worker            << left_justify(Entry.typeName(), 8) << " "
9337*9880d681SAndroid Build Coastguard Worker            << format_decimal(Entry.addend(), 8) << "   " << Entry.symbolName()
9338*9880d681SAndroid Build Coastguard Worker            << "\n";
9339*9880d681SAndroid Build Coastguard Worker   }
9340*9880d681SAndroid Build Coastguard Worker }
9341*9880d681SAndroid Build Coastguard Worker 
9342*9880d681SAndroid Build Coastguard Worker // get_dyld_bind_info_symbolname() is used for disassembly and passed an
9343*9880d681SAndroid Build Coastguard Worker // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
9344*9880d681SAndroid Build Coastguard Worker // information for that address. If the address is found its binding symbol
9345*9880d681SAndroid Build Coastguard Worker // name is returned.  If not nullptr is returned.
get_dyld_bind_info_symbolname(uint64_t ReferenceValue,struct DisassembleInfo * info)9346*9880d681SAndroid Build Coastguard Worker static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
9347*9880d681SAndroid Build Coastguard Worker                                                  struct DisassembleInfo *info) {
9348*9880d681SAndroid Build Coastguard Worker   if (info->bindtable == nullptr) {
9349*9880d681SAndroid Build Coastguard Worker     info->bindtable = new (BindTable);
9350*9880d681SAndroid Build Coastguard Worker     SegInfo sectionTable(info->O);
9351*9880d681SAndroid Build Coastguard Worker     for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) {
9352*9880d681SAndroid Build Coastguard Worker       uint32_t SegIndex = Entry.segmentIndex();
9353*9880d681SAndroid Build Coastguard Worker       uint64_t OffsetInSeg = Entry.segmentOffset();
9354*9880d681SAndroid Build Coastguard Worker       if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg))
9355*9880d681SAndroid Build Coastguard Worker         continue;
9356*9880d681SAndroid Build Coastguard Worker       uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
9357*9880d681SAndroid Build Coastguard Worker       const char *SymbolName = nullptr;
9358*9880d681SAndroid Build Coastguard Worker       StringRef name = Entry.symbolName();
9359*9880d681SAndroid Build Coastguard Worker       if (!name.empty())
9360*9880d681SAndroid Build Coastguard Worker         SymbolName = name.data();
9361*9880d681SAndroid Build Coastguard Worker       info->bindtable->push_back(std::make_pair(Address, SymbolName));
9362*9880d681SAndroid Build Coastguard Worker     }
9363*9880d681SAndroid Build Coastguard Worker   }
9364*9880d681SAndroid Build Coastguard Worker   for (bind_table_iterator BI = info->bindtable->begin(),
9365*9880d681SAndroid Build Coastguard Worker                            BE = info->bindtable->end();
9366*9880d681SAndroid Build Coastguard Worker        BI != BE; ++BI) {
9367*9880d681SAndroid Build Coastguard Worker     uint64_t Address = BI->first;
9368*9880d681SAndroid Build Coastguard Worker     if (ReferenceValue == Address) {
9369*9880d681SAndroid Build Coastguard Worker       const char *SymbolName = BI->second;
9370*9880d681SAndroid Build Coastguard Worker       return SymbolName;
9371*9880d681SAndroid Build Coastguard Worker     }
9372*9880d681SAndroid Build Coastguard Worker   }
9373*9880d681SAndroid Build Coastguard Worker   return nullptr;
9374*9880d681SAndroid Build Coastguard Worker }
9375