13b0f4066SDimitry Andric //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
23b0f4066SDimitry Andric //
33b0f4066SDimitry Andric //                     The LLVM Compiler Infrastructure
43b0f4066SDimitry Andric //
53b0f4066SDimitry Andric // This file is distributed under the University of Illinois Open Source
63b0f4066SDimitry Andric // License. See LICENSE.TXT for details.
73b0f4066SDimitry Andric //
83b0f4066SDimitry Andric //===----------------------------------------------------------------------===//
93b0f4066SDimitry Andric //
103b0f4066SDimitry Andric // This file defines the MachOObjectFile class, which binds the MachOObject
113b0f4066SDimitry Andric // class to the generic ObjectFile wrapper.
123b0f4066SDimitry Andric //
133b0f4066SDimitry Andric //===----------------------------------------------------------------------===//
143b0f4066SDimitry Andric 
156122f3e6SDimitry Andric #include "llvm/Object/MachO.h"
1691bc56edSDimitry Andric #include "llvm/ADT/STLExtras.h"
17139f7f9bSDimitry Andric #include "llvm/ADT/Triple.h"
18284c1978SDimitry Andric #include "llvm/Support/DataExtractor.h"
19dff0c46cSDimitry Andric #include "llvm/Support/Format.h"
20284c1978SDimitry Andric #include "llvm/Support/Host.h"
213b0f4066SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
22f785676fSDimitry Andric #include "llvm/Support/raw_ostream.h"
233b0f4066SDimitry Andric #include <cctype>
243b0f4066SDimitry Andric #include <cstring>
253b0f4066SDimitry Andric #include <limits>
263b0f4066SDimitry Andric 
273b0f4066SDimitry Andric using namespace llvm;
283b0f4066SDimitry Andric using namespace object;
293b0f4066SDimitry Andric 
3091bc56edSDimitry Andric namespace {
31f785676fSDimitry Andric   struct section_base {
32f785676fSDimitry Andric     char sectname[16];
33f785676fSDimitry Andric     char segname[16];
34284c1978SDimitry Andric   };
356122f3e6SDimitry Andric }
363b0f4066SDimitry Andric 
37284c1978SDimitry Andric template<typename T>
3891bc56edSDimitry Andric static T getStruct(const MachOObjectFile *O, const char *P) {
39284c1978SDimitry Andric   T Cmd;
40284c1978SDimitry Andric   memcpy(&Cmd, P, sizeof(T));
41284c1978SDimitry Andric   if (O->isLittleEndian() != sys::IsLittleEndianHost)
4291bc56edSDimitry Andric     MachO::swapStruct(Cmd);
43284c1978SDimitry Andric   return Cmd;
44284c1978SDimitry Andric }
45284c1978SDimitry Andric 
46284c1978SDimitry Andric static uint32_t
47284c1978SDimitry Andric getSegmentLoadCommandNumSections(const MachOObjectFile *O,
48284c1978SDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &L) {
49284c1978SDimitry Andric   if (O->is64Bit()) {
50f785676fSDimitry Andric     MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
51f785676fSDimitry Andric     return S.nsects;
52284c1978SDimitry Andric   }
53f785676fSDimitry Andric   MachO::segment_command S = O->getSegmentLoadCommand(L);
54f785676fSDimitry Andric   return S.nsects;
55284c1978SDimitry Andric }
56284c1978SDimitry Andric 
57284c1978SDimitry Andric static const char *
58284c1978SDimitry Andric getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
59284c1978SDimitry Andric               unsigned Sec) {
60284c1978SDimitry Andric   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
61284c1978SDimitry Andric 
62284c1978SDimitry Andric   bool Is64 = O->is64Bit();
63f785676fSDimitry Andric   unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
64f785676fSDimitry Andric                                     sizeof(MachO::segment_command);
65f785676fSDimitry Andric   unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
66f785676fSDimitry Andric                                 sizeof(MachO::section);
67284c1978SDimitry Andric 
68284c1978SDimitry Andric   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
69284c1978SDimitry Andric   return reinterpret_cast<const char*>(SectionAddr);
70284c1978SDimitry Andric }
71284c1978SDimitry Andric 
72284c1978SDimitry Andric static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
73284c1978SDimitry Andric   return O->getData().substr(Offset, 1).data();
74284c1978SDimitry Andric }
75284c1978SDimitry Andric 
7691bc56edSDimitry Andric static MachO::nlist_base
77284c1978SDimitry Andric getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
78284c1978SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
7991bc56edSDimitry Andric   return getStruct<MachO::nlist_base>(O, P);
80284c1978SDimitry Andric }
81284c1978SDimitry Andric 
82284c1978SDimitry Andric static StringRef parseSegmentOrSectionName(const char *P) {
83284c1978SDimitry Andric   if (P[15] == 0)
84284c1978SDimitry Andric     // Null terminated.
85284c1978SDimitry Andric     return P;
86284c1978SDimitry Andric   // Not null terminated, so this is a 16 char string.
87284c1978SDimitry Andric   return StringRef(P, 16);
88284c1978SDimitry Andric }
89284c1978SDimitry Andric 
90284c1978SDimitry Andric // Helper to advance a section or symbol iterator multiple increments at a time.
91284c1978SDimitry Andric template<class T>
9291bc56edSDimitry Andric static void advance(T &it, size_t Val) {
9391bc56edSDimitry Andric   while (Val--)
9491bc56edSDimitry Andric     ++it;
95284c1978SDimitry Andric }
963b0f4066SDimitry Andric 
97284c1978SDimitry Andric static unsigned getCPUType(const MachOObjectFile *O) {
98f785676fSDimitry Andric   return O->getHeader().cputype;
99284c1978SDimitry Andric }
100284c1978SDimitry Andric 
101284c1978SDimitry Andric static void printRelocationTargetName(const MachOObjectFile *O,
102f785676fSDimitry Andric                                       const MachO::any_relocation_info &RE,
103284c1978SDimitry Andric                                       raw_string_ostream &fmt) {
104284c1978SDimitry Andric   bool IsScattered = O->isRelocationScattered(RE);
105284c1978SDimitry Andric 
106284c1978SDimitry Andric   // Target of a scattered relocation is an address.  In the interest of
107284c1978SDimitry Andric   // generating pretty output, scan through the symbol table looking for a
108284c1978SDimitry Andric   // symbol that aligns with that address.  If we find one, print it.
109284c1978SDimitry Andric   // Otherwise, we just print the hex address of the target.
110284c1978SDimitry Andric   if (IsScattered) {
111284c1978SDimitry Andric     uint32_t Val = O->getPlainRelocationSymbolNum(RE);
112284c1978SDimitry Andric 
11391bc56edSDimitry Andric     for (const SymbolRef &Symbol : O->symbols()) {
11491bc56edSDimitry Andric       std::error_code ec;
115284c1978SDimitry Andric       uint64_t Addr;
116284c1978SDimitry Andric       StringRef Name;
117284c1978SDimitry Andric 
11891bc56edSDimitry Andric       if ((ec = Symbol.getAddress(Addr)))
119284c1978SDimitry Andric         report_fatal_error(ec.message());
12091bc56edSDimitry Andric       if (Addr != Val)
12191bc56edSDimitry Andric         continue;
12291bc56edSDimitry Andric       if ((ec = Symbol.getName(Name)))
123284c1978SDimitry Andric         report_fatal_error(ec.message());
124284c1978SDimitry Andric       fmt << Name;
1253b0f4066SDimitry Andric       return;
1263b0f4066SDimitry Andric     }
1273b0f4066SDimitry Andric 
128284c1978SDimitry Andric     // If we couldn't find a symbol that this relocation refers to, try
129284c1978SDimitry Andric     // to find a section beginning instead.
13091bc56edSDimitry Andric     for (const SectionRef &Section : O->sections()) {
13191bc56edSDimitry Andric       std::error_code ec;
132284c1978SDimitry Andric       uint64_t Addr;
133284c1978SDimitry Andric       StringRef Name;
134284c1978SDimitry Andric 
13591bc56edSDimitry Andric       if ((ec = Section.getAddress(Addr)))
136284c1978SDimitry Andric         report_fatal_error(ec.message());
13791bc56edSDimitry Andric       if (Addr != Val)
13891bc56edSDimitry Andric         continue;
13991bc56edSDimitry Andric       if ((ec = Section.getName(Name)))
140284c1978SDimitry Andric         report_fatal_error(ec.message());
141284c1978SDimitry Andric       fmt << Name;
142284c1978SDimitry Andric       return;
143284c1978SDimitry Andric     }
144284c1978SDimitry Andric 
145284c1978SDimitry Andric     fmt << format("0x%x", Val);
146284c1978SDimitry Andric     return;
147284c1978SDimitry Andric   }
148284c1978SDimitry Andric 
149284c1978SDimitry Andric   StringRef S;
150284c1978SDimitry Andric   bool isExtern = O->getPlainRelocationExternal(RE);
151f785676fSDimitry Andric   uint64_t Val = O->getPlainRelocationSymbolNum(RE);
152284c1978SDimitry Andric 
153284c1978SDimitry Andric   if (isExtern) {
15491bc56edSDimitry Andric     symbol_iterator SI = O->symbol_begin();
15591bc56edSDimitry Andric     advance(SI, Val);
156284c1978SDimitry Andric     SI->getName(S);
157284c1978SDimitry Andric   } else {
15891bc56edSDimitry Andric     section_iterator SI = O->section_begin();
159f785676fSDimitry Andric     // Adjust for the fact that sections are 1-indexed.
16091bc56edSDimitry Andric     advance(SI, Val - 1);
161284c1978SDimitry Andric     SI->getName(S);
162284c1978SDimitry Andric   }
163284c1978SDimitry Andric 
164284c1978SDimitry Andric   fmt << S;
165284c1978SDimitry Andric }
166284c1978SDimitry Andric 
167f785676fSDimitry Andric static uint32_t
168f785676fSDimitry Andric getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
169f785676fSDimitry Andric   return RE.r_word0;
170284c1978SDimitry Andric }
171284c1978SDimitry Andric 
172284c1978SDimitry Andric static unsigned
173f785676fSDimitry Andric getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
174f785676fSDimitry Andric   return RE.r_word0 & 0xffffff;
175284c1978SDimitry Andric }
176284c1978SDimitry Andric 
177284c1978SDimitry Andric static bool getPlainRelocationPCRel(const MachOObjectFile *O,
178f785676fSDimitry Andric                                     const MachO::any_relocation_info &RE) {
179284c1978SDimitry Andric   if (O->isLittleEndian())
180f785676fSDimitry Andric     return (RE.r_word1 >> 24) & 1;
181f785676fSDimitry Andric   return (RE.r_word1 >> 7) & 1;
182284c1978SDimitry Andric }
183284c1978SDimitry Andric 
184284c1978SDimitry Andric static bool
185284c1978SDimitry Andric getScatteredRelocationPCRel(const MachOObjectFile *O,
186f785676fSDimitry Andric                             const MachO::any_relocation_info &RE) {
187f785676fSDimitry Andric   return (RE.r_word0 >> 30) & 1;
188284c1978SDimitry Andric }
189284c1978SDimitry Andric 
190284c1978SDimitry Andric static unsigned getPlainRelocationLength(const MachOObjectFile *O,
191f785676fSDimitry Andric                                          const MachO::any_relocation_info &RE) {
192284c1978SDimitry Andric   if (O->isLittleEndian())
193f785676fSDimitry Andric     return (RE.r_word1 >> 25) & 3;
194f785676fSDimitry Andric   return (RE.r_word1 >> 5) & 3;
195284c1978SDimitry Andric }
196284c1978SDimitry Andric 
197284c1978SDimitry Andric static unsigned
198f785676fSDimitry Andric getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
199f785676fSDimitry Andric   return (RE.r_word0 >> 28) & 3;
200284c1978SDimitry Andric }
201284c1978SDimitry Andric 
202284c1978SDimitry Andric static unsigned getPlainRelocationType(const MachOObjectFile *O,
203f785676fSDimitry Andric                                        const MachO::any_relocation_info &RE) {
204284c1978SDimitry Andric   if (O->isLittleEndian())
205f785676fSDimitry Andric     return RE.r_word1 >> 28;
206f785676fSDimitry Andric   return RE.r_word1 & 0xf;
207284c1978SDimitry Andric }
208284c1978SDimitry Andric 
209f785676fSDimitry Andric static unsigned
210f785676fSDimitry Andric getScatteredRelocationType(const MachO::any_relocation_info &RE) {
211f785676fSDimitry Andric   return (RE.r_word0 >> 24) & 0xf;
212284c1978SDimitry Andric }
213284c1978SDimitry Andric 
214284c1978SDimitry Andric static uint32_t getSectionFlags(const MachOObjectFile *O,
215284c1978SDimitry Andric                                 DataRefImpl Sec) {
216284c1978SDimitry Andric   if (O->is64Bit()) {
217f785676fSDimitry Andric     MachO::section_64 Sect = O->getSection64(Sec);
218f785676fSDimitry Andric     return Sect.flags;
219284c1978SDimitry Andric   }
220f785676fSDimitry Andric   MachO::section Sect = O->getSection(Sec);
221f785676fSDimitry Andric   return Sect.flags;
222284c1978SDimitry Andric }
223284c1978SDimitry Andric 
22491bc56edSDimitry Andric MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,
225284c1978SDimitry Andric                                  bool IsLittleEndian, bool Is64bits,
22691bc56edSDimitry Andric                                  std::error_code &EC)
22791bc56edSDimitry Andric     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)),
22891bc56edSDimitry Andric       SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
22991bc56edSDimitry Andric       DataInCodeLoadCmd(nullptr) {
230f785676fSDimitry Andric   uint32_t LoadCommandCount = this->getHeader().ncmds;
231f785676fSDimitry Andric   MachO::LoadCommandType SegmentLoadType = is64Bit() ?
232f785676fSDimitry Andric     MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
233284c1978SDimitry Andric 
234284c1978SDimitry Andric   MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
235284c1978SDimitry Andric   for (unsigned I = 0; ; ++I) {
236f785676fSDimitry Andric     if (Load.C.cmd == MachO::LC_SYMTAB) {
237284c1978SDimitry Andric       assert(!SymtabLoadCmd && "Multiple symbol tables");
238284c1978SDimitry Andric       SymtabLoadCmd = Load.Ptr;
239f785676fSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
240284c1978SDimitry Andric       assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
241284c1978SDimitry Andric       DysymtabLoadCmd = Load.Ptr;
242f785676fSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
243f785676fSDimitry Andric       assert(!DataInCodeLoadCmd && "Multiple data in code tables");
244f785676fSDimitry Andric       DataInCodeLoadCmd = Load.Ptr;
245f785676fSDimitry Andric     } else if (Load.C.cmd == SegmentLoadType) {
246284c1978SDimitry Andric       uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
247284c1978SDimitry Andric       for (unsigned J = 0; J < NumSections; ++J) {
248284c1978SDimitry Andric         const char *Sec = getSectionPtr(this, Load, J);
249284c1978SDimitry Andric         Sections.push_back(Sec);
2503b0f4066SDimitry Andric       }
25191bc56edSDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
25291bc56edSDimitry Andric                Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
25391bc56edSDimitry Andric                Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
25491bc56edSDimitry Andric                Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
25591bc56edSDimitry Andric                Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
25691bc56edSDimitry Andric       Libraries.push_back(Load.Ptr);
2573b0f4066SDimitry Andric     }
2583b0f4066SDimitry Andric 
259284c1978SDimitry Andric     if (I == LoadCommandCount - 1)
260284c1978SDimitry Andric       break;
261284c1978SDimitry Andric     else
262284c1978SDimitry Andric       Load = getNextLoadCommandInfo(Load);
263284c1978SDimitry Andric   }
2643b0f4066SDimitry Andric }
2653b0f4066SDimitry Andric 
26691bc56edSDimitry Andric void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
267284c1978SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
268f785676fSDimitry Andric     sizeof(MachO::nlist_64) :
269f785676fSDimitry Andric     sizeof(MachO::nlist);
270284c1978SDimitry Andric   Symb.p += SymbolTableEntrySize;
2713b0f4066SDimitry Andric }
2723b0f4066SDimitry Andric 
27391bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
274284c1978SDimitry Andric                                                StringRef &Res) const {
275284c1978SDimitry Andric   StringRef StringTable = getStringTableData();
27691bc56edSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
277f785676fSDimitry Andric   const char *Start = &StringTable.data()[Entry.n_strx];
278284c1978SDimitry Andric   Res = StringRef(Start);
279284c1978SDimitry Andric   return object_error::success;
280284c1978SDimitry Andric }
281284c1978SDimitry Andric 
28291bc56edSDimitry Andric // getIndirectName() returns the name of the alias'ed symbol who's string table
28391bc56edSDimitry Andric // index is in the n_value field.
28491bc56edSDimitry Andric std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
28591bc56edSDimitry Andric                                                  StringRef &Res) const {
28691bc56edSDimitry Andric   StringRef StringTable = getStringTableData();
28791bc56edSDimitry Andric   uint64_t NValue;
28891bc56edSDimitry Andric   if (is64Bit()) {
28991bc56edSDimitry Andric     MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
29091bc56edSDimitry Andric     NValue = Entry.n_value;
29191bc56edSDimitry Andric     if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
29291bc56edSDimitry Andric       return object_error::parse_failed;
29391bc56edSDimitry Andric   } else {
29491bc56edSDimitry Andric     MachO::nlist Entry = getSymbolTableEntry(Symb);
29591bc56edSDimitry Andric     NValue = Entry.n_value;
29691bc56edSDimitry Andric     if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
29791bc56edSDimitry Andric       return object_error::parse_failed;
29891bc56edSDimitry Andric   }
29991bc56edSDimitry Andric   if (NValue >= StringTable.size())
30091bc56edSDimitry Andric     return object_error::parse_failed;
30191bc56edSDimitry Andric   const char *Start = &StringTable.data()[NValue];
30291bc56edSDimitry Andric   Res = StringRef(Start);
30391bc56edSDimitry Andric   return object_error::success;
30491bc56edSDimitry Andric }
30591bc56edSDimitry Andric 
30691bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
307284c1978SDimitry Andric                                                   uint64_t &Res) const {
308284c1978SDimitry Andric   if (is64Bit()) {
309f785676fSDimitry Andric     MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
31091bc56edSDimitry Andric     if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
31191bc56edSDimitry Andric         Entry.n_value == 0)
31291bc56edSDimitry Andric       Res = UnknownAddressOrSize;
31391bc56edSDimitry Andric     else
314f785676fSDimitry Andric       Res = Entry.n_value;
31517a519f9SDimitry Andric   } else {
316f785676fSDimitry Andric     MachO::nlist Entry = getSymbolTableEntry(Symb);
31791bc56edSDimitry Andric     if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
31891bc56edSDimitry Andric         Entry.n_value == 0)
31991bc56edSDimitry Andric       Res = UnknownAddressOrSize;
32091bc56edSDimitry Andric     else
321f785676fSDimitry Andric       Res = Entry.n_value;
32217a519f9SDimitry Andric   }
32317a519f9SDimitry Andric   return object_error::success;
3243b0f4066SDimitry Andric }
3253b0f4066SDimitry Andric 
32691bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
327284c1978SDimitry Andric                                                     uint32_t &Result) const {
32891bc56edSDimitry Andric   uint32_t flags = getSymbolFlags(DRI);
329284c1978SDimitry Andric   if (flags & SymbolRef::SF_Common) {
33091bc56edSDimitry Andric     MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
331f785676fSDimitry Andric     Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
33217a519f9SDimitry Andric   } else {
333284c1978SDimitry Andric     Result = 0;
33417a519f9SDimitry Andric   }
33517a519f9SDimitry Andric   return object_error::success;
3363b0f4066SDimitry Andric }
3373b0f4066SDimitry Andric 
33891bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
33917a519f9SDimitry Andric                                                uint64_t &Result) const {
340dff0c46cSDimitry Andric   uint64_t BeginOffset;
341dff0c46cSDimitry Andric   uint64_t EndOffset = 0;
342dff0c46cSDimitry Andric   uint8_t SectionIndex;
343284c1978SDimitry Andric 
34491bc56edSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
345284c1978SDimitry Andric   uint64_t Value;
346284c1978SDimitry Andric   getSymbolAddress(DRI, Value);
34791bc56edSDimitry Andric   if (Value == UnknownAddressOrSize) {
34891bc56edSDimitry Andric     Result = UnknownAddressOrSize;
34991bc56edSDimitry Andric     return object_error::success;
35091bc56edSDimitry Andric   }
351284c1978SDimitry Andric 
352284c1978SDimitry Andric   BeginOffset = Value;
353284c1978SDimitry Andric 
354f785676fSDimitry Andric   SectionIndex = Entry.n_sect;
355dff0c46cSDimitry Andric   if (!SectionIndex) {
35691bc56edSDimitry Andric     uint32_t flags = getSymbolFlags(DRI);
357dff0c46cSDimitry Andric     if (flags & SymbolRef::SF_Common)
358284c1978SDimitry Andric       Result = Value;
359dff0c46cSDimitry Andric     else
36017a519f9SDimitry Andric       Result = UnknownAddressOrSize;
36117a519f9SDimitry Andric     return object_error::success;
3623b0f4066SDimitry Andric   }
363dff0c46cSDimitry Andric   // Unfortunately symbols are unsorted so we need to touch all
364dff0c46cSDimitry Andric   // symbols from load command
36591bc56edSDimitry Andric   for (const SymbolRef &Symbol : symbols()) {
36691bc56edSDimitry Andric     DataRefImpl DRI = Symbol.getRawDataRefImpl();
367284c1978SDimitry Andric     Entry = getSymbolTableEntryBase(this, DRI);
368284c1978SDimitry Andric     getSymbolAddress(DRI, Value);
36991bc56edSDimitry Andric     if (Value == UnknownAddressOrSize)
37091bc56edSDimitry Andric       continue;
371f785676fSDimitry Andric     if (Entry.n_sect == SectionIndex && Value > BeginOffset)
372284c1978SDimitry Andric       if (!EndOffset || Value < EndOffset)
373284c1978SDimitry Andric         EndOffset = Value;
374dff0c46cSDimitry Andric   }
375dff0c46cSDimitry Andric   if (!EndOffset) {
376dff0c46cSDimitry Andric     uint64_t Size;
377284c1978SDimitry Andric     DataRefImpl Sec;
378284c1978SDimitry Andric     Sec.d.a = SectionIndex-1;
379284c1978SDimitry Andric     getSectionSize(Sec, Size);
380284c1978SDimitry Andric     getSectionAddress(Sec, EndOffset);
381dff0c46cSDimitry Andric     EndOffset += Size;
382dff0c46cSDimitry Andric   }
383dff0c46cSDimitry Andric   Result = EndOffset - BeginOffset;
384dff0c46cSDimitry Andric   return object_error::success;
385dff0c46cSDimitry Andric }
3863b0f4066SDimitry Andric 
38791bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
388dff0c46cSDimitry Andric                                                SymbolRef::Type &Res) const {
38991bc56edSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
390f785676fSDimitry Andric   uint8_t n_type = Entry.n_type;
391284c1978SDimitry Andric 
3926122f3e6SDimitry Andric   Res = SymbolRef::ST_Other;
3936122f3e6SDimitry Andric 
3946122f3e6SDimitry Andric   // If this is a STAB debugging symbol, we can do nothing more.
395f785676fSDimitry Andric   if (n_type & MachO::N_STAB) {
396dff0c46cSDimitry Andric     Res = SymbolRef::ST_Debug;
3976122f3e6SDimitry Andric     return object_error::success;
398dff0c46cSDimitry Andric   }
3996122f3e6SDimitry Andric 
400f785676fSDimitry Andric   switch (n_type & MachO::N_TYPE) {
401f785676fSDimitry Andric     case MachO::N_UNDF :
402dff0c46cSDimitry Andric       Res = SymbolRef::ST_Unknown;
4036122f3e6SDimitry Andric       break;
404f785676fSDimitry Andric     case MachO::N_SECT :
4056122f3e6SDimitry Andric       Res = SymbolRef::ST_Function;
4066122f3e6SDimitry Andric       break;
4076122f3e6SDimitry Andric   }
4086122f3e6SDimitry Andric   return object_error::success;
4096122f3e6SDimitry Andric }
4106122f3e6SDimitry Andric 
41191bc56edSDimitry Andric uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
41291bc56edSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
413284c1978SDimitry Andric 
414f785676fSDimitry Andric   uint8_t MachOType = Entry.n_type;
415f785676fSDimitry Andric   uint16_t MachOFlags = Entry.n_desc;
416284c1978SDimitry Andric 
41791bc56edSDimitry Andric   uint32_t Result = SymbolRef::SF_None;
418284c1978SDimitry Andric 
419f785676fSDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
420284c1978SDimitry Andric     Result |= SymbolRef::SF_Undefined;
421284c1978SDimitry Andric 
42291bc56edSDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
42391bc56edSDimitry Andric     Result |= SymbolRef::SF_Indirect;
42491bc56edSDimitry Andric 
425f785676fSDimitry Andric   if (MachOType & MachO::N_STAB)
426284c1978SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
427284c1978SDimitry Andric 
428f785676fSDimitry Andric   if (MachOType & MachO::N_EXT) {
429284c1978SDimitry Andric     Result |= SymbolRef::SF_Global;
430f785676fSDimitry Andric     if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
431284c1978SDimitry Andric       uint64_t Value;
432284c1978SDimitry Andric       getSymbolAddress(DRI, Value);
43391bc56edSDimitry Andric       if (Value && Value != UnknownAddressOrSize)
434284c1978SDimitry Andric         Result |= SymbolRef::SF_Common;
435284c1978SDimitry Andric     }
436284c1978SDimitry Andric   }
437284c1978SDimitry Andric 
438f785676fSDimitry Andric   if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
439284c1978SDimitry Andric     Result |= SymbolRef::SF_Weak;
440284c1978SDimitry Andric 
441f785676fSDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
442284c1978SDimitry Andric     Result |= SymbolRef::SF_Absolute;
443284c1978SDimitry Andric 
44491bc56edSDimitry Andric   return Result;
445284c1978SDimitry Andric }
446284c1978SDimitry Andric 
44791bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
448284c1978SDimitry Andric                                                   section_iterator &Res) const {
44991bc56edSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
450f785676fSDimitry Andric   uint8_t index = Entry.n_sect;
451284c1978SDimitry Andric 
452284c1978SDimitry Andric   if (index == 0) {
45391bc56edSDimitry Andric     Res = section_end();
454284c1978SDimitry Andric   } else {
455284c1978SDimitry Andric     DataRefImpl DRI;
456284c1978SDimitry Andric     DRI.d.a = index - 1;
457284c1978SDimitry Andric     Res = section_iterator(SectionRef(DRI, this));
458284c1978SDimitry Andric   }
459284c1978SDimitry Andric 
460284c1978SDimitry Andric   return object_error::success;
461284c1978SDimitry Andric }
462284c1978SDimitry Andric 
46391bc56edSDimitry Andric void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
464284c1978SDimitry Andric   Sec.d.a++;
4653b0f4066SDimitry Andric }
4663b0f4066SDimitry Andric 
46791bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
46891bc56edSDimitry Andric                                                 StringRef &Result) const {
469284c1978SDimitry Andric   ArrayRef<char> Raw = getSectionRawName(Sec);
470284c1978SDimitry Andric   Result = parseSegmentOrSectionName(Raw.data());
471284c1978SDimitry Andric   return object_error::success;
4723b0f4066SDimitry Andric }
4733b0f4066SDimitry Andric 
47491bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
47591bc56edSDimitry Andric                                                    uint64_t &Res) const {
476284c1978SDimitry Andric   if (is64Bit()) {
477f785676fSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
478f785676fSDimitry Andric     Res = Sect.addr;
47917a519f9SDimitry Andric   } else {
480f785676fSDimitry Andric     MachO::section Sect = getSection(Sec);
481f785676fSDimitry Andric     Res = Sect.addr;
48217a519f9SDimitry Andric   }
483139f7f9bSDimitry Andric   return object_error::success;
484139f7f9bSDimitry Andric }
485139f7f9bSDimitry Andric 
48691bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
48791bc56edSDimitry Andric                                                 uint64_t &Res) const {
488284c1978SDimitry Andric   if (is64Bit()) {
489f785676fSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
490f785676fSDimitry Andric     Res = Sect.size;
491139f7f9bSDimitry Andric   } else {
492f785676fSDimitry Andric     MachO::section Sect = getSection(Sec);
493f785676fSDimitry Andric     Res = Sect.size;
494139f7f9bSDimitry Andric   }
495284c1978SDimitry Andric 
49617a519f9SDimitry Andric   return object_error::success;
4973b0f4066SDimitry Andric }
4983b0f4066SDimitry Andric 
49991bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
50091bc56edSDimitry Andric                                                     StringRef &Res) const {
501284c1978SDimitry Andric   uint32_t Offset;
502284c1978SDimitry Andric   uint64_t Size;
503284c1978SDimitry Andric 
504284c1978SDimitry Andric   if (is64Bit()) {
505f785676fSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
506f785676fSDimitry Andric     Offset = Sect.offset;
507f785676fSDimitry Andric     Size = Sect.size;
50817a519f9SDimitry Andric   } else {
509f785676fSDimitry Andric     MachO::section Sect = getSection(Sec);
510f785676fSDimitry Andric     Offset = Sect.offset;
511f785676fSDimitry Andric     Size = Sect.size;
51217a519f9SDimitry Andric   }
513284c1978SDimitry Andric 
514284c1978SDimitry Andric   Res = this->getData().substr(Offset, Size);
51517a519f9SDimitry Andric   return object_error::success;
5163b0f4066SDimitry Andric }
5173b0f4066SDimitry Andric 
51891bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
51991bc56edSDimitry Andric                                                      uint64_t &Res) const {
520284c1978SDimitry Andric   uint32_t Align;
521284c1978SDimitry Andric   if (is64Bit()) {
522f785676fSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
523f785676fSDimitry Andric     Align = Sect.align;
52417a519f9SDimitry Andric   } else {
525f785676fSDimitry Andric     MachO::section Sect = getSection(Sec);
526f785676fSDimitry Andric     Align = Sect.align;
52717a519f9SDimitry Andric   }
528284c1978SDimitry Andric 
529284c1978SDimitry Andric   Res = uint64_t(1) << Align;
53017a519f9SDimitry Andric   return object_error::success;
5313b0f4066SDimitry Andric }
5323b0f4066SDimitry Andric 
53391bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
53491bc56edSDimitry Andric                                                bool &Res) const {
535284c1978SDimitry Andric   uint32_t Flags = getSectionFlags(this, Sec);
536f785676fSDimitry Andric   Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
53717a519f9SDimitry Andric   return object_error::success;
5383b0f4066SDimitry Andric }
5393b0f4066SDimitry Andric 
54091bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
54191bc56edSDimitry Andric                                                bool &Result) const {
54291bc56edSDimitry Andric   uint32_t Flags = getSectionFlags(this, Sec);
54391bc56edSDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
54491bc56edSDimitry Andric   Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
54591bc56edSDimitry Andric            !(SectionType == MachO::S_ZEROFILL ||
54691bc56edSDimitry Andric              SectionType == MachO::S_GB_ZEROFILL);
54717a519f9SDimitry Andric   return object_error::success;
5483b0f4066SDimitry Andric }
5493b0f4066SDimitry Andric 
55091bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
55191bc56edSDimitry Andric                                               bool &Result) const {
55291bc56edSDimitry Andric   uint32_t Flags = getSectionFlags(this, Sec);
55391bc56edSDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
55491bc56edSDimitry Andric   Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
55591bc56edSDimitry Andric            (SectionType == MachO::S_ZEROFILL ||
55691bc56edSDimitry Andric             SectionType == MachO::S_GB_ZEROFILL);
5576122f3e6SDimitry Andric   return object_error::success;
5586122f3e6SDimitry Andric }
5596122f3e6SDimitry Andric 
56091bc56edSDimitry Andric std::error_code
561284c1978SDimitry Andric MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
562dff0c46cSDimitry Andric                                                bool &Result) const {
5633861d79fSDimitry Andric   // FIXME: Unimplemented.
564dff0c46cSDimitry Andric   Result = true;
565dff0c46cSDimitry Andric   return object_error::success;
566dff0c46cSDimitry Andric }
567dff0c46cSDimitry Andric 
56891bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
569dff0c46cSDimitry Andric                                                   bool &Result) const {
5703861d79fSDimitry Andric   // FIXME: Unimplemented.
571dff0c46cSDimitry Andric   Result = false;
572dff0c46cSDimitry Andric   return object_error::success;
573dff0c46cSDimitry Andric }
574dff0c46cSDimitry Andric 
57591bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
57691bc56edSDimitry Andric                                                    bool &Res) const {
577284c1978SDimitry Andric   uint32_t Flags = getSectionFlags(this, Sec);
578f785676fSDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
579f785676fSDimitry Andric   Res = SectionType == MachO::S_ZEROFILL ||
580f785676fSDimitry Andric     SectionType == MachO::S_GB_ZEROFILL;
581dff0c46cSDimitry Andric   return object_error::success;
582dff0c46cSDimitry Andric }
583dff0c46cSDimitry Andric 
58491bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
5853861d79fSDimitry Andric                                                        bool &Result) const {
5863861d79fSDimitry Andric   // Consider using the code from isSectionText to look for __const sections.
5873861d79fSDimitry Andric   // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
5883861d79fSDimitry Andric   // to use section attributes to distinguish code from data.
5893861d79fSDimitry Andric 
5903861d79fSDimitry Andric   // FIXME: Unimplemented.
5913861d79fSDimitry Andric   Result = false;
5923861d79fSDimitry Andric   return object_error::success;
5933861d79fSDimitry Andric }
5943861d79fSDimitry Andric 
59591bc56edSDimitry Andric std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
59691bc56edSDimitry Andric                                                        DataRefImpl Symb,
5976122f3e6SDimitry Andric                                                        bool &Result) const {
598dff0c46cSDimitry Andric   SymbolRef::Type ST;
599284c1978SDimitry Andric   this->getSymbolType(Symb, ST);
600dff0c46cSDimitry Andric   if (ST == SymbolRef::ST_Unknown) {
6016122f3e6SDimitry Andric     Result = false;
6026122f3e6SDimitry Andric     return object_error::success;
6036122f3e6SDimitry Andric   }
6046122f3e6SDimitry Andric 
6056122f3e6SDimitry Andric   uint64_t SectBegin, SectEnd;
6066122f3e6SDimitry Andric   getSectionAddress(Sec, SectBegin);
6076122f3e6SDimitry Andric   getSectionSize(Sec, SectEnd);
6086122f3e6SDimitry Andric   SectEnd += SectBegin;
6096122f3e6SDimitry Andric 
610284c1978SDimitry Andric   uint64_t SymAddr;
611284c1978SDimitry Andric   getSymbolAddress(Symb, SymAddr);
6126122f3e6SDimitry Andric   Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
6136122f3e6SDimitry Andric 
6146122f3e6SDimitry Andric   return object_error::success;
6156122f3e6SDimitry Andric }
6166122f3e6SDimitry Andric 
617f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
618284c1978SDimitry Andric   DataRefImpl Ret;
61991bc56edSDimitry Andric   Ret.d.a = Sec.d.a;
62091bc56edSDimitry Andric   Ret.d.b = 0;
621284c1978SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
6223b0f4066SDimitry Andric }
6233b0f4066SDimitry Andric 
624284c1978SDimitry Andric relocation_iterator
625f785676fSDimitry Andric MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
626284c1978SDimitry Andric   uint32_t Num;
627284c1978SDimitry Andric   if (is64Bit()) {
628f785676fSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
629f785676fSDimitry Andric     Num = Sect.nreloc;
6306122f3e6SDimitry Andric   } else {
631f785676fSDimitry Andric     MachO::section Sect = getSection(Sec);
632f785676fSDimitry Andric     Num = Sect.nreloc;
6336122f3e6SDimitry Andric   }
634284c1978SDimitry Andric 
635284c1978SDimitry Andric   DataRefImpl Ret;
63691bc56edSDimitry Andric   Ret.d.a = Sec.d.a;
63791bc56edSDimitry Andric   Ret.d.b = Num;
638284c1978SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
6396122f3e6SDimitry Andric }
640284c1978SDimitry Andric 
64191bc56edSDimitry Andric void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
64291bc56edSDimitry Andric   ++Rel.d.b;
64391bc56edSDimitry Andric }
64491bc56edSDimitry Andric 
64591bc56edSDimitry Andric std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
64691bc56edSDimitry Andric                                                       uint64_t &Res) const {
64791bc56edSDimitry Andric   uint64_t Offset;
64891bc56edSDimitry Andric   getRelocationOffset(Rel, Offset);
64991bc56edSDimitry Andric 
65091bc56edSDimitry Andric   DataRefImpl Sec;
65191bc56edSDimitry Andric   Sec.d.a = Rel.d.a;
65291bc56edSDimitry Andric   uint64_t SecAddress;
65391bc56edSDimitry Andric   getSectionAddress(Sec, SecAddress);
65491bc56edSDimitry Andric   Res = SecAddress + Offset;
6556122f3e6SDimitry Andric   return object_error::success;
6566122f3e6SDimitry Andric }
657dff0c46cSDimitry Andric 
65891bc56edSDimitry Andric std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
659dff0c46cSDimitry Andric                                                      uint64_t &Res) const {
66091bc56edSDimitry Andric   assert(getHeader().filetype == MachO::MH_OBJECT &&
66191bc56edSDimitry Andric          "Only implemented for MH_OBJECT");
662f785676fSDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
663284c1978SDimitry Andric   Res = getAnyRelocationAddress(RE);
6646122f3e6SDimitry Andric   return object_error::success;
6656122f3e6SDimitry Andric }
6666122f3e6SDimitry Andric 
667f785676fSDimitry Andric symbol_iterator
668f785676fSDimitry Andric MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
669f785676fSDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
67091bc56edSDimitry Andric   if (isRelocationScattered(RE))
67191bc56edSDimitry Andric     return symbol_end();
67291bc56edSDimitry Andric 
673284c1978SDimitry Andric   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
674284c1978SDimitry Andric   bool isExtern = getPlainRelocationExternal(RE);
675f785676fSDimitry Andric   if (!isExtern)
67691bc56edSDimitry Andric     return symbol_end();
677284c1978SDimitry Andric 
678f785676fSDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
679284c1978SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
680f785676fSDimitry Andric     sizeof(MachO::nlist_64) :
681f785676fSDimitry Andric     sizeof(MachO::nlist);
682f785676fSDimitry Andric   uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
6836122f3e6SDimitry Andric   DataRefImpl Sym;
684284c1978SDimitry Andric   Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
685f785676fSDimitry Andric   return symbol_iterator(SymbolRef(Sym, this));
6866122f3e6SDimitry Andric }
687284c1978SDimitry Andric 
68891bc56edSDimitry Andric std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
689dff0c46cSDimitry Andric                                                    uint64_t &Res) const {
690f785676fSDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
691284c1978SDimitry Andric   Res = getAnyRelocationType(RE);
6926122f3e6SDimitry Andric   return object_error::success;
6936122f3e6SDimitry Andric }
694284c1978SDimitry Andric 
69591bc56edSDimitry Andric std::error_code
696284c1978SDimitry Andric MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
6976122f3e6SDimitry Andric                                        SmallVectorImpl<char> &Result) const {
698dff0c46cSDimitry Andric   StringRef res;
699284c1978SDimitry Andric   uint64_t RType;
700284c1978SDimitry Andric   getRelocationType(Rel, RType);
701dff0c46cSDimitry Andric 
702284c1978SDimitry Andric   unsigned Arch = this->getArch();
703dff0c46cSDimitry Andric 
704dff0c46cSDimitry Andric   switch (Arch) {
705dff0c46cSDimitry Andric     case Triple::x86: {
7067ae0e2c9SDimitry Andric       static const char *const Table[] =  {
707dff0c46cSDimitry Andric         "GENERIC_RELOC_VANILLA",
708dff0c46cSDimitry Andric         "GENERIC_RELOC_PAIR",
709dff0c46cSDimitry Andric         "GENERIC_RELOC_SECTDIFF",
710dff0c46cSDimitry Andric         "GENERIC_RELOC_PB_LA_PTR",
711dff0c46cSDimitry Andric         "GENERIC_RELOC_LOCAL_SECTDIFF",
712dff0c46cSDimitry Andric         "GENERIC_RELOC_TLV" };
713dff0c46cSDimitry Andric 
71491bc56edSDimitry Andric       if (RType > 5)
715dff0c46cSDimitry Andric         res = "Unknown";
716dff0c46cSDimitry Andric       else
717284c1978SDimitry Andric         res = Table[RType];
718dff0c46cSDimitry Andric       break;
719dff0c46cSDimitry Andric     }
720dff0c46cSDimitry Andric     case Triple::x86_64: {
7217ae0e2c9SDimitry Andric       static const char *const Table[] =  {
722dff0c46cSDimitry Andric         "X86_64_RELOC_UNSIGNED",
723dff0c46cSDimitry Andric         "X86_64_RELOC_SIGNED",
724dff0c46cSDimitry Andric         "X86_64_RELOC_BRANCH",
725dff0c46cSDimitry Andric         "X86_64_RELOC_GOT_LOAD",
726dff0c46cSDimitry Andric         "X86_64_RELOC_GOT",
727dff0c46cSDimitry Andric         "X86_64_RELOC_SUBTRACTOR",
728dff0c46cSDimitry Andric         "X86_64_RELOC_SIGNED_1",
729dff0c46cSDimitry Andric         "X86_64_RELOC_SIGNED_2",
730dff0c46cSDimitry Andric         "X86_64_RELOC_SIGNED_4",
731dff0c46cSDimitry Andric         "X86_64_RELOC_TLV" };
732dff0c46cSDimitry Andric 
733284c1978SDimitry Andric       if (RType > 9)
734dff0c46cSDimitry Andric         res = "Unknown";
735dff0c46cSDimitry Andric       else
736284c1978SDimitry Andric         res = Table[RType];
737dff0c46cSDimitry Andric       break;
738dff0c46cSDimitry Andric     }
739dff0c46cSDimitry Andric     case Triple::arm: {
7407ae0e2c9SDimitry Andric       static const char *const Table[] =  {
741dff0c46cSDimitry Andric         "ARM_RELOC_VANILLA",
742dff0c46cSDimitry Andric         "ARM_RELOC_PAIR",
743dff0c46cSDimitry Andric         "ARM_RELOC_SECTDIFF",
744dff0c46cSDimitry Andric         "ARM_RELOC_LOCAL_SECTDIFF",
745dff0c46cSDimitry Andric         "ARM_RELOC_PB_LA_PTR",
746dff0c46cSDimitry Andric         "ARM_RELOC_BR24",
747dff0c46cSDimitry Andric         "ARM_THUMB_RELOC_BR22",
748dff0c46cSDimitry Andric         "ARM_THUMB_32BIT_BRANCH",
749dff0c46cSDimitry Andric         "ARM_RELOC_HALF",
750dff0c46cSDimitry Andric         "ARM_RELOC_HALF_SECTDIFF" };
751dff0c46cSDimitry Andric 
752284c1978SDimitry Andric       if (RType > 9)
753dff0c46cSDimitry Andric         res = "Unknown";
754dff0c46cSDimitry Andric       else
755284c1978SDimitry Andric         res = Table[RType];
756dff0c46cSDimitry Andric       break;
757dff0c46cSDimitry Andric     }
75891bc56edSDimitry Andric     case Triple::arm64:
75991bc56edSDimitry Andric     case Triple::aarch64: {
76091bc56edSDimitry Andric       static const char *const Table[] = {
76191bc56edSDimitry Andric         "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
76291bc56edSDimitry Andric         "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
76391bc56edSDimitry Andric         "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
76491bc56edSDimitry Andric         "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
76591bc56edSDimitry Andric         "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
76691bc56edSDimitry Andric         "ARM64_RELOC_ADDEND"
76791bc56edSDimitry Andric       };
76891bc56edSDimitry Andric 
76991bc56edSDimitry Andric       if (RType >= array_lengthof(Table))
77091bc56edSDimitry Andric         res = "Unknown";
77191bc56edSDimitry Andric       else
77291bc56edSDimitry Andric         res = Table[RType];
77391bc56edSDimitry Andric       break;
77491bc56edSDimitry Andric     }
775dff0c46cSDimitry Andric     case Triple::ppc: {
7767ae0e2c9SDimitry Andric       static const char *const Table[] =  {
777dff0c46cSDimitry Andric         "PPC_RELOC_VANILLA",
778dff0c46cSDimitry Andric         "PPC_RELOC_PAIR",
779dff0c46cSDimitry Andric         "PPC_RELOC_BR14",
780dff0c46cSDimitry Andric         "PPC_RELOC_BR24",
781dff0c46cSDimitry Andric         "PPC_RELOC_HI16",
782dff0c46cSDimitry Andric         "PPC_RELOC_LO16",
783dff0c46cSDimitry Andric         "PPC_RELOC_HA16",
784dff0c46cSDimitry Andric         "PPC_RELOC_LO14",
785dff0c46cSDimitry Andric         "PPC_RELOC_SECTDIFF",
786dff0c46cSDimitry Andric         "PPC_RELOC_PB_LA_PTR",
787dff0c46cSDimitry Andric         "PPC_RELOC_HI16_SECTDIFF",
788dff0c46cSDimitry Andric         "PPC_RELOC_LO16_SECTDIFF",
789dff0c46cSDimitry Andric         "PPC_RELOC_HA16_SECTDIFF",
790dff0c46cSDimitry Andric         "PPC_RELOC_JBSR",
791dff0c46cSDimitry Andric         "PPC_RELOC_LO14_SECTDIFF",
792dff0c46cSDimitry Andric         "PPC_RELOC_LOCAL_SECTDIFF" };
793dff0c46cSDimitry Andric 
79491bc56edSDimitry Andric       if (RType > 15)
79591bc56edSDimitry Andric         res = "Unknown";
79691bc56edSDimitry Andric       else
797284c1978SDimitry Andric         res = Table[RType];
798dff0c46cSDimitry Andric       break;
799dff0c46cSDimitry Andric     }
800dff0c46cSDimitry Andric     case Triple::UnknownArch:
801dff0c46cSDimitry Andric       res = "Unknown";
802dff0c46cSDimitry Andric       break;
803dff0c46cSDimitry Andric   }
804dff0c46cSDimitry Andric   Result.append(res.begin(), res.end());
8056122f3e6SDimitry Andric   return object_error::success;
8066122f3e6SDimitry Andric }
807284c1978SDimitry Andric 
80891bc56edSDimitry Andric std::error_code
809284c1978SDimitry Andric MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
8106122f3e6SDimitry Andric                                           SmallVectorImpl<char> &Result) const {
811f785676fSDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
812dff0c46cSDimitry Andric 
813284c1978SDimitry Andric   unsigned Arch = this->getArch();
814dff0c46cSDimitry Andric 
815dff0c46cSDimitry Andric   std::string fmtbuf;
816dff0c46cSDimitry Andric   raw_string_ostream fmt(fmtbuf);
817284c1978SDimitry Andric   unsigned Type = this->getAnyRelocationType(RE);
818284c1978SDimitry Andric   bool IsPCRel = this->getAnyRelocationPCRel(RE);
819dff0c46cSDimitry Andric 
820dff0c46cSDimitry Andric   // Determine any addends that should be displayed with the relocation.
821dff0c46cSDimitry Andric   // These require decoding the relocation type, which is triple-specific.
822dff0c46cSDimitry Andric 
823dff0c46cSDimitry Andric   // X86_64 has entirely custom relocation types.
824dff0c46cSDimitry Andric   if (Arch == Triple::x86_64) {
825284c1978SDimitry Andric     bool isPCRel = getAnyRelocationPCRel(RE);
826dff0c46cSDimitry Andric 
827dff0c46cSDimitry Andric     switch (Type) {
828f785676fSDimitry Andric       case MachO::X86_64_RELOC_GOT_LOAD:
829f785676fSDimitry Andric       case MachO::X86_64_RELOC_GOT: {
830284c1978SDimitry Andric         printRelocationTargetName(this, RE, fmt);
831dff0c46cSDimitry Andric         fmt << "@GOT";
832dff0c46cSDimitry Andric         if (isPCRel) fmt << "PCREL";
833dff0c46cSDimitry Andric         break;
834dff0c46cSDimitry Andric       }
835f785676fSDimitry Andric       case MachO::X86_64_RELOC_SUBTRACTOR: {
836dff0c46cSDimitry Andric         DataRefImpl RelNext = Rel;
83791bc56edSDimitry Andric         moveRelocationNext(RelNext);
838f785676fSDimitry Andric         MachO::any_relocation_info RENext = getRelocation(RelNext);
839dff0c46cSDimitry Andric 
840f785676fSDimitry Andric         // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
841dff0c46cSDimitry Andric         // X86_64_RELOC_UNSIGNED.
842dff0c46cSDimitry Andric         // NOTE: Scattered relocations don't exist on x86_64.
843284c1978SDimitry Andric         unsigned RType = getAnyRelocationType(RENext);
844f785676fSDimitry Andric         if (RType != MachO::X86_64_RELOC_UNSIGNED)
845dff0c46cSDimitry Andric           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
846dff0c46cSDimitry Andric                              "X86_64_RELOC_SUBTRACTOR.");
847dff0c46cSDimitry Andric 
848f785676fSDimitry Andric         // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
849f785676fSDimitry Andric         // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
850284c1978SDimitry Andric         printRelocationTargetName(this, RENext, fmt);
851dff0c46cSDimitry Andric         fmt << "-";
852284c1978SDimitry Andric         printRelocationTargetName(this, RE, fmt);
853139f7f9bSDimitry Andric         break;
854dff0c46cSDimitry Andric       }
855f785676fSDimitry Andric       case MachO::X86_64_RELOC_TLV:
856284c1978SDimitry Andric         printRelocationTargetName(this, RE, fmt);
857dff0c46cSDimitry Andric         fmt << "@TLV";
858dff0c46cSDimitry Andric         if (isPCRel) fmt << "P";
859dff0c46cSDimitry Andric         break;
860f785676fSDimitry Andric       case MachO::X86_64_RELOC_SIGNED_1:
861284c1978SDimitry Andric         printRelocationTargetName(this, RE, fmt);
862dff0c46cSDimitry Andric         fmt << "-1";
863dff0c46cSDimitry Andric         break;
864f785676fSDimitry Andric       case MachO::X86_64_RELOC_SIGNED_2:
865284c1978SDimitry Andric         printRelocationTargetName(this, RE, fmt);
866dff0c46cSDimitry Andric         fmt << "-2";
867dff0c46cSDimitry Andric         break;
868f785676fSDimitry Andric       case MachO::X86_64_RELOC_SIGNED_4:
869284c1978SDimitry Andric         printRelocationTargetName(this, RE, fmt);
870dff0c46cSDimitry Andric         fmt << "-4";
871dff0c46cSDimitry Andric         break;
872dff0c46cSDimitry Andric       default:
873284c1978SDimitry Andric         printRelocationTargetName(this, RE, fmt);
874dff0c46cSDimitry Andric         break;
875dff0c46cSDimitry Andric     }
876dff0c46cSDimitry Andric   // X86 and ARM share some relocation types in common.
877f785676fSDimitry Andric   } else if (Arch == Triple::x86 || Arch == Triple::arm ||
878f785676fSDimitry Andric              Arch == Triple::ppc) {
879dff0c46cSDimitry Andric     // Generic relocation types...
880dff0c46cSDimitry Andric     switch (Type) {
881f785676fSDimitry Andric       case MachO::GENERIC_RELOC_PAIR: // prints no info
882dff0c46cSDimitry Andric         return object_error::success;
883f785676fSDimitry Andric       case MachO::GENERIC_RELOC_SECTDIFF: {
884dff0c46cSDimitry Andric         DataRefImpl RelNext = Rel;
88591bc56edSDimitry Andric         moveRelocationNext(RelNext);
886f785676fSDimitry Andric         MachO::any_relocation_info RENext = getRelocation(RelNext);
887dff0c46cSDimitry Andric 
888dff0c46cSDimitry Andric         // X86 sect diff's must be followed by a relocation of type
889dff0c46cSDimitry Andric         // GENERIC_RELOC_PAIR.
890284c1978SDimitry Andric         unsigned RType = getAnyRelocationType(RENext);
891284c1978SDimitry Andric 
892f785676fSDimitry Andric         if (RType != MachO::GENERIC_RELOC_PAIR)
893dff0c46cSDimitry Andric           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
894dff0c46cSDimitry Andric                              "GENERIC_RELOC_SECTDIFF.");
895dff0c46cSDimitry Andric 
896284c1978SDimitry Andric         printRelocationTargetName(this, RE, fmt);
897dff0c46cSDimitry Andric         fmt << "-";
898284c1978SDimitry Andric         printRelocationTargetName(this, RENext, fmt);
899dff0c46cSDimitry Andric         break;
900dff0c46cSDimitry Andric       }
901dff0c46cSDimitry Andric     }
902dff0c46cSDimitry Andric 
903f785676fSDimitry Andric     if (Arch == Triple::x86 || Arch == Triple::ppc) {
904dff0c46cSDimitry Andric       switch (Type) {
905f785676fSDimitry Andric         case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
906dff0c46cSDimitry Andric           DataRefImpl RelNext = Rel;
90791bc56edSDimitry Andric           moveRelocationNext(RelNext);
908f785676fSDimitry Andric           MachO::any_relocation_info RENext = getRelocation(RelNext);
909dff0c46cSDimitry Andric 
910dff0c46cSDimitry Andric           // X86 sect diff's must be followed by a relocation of type
911dff0c46cSDimitry Andric           // GENERIC_RELOC_PAIR.
912284c1978SDimitry Andric           unsigned RType = getAnyRelocationType(RENext);
913f785676fSDimitry Andric           if (RType != MachO::GENERIC_RELOC_PAIR)
914dff0c46cSDimitry Andric             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
915dff0c46cSDimitry Andric                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
916dff0c46cSDimitry Andric 
917284c1978SDimitry Andric           printRelocationTargetName(this, RE, fmt);
918dff0c46cSDimitry Andric           fmt << "-";
919284c1978SDimitry Andric           printRelocationTargetName(this, RENext, fmt);
920dff0c46cSDimitry Andric           break;
921dff0c46cSDimitry Andric         }
922f785676fSDimitry Andric         case MachO::GENERIC_RELOC_TLV: {
923284c1978SDimitry Andric           printRelocationTargetName(this, RE, fmt);
924dff0c46cSDimitry Andric           fmt << "@TLV";
925284c1978SDimitry Andric           if (IsPCRel) fmt << "P";
926dff0c46cSDimitry Andric           break;
927dff0c46cSDimitry Andric         }
928dff0c46cSDimitry Andric         default:
929284c1978SDimitry Andric           printRelocationTargetName(this, RE, fmt);
930dff0c46cSDimitry Andric       }
931dff0c46cSDimitry Andric     } else { // ARM-specific relocations
932dff0c46cSDimitry Andric       switch (Type) {
933f785676fSDimitry Andric         case MachO::ARM_RELOC_HALF:
934f785676fSDimitry Andric         case MachO::ARM_RELOC_HALF_SECTDIFF: {
935dff0c46cSDimitry Andric           // Half relocations steal a bit from the length field to encode
936dff0c46cSDimitry Andric           // whether this is an upper16 or a lower16 relocation.
937284c1978SDimitry Andric           bool isUpper = getAnyRelocationLength(RE) >> 1;
938dff0c46cSDimitry Andric 
939dff0c46cSDimitry Andric           if (isUpper)
940dff0c46cSDimitry Andric             fmt << ":upper16:(";
941dff0c46cSDimitry Andric           else
942dff0c46cSDimitry Andric             fmt << ":lower16:(";
943284c1978SDimitry Andric           printRelocationTargetName(this, RE, fmt);
944dff0c46cSDimitry Andric 
945dff0c46cSDimitry Andric           DataRefImpl RelNext = Rel;
94691bc56edSDimitry Andric           moveRelocationNext(RelNext);
947f785676fSDimitry Andric           MachO::any_relocation_info RENext = getRelocation(RelNext);
948dff0c46cSDimitry Andric 
949dff0c46cSDimitry Andric           // ARM half relocs must be followed by a relocation of type
950dff0c46cSDimitry Andric           // ARM_RELOC_PAIR.
951284c1978SDimitry Andric           unsigned RType = getAnyRelocationType(RENext);
952f785676fSDimitry Andric           if (RType != MachO::ARM_RELOC_PAIR)
953dff0c46cSDimitry Andric             report_fatal_error("Expected ARM_RELOC_PAIR after "
954f785676fSDimitry Andric                                "ARM_RELOC_HALF");
955dff0c46cSDimitry Andric 
956dff0c46cSDimitry Andric           // NOTE: The half of the target virtual address is stashed in the
957dff0c46cSDimitry Andric           // address field of the secondary relocation, but we can't reverse
958dff0c46cSDimitry Andric           // engineer the constant offset from it without decoding the movw/movt
959dff0c46cSDimitry Andric           // instruction to find the other half in its immediate field.
960dff0c46cSDimitry Andric 
961dff0c46cSDimitry Andric           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
962dff0c46cSDimitry Andric           // symbol/section pointer of the follow-on relocation.
963f785676fSDimitry Andric           if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
964dff0c46cSDimitry Andric             fmt << "-";
965284c1978SDimitry Andric             printRelocationTargetName(this, RENext, fmt);
966dff0c46cSDimitry Andric           }
967dff0c46cSDimitry Andric 
968dff0c46cSDimitry Andric           fmt << ")";
969dff0c46cSDimitry Andric           break;
970dff0c46cSDimitry Andric         }
971dff0c46cSDimitry Andric         default: {
972284c1978SDimitry Andric           printRelocationTargetName(this, RE, fmt);
973dff0c46cSDimitry Andric         }
974dff0c46cSDimitry Andric       }
975dff0c46cSDimitry Andric     }
976dff0c46cSDimitry Andric   } else
977284c1978SDimitry Andric     printRelocationTargetName(this, RE, fmt);
978dff0c46cSDimitry Andric 
979dff0c46cSDimitry Andric   fmt.flush();
980dff0c46cSDimitry Andric   Result.append(fmtbuf.begin(), fmtbuf.end());
9816122f3e6SDimitry Andric   return object_error::success;
9826122f3e6SDimitry Andric }
9836122f3e6SDimitry Andric 
98491bc56edSDimitry Andric std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
98591bc56edSDimitry Andric                                                      bool &Result) const {
986dff0c46cSDimitry Andric   unsigned Arch = getArch();
987284c1978SDimitry Andric   uint64_t Type;
988284c1978SDimitry Andric   getRelocationType(Rel, Type);
989dff0c46cSDimitry Andric 
990dff0c46cSDimitry Andric   Result = false;
991dff0c46cSDimitry Andric 
992dff0c46cSDimitry Andric   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
993dff0c46cSDimitry Andric   // is always hidden.
994f785676fSDimitry Andric   if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
995f785676fSDimitry Andric     if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
996dff0c46cSDimitry Andric   } else if (Arch == Triple::x86_64) {
997dff0c46cSDimitry Andric     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
998f785676fSDimitry Andric     // an X86_64_RELOC_SUBTRACTOR.
999f785676fSDimitry Andric     if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1000dff0c46cSDimitry Andric       DataRefImpl RelPrev = Rel;
1001dff0c46cSDimitry Andric       RelPrev.d.a--;
1002284c1978SDimitry Andric       uint64_t PrevType;
1003284c1978SDimitry Andric       getRelocationType(RelPrev, PrevType);
1004f785676fSDimitry Andric       if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1005284c1978SDimitry Andric         Result = true;
1006dff0c46cSDimitry Andric     }
1007dff0c46cSDimitry Andric   }
1008dff0c46cSDimitry Andric 
1009dff0c46cSDimitry Andric   return object_error::success;
1010dff0c46cSDimitry Andric }
1011dff0c46cSDimitry Andric 
101291bc56edSDimitry Andric std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1013dff0c46cSDimitry Andric                                                 LibraryRef &Res) const {
1014dff0c46cSDimitry Andric   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1015dff0c46cSDimitry Andric }
1016dff0c46cSDimitry Andric 
101791bc56edSDimitry Andric std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1018dff0c46cSDimitry Andric                                                 StringRef &Res) const {
1019dff0c46cSDimitry Andric   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1020dff0c46cSDimitry Andric }
1021dff0c46cSDimitry Andric 
102291bc56edSDimitry Andric //
102391bc56edSDimitry Andric // guessLibraryShortName() is passed a name of a dynamic library and returns a
102491bc56edSDimitry Andric // guess on what the short name is.  Then name is returned as a substring of the
102591bc56edSDimitry Andric // StringRef Name passed in.  The name of the dynamic library is recognized as
102691bc56edSDimitry Andric // a framework if it has one of the two following forms:
102791bc56edSDimitry Andric //      Foo.framework/Versions/A/Foo
102891bc56edSDimitry Andric //      Foo.framework/Foo
102991bc56edSDimitry Andric // Where A and Foo can be any string.  And may contain a trailing suffix
103091bc56edSDimitry Andric // starting with an underbar.  If the Name is recognized as a framework then
103191bc56edSDimitry Andric // isFramework is set to true else it is set to false.  If the Name has a
103291bc56edSDimitry Andric // suffix then Suffix is set to the substring in Name that contains the suffix
103391bc56edSDimitry Andric // else it is set to a NULL StringRef.
103491bc56edSDimitry Andric //
103591bc56edSDimitry Andric // The Name of the dynamic library is recognized as a library name if it has
103691bc56edSDimitry Andric // one of the two following forms:
103791bc56edSDimitry Andric //      libFoo.A.dylib
103891bc56edSDimitry Andric //      libFoo.dylib
103991bc56edSDimitry Andric // The library may have a suffix trailing the name Foo of the form:
104091bc56edSDimitry Andric //      libFoo_profile.A.dylib
104191bc56edSDimitry Andric //      libFoo_profile.dylib
104291bc56edSDimitry Andric //
104391bc56edSDimitry Andric // The Name of the dynamic library is also recognized as a library name if it
104491bc56edSDimitry Andric // has the following form:
104591bc56edSDimitry Andric //      Foo.qtx
104691bc56edSDimitry Andric //
104791bc56edSDimitry Andric // If the Name of the dynamic library is none of the forms above then a NULL
104891bc56edSDimitry Andric // StringRef is returned.
104991bc56edSDimitry Andric //
105091bc56edSDimitry Andric StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
105191bc56edSDimitry Andric                                                  bool &isFramework,
105291bc56edSDimitry Andric                                                  StringRef &Suffix) {
105391bc56edSDimitry Andric   StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
105491bc56edSDimitry Andric   size_t a, b, c, d, Idx;
1055dff0c46cSDimitry Andric 
105691bc56edSDimitry Andric   isFramework = false;
105791bc56edSDimitry Andric   Suffix = StringRef();
105891bc56edSDimitry Andric 
105991bc56edSDimitry Andric   // Pull off the last component and make Foo point to it
106091bc56edSDimitry Andric   a = Name.rfind('/');
106191bc56edSDimitry Andric   if (a == Name.npos || a == 0)
106291bc56edSDimitry Andric     goto guess_library;
106391bc56edSDimitry Andric   Foo = Name.slice(a+1, Name.npos);
106491bc56edSDimitry Andric 
106591bc56edSDimitry Andric   // Look for a suffix starting with a '_'
106691bc56edSDimitry Andric   Idx = Foo.rfind('_');
106791bc56edSDimitry Andric   if (Idx != Foo.npos && Foo.size() >= 2) {
106891bc56edSDimitry Andric     Suffix = Foo.slice(Idx, Foo.npos);
106991bc56edSDimitry Andric     Foo = Foo.slice(0, Idx);
1070284c1978SDimitry Andric   }
1071284c1978SDimitry Andric 
107291bc56edSDimitry Andric   // First look for the form Foo.framework/Foo
107391bc56edSDimitry Andric   b = Name.rfind('/', a);
107491bc56edSDimitry Andric   if (b == Name.npos)
107591bc56edSDimitry Andric     Idx = 0;
107691bc56edSDimitry Andric   else
107791bc56edSDimitry Andric     Idx = b+1;
107891bc56edSDimitry Andric   F = Name.slice(Idx, Idx + Foo.size());
107991bc56edSDimitry Andric   DotFramework = Name.slice(Idx + Foo.size(),
108091bc56edSDimitry Andric                             Idx + Foo.size() + sizeof(".framework/")-1);
108191bc56edSDimitry Andric   if (F == Foo && DotFramework == ".framework/") {
108291bc56edSDimitry Andric     isFramework = true;
108391bc56edSDimitry Andric     return Foo;
108491bc56edSDimitry Andric   }
108591bc56edSDimitry Andric 
108691bc56edSDimitry Andric   // Next look for the form Foo.framework/Versions/A/Foo
108791bc56edSDimitry Andric   if (b == Name.npos)
108891bc56edSDimitry Andric     goto guess_library;
108991bc56edSDimitry Andric   c =  Name.rfind('/', b);
109091bc56edSDimitry Andric   if (c == Name.npos || c == 0)
109191bc56edSDimitry Andric     goto guess_library;
109291bc56edSDimitry Andric   V = Name.slice(c+1, Name.npos);
109391bc56edSDimitry Andric   if (!V.startswith("Versions/"))
109491bc56edSDimitry Andric     goto guess_library;
109591bc56edSDimitry Andric   d =  Name.rfind('/', c);
109691bc56edSDimitry Andric   if (d == Name.npos)
109791bc56edSDimitry Andric     Idx = 0;
109891bc56edSDimitry Andric   else
109991bc56edSDimitry Andric     Idx = d+1;
110091bc56edSDimitry Andric   F = Name.slice(Idx, Idx + Foo.size());
110191bc56edSDimitry Andric   DotFramework = Name.slice(Idx + Foo.size(),
110291bc56edSDimitry Andric                             Idx + Foo.size() + sizeof(".framework/")-1);
110391bc56edSDimitry Andric   if (F == Foo && DotFramework == ".framework/") {
110491bc56edSDimitry Andric     isFramework = true;
110591bc56edSDimitry Andric     return Foo;
110691bc56edSDimitry Andric   }
110791bc56edSDimitry Andric 
110891bc56edSDimitry Andric guess_library:
110991bc56edSDimitry Andric   // pull off the suffix after the "." and make a point to it
111091bc56edSDimitry Andric   a = Name.rfind('.');
111191bc56edSDimitry Andric   if (a == Name.npos || a == 0)
111291bc56edSDimitry Andric     return StringRef();
111391bc56edSDimitry Andric   Dylib = Name.slice(a, Name.npos);
111491bc56edSDimitry Andric   if (Dylib != ".dylib")
111591bc56edSDimitry Andric     goto guess_qtx;
111691bc56edSDimitry Andric 
111791bc56edSDimitry Andric   // First pull off the version letter for the form Foo.A.dylib if any.
111891bc56edSDimitry Andric   if (a >= 3) {
111991bc56edSDimitry Andric     Dot = Name.slice(a-2, a-1);
112091bc56edSDimitry Andric     if (Dot == ".")
112191bc56edSDimitry Andric       a = a - 2;
112291bc56edSDimitry Andric   }
112391bc56edSDimitry Andric 
112491bc56edSDimitry Andric   b = Name.rfind('/', a);
112591bc56edSDimitry Andric   if (b == Name.npos)
112691bc56edSDimitry Andric     b = 0;
112791bc56edSDimitry Andric   else
112891bc56edSDimitry Andric     b = b+1;
112991bc56edSDimitry Andric   // ignore any suffix after an underbar like Foo_profile.A.dylib
113091bc56edSDimitry Andric   Idx = Name.find('_', b);
113191bc56edSDimitry Andric   if (Idx != Name.npos && Idx != b) {
113291bc56edSDimitry Andric     Lib = Name.slice(b, Idx);
113391bc56edSDimitry Andric     Suffix = Name.slice(Idx, a);
113491bc56edSDimitry Andric   }
113591bc56edSDimitry Andric   else
113691bc56edSDimitry Andric     Lib = Name.slice(b, a);
113791bc56edSDimitry Andric   // There are incorrect library names of the form:
113891bc56edSDimitry Andric   // libATS.A_profile.dylib so check for these.
113991bc56edSDimitry Andric   if (Lib.size() >= 3) {
114091bc56edSDimitry Andric     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
114191bc56edSDimitry Andric     if (Dot == ".")
114291bc56edSDimitry Andric       Lib = Lib.slice(0, Lib.size()-2);
114391bc56edSDimitry Andric   }
114491bc56edSDimitry Andric   return Lib;
114591bc56edSDimitry Andric 
114691bc56edSDimitry Andric guess_qtx:
114791bc56edSDimitry Andric   Qtx = Name.slice(a, Name.npos);
114891bc56edSDimitry Andric   if (Qtx != ".qtx")
114991bc56edSDimitry Andric     return StringRef();
115091bc56edSDimitry Andric   b = Name.rfind('/', a);
115191bc56edSDimitry Andric   if (b == Name.npos)
115291bc56edSDimitry Andric     Lib = Name.slice(0, a);
115391bc56edSDimitry Andric   else
115491bc56edSDimitry Andric     Lib = Name.slice(b+1, a);
115591bc56edSDimitry Andric   // There are library names of the form: QT.A.qtx so check for these.
115691bc56edSDimitry Andric   if (Lib.size() >= 3) {
115791bc56edSDimitry Andric     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
115891bc56edSDimitry Andric     if (Dot == ".")
115991bc56edSDimitry Andric       Lib = Lib.slice(0, Lib.size()-2);
116091bc56edSDimitry Andric   }
116191bc56edSDimitry Andric   return Lib;
116291bc56edSDimitry Andric }
116391bc56edSDimitry Andric 
116491bc56edSDimitry Andric // getLibraryShortNameByIndex() is used to get the short name of the library
116591bc56edSDimitry Andric // for an undefined symbol in a linked Mach-O binary that was linked with the
116691bc56edSDimitry Andric // normal two-level namespace default (that is MH_TWOLEVEL in the header).
116791bc56edSDimitry Andric // It is passed the index (0 - based) of the library as translated from
116891bc56edSDimitry Andric // GET_LIBRARY_ORDINAL (1 - based).
116991bc56edSDimitry Andric std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
117091bc56edSDimitry Andric                                                             StringRef &Res) {
117191bc56edSDimitry Andric   if (Index >= Libraries.size())
117291bc56edSDimitry Andric     return object_error::parse_failed;
117391bc56edSDimitry Andric 
117491bc56edSDimitry Andric   MachO::dylib_command D =
117591bc56edSDimitry Andric     getStruct<MachO::dylib_command>(this, Libraries[Index]);
117691bc56edSDimitry Andric   if (D.dylib.name >= D.cmdsize)
117791bc56edSDimitry Andric     return object_error::parse_failed;
117891bc56edSDimitry Andric 
117991bc56edSDimitry Andric   // If the cache of LibrariesShortNames is not built up do that first for
118091bc56edSDimitry Andric   // all the Libraries.
118191bc56edSDimitry Andric   if (LibrariesShortNames.size() == 0) {
118291bc56edSDimitry Andric     for (unsigned i = 0; i < Libraries.size(); i++) {
118391bc56edSDimitry Andric       MachO::dylib_command D =
118491bc56edSDimitry Andric         getStruct<MachO::dylib_command>(this, Libraries[i]);
118591bc56edSDimitry Andric       if (D.dylib.name >= D.cmdsize) {
118691bc56edSDimitry Andric         LibrariesShortNames.push_back(StringRef());
118791bc56edSDimitry Andric         continue;
118891bc56edSDimitry Andric       }
118991bc56edSDimitry Andric       const char *P = (const char *)(Libraries[i]) + D.dylib.name;
119091bc56edSDimitry Andric       StringRef Name = StringRef(P);
119191bc56edSDimitry Andric       StringRef Suffix;
119291bc56edSDimitry Andric       bool isFramework;
119391bc56edSDimitry Andric       StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
119491bc56edSDimitry Andric       if (shortName == StringRef())
119591bc56edSDimitry Andric         LibrariesShortNames.push_back(Name);
119691bc56edSDimitry Andric       else
119791bc56edSDimitry Andric         LibrariesShortNames.push_back(shortName);
119891bc56edSDimitry Andric     }
119991bc56edSDimitry Andric   }
120091bc56edSDimitry Andric 
120191bc56edSDimitry Andric   Res = LibrariesShortNames[Index];
120291bc56edSDimitry Andric   return object_error::success;
120391bc56edSDimitry Andric }
120491bc56edSDimitry Andric 
120591bc56edSDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
120691bc56edSDimitry Andric   return getSymbolByIndex(0);
120791bc56edSDimitry Andric }
120891bc56edSDimitry Andric 
120991bc56edSDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1210284c1978SDimitry Andric   DataRefImpl DRI;
1211284c1978SDimitry Andric   if (!SymtabLoadCmd)
121291bc56edSDimitry Andric     return basic_symbol_iterator(SymbolRef(DRI, this));
1213284c1978SDimitry Andric 
1214f785676fSDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
1215284c1978SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
1216f785676fSDimitry Andric     sizeof(MachO::nlist_64) :
1217f785676fSDimitry Andric     sizeof(MachO::nlist);
1218f785676fSDimitry Andric   unsigned Offset = Symtab.symoff +
1219f785676fSDimitry Andric     Symtab.nsyms * SymbolTableEntrySize;
1220284c1978SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
122191bc56edSDimitry Andric   return basic_symbol_iterator(SymbolRef(DRI, this));
1222284c1978SDimitry Andric }
1223284c1978SDimitry Andric 
122491bc56edSDimitry Andric basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
122591bc56edSDimitry Andric   DataRefImpl DRI;
122691bc56edSDimitry Andric   if (!SymtabLoadCmd)
122791bc56edSDimitry Andric     return basic_symbol_iterator(SymbolRef(DRI, this));
122891bc56edSDimitry Andric 
122991bc56edSDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
123091bc56edSDimitry Andric   assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
123191bc56edSDimitry Andric   unsigned SymbolTableEntrySize =
123291bc56edSDimitry Andric     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
123391bc56edSDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
123491bc56edSDimitry Andric   DRI.p += Index * SymbolTableEntrySize;
123591bc56edSDimitry Andric   return basic_symbol_iterator(SymbolRef(DRI, this));
1236284c1978SDimitry Andric }
1237284c1978SDimitry Andric 
123891bc56edSDimitry Andric section_iterator MachOObjectFile::section_begin() const {
1239284c1978SDimitry Andric   DataRefImpl DRI;
1240284c1978SDimitry Andric   return section_iterator(SectionRef(DRI, this));
1241284c1978SDimitry Andric }
1242284c1978SDimitry Andric 
124391bc56edSDimitry Andric section_iterator MachOObjectFile::section_end() const {
1244284c1978SDimitry Andric   DataRefImpl DRI;
1245284c1978SDimitry Andric   DRI.d.a = Sections.size();
1246284c1978SDimitry Andric   return section_iterator(SectionRef(DRI, this));
1247284c1978SDimitry Andric }
1248284c1978SDimitry Andric 
124991bc56edSDimitry Andric library_iterator MachOObjectFile::needed_library_begin() const {
1250284c1978SDimitry Andric   // TODO: implement
1251284c1978SDimitry Andric   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1252284c1978SDimitry Andric }
1253284c1978SDimitry Andric 
125491bc56edSDimitry Andric library_iterator MachOObjectFile::needed_library_end() const {
1255284c1978SDimitry Andric   // TODO: implement
1256284c1978SDimitry Andric   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1257284c1978SDimitry Andric }
12583b0f4066SDimitry Andric 
12593b0f4066SDimitry Andric uint8_t MachOObjectFile::getBytesInAddress() const {
1260284c1978SDimitry Andric   return is64Bit() ? 8 : 4;
12613b0f4066SDimitry Andric }
12623b0f4066SDimitry Andric 
12633b0f4066SDimitry Andric StringRef MachOObjectFile::getFileFormatName() const {
1264284c1978SDimitry Andric   unsigned CPUType = getCPUType(this);
1265284c1978SDimitry Andric   if (!is64Bit()) {
1266284c1978SDimitry Andric     switch (CPUType) {
1267f785676fSDimitry Andric     case llvm::MachO::CPU_TYPE_I386:
12683b0f4066SDimitry Andric       return "Mach-O 32-bit i386";
1269f785676fSDimitry Andric     case llvm::MachO::CPU_TYPE_ARM:
12703b0f4066SDimitry Andric       return "Mach-O arm";
1271f785676fSDimitry Andric     case llvm::MachO::CPU_TYPE_POWERPC:
12723b0f4066SDimitry Andric       return "Mach-O 32-bit ppc";
12733b0f4066SDimitry Andric     default:
1274f785676fSDimitry Andric       assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
12753b0f4066SDimitry Andric              "64-bit object file when we're not 64-bit?");
12763b0f4066SDimitry Andric       return "Mach-O 32-bit unknown";
12773b0f4066SDimitry Andric     }
12783b0f4066SDimitry Andric   }
12793b0f4066SDimitry Andric 
1280139f7f9bSDimitry Andric   // Make sure the cpu type has the correct mask.
1281f785676fSDimitry Andric   assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1282f785676fSDimitry Andric          == llvm::MachO::CPU_ARCH_ABI64 &&
1283139f7f9bSDimitry Andric          "32-bit object file when we're 64-bit?");
1284139f7f9bSDimitry Andric 
1285284c1978SDimitry Andric   switch (CPUType) {
1286f785676fSDimitry Andric   case llvm::MachO::CPU_TYPE_X86_64:
12873b0f4066SDimitry Andric     return "Mach-O 64-bit x86-64";
128891bc56edSDimitry Andric   case llvm::MachO::CPU_TYPE_ARM64:
128991bc56edSDimitry Andric     return "Mach-O arm64";
1290f785676fSDimitry Andric   case llvm::MachO::CPU_TYPE_POWERPC64:
12913b0f4066SDimitry Andric     return "Mach-O 64-bit ppc64";
12923b0f4066SDimitry Andric   default:
12933b0f4066SDimitry Andric     return "Mach-O 64-bit unknown";
12943b0f4066SDimitry Andric   }
12953b0f4066SDimitry Andric }
12963b0f4066SDimitry Andric 
1297f785676fSDimitry Andric Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1298f785676fSDimitry Andric   switch (CPUType) {
1299f785676fSDimitry Andric   case llvm::MachO::CPU_TYPE_I386:
13003b0f4066SDimitry Andric     return Triple::x86;
1301f785676fSDimitry Andric   case llvm::MachO::CPU_TYPE_X86_64:
13023b0f4066SDimitry Andric     return Triple::x86_64;
1303f785676fSDimitry Andric   case llvm::MachO::CPU_TYPE_ARM:
13043b0f4066SDimitry Andric     return Triple::arm;
130591bc56edSDimitry Andric   case llvm::MachO::CPU_TYPE_ARM64:
130691bc56edSDimitry Andric     return Triple::arm64;
1307f785676fSDimitry Andric   case llvm::MachO::CPU_TYPE_POWERPC:
13083b0f4066SDimitry Andric     return Triple::ppc;
1309f785676fSDimitry Andric   case llvm::MachO::CPU_TYPE_POWERPC64:
13103b0f4066SDimitry Andric     return Triple::ppc64;
13113b0f4066SDimitry Andric   default:
13123b0f4066SDimitry Andric     return Triple::UnknownArch;
13133b0f4066SDimitry Andric   }
13143b0f4066SDimitry Andric }
13153b0f4066SDimitry Andric 
131691bc56edSDimitry Andric Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
131791bc56edSDimitry Andric   switch (CPUType) {
131891bc56edSDimitry Andric   case MachO::CPU_TYPE_I386:
131991bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
132091bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_I386_ALL:
132191bc56edSDimitry Andric       return Triple("i386-apple-darwin");
132291bc56edSDimitry Andric     default:
132391bc56edSDimitry Andric       return Triple();
132491bc56edSDimitry Andric     }
132591bc56edSDimitry Andric   case MachO::CPU_TYPE_X86_64:
132691bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
132791bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_X86_64_ALL:
132891bc56edSDimitry Andric       return Triple("x86_64-apple-darwin");
132991bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_X86_64_H:
133091bc56edSDimitry Andric       return Triple("x86_64h-apple-darwin");
133191bc56edSDimitry Andric     default:
133291bc56edSDimitry Andric       return Triple();
133391bc56edSDimitry Andric     }
133491bc56edSDimitry Andric   case MachO::CPU_TYPE_ARM:
133591bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
133691bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V4T:
133791bc56edSDimitry Andric       return Triple("armv4t-apple-darwin");
133891bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
133991bc56edSDimitry Andric       return Triple("armv5e-apple-darwin");
134091bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V6:
134191bc56edSDimitry Andric       return Triple("armv6-apple-darwin");
134291bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V6M:
134391bc56edSDimitry Andric       return Triple("armv6m-apple-darwin");
134491bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7EM:
134591bc56edSDimitry Andric       return Triple("armv7em-apple-darwin");
134691bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7K:
134791bc56edSDimitry Andric       return Triple("armv7k-apple-darwin");
134891bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7M:
134991bc56edSDimitry Andric       return Triple("armv7m-apple-darwin");
135091bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7S:
135191bc56edSDimitry Andric       return Triple("armv7s-apple-darwin");
135291bc56edSDimitry Andric     default:
135391bc56edSDimitry Andric       return Triple();
135491bc56edSDimitry Andric     }
135591bc56edSDimitry Andric   case MachO::CPU_TYPE_ARM64:
135691bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
135791bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM64_ALL:
135891bc56edSDimitry Andric       return Triple("arm64-apple-darwin");
135991bc56edSDimitry Andric     default:
136091bc56edSDimitry Andric       return Triple();
136191bc56edSDimitry Andric     }
136291bc56edSDimitry Andric   case MachO::CPU_TYPE_POWERPC:
136391bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
136491bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_POWERPC_ALL:
136591bc56edSDimitry Andric       return Triple("ppc-apple-darwin");
136691bc56edSDimitry Andric     default:
136791bc56edSDimitry Andric       return Triple();
136891bc56edSDimitry Andric     }
136991bc56edSDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
137091bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
137191bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_POWERPC_ALL:
137291bc56edSDimitry Andric       return Triple("ppc64-apple-darwin");
137391bc56edSDimitry Andric     default:
137491bc56edSDimitry Andric       return Triple();
137591bc56edSDimitry Andric     }
137691bc56edSDimitry Andric   default:
137791bc56edSDimitry Andric     return Triple();
137891bc56edSDimitry Andric   }
137991bc56edSDimitry Andric }
138091bc56edSDimitry Andric 
138191bc56edSDimitry Andric Triple MachOObjectFile::getHostArch() {
138291bc56edSDimitry Andric   return Triple(sys::getDefaultTargetTriple());
138391bc56edSDimitry Andric }
138491bc56edSDimitry Andric 
138591bc56edSDimitry Andric Triple MachOObjectFile::getArch(StringRef ArchFlag) {
138691bc56edSDimitry Andric   if (ArchFlag == "i386")
138791bc56edSDimitry Andric     return Triple("i386-apple-darwin");
138891bc56edSDimitry Andric   else if (ArchFlag == "x86_64")
138991bc56edSDimitry Andric     return Triple("x86_64-apple-darwin");
139091bc56edSDimitry Andric   else if (ArchFlag == "x86_64h")
139191bc56edSDimitry Andric     return Triple("x86_64h-apple-darwin");
139291bc56edSDimitry Andric   else if (ArchFlag == "armv4t" || ArchFlag == "arm")
139391bc56edSDimitry Andric     return Triple("armv4t-apple-darwin");
139491bc56edSDimitry Andric   else if (ArchFlag == "armv5e")
139591bc56edSDimitry Andric     return Triple("armv5e-apple-darwin");
139691bc56edSDimitry Andric   else if (ArchFlag == "armv6")
139791bc56edSDimitry Andric     return Triple("armv6-apple-darwin");
139891bc56edSDimitry Andric   else if (ArchFlag == "armv6m")
139991bc56edSDimitry Andric     return Triple("armv6m-apple-darwin");
140091bc56edSDimitry Andric   else if (ArchFlag == "armv7em")
140191bc56edSDimitry Andric     return Triple("armv7em-apple-darwin");
140291bc56edSDimitry Andric   else if (ArchFlag == "armv7k")
140391bc56edSDimitry Andric     return Triple("armv7k-apple-darwin");
140491bc56edSDimitry Andric   else if (ArchFlag == "armv7k")
140591bc56edSDimitry Andric     return Triple("armv7m-apple-darwin");
140691bc56edSDimitry Andric   else if (ArchFlag == "armv7s")
140791bc56edSDimitry Andric     return Triple("armv7s-apple-darwin");
140891bc56edSDimitry Andric   else if (ArchFlag == "arm64")
140991bc56edSDimitry Andric     return Triple("arm64-apple-darwin");
141091bc56edSDimitry Andric   else if (ArchFlag == "ppc")
141191bc56edSDimitry Andric     return Triple("ppc-apple-darwin");
141291bc56edSDimitry Andric   else if (ArchFlag == "ppc64")
141391bc56edSDimitry Andric     return Triple("ppc64-apple-darwin");
141491bc56edSDimitry Andric   else
141591bc56edSDimitry Andric     return Triple();
141691bc56edSDimitry Andric }
141791bc56edSDimitry Andric 
1418f785676fSDimitry Andric unsigned MachOObjectFile::getArch() const {
1419f785676fSDimitry Andric   return getArch(getCPUType(this));
1420f785676fSDimitry Andric }
1421f785676fSDimitry Andric 
1422284c1978SDimitry Andric StringRef MachOObjectFile::getLoadName() const {
1423284c1978SDimitry Andric   // TODO: Implement
1424284c1978SDimitry Andric   report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1425284c1978SDimitry Andric }
1426284c1978SDimitry Andric 
1427f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1428284c1978SDimitry Andric   DataRefImpl DRI;
1429284c1978SDimitry Andric   DRI.d.a = Index;
1430f785676fSDimitry Andric   return section_rel_begin(DRI);
1431284c1978SDimitry Andric }
1432284c1978SDimitry Andric 
1433f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1434284c1978SDimitry Andric   DataRefImpl DRI;
1435284c1978SDimitry Andric   DRI.d.a = Index;
1436f785676fSDimitry Andric   return section_rel_end(DRI);
1437f785676fSDimitry Andric }
1438f785676fSDimitry Andric 
1439f785676fSDimitry Andric dice_iterator MachOObjectFile::begin_dices() const {
1440f785676fSDimitry Andric   DataRefImpl DRI;
1441f785676fSDimitry Andric   if (!DataInCodeLoadCmd)
1442f785676fSDimitry Andric     return dice_iterator(DiceRef(DRI, this));
1443f785676fSDimitry Andric 
1444f785676fSDimitry Andric   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1445f785676fSDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1446f785676fSDimitry Andric   return dice_iterator(DiceRef(DRI, this));
1447f785676fSDimitry Andric }
1448f785676fSDimitry Andric 
1449f785676fSDimitry Andric dice_iterator MachOObjectFile::end_dices() const {
1450f785676fSDimitry Andric   DataRefImpl DRI;
1451f785676fSDimitry Andric   if (!DataInCodeLoadCmd)
1452f785676fSDimitry Andric     return dice_iterator(DiceRef(DRI, this));
1453f785676fSDimitry Andric 
1454f785676fSDimitry Andric   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1455f785676fSDimitry Andric   unsigned Offset = DicLC.dataoff + DicLC.datasize;
1456f785676fSDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1457f785676fSDimitry Andric   return dice_iterator(DiceRef(DRI, this));
1458284c1978SDimitry Andric }
1459284c1978SDimitry Andric 
1460284c1978SDimitry Andric StringRef
1461284c1978SDimitry Andric MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1462284c1978SDimitry Andric   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1463284c1978SDimitry Andric   return parseSegmentOrSectionName(Raw.data());
1464284c1978SDimitry Andric }
1465284c1978SDimitry Andric 
1466284c1978SDimitry Andric ArrayRef<char>
1467284c1978SDimitry Andric MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1468f785676fSDimitry Andric   const section_base *Base =
1469f785676fSDimitry Andric     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1470f785676fSDimitry Andric   return ArrayRef<char>(Base->sectname);
1471284c1978SDimitry Andric }
1472284c1978SDimitry Andric 
1473284c1978SDimitry Andric ArrayRef<char>
1474284c1978SDimitry Andric MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1475f785676fSDimitry Andric   const section_base *Base =
1476f785676fSDimitry Andric     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1477f785676fSDimitry Andric   return ArrayRef<char>(Base->segname);
1478284c1978SDimitry Andric }
1479284c1978SDimitry Andric 
1480284c1978SDimitry Andric bool
1481f785676fSDimitry Andric MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1482284c1978SDimitry Andric   const {
1483f785676fSDimitry Andric   if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1484284c1978SDimitry Andric     return false;
1485f785676fSDimitry Andric   return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1486284c1978SDimitry Andric }
1487284c1978SDimitry Andric 
1488f785676fSDimitry Andric unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1489f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
1490284c1978SDimitry Andric   if (isLittleEndian())
1491f785676fSDimitry Andric     return RE.r_word1 & 0xffffff;
1492f785676fSDimitry Andric   return RE.r_word1 >> 8;
1493284c1978SDimitry Andric }
1494284c1978SDimitry Andric 
1495f785676fSDimitry Andric bool MachOObjectFile::getPlainRelocationExternal(
1496f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
1497284c1978SDimitry Andric   if (isLittleEndian())
1498f785676fSDimitry Andric     return (RE.r_word1 >> 27) & 1;
1499f785676fSDimitry Andric   return (RE.r_word1 >> 4) & 1;
1500284c1978SDimitry Andric }
1501284c1978SDimitry Andric 
1502f785676fSDimitry Andric bool MachOObjectFile::getScatteredRelocationScattered(
1503f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
1504f785676fSDimitry Andric   return RE.r_word0 >> 31;
1505284c1978SDimitry Andric }
1506284c1978SDimitry Andric 
1507f785676fSDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationValue(
1508f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
1509f785676fSDimitry Andric   return RE.r_word1;
1510284c1978SDimitry Andric }
1511284c1978SDimitry Andric 
1512f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationAddress(
1513f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
1514284c1978SDimitry Andric   if (isRelocationScattered(RE))
1515284c1978SDimitry Andric     return getScatteredRelocationAddress(RE);
1516284c1978SDimitry Andric   return getPlainRelocationAddress(RE);
1517284c1978SDimitry Andric }
1518284c1978SDimitry Andric 
1519f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationPCRel(
1520f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
1521284c1978SDimitry Andric   if (isRelocationScattered(RE))
1522284c1978SDimitry Andric     return getScatteredRelocationPCRel(this, RE);
1523284c1978SDimitry Andric   return getPlainRelocationPCRel(this, RE);
1524284c1978SDimitry Andric }
1525284c1978SDimitry Andric 
1526f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationLength(
1527f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
1528284c1978SDimitry Andric   if (isRelocationScattered(RE))
1529284c1978SDimitry Andric     return getScatteredRelocationLength(RE);
1530284c1978SDimitry Andric   return getPlainRelocationLength(this, RE);
1531284c1978SDimitry Andric }
1532284c1978SDimitry Andric 
1533284c1978SDimitry Andric unsigned
1534f785676fSDimitry Andric MachOObjectFile::getAnyRelocationType(
1535f785676fSDimitry Andric                                    const MachO::any_relocation_info &RE) const {
1536284c1978SDimitry Andric   if (isRelocationScattered(RE))
1537284c1978SDimitry Andric     return getScatteredRelocationType(RE);
1538284c1978SDimitry Andric   return getPlainRelocationType(this, RE);
1539284c1978SDimitry Andric }
1540284c1978SDimitry Andric 
1541284c1978SDimitry Andric SectionRef
1542f785676fSDimitry Andric MachOObjectFile::getRelocationSection(
1543f785676fSDimitry Andric                                    const MachO::any_relocation_info &RE) const {
1544284c1978SDimitry Andric   if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
154591bc56edSDimitry Andric     return *section_end();
1546284c1978SDimitry Andric   unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1547284c1978SDimitry Andric   DataRefImpl DRI;
1548284c1978SDimitry Andric   DRI.d.a = SecNum;
1549284c1978SDimitry Andric   return SectionRef(DRI, this);
1550284c1978SDimitry Andric }
1551284c1978SDimitry Andric 
1552284c1978SDimitry Andric MachOObjectFile::LoadCommandInfo
1553284c1978SDimitry Andric MachOObjectFile::getFirstLoadCommandInfo() const {
1554284c1978SDimitry Andric   MachOObjectFile::LoadCommandInfo Load;
1555284c1978SDimitry Andric 
1556f785676fSDimitry Andric   unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1557f785676fSDimitry Andric                                     sizeof(MachO::mach_header);
1558284c1978SDimitry Andric   Load.Ptr = getPtr(this, HeaderSize);
1559f785676fSDimitry Andric   Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
1560284c1978SDimitry Andric   return Load;
1561284c1978SDimitry Andric }
1562284c1978SDimitry Andric 
1563284c1978SDimitry Andric MachOObjectFile::LoadCommandInfo
1564284c1978SDimitry Andric MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1565284c1978SDimitry Andric   MachOObjectFile::LoadCommandInfo Next;
1566f785676fSDimitry Andric   Next.Ptr = L.Ptr + L.C.cmdsize;
1567f785676fSDimitry Andric   Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
1568284c1978SDimitry Andric   return Next;
1569284c1978SDimitry Andric }
1570284c1978SDimitry Andric 
1571f785676fSDimitry Andric MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1572f785676fSDimitry Andric   return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1573284c1978SDimitry Andric }
1574284c1978SDimitry Andric 
1575f785676fSDimitry Andric MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1576f785676fSDimitry Andric   return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1577284c1978SDimitry Andric }
1578284c1978SDimitry Andric 
1579f785676fSDimitry Andric MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1580284c1978SDimitry Andric                                            unsigned Index) const {
1581284c1978SDimitry Andric   const char *Sec = getSectionPtr(this, L, Index);
1582f785676fSDimitry Andric   return getStruct<MachO::section>(this, Sec);
1583284c1978SDimitry Andric }
1584284c1978SDimitry Andric 
1585f785676fSDimitry Andric MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1586284c1978SDimitry Andric                                                 unsigned Index) const {
1587284c1978SDimitry Andric   const char *Sec = getSectionPtr(this, L, Index);
1588f785676fSDimitry Andric   return getStruct<MachO::section_64>(this, Sec);
1589284c1978SDimitry Andric }
1590284c1978SDimitry Andric 
1591f785676fSDimitry Andric MachO::nlist
1592284c1978SDimitry Andric MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1593284c1978SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
1594f785676fSDimitry Andric   return getStruct<MachO::nlist>(this, P);
1595284c1978SDimitry Andric }
1596284c1978SDimitry Andric 
1597f785676fSDimitry Andric MachO::nlist_64
1598284c1978SDimitry Andric MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1599284c1978SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
1600f785676fSDimitry Andric   return getStruct<MachO::nlist_64>(this, P);
1601284c1978SDimitry Andric }
1602284c1978SDimitry Andric 
1603f785676fSDimitry Andric MachO::linkedit_data_command
1604f785676fSDimitry Andric MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1605f785676fSDimitry Andric   return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1606284c1978SDimitry Andric }
1607284c1978SDimitry Andric 
1608f785676fSDimitry Andric MachO::segment_command
1609284c1978SDimitry Andric MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1610f785676fSDimitry Andric   return getStruct<MachO::segment_command>(this, L.Ptr);
1611284c1978SDimitry Andric }
1612284c1978SDimitry Andric 
1613f785676fSDimitry Andric MachO::segment_command_64
1614284c1978SDimitry Andric MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1615f785676fSDimitry Andric   return getStruct<MachO::segment_command_64>(this, L.Ptr);
1616284c1978SDimitry Andric }
1617284c1978SDimitry Andric 
1618f785676fSDimitry Andric MachO::linker_options_command
1619284c1978SDimitry Andric MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
1620f785676fSDimitry Andric   return getStruct<MachO::linker_options_command>(this, L.Ptr);
1621284c1978SDimitry Andric }
1622284c1978SDimitry Andric 
162391bc56edSDimitry Andric MachO::version_min_command
162491bc56edSDimitry Andric MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
162591bc56edSDimitry Andric   return getStruct<MachO::version_min_command>(this, L.Ptr);
162691bc56edSDimitry Andric }
162791bc56edSDimitry Andric 
162891bc56edSDimitry Andric MachO::dylib_command
162991bc56edSDimitry Andric MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
163091bc56edSDimitry Andric   return getStruct<MachO::dylib_command>(this, L.Ptr);
163191bc56edSDimitry Andric }
163291bc56edSDimitry Andric 
163391bc56edSDimitry Andric 
1634f785676fSDimitry Andric MachO::any_relocation_info
1635284c1978SDimitry Andric MachOObjectFile::getRelocation(DataRefImpl Rel) const {
163691bc56edSDimitry Andric   DataRefImpl Sec;
163791bc56edSDimitry Andric   Sec.d.a = Rel.d.a;
163891bc56edSDimitry Andric   uint32_t Offset;
163991bc56edSDimitry Andric   if (is64Bit()) {
164091bc56edSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
164191bc56edSDimitry Andric     Offset = Sect.reloff;
164291bc56edSDimitry Andric   } else {
164391bc56edSDimitry Andric     MachO::section Sect = getSection(Sec);
164491bc56edSDimitry Andric     Offset = Sect.reloff;
164591bc56edSDimitry Andric   }
164691bc56edSDimitry Andric 
164791bc56edSDimitry Andric   auto P = reinterpret_cast<const MachO::any_relocation_info *>(
164891bc56edSDimitry Andric       getPtr(this, Offset)) + Rel.d.b;
164991bc56edSDimitry Andric   return getStruct<MachO::any_relocation_info>(
165091bc56edSDimitry Andric       this, reinterpret_cast<const char *>(P));
1651284c1978SDimitry Andric }
1652284c1978SDimitry Andric 
1653f785676fSDimitry Andric MachO::data_in_code_entry
1654f785676fSDimitry Andric MachOObjectFile::getDice(DataRefImpl Rel) const {
1655f785676fSDimitry Andric   const char *P = reinterpret_cast<const char *>(Rel.p);
1656f785676fSDimitry Andric   return getStruct<MachO::data_in_code_entry>(this, P);
1657284c1978SDimitry Andric }
1658284c1978SDimitry Andric 
1659f785676fSDimitry Andric MachO::mach_header MachOObjectFile::getHeader() const {
1660f785676fSDimitry Andric   return getStruct<MachO::mach_header>(this, getPtr(this, 0));
1661284c1978SDimitry Andric }
1662284c1978SDimitry Andric 
1663f785676fSDimitry Andric MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1664f785676fSDimitry Andric   return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
1665f785676fSDimitry Andric }
1666f785676fSDimitry Andric 
1667f785676fSDimitry Andric uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1668f785676fSDimitry Andric                                              const MachO::dysymtab_command &DLC,
1669284c1978SDimitry Andric                                              unsigned Index) const {
1670f785676fSDimitry Andric   uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1671f785676fSDimitry Andric   return getStruct<uint32_t>(this, getPtr(this, Offset));
1672284c1978SDimitry Andric }
1673284c1978SDimitry Andric 
1674f785676fSDimitry Andric MachO::data_in_code_entry
1675284c1978SDimitry Andric MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1676284c1978SDimitry Andric                                          unsigned Index) const {
1677f785676fSDimitry Andric   uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1678f785676fSDimitry Andric   return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
1679284c1978SDimitry Andric }
1680284c1978SDimitry Andric 
1681f785676fSDimitry Andric MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1682f785676fSDimitry Andric   return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1683284c1978SDimitry Andric }
1684284c1978SDimitry Andric 
1685f785676fSDimitry Andric MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1686f785676fSDimitry Andric   return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1687f785676fSDimitry Andric }
1688f785676fSDimitry Andric 
1689f785676fSDimitry Andric MachO::linkedit_data_command
1690f785676fSDimitry Andric MachOObjectFile::getDataInCodeLoadCommand() const {
1691f785676fSDimitry Andric   if (DataInCodeLoadCmd)
1692f785676fSDimitry Andric     return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
1693f785676fSDimitry Andric 
1694f785676fSDimitry Andric   // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
1695f785676fSDimitry Andric   MachO::linkedit_data_command Cmd;
1696f785676fSDimitry Andric   Cmd.cmd = MachO::LC_DATA_IN_CODE;
1697f785676fSDimitry Andric   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1698f785676fSDimitry Andric   Cmd.dataoff = 0;
1699f785676fSDimitry Andric   Cmd.datasize = 0;
1700f785676fSDimitry Andric   return Cmd;
1701284c1978SDimitry Andric }
1702284c1978SDimitry Andric 
1703284c1978SDimitry Andric StringRef MachOObjectFile::getStringTableData() const {
1704f785676fSDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
1705f785676fSDimitry Andric   return getData().substr(S.stroff, S.strsize);
1706284c1978SDimitry Andric }
1707284c1978SDimitry Andric 
1708284c1978SDimitry Andric bool MachOObjectFile::is64Bit() const {
1709284c1978SDimitry Andric   return getType() == getMachOType(false, true) ||
1710284c1978SDimitry Andric     getType() == getMachOType(true, true);
1711284c1978SDimitry Andric }
1712284c1978SDimitry Andric 
1713284c1978SDimitry Andric void MachOObjectFile::ReadULEB128s(uint64_t Index,
1714284c1978SDimitry Andric                                    SmallVectorImpl<uint64_t> &Out) const {
1715284c1978SDimitry Andric   DataExtractor extractor(ObjectFile::getData(), true, 0);
1716284c1978SDimitry Andric 
1717284c1978SDimitry Andric   uint32_t offset = Index;
1718284c1978SDimitry Andric   uint64_t data = 0;
1719284c1978SDimitry Andric   while (uint64_t delta = extractor.getULEB128(&offset)) {
1720284c1978SDimitry Andric     data += delta;
1721284c1978SDimitry Andric     Out.push_back(data);
1722284c1978SDimitry Andric   }
1723284c1978SDimitry Andric }
1724284c1978SDimitry Andric 
172591bc56edSDimitry Andric ErrorOr<ObjectFile *>
172691bc56edSDimitry Andric ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
1727284c1978SDimitry Andric   StringRef Magic = Buffer->getBuffer().slice(0, 4);
172891bc56edSDimitry Andric   std::error_code EC;
172991bc56edSDimitry Andric   std::unique_ptr<MachOObjectFile> Ret;
1730284c1978SDimitry Andric   if (Magic == "\xFE\xED\xFA\xCE")
173191bc56edSDimitry Andric     Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
1732284c1978SDimitry Andric   else if (Magic == "\xCE\xFA\xED\xFE")
173391bc56edSDimitry Andric     Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
1734284c1978SDimitry Andric   else if (Magic == "\xFE\xED\xFA\xCF")
173591bc56edSDimitry Andric     Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
1736284c1978SDimitry Andric   else if (Magic == "\xCF\xFA\xED\xFE")
173791bc56edSDimitry Andric     Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
173891bc56edSDimitry Andric   else
173991bc56edSDimitry Andric     return object_error::parse_failed;
174091bc56edSDimitry Andric 
174191bc56edSDimitry Andric   if (EC)
174291bc56edSDimitry Andric     return EC;
174391bc56edSDimitry Andric   return Ret.release();
1744f785676fSDimitry Andric }
1745284c1978SDimitry Andric 
1746