1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include <cctype>
28 #include <cstring>
29 #include <limits>
30 
31 using namespace llvm;
32 using namespace object;
33 
34 namespace {
35   struct section_base {
36     char sectname[16];
37     char segname[16];
38   };
39 }
40 
41 // FIXME: Replace all uses of this function with getStructOrErr.
42 template <typename T>
getStruct(const MachOObjectFile * O,const char * P)43 static T getStruct(const MachOObjectFile *O, const char *P) {
44   // Don't read before the beginning or past the end of the file
45   if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46     report_fatal_error("Malformed MachO file.");
47 
48   T Cmd;
49   memcpy(&Cmd, P, sizeof(T));
50   if (O->isLittleEndian() != sys::IsLittleEndianHost)
51     MachO::swapStruct(Cmd);
52   return Cmd;
53 }
54 
55 template <typename T>
getStructOrErr(const MachOObjectFile * O,const char * P)56 static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57   // Don't read before the beginning or past the end of the file
58   if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59     return object_error::parse_failed;
60 
61   T Cmd;
62   memcpy(&Cmd, P, sizeof(T));
63   if (O->isLittleEndian() != sys::IsLittleEndianHost)
64     MachO::swapStruct(Cmd);
65   return Cmd;
66 }
67 
68 static const char *
getSectionPtr(const MachOObjectFile * O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)69 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
70               unsigned Sec) {
71   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
72 
73   bool Is64 = O->is64Bit();
74   unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75                                     sizeof(MachO::segment_command);
76   unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77                                 sizeof(MachO::section);
78 
79   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
80   return reinterpret_cast<const char*>(SectionAddr);
81 }
82 
getPtr(const MachOObjectFile * O,size_t Offset)83 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84   return O->getData().substr(Offset, 1).data();
85 }
86 
87 static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile * O,DataRefImpl DRI)88 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
89   const char *P = reinterpret_cast<const char *>(DRI.p);
90   return getStruct<MachO::nlist_base>(O, P);
91 }
92 
parseSegmentOrSectionName(const char * P)93 static StringRef parseSegmentOrSectionName(const char *P) {
94   if (P[15] == 0)
95     // Null terminated.
96     return P;
97   // Not null terminated, so this is a 16 char string.
98   return StringRef(P, 16);
99 }
100 
101 // Helper to advance a section or symbol iterator multiple increments at a time.
102 template<class T>
advance(T & it,size_t Val)103 static void advance(T &it, size_t Val) {
104   while (Val--)
105     ++it;
106 }
107 
getCPUType(const MachOObjectFile * O)108 static unsigned getCPUType(const MachOObjectFile *O) {
109   return O->getHeader().cputype;
110 }
111 
112 static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)113 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
114   return RE.r_word0;
115 }
116 
117 static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)118 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119   return RE.r_word0 & 0xffffff;
120 }
121 
getPlainRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)122 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
123                                     const MachO::any_relocation_info &RE) {
124   if (O->isLittleEndian())
125     return (RE.r_word1 >> 24) & 1;
126   return (RE.r_word1 >> 7) & 1;
127 }
128 
129 static bool
getScatteredRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)130 getScatteredRelocationPCRel(const MachOObjectFile *O,
131                             const MachO::any_relocation_info &RE) {
132   return (RE.r_word0 >> 30) & 1;
133 }
134 
getPlainRelocationLength(const MachOObjectFile * O,const MachO::any_relocation_info & RE)135 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
136                                          const MachO::any_relocation_info &RE) {
137   if (O->isLittleEndian())
138     return (RE.r_word1 >> 25) & 3;
139   return (RE.r_word1 >> 5) & 3;
140 }
141 
142 static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144   return (RE.r_word0 >> 28) & 3;
145 }
146 
getPlainRelocationType(const MachOObjectFile * O,const MachO::any_relocation_info & RE)147 static unsigned getPlainRelocationType(const MachOObjectFile *O,
148                                        const MachO::any_relocation_info &RE) {
149   if (O->isLittleEndian())
150     return RE.r_word1 >> 28;
151   return RE.r_word1 & 0xf;
152 }
153 
getSectionFlags(const MachOObjectFile * O,DataRefImpl Sec)154 static uint32_t getSectionFlags(const MachOObjectFile *O,
155                                 DataRefImpl Sec) {
156   if (O->is64Bit()) {
157     MachO::section_64 Sect = O->getSection64(Sec);
158     return Sect.flags;
159   }
160   MachO::section Sect = O->getSection(Sec);
161   return Sect.flags;
162 }
163 
164 static ErrorOr<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile * Obj,const char * Ptr)165 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
166   auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
167   if (!CmdOrErr)
168     return CmdOrErr.getError();
169   if (CmdOrErr->cmdsize < 8)
170     return object_error::macho_small_load_command;
171   MachOObjectFile::LoadCommandInfo Load;
172   Load.Ptr = Ptr;
173   Load.C = CmdOrErr.get();
174   return Load;
175 }
176 
177 static ErrorOr<MachOObjectFile::LoadCommandInfo>
getFirstLoadCommandInfo(const MachOObjectFile * Obj)178 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179   unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180                                        : sizeof(MachO::mach_header);
181   return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
182 }
183 
184 static ErrorOr<MachOObjectFile::LoadCommandInfo>
getNextLoadCommandInfo(const MachOObjectFile * Obj,const MachOObjectFile::LoadCommandInfo & L)185 getNextLoadCommandInfo(const MachOObjectFile *Obj,
186                        const MachOObjectFile::LoadCommandInfo &L) {
187   return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
188 }
189 
190 template <typename T>
parseHeader(const MachOObjectFile * Obj,T & Header,std::error_code & EC)191 static void parseHeader(const MachOObjectFile *Obj, T &Header,
192                         std::error_code &EC) {
193   auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
194   if (HeaderOrErr)
195     Header = HeaderOrErr.get();
196   else
197     EC = HeaderOrErr.getError();
198 }
199 
200 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201 // sections to \param Sections, and optionally sets
202 // \param IsPageZeroSegment to true.
203 template <typename SegmentCmd>
parseSegmentLoadCommand(const MachOObjectFile * Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & Sections,bool & IsPageZeroSegment)204 static std::error_code parseSegmentLoadCommand(
205     const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206     SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207   const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208   if (Load.C.cmdsize < SegmentLoadSize)
209     return object_error::macho_load_segment_too_small;
210   auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
211   if (!SegOrErr)
212     return SegOrErr.getError();
213   SegmentCmd S = SegOrErr.get();
214   const unsigned SectionSize =
215       Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216   if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217       S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218     return object_error::macho_load_segment_too_many_sections;
219   for (unsigned J = 0; J < S.nsects; ++J) {
220     const char *Sec = getSectionPtr(Obj, Load, J);
221     Sections.push_back(Sec);
222   }
223   IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
224   return std::error_code();
225 }
226 
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,std::error_code & EC)227 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228                                  bool Is64bits, std::error_code &EC)
229     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
230       SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
231       DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232       DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233       HasPageZeroSegment(false) {
234   if (is64Bit())
235     parseHeader(this, Header64, EC);
236   else
237     parseHeader(this, Header, EC);
238   if (EC)
239     return;
240 
241   uint32_t LoadCommandCount = getHeader().ncmds;
242   if (LoadCommandCount == 0)
243     return;
244 
245   auto LoadOrErr = getFirstLoadCommandInfo(this);
246   if (!LoadOrErr) {
247     EC = LoadOrErr.getError();
248     return;
249   }
250   LoadCommandInfo Load = LoadOrErr.get();
251   for (unsigned I = 0; I < LoadCommandCount; ++I) {
252     LoadCommands.push_back(Load);
253     if (Load.C.cmd == MachO::LC_SYMTAB) {
254       // Multiple symbol tables
255       if (SymtabLoadCmd) {
256         EC = object_error::parse_failed;
257         return;
258       }
259       SymtabLoadCmd = Load.Ptr;
260     } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
261       // Multiple dynamic symbol tables
262       if (DysymtabLoadCmd) {
263         EC = object_error::parse_failed;
264         return;
265       }
266       DysymtabLoadCmd = Load.Ptr;
267     } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
268       // Multiple data in code tables
269       if (DataInCodeLoadCmd) {
270         EC = object_error::parse_failed;
271         return;
272       }
273       DataInCodeLoadCmd = Load.Ptr;
274     } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275       // Multiple linker optimization hint tables
276       if (LinkOptHintsLoadCmd) {
277         EC = object_error::parse_failed;
278         return;
279       }
280       LinkOptHintsLoadCmd = Load.Ptr;
281     } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282                Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
283       // Multiple dyldinfo load commands
284       if (DyldInfoLoadCmd) {
285         EC = object_error::parse_failed;
286         return;
287       }
288       DyldInfoLoadCmd = Load.Ptr;
289     } else if (Load.C.cmd == MachO::LC_UUID) {
290       // Multiple UUID load commands
291       if (UuidLoadCmd) {
292         EC = object_error::parse_failed;
293         return;
294       }
295       UuidLoadCmd = Load.Ptr;
296     } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297       if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298                this, Load, Sections, HasPageZeroSegment)))
299         return;
300     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301       if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302                this, Load, Sections, HasPageZeroSegment)))
303         return;
304     } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305                Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306                Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307                Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308                Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309       Libraries.push_back(Load.Ptr);
310     }
311     if (I < LoadCommandCount - 1) {
312       auto LoadOrErr = getNextLoadCommandInfo(this, Load);
313       if (!LoadOrErr) {
314         EC = LoadOrErr.getError();
315         return;
316       }
317       Load = LoadOrErr.get();
318     }
319   }
320   assert(LoadCommands.size() == LoadCommandCount);
321 }
322 
moveSymbolNext(DataRefImpl & Symb) const323 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
324   unsigned SymbolTableEntrySize = is64Bit() ?
325     sizeof(MachO::nlist_64) :
326     sizeof(MachO::nlist);
327   Symb.p += SymbolTableEntrySize;
328 }
329 
getSymbolName(DataRefImpl Symb) const330 ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
331   StringRef StringTable = getStringTableData();
332   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
333   const char *Start = &StringTable.data()[Entry.n_strx];
334   if (Start < getData().begin() || Start >= getData().end())
335     report_fatal_error(
336         "Symbol name entry points before beginning or past end of file.");
337   return StringRef(Start);
338 }
339 
getSectionType(SectionRef Sec) const340 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
341   DataRefImpl DRI = Sec.getRawDataRefImpl();
342   uint32_t Flags = getSectionFlags(this, DRI);
343   return Flags & MachO::SECTION_TYPE;
344 }
345 
getNValue(DataRefImpl Sym) const346 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
347   if (is64Bit()) {
348     MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
349     return Entry.n_value;
350   }
351   MachO::nlist Entry = getSymbolTableEntry(Sym);
352   return Entry.n_value;
353 }
354 
355 // getIndirectName() returns the name of the alias'ed symbol who's string table
356 // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const357 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
358                                                  StringRef &Res) const {
359   StringRef StringTable = getStringTableData();
360   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
361   if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362     return object_error::parse_failed;
363   uint64_t NValue = getNValue(Symb);
364   if (NValue >= StringTable.size())
365     return object_error::parse_failed;
366   const char *Start = &StringTable.data()[NValue];
367   Res = StringRef(Start);
368   return std::error_code();
369 }
370 
getSymbolValueImpl(DataRefImpl Sym) const371 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
372   return getNValue(Sym);
373 }
374 
getSymbolAddress(DataRefImpl Sym) const375 ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
376   return getSymbolValue(Sym);
377 }
378 
getSymbolAlignment(DataRefImpl DRI) const379 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
380   uint32_t flags = getSymbolFlags(DRI);
381   if (flags & SymbolRef::SF_Common) {
382     MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
383     return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
384   }
385   return 0;
386 }
387 
getCommonSymbolSizeImpl(DataRefImpl DRI) const388 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
389   return getNValue(DRI);
390 }
391 
getSymbolType(DataRefImpl Symb) const392 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
393   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
394   uint8_t n_type = Entry.n_type;
395 
396   // If this is a STAB debugging symbol, we can do nothing more.
397   if (n_type & MachO::N_STAB)
398     return SymbolRef::ST_Debug;
399 
400   switch (n_type & MachO::N_TYPE) {
401     case MachO::N_UNDF :
402       return SymbolRef::ST_Unknown;
403     case MachO::N_SECT :
404       section_iterator Sec = *getSymbolSection(Symb);
405       if (Sec->isData() || Sec->isBSS())
406         return SymbolRef::ST_Data;
407       return SymbolRef::ST_Function;
408   }
409   return SymbolRef::ST_Other;
410 }
411 
getSymbolFlags(DataRefImpl DRI) const412 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
413   MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
414 
415   uint8_t MachOType = Entry.n_type;
416   uint16_t MachOFlags = Entry.n_desc;
417 
418   uint32_t Result = SymbolRef::SF_None;
419 
420   if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
421     Result |= SymbolRef::SF_Indirect;
422 
423   if (MachOType & MachO::N_STAB)
424     Result |= SymbolRef::SF_FormatSpecific;
425 
426   if (MachOType & MachO::N_EXT) {
427     Result |= SymbolRef::SF_Global;
428     if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
429       if (getNValue(DRI))
430         Result |= SymbolRef::SF_Common;
431       else
432         Result |= SymbolRef::SF_Undefined;
433     }
434 
435     if (!(MachOType & MachO::N_PEXT))
436       Result |= SymbolRef::SF_Exported;
437   }
438 
439   if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
440     Result |= SymbolRef::SF_Weak;
441 
442   if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
443     Result |= SymbolRef::SF_Thumb;
444 
445   if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
446     Result |= SymbolRef::SF_Absolute;
447 
448   return Result;
449 }
450 
451 ErrorOr<section_iterator>
getSymbolSection(DataRefImpl Symb) const452 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
453   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
454   uint8_t index = Entry.n_sect;
455 
456   if (index == 0)
457     return section_end();
458   DataRefImpl DRI;
459   DRI.d.a = index - 1;
460   if (DRI.d.a >= Sections.size())
461     report_fatal_error("getSymbolSection: Invalid section index.");
462   return section_iterator(SectionRef(DRI, this));
463 }
464 
getSymbolSectionID(SymbolRef Sym) const465 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
466   MachO::nlist_base Entry =
467       getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
468   return Entry.n_sect - 1;
469 }
470 
moveSectionNext(DataRefImpl & Sec) const471 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
472   Sec.d.a++;
473 }
474 
getSectionName(DataRefImpl Sec,StringRef & Result) const475 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
476                                                 StringRef &Result) const {
477   ArrayRef<char> Raw = getSectionRawName(Sec);
478   Result = parseSegmentOrSectionName(Raw.data());
479   return std::error_code();
480 }
481 
getSectionAddress(DataRefImpl Sec) const482 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
483   if (is64Bit())
484     return getSection64(Sec).addr;
485   return getSection(Sec).addr;
486 }
487 
getSectionSize(DataRefImpl Sec) const488 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
489   // In the case if a malformed Mach-O file where the section offset is past
490   // the end of the file or some part of the section size is past the end of
491   // the file return a size of zero or a size that covers the rest of the file
492   // but does not extend past the end of the file.
493   uint32_t SectOffset, SectType;
494   uint64_t SectSize;
495 
496   if (is64Bit()) {
497     MachO::section_64 Sect = getSection64(Sec);
498     SectOffset = Sect.offset;
499     SectSize = Sect.size;
500     SectType = Sect.flags & MachO::SECTION_TYPE;
501   } else {
502     MachO::section Sect = getSection(Sec);
503     SectOffset = Sect.offset;
504     SectSize = Sect.size;
505     SectType = Sect.flags & MachO::SECTION_TYPE;
506   }
507   if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
508     return SectSize;
509   uint64_t FileSize = getData().size();
510   if (SectOffset > FileSize)
511     return 0;
512   if (FileSize - SectOffset < SectSize)
513     return FileSize - SectOffset;
514   return SectSize;
515 }
516 
getSectionContents(DataRefImpl Sec,StringRef & Res) const517 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
518                                                     StringRef &Res) const {
519   uint32_t Offset;
520   uint64_t Size;
521 
522   if (is64Bit()) {
523     MachO::section_64 Sect = getSection64(Sec);
524     Offset = Sect.offset;
525     Size = Sect.size;
526   } else {
527     MachO::section Sect = getSection(Sec);
528     Offset = Sect.offset;
529     Size = Sect.size;
530   }
531 
532   Res = this->getData().substr(Offset, Size);
533   return std::error_code();
534 }
535 
getSectionAlignment(DataRefImpl Sec) const536 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
537   uint32_t Align;
538   if (is64Bit()) {
539     MachO::section_64 Sect = getSection64(Sec);
540     Align = Sect.align;
541   } else {
542     MachO::section Sect = getSection(Sec);
543     Align = Sect.align;
544   }
545 
546   return uint64_t(1) << Align;
547 }
548 
isSectionText(DataRefImpl Sec) const549 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
550   uint32_t Flags = getSectionFlags(this, Sec);
551   return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
552 }
553 
isSectionData(DataRefImpl Sec) const554 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
555   uint32_t Flags = getSectionFlags(this, Sec);
556   unsigned SectionType = Flags & MachO::SECTION_TYPE;
557   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
558          !(SectionType == MachO::S_ZEROFILL ||
559            SectionType == MachO::S_GB_ZEROFILL);
560 }
561 
isSectionBSS(DataRefImpl Sec) const562 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
563   uint32_t Flags = getSectionFlags(this, Sec);
564   unsigned SectionType = Flags & MachO::SECTION_TYPE;
565   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
566          (SectionType == MachO::S_ZEROFILL ||
567           SectionType == MachO::S_GB_ZEROFILL);
568 }
569 
getSectionID(SectionRef Sec) const570 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
571   return Sec.getRawDataRefImpl().d.a;
572 }
573 
isSectionVirtual(DataRefImpl Sec) const574 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
575   // FIXME: Unimplemented.
576   return false;
577 }
578 
section_rel_begin(DataRefImpl Sec) const579 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
580   DataRefImpl Ret;
581   Ret.d.a = Sec.d.a;
582   Ret.d.b = 0;
583   return relocation_iterator(RelocationRef(Ret, this));
584 }
585 
586 relocation_iterator
section_rel_end(DataRefImpl Sec) const587 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
588   uint32_t Num;
589   if (is64Bit()) {
590     MachO::section_64 Sect = getSection64(Sec);
591     Num = Sect.nreloc;
592   } else {
593     MachO::section Sect = getSection(Sec);
594     Num = Sect.nreloc;
595   }
596 
597   DataRefImpl Ret;
598   Ret.d.a = Sec.d.a;
599   Ret.d.b = Num;
600   return relocation_iterator(RelocationRef(Ret, this));
601 }
602 
moveRelocationNext(DataRefImpl & Rel) const603 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
604   ++Rel.d.b;
605 }
606 
getRelocationOffset(DataRefImpl Rel) const607 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
608   assert(getHeader().filetype == MachO::MH_OBJECT &&
609          "Only implemented for MH_OBJECT");
610   MachO::any_relocation_info RE = getRelocation(Rel);
611   return getAnyRelocationAddress(RE);
612 }
613 
614 symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const615 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
616   MachO::any_relocation_info RE = getRelocation(Rel);
617   if (isRelocationScattered(RE))
618     return symbol_end();
619 
620   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
621   bool isExtern = getPlainRelocationExternal(RE);
622   if (!isExtern)
623     return symbol_end();
624 
625   MachO::symtab_command S = getSymtabLoadCommand();
626   unsigned SymbolTableEntrySize = is64Bit() ?
627     sizeof(MachO::nlist_64) :
628     sizeof(MachO::nlist);
629   uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
630   DataRefImpl Sym;
631   Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
632   return symbol_iterator(SymbolRef(Sym, this));
633 }
634 
635 section_iterator
getRelocationSection(DataRefImpl Rel) const636 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
637   return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
638 }
639 
getRelocationType(DataRefImpl Rel) const640 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
641   MachO::any_relocation_info RE = getRelocation(Rel);
642   return getAnyRelocationType(RE);
643 }
644 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const645 void MachOObjectFile::getRelocationTypeName(
646     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
647   StringRef res;
648   uint64_t RType = getRelocationType(Rel);
649 
650   unsigned Arch = this->getArch();
651 
652   switch (Arch) {
653     case Triple::x86: {
654       static const char *const Table[] =  {
655         "GENERIC_RELOC_VANILLA",
656         "GENERIC_RELOC_PAIR",
657         "GENERIC_RELOC_SECTDIFF",
658         "GENERIC_RELOC_PB_LA_PTR",
659         "GENERIC_RELOC_LOCAL_SECTDIFF",
660         "GENERIC_RELOC_TLV" };
661 
662       if (RType > 5)
663         res = "Unknown";
664       else
665         res = Table[RType];
666       break;
667     }
668     case Triple::x86_64: {
669       static const char *const Table[] =  {
670         "X86_64_RELOC_UNSIGNED",
671         "X86_64_RELOC_SIGNED",
672         "X86_64_RELOC_BRANCH",
673         "X86_64_RELOC_GOT_LOAD",
674         "X86_64_RELOC_GOT",
675         "X86_64_RELOC_SUBTRACTOR",
676         "X86_64_RELOC_SIGNED_1",
677         "X86_64_RELOC_SIGNED_2",
678         "X86_64_RELOC_SIGNED_4",
679         "X86_64_RELOC_TLV" };
680 
681       if (RType > 9)
682         res = "Unknown";
683       else
684         res = Table[RType];
685       break;
686     }
687     case Triple::arm: {
688       static const char *const Table[] =  {
689         "ARM_RELOC_VANILLA",
690         "ARM_RELOC_PAIR",
691         "ARM_RELOC_SECTDIFF",
692         "ARM_RELOC_LOCAL_SECTDIFF",
693         "ARM_RELOC_PB_LA_PTR",
694         "ARM_RELOC_BR24",
695         "ARM_THUMB_RELOC_BR22",
696         "ARM_THUMB_32BIT_BRANCH",
697         "ARM_RELOC_HALF",
698         "ARM_RELOC_HALF_SECTDIFF" };
699 
700       if (RType > 9)
701         res = "Unknown";
702       else
703         res = Table[RType];
704       break;
705     }
706     case Triple::aarch64: {
707       static const char *const Table[] = {
708         "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
709         "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
710         "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
711         "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
712         "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
713         "ARM64_RELOC_ADDEND"
714       };
715 
716       if (RType >= array_lengthof(Table))
717         res = "Unknown";
718       else
719         res = Table[RType];
720       break;
721     }
722     case Triple::ppc: {
723       static const char *const Table[] =  {
724         "PPC_RELOC_VANILLA",
725         "PPC_RELOC_PAIR",
726         "PPC_RELOC_BR14",
727         "PPC_RELOC_BR24",
728         "PPC_RELOC_HI16",
729         "PPC_RELOC_LO16",
730         "PPC_RELOC_HA16",
731         "PPC_RELOC_LO14",
732         "PPC_RELOC_SECTDIFF",
733         "PPC_RELOC_PB_LA_PTR",
734         "PPC_RELOC_HI16_SECTDIFF",
735         "PPC_RELOC_LO16_SECTDIFF",
736         "PPC_RELOC_HA16_SECTDIFF",
737         "PPC_RELOC_JBSR",
738         "PPC_RELOC_LO14_SECTDIFF",
739         "PPC_RELOC_LOCAL_SECTDIFF" };
740 
741       if (RType > 15)
742         res = "Unknown";
743       else
744         res = Table[RType];
745       break;
746     }
747     case Triple::UnknownArch:
748       res = "Unknown";
749       break;
750   }
751   Result.append(res.begin(), res.end());
752 }
753 
getRelocationLength(DataRefImpl Rel) const754 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
755   MachO::any_relocation_info RE = getRelocation(Rel);
756   return getAnyRelocationLength(RE);
757 }
758 
759 //
760 // guessLibraryShortName() is passed a name of a dynamic library and returns a
761 // guess on what the short name is.  Then name is returned as a substring of the
762 // StringRef Name passed in.  The name of the dynamic library is recognized as
763 // a framework if it has one of the two following forms:
764 //      Foo.framework/Versions/A/Foo
765 //      Foo.framework/Foo
766 // Where A and Foo can be any string.  And may contain a trailing suffix
767 // starting with an underbar.  If the Name is recognized as a framework then
768 // isFramework is set to true else it is set to false.  If the Name has a
769 // suffix then Suffix is set to the substring in Name that contains the suffix
770 // else it is set to a NULL StringRef.
771 //
772 // The Name of the dynamic library is recognized as a library name if it has
773 // one of the two following forms:
774 //      libFoo.A.dylib
775 //      libFoo.dylib
776 // The library may have a suffix trailing the name Foo of the form:
777 //      libFoo_profile.A.dylib
778 //      libFoo_profile.dylib
779 //
780 // The Name of the dynamic library is also recognized as a library name if it
781 // has the following form:
782 //      Foo.qtx
783 //
784 // If the Name of the dynamic library is none of the forms above then a NULL
785 // StringRef is returned.
786 //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)787 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
788                                                  bool &isFramework,
789                                                  StringRef &Suffix) {
790   StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
791   size_t a, b, c, d, Idx;
792 
793   isFramework = false;
794   Suffix = StringRef();
795 
796   // Pull off the last component and make Foo point to it
797   a = Name.rfind('/');
798   if (a == Name.npos || a == 0)
799     goto guess_library;
800   Foo = Name.slice(a+1, Name.npos);
801 
802   // Look for a suffix starting with a '_'
803   Idx = Foo.rfind('_');
804   if (Idx != Foo.npos && Foo.size() >= 2) {
805     Suffix = Foo.slice(Idx, Foo.npos);
806     Foo = Foo.slice(0, Idx);
807   }
808 
809   // First look for the form Foo.framework/Foo
810   b = Name.rfind('/', a);
811   if (b == Name.npos)
812     Idx = 0;
813   else
814     Idx = b+1;
815   F = Name.slice(Idx, Idx + Foo.size());
816   DotFramework = Name.slice(Idx + Foo.size(),
817                             Idx + Foo.size() + sizeof(".framework/")-1);
818   if (F == Foo && DotFramework == ".framework/") {
819     isFramework = true;
820     return Foo;
821   }
822 
823   // Next look for the form Foo.framework/Versions/A/Foo
824   if (b == Name.npos)
825     goto guess_library;
826   c =  Name.rfind('/', b);
827   if (c == Name.npos || c == 0)
828     goto guess_library;
829   V = Name.slice(c+1, Name.npos);
830   if (!V.startswith("Versions/"))
831     goto guess_library;
832   d =  Name.rfind('/', c);
833   if (d == Name.npos)
834     Idx = 0;
835   else
836     Idx = d+1;
837   F = Name.slice(Idx, Idx + Foo.size());
838   DotFramework = Name.slice(Idx + Foo.size(),
839                             Idx + Foo.size() + sizeof(".framework/")-1);
840   if (F == Foo && DotFramework == ".framework/") {
841     isFramework = true;
842     return Foo;
843   }
844 
845 guess_library:
846   // pull off the suffix after the "." and make a point to it
847   a = Name.rfind('.');
848   if (a == Name.npos || a == 0)
849     return StringRef();
850   Dylib = Name.slice(a, Name.npos);
851   if (Dylib != ".dylib")
852     goto guess_qtx;
853 
854   // First pull off the version letter for the form Foo.A.dylib if any.
855   if (a >= 3) {
856     Dot = Name.slice(a-2, a-1);
857     if (Dot == ".")
858       a = a - 2;
859   }
860 
861   b = Name.rfind('/', a);
862   if (b == Name.npos)
863     b = 0;
864   else
865     b = b+1;
866   // ignore any suffix after an underbar like Foo_profile.A.dylib
867   Idx = Name.find('_', b);
868   if (Idx != Name.npos && Idx != b) {
869     Lib = Name.slice(b, Idx);
870     Suffix = Name.slice(Idx, a);
871   }
872   else
873     Lib = Name.slice(b, a);
874   // There are incorrect library names of the form:
875   // libATS.A_profile.dylib so check for these.
876   if (Lib.size() >= 3) {
877     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
878     if (Dot == ".")
879       Lib = Lib.slice(0, Lib.size()-2);
880   }
881   return Lib;
882 
883 guess_qtx:
884   Qtx = Name.slice(a, Name.npos);
885   if (Qtx != ".qtx")
886     return StringRef();
887   b = Name.rfind('/', a);
888   if (b == Name.npos)
889     Lib = Name.slice(0, a);
890   else
891     Lib = Name.slice(b+1, a);
892   // There are library names of the form: QT.A.qtx so check for these.
893   if (Lib.size() >= 3) {
894     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
895     if (Dot == ".")
896       Lib = Lib.slice(0, Lib.size()-2);
897   }
898   return Lib;
899 }
900 
901 // getLibraryShortNameByIndex() is used to get the short name of the library
902 // for an undefined symbol in a linked Mach-O binary that was linked with the
903 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
904 // It is passed the index (0 - based) of the library as translated from
905 // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const906 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
907                                                          StringRef &Res) const {
908   if (Index >= Libraries.size())
909     return object_error::parse_failed;
910 
911   // If the cache of LibrariesShortNames is not built up do that first for
912   // all the Libraries.
913   if (LibrariesShortNames.size() == 0) {
914     for (unsigned i = 0; i < Libraries.size(); i++) {
915       MachO::dylib_command D =
916         getStruct<MachO::dylib_command>(this, Libraries[i]);
917       if (D.dylib.name >= D.cmdsize)
918         return object_error::parse_failed;
919       const char *P = (const char *)(Libraries[i]) + D.dylib.name;
920       StringRef Name = StringRef(P);
921       if (D.dylib.name+Name.size() >= D.cmdsize)
922         return object_error::parse_failed;
923       StringRef Suffix;
924       bool isFramework;
925       StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
926       if (shortName.empty())
927         LibrariesShortNames.push_back(Name);
928       else
929         LibrariesShortNames.push_back(shortName);
930     }
931   }
932 
933   Res = LibrariesShortNames[Index];
934   return std::error_code();
935 }
936 
937 section_iterator
getRelocationRelocatedSection(relocation_iterator Rel) const938 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
939   DataRefImpl Sec;
940   Sec.d.a = Rel->getRawDataRefImpl().d.a;
941   return section_iterator(SectionRef(Sec, this));
942 }
943 
symbol_begin_impl() const944 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
945   return getSymbolByIndex(0);
946 }
947 
symbol_end_impl() const948 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
949   DataRefImpl DRI;
950   if (!SymtabLoadCmd)
951     return basic_symbol_iterator(SymbolRef(DRI, this));
952 
953   MachO::symtab_command Symtab = getSymtabLoadCommand();
954   unsigned SymbolTableEntrySize = is64Bit() ?
955     sizeof(MachO::nlist_64) :
956     sizeof(MachO::nlist);
957   unsigned Offset = Symtab.symoff +
958     Symtab.nsyms * SymbolTableEntrySize;
959   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
960   return basic_symbol_iterator(SymbolRef(DRI, this));
961 }
962 
getSymbolByIndex(unsigned Index) const963 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
964   DataRefImpl DRI;
965   if (!SymtabLoadCmd)
966     return basic_symbol_iterator(SymbolRef(DRI, this));
967 
968   MachO::symtab_command Symtab = getSymtabLoadCommand();
969   if (Index >= Symtab.nsyms)
970     report_fatal_error("Requested symbol index is out of range.");
971   unsigned SymbolTableEntrySize =
972     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
973   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
974   DRI.p += Index * SymbolTableEntrySize;
975   return basic_symbol_iterator(SymbolRef(DRI, this));
976 }
977 
section_begin() const978 section_iterator MachOObjectFile::section_begin() const {
979   DataRefImpl DRI;
980   return section_iterator(SectionRef(DRI, this));
981 }
982 
section_end() const983 section_iterator MachOObjectFile::section_end() const {
984   DataRefImpl DRI;
985   DRI.d.a = Sections.size();
986   return section_iterator(SectionRef(DRI, this));
987 }
988 
getBytesInAddress() const989 uint8_t MachOObjectFile::getBytesInAddress() const {
990   return is64Bit() ? 8 : 4;
991 }
992 
getFileFormatName() const993 StringRef MachOObjectFile::getFileFormatName() const {
994   unsigned CPUType = getCPUType(this);
995   if (!is64Bit()) {
996     switch (CPUType) {
997     case llvm::MachO::CPU_TYPE_I386:
998       return "Mach-O 32-bit i386";
999     case llvm::MachO::CPU_TYPE_ARM:
1000       return "Mach-O arm";
1001     case llvm::MachO::CPU_TYPE_POWERPC:
1002       return "Mach-O 32-bit ppc";
1003     default:
1004       return "Mach-O 32-bit unknown";
1005     }
1006   }
1007 
1008   switch (CPUType) {
1009   case llvm::MachO::CPU_TYPE_X86_64:
1010     return "Mach-O 64-bit x86-64";
1011   case llvm::MachO::CPU_TYPE_ARM64:
1012     return "Mach-O arm64";
1013   case llvm::MachO::CPU_TYPE_POWERPC64:
1014     return "Mach-O 64-bit ppc64";
1015   default:
1016     return "Mach-O 64-bit unknown";
1017   }
1018 }
1019 
getArch(uint32_t CPUType)1020 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1021   switch (CPUType) {
1022   case llvm::MachO::CPU_TYPE_I386:
1023     return Triple::x86;
1024   case llvm::MachO::CPU_TYPE_X86_64:
1025     return Triple::x86_64;
1026   case llvm::MachO::CPU_TYPE_ARM:
1027     return Triple::arm;
1028   case llvm::MachO::CPU_TYPE_ARM64:
1029     return Triple::aarch64;
1030   case llvm::MachO::CPU_TYPE_POWERPC:
1031     return Triple::ppc;
1032   case llvm::MachO::CPU_TYPE_POWERPC64:
1033     return Triple::ppc64;
1034   default:
1035     return Triple::UnknownArch;
1036   }
1037 }
1038 
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1039 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1040                                 const char **McpuDefault) {
1041   if (McpuDefault)
1042     *McpuDefault = nullptr;
1043 
1044   switch (CPUType) {
1045   case MachO::CPU_TYPE_I386:
1046     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1047     case MachO::CPU_SUBTYPE_I386_ALL:
1048       return Triple("i386-apple-darwin");
1049     default:
1050       return Triple();
1051     }
1052   case MachO::CPU_TYPE_X86_64:
1053     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1054     case MachO::CPU_SUBTYPE_X86_64_ALL:
1055       return Triple("x86_64-apple-darwin");
1056     case MachO::CPU_SUBTYPE_X86_64_H:
1057       return Triple("x86_64h-apple-darwin");
1058     default:
1059       return Triple();
1060     }
1061   case MachO::CPU_TYPE_ARM:
1062     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1063     case MachO::CPU_SUBTYPE_ARM_V4T:
1064       return Triple("armv4t-apple-darwin");
1065     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1066       return Triple("armv5e-apple-darwin");
1067     case MachO::CPU_SUBTYPE_ARM_XSCALE:
1068       return Triple("xscale-apple-darwin");
1069     case MachO::CPU_SUBTYPE_ARM_V6:
1070       return Triple("armv6-apple-darwin");
1071     case MachO::CPU_SUBTYPE_ARM_V6M:
1072       if (McpuDefault)
1073         *McpuDefault = "cortex-m0";
1074       return Triple("armv6m-apple-darwin");
1075     case MachO::CPU_SUBTYPE_ARM_V7:
1076       return Triple("armv7-apple-darwin");
1077     case MachO::CPU_SUBTYPE_ARM_V7EM:
1078       if (McpuDefault)
1079         *McpuDefault = "cortex-m4";
1080       return Triple("armv7em-apple-darwin");
1081     case MachO::CPU_SUBTYPE_ARM_V7K:
1082       return Triple("armv7k-apple-darwin");
1083     case MachO::CPU_SUBTYPE_ARM_V7M:
1084       if (McpuDefault)
1085         *McpuDefault = "cortex-m3";
1086       return Triple("armv7m-apple-darwin");
1087     case MachO::CPU_SUBTYPE_ARM_V7S:
1088       return Triple("armv7s-apple-darwin");
1089     default:
1090       return Triple();
1091     }
1092   case MachO::CPU_TYPE_ARM64:
1093     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1094     case MachO::CPU_SUBTYPE_ARM64_ALL:
1095       return Triple("arm64-apple-darwin");
1096     default:
1097       return Triple();
1098     }
1099   case MachO::CPU_TYPE_POWERPC:
1100     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1101     case MachO::CPU_SUBTYPE_POWERPC_ALL:
1102       return Triple("ppc-apple-darwin");
1103     default:
1104       return Triple();
1105     }
1106   case MachO::CPU_TYPE_POWERPC64:
1107     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1108     case MachO::CPU_SUBTYPE_POWERPC_ALL:
1109       return Triple("ppc64-apple-darwin");
1110     default:
1111       return Triple();
1112     }
1113   default:
1114     return Triple();
1115   }
1116 }
1117 
getThumbArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1118 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1119                                      const char **McpuDefault) {
1120   if (McpuDefault)
1121     *McpuDefault = nullptr;
1122 
1123   switch (CPUType) {
1124   case MachO::CPU_TYPE_ARM:
1125     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1126     case MachO::CPU_SUBTYPE_ARM_V4T:
1127       return Triple("thumbv4t-apple-darwin");
1128     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1129       return Triple("thumbv5e-apple-darwin");
1130     case MachO::CPU_SUBTYPE_ARM_XSCALE:
1131       return Triple("xscale-apple-darwin");
1132     case MachO::CPU_SUBTYPE_ARM_V6:
1133       return Triple("thumbv6-apple-darwin");
1134     case MachO::CPU_SUBTYPE_ARM_V6M:
1135       if (McpuDefault)
1136         *McpuDefault = "cortex-m0";
1137       return Triple("thumbv6m-apple-darwin");
1138     case MachO::CPU_SUBTYPE_ARM_V7:
1139       return Triple("thumbv7-apple-darwin");
1140     case MachO::CPU_SUBTYPE_ARM_V7EM:
1141       if (McpuDefault)
1142         *McpuDefault = "cortex-m4";
1143       return Triple("thumbv7em-apple-darwin");
1144     case MachO::CPU_SUBTYPE_ARM_V7K:
1145       return Triple("thumbv7k-apple-darwin");
1146     case MachO::CPU_SUBTYPE_ARM_V7M:
1147       if (McpuDefault)
1148         *McpuDefault = "cortex-m3";
1149       return Triple("thumbv7m-apple-darwin");
1150     case MachO::CPU_SUBTYPE_ARM_V7S:
1151       return Triple("thumbv7s-apple-darwin");
1152     default:
1153       return Triple();
1154     }
1155   default:
1156     return Triple();
1157   }
1158 }
1159 
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,Triple * ThumbTriple)1160 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1161                                 const char **McpuDefault, Triple *ThumbTriple) {
1162   Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1163   *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1164                                                McpuDefault);
1165   return T;
1166 }
1167 
getHostArch()1168 Triple MachOObjectFile::getHostArch() {
1169   return Triple(sys::getDefaultTargetTriple());
1170 }
1171 
isValidArch(StringRef ArchFlag)1172 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1173   return StringSwitch<bool>(ArchFlag)
1174       .Case("i386", true)
1175       .Case("x86_64", true)
1176       .Case("x86_64h", true)
1177       .Case("armv4t", true)
1178       .Case("arm", true)
1179       .Case("armv5e", true)
1180       .Case("armv6", true)
1181       .Case("armv6m", true)
1182       .Case("armv7", true)
1183       .Case("armv7em", true)
1184       .Case("armv7k", true)
1185       .Case("armv7m", true)
1186       .Case("armv7s", true)
1187       .Case("arm64", true)
1188       .Case("ppc", true)
1189       .Case("ppc64", true)
1190       .Default(false);
1191 }
1192 
getArch() const1193 unsigned MachOObjectFile::getArch() const {
1194   return getArch(getCPUType(this));
1195 }
1196 
getArch(const char ** McpuDefault,Triple * ThumbTriple) const1197 Triple MachOObjectFile::getArch(const char **McpuDefault,
1198                                 Triple *ThumbTriple) const {
1199   *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1200   return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1201 }
1202 
section_rel_begin(unsigned Index) const1203 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1204   DataRefImpl DRI;
1205   DRI.d.a = Index;
1206   return section_rel_begin(DRI);
1207 }
1208 
section_rel_end(unsigned Index) const1209 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1210   DataRefImpl DRI;
1211   DRI.d.a = Index;
1212   return section_rel_end(DRI);
1213 }
1214 
begin_dices() const1215 dice_iterator MachOObjectFile::begin_dices() const {
1216   DataRefImpl DRI;
1217   if (!DataInCodeLoadCmd)
1218     return dice_iterator(DiceRef(DRI, this));
1219 
1220   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1221   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1222   return dice_iterator(DiceRef(DRI, this));
1223 }
1224 
end_dices() const1225 dice_iterator MachOObjectFile::end_dices() const {
1226   DataRefImpl DRI;
1227   if (!DataInCodeLoadCmd)
1228     return dice_iterator(DiceRef(DRI, this));
1229 
1230   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1231   unsigned Offset = DicLC.dataoff + DicLC.datasize;
1232   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1233   return dice_iterator(DiceRef(DRI, this));
1234 }
1235 
ExportEntry(ArrayRef<uint8_t> T)1236 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1237     : Trie(T), Malformed(false), Done(false) {}
1238 
moveToFirst()1239 void ExportEntry::moveToFirst() {
1240   pushNode(0);
1241   pushDownUntilBottom();
1242 }
1243 
moveToEnd()1244 void ExportEntry::moveToEnd() {
1245   Stack.clear();
1246   Done = true;
1247 }
1248 
operator ==(const ExportEntry & Other) const1249 bool ExportEntry::operator==(const ExportEntry &Other) const {
1250   // Common case, one at end, other iterating from begin.
1251   if (Done || Other.Done)
1252     return (Done == Other.Done);
1253   // Not equal if different stack sizes.
1254   if (Stack.size() != Other.Stack.size())
1255     return false;
1256   // Not equal if different cumulative strings.
1257   if (!CumulativeString.equals(Other.CumulativeString))
1258     return false;
1259   // Equal if all nodes in both stacks match.
1260   for (unsigned i=0; i < Stack.size(); ++i) {
1261     if (Stack[i].Start != Other.Stack[i].Start)
1262       return false;
1263   }
1264   return true;
1265 }
1266 
readULEB128(const uint8_t * & Ptr)1267 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1268   unsigned Count;
1269   uint64_t Result = decodeULEB128(Ptr, &Count);
1270   Ptr += Count;
1271   if (Ptr > Trie.end()) {
1272     Ptr = Trie.end();
1273     Malformed = true;
1274   }
1275   return Result;
1276 }
1277 
name() const1278 StringRef ExportEntry::name() const {
1279   return CumulativeString;
1280 }
1281 
flags() const1282 uint64_t ExportEntry::flags() const {
1283   return Stack.back().Flags;
1284 }
1285 
address() const1286 uint64_t ExportEntry::address() const {
1287   return Stack.back().Address;
1288 }
1289 
other() const1290 uint64_t ExportEntry::other() const {
1291   return Stack.back().Other;
1292 }
1293 
otherName() const1294 StringRef ExportEntry::otherName() const {
1295   const char* ImportName = Stack.back().ImportName;
1296   if (ImportName)
1297     return StringRef(ImportName);
1298   return StringRef();
1299 }
1300 
nodeOffset() const1301 uint32_t ExportEntry::nodeOffset() const {
1302   return Stack.back().Start - Trie.begin();
1303 }
1304 
NodeState(const uint8_t * Ptr)1305 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1306     : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1307       ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1308       ParentStringLength(0), IsExportNode(false) {}
1309 
pushNode(uint64_t offset)1310 void ExportEntry::pushNode(uint64_t offset) {
1311   const uint8_t *Ptr = Trie.begin() + offset;
1312   NodeState State(Ptr);
1313   uint64_t ExportInfoSize = readULEB128(State.Current);
1314   State.IsExportNode = (ExportInfoSize != 0);
1315   const uint8_t* Children = State.Current + ExportInfoSize;
1316   if (State.IsExportNode) {
1317     State.Flags = readULEB128(State.Current);
1318     if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1319       State.Address = 0;
1320       State.Other = readULEB128(State.Current); // dylib ordinal
1321       State.ImportName = reinterpret_cast<const char*>(State.Current);
1322     } else {
1323       State.Address = readULEB128(State.Current);
1324       if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1325         State.Other = readULEB128(State.Current);
1326     }
1327   }
1328   State.ChildCount = *Children;
1329   State.Current = Children + 1;
1330   State.NextChildIndex = 0;
1331   State.ParentStringLength = CumulativeString.size();
1332   Stack.push_back(State);
1333 }
1334 
pushDownUntilBottom()1335 void ExportEntry::pushDownUntilBottom() {
1336   while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1337     NodeState &Top = Stack.back();
1338     CumulativeString.resize(Top.ParentStringLength);
1339     for (;*Top.Current != 0; Top.Current++) {
1340       char C = *Top.Current;
1341       CumulativeString.push_back(C);
1342     }
1343     Top.Current += 1;
1344     uint64_t childNodeIndex = readULEB128(Top.Current);
1345     Top.NextChildIndex += 1;
1346     pushNode(childNodeIndex);
1347   }
1348   if (!Stack.back().IsExportNode) {
1349     Malformed = true;
1350     moveToEnd();
1351   }
1352 }
1353 
1354 // We have a trie data structure and need a way to walk it that is compatible
1355 // with the C++ iterator model. The solution is a non-recursive depth first
1356 // traversal where the iterator contains a stack of parent nodes along with a
1357 // string that is the accumulation of all edge strings along the parent chain
1358 // to this point.
1359 //
1360 // There is one "export" node for each exported symbol.  But because some
1361 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1362 // node may have child nodes too.
1363 //
1364 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1365 // child until hitting a node with no children (which is an export node or
1366 // else the trie is malformed). On the way down, each node is pushed on the
1367 // stack ivar.  If there is no more ways down, it pops up one and tries to go
1368 // down a sibling path until a childless node is reached.
moveNext()1369 void ExportEntry::moveNext() {
1370   if (Stack.empty() || !Stack.back().IsExportNode) {
1371     Malformed = true;
1372     moveToEnd();
1373     return;
1374   }
1375 
1376   Stack.pop_back();
1377   while (!Stack.empty()) {
1378     NodeState &Top = Stack.back();
1379     if (Top.NextChildIndex < Top.ChildCount) {
1380       pushDownUntilBottom();
1381       // Now at the next export node.
1382       return;
1383     } else {
1384       if (Top.IsExportNode) {
1385         // This node has no children but is itself an export node.
1386         CumulativeString.resize(Top.ParentStringLength);
1387         return;
1388       }
1389       Stack.pop_back();
1390     }
1391   }
1392   Done = true;
1393 }
1394 
1395 iterator_range<export_iterator>
exports(ArrayRef<uint8_t> Trie)1396 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1397   ExportEntry Start(Trie);
1398   if (Trie.size() == 0)
1399     Start.moveToEnd();
1400   else
1401     Start.moveToFirst();
1402 
1403   ExportEntry Finish(Trie);
1404   Finish.moveToEnd();
1405 
1406   return make_range(export_iterator(Start), export_iterator(Finish));
1407 }
1408 
exports() const1409 iterator_range<export_iterator> MachOObjectFile::exports() const {
1410   return exports(getDyldInfoExportsTrie());
1411 }
1412 
MachORebaseEntry(ArrayRef<uint8_t> Bytes,bool is64Bit)1413 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1414     : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1415       RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1416       PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1417 
moveToFirst()1418 void MachORebaseEntry::moveToFirst() {
1419   Ptr = Opcodes.begin();
1420   moveNext();
1421 }
1422 
moveToEnd()1423 void MachORebaseEntry::moveToEnd() {
1424   Ptr = Opcodes.end();
1425   RemainingLoopCount = 0;
1426   Done = true;
1427 }
1428 
moveNext()1429 void MachORebaseEntry::moveNext() {
1430   // If in the middle of some loop, move to next rebasing in loop.
1431   SegmentOffset += AdvanceAmount;
1432   if (RemainingLoopCount) {
1433     --RemainingLoopCount;
1434     return;
1435   }
1436   if (Ptr == Opcodes.end()) {
1437     Done = true;
1438     return;
1439   }
1440   bool More = true;
1441   while (More && !Malformed) {
1442     // Parse next opcode and set up next loop.
1443     uint8_t Byte = *Ptr++;
1444     uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1445     uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1446     switch (Opcode) {
1447     case MachO::REBASE_OPCODE_DONE:
1448       More = false;
1449       Done = true;
1450       moveToEnd();
1451       DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1452       break;
1453     case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1454       RebaseType = ImmValue;
1455       DEBUG_WITH_TYPE(
1456           "mach-o-rebase",
1457           llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1458                        << "RebaseType=" << (int) RebaseType << "\n");
1459       break;
1460     case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1461       SegmentIndex = ImmValue;
1462       SegmentOffset = readULEB128();
1463       DEBUG_WITH_TYPE(
1464           "mach-o-rebase",
1465           llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1466                        << "SegmentIndex=" << SegmentIndex << ", "
1467                        << format("SegmentOffset=0x%06X", SegmentOffset)
1468                        << "\n");
1469       break;
1470     case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1471       SegmentOffset += readULEB128();
1472       DEBUG_WITH_TYPE("mach-o-rebase",
1473                       llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1474                                    << format("SegmentOffset=0x%06X",
1475                                              SegmentOffset) << "\n");
1476       break;
1477     case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1478       SegmentOffset += ImmValue * PointerSize;
1479       DEBUG_WITH_TYPE("mach-o-rebase",
1480                       llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1481                                    << format("SegmentOffset=0x%06X",
1482                                              SegmentOffset) << "\n");
1483       break;
1484     case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1485       AdvanceAmount = PointerSize;
1486       RemainingLoopCount = ImmValue - 1;
1487       DEBUG_WITH_TYPE(
1488           "mach-o-rebase",
1489           llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1490                        << format("SegmentOffset=0x%06X", SegmentOffset)
1491                        << ", AdvanceAmount=" << AdvanceAmount
1492                        << ", RemainingLoopCount=" << RemainingLoopCount
1493                        << "\n");
1494       return;
1495     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1496       AdvanceAmount = PointerSize;
1497       RemainingLoopCount = readULEB128() - 1;
1498       DEBUG_WITH_TYPE(
1499           "mach-o-rebase",
1500           llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1501                        << format("SegmentOffset=0x%06X", SegmentOffset)
1502                        << ", AdvanceAmount=" << AdvanceAmount
1503                        << ", RemainingLoopCount=" << RemainingLoopCount
1504                        << "\n");
1505       return;
1506     case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1507       AdvanceAmount = readULEB128() + PointerSize;
1508       RemainingLoopCount = 0;
1509       DEBUG_WITH_TYPE(
1510           "mach-o-rebase",
1511           llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1512                        << format("SegmentOffset=0x%06X", SegmentOffset)
1513                        << ", AdvanceAmount=" << AdvanceAmount
1514                        << ", RemainingLoopCount=" << RemainingLoopCount
1515                        << "\n");
1516       return;
1517     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1518       RemainingLoopCount = readULEB128() - 1;
1519       AdvanceAmount = readULEB128() + PointerSize;
1520       DEBUG_WITH_TYPE(
1521           "mach-o-rebase",
1522           llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1523                        << format("SegmentOffset=0x%06X", SegmentOffset)
1524                        << ", AdvanceAmount=" << AdvanceAmount
1525                        << ", RemainingLoopCount=" << RemainingLoopCount
1526                        << "\n");
1527       return;
1528     default:
1529       Malformed = true;
1530     }
1531   }
1532 }
1533 
readULEB128()1534 uint64_t MachORebaseEntry::readULEB128() {
1535   unsigned Count;
1536   uint64_t Result = decodeULEB128(Ptr, &Count);
1537   Ptr += Count;
1538   if (Ptr > Opcodes.end()) {
1539     Ptr = Opcodes.end();
1540     Malformed = true;
1541   }
1542   return Result;
1543 }
1544 
segmentIndex() const1545 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1546 
segmentOffset() const1547 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1548 
typeName() const1549 StringRef MachORebaseEntry::typeName() const {
1550   switch (RebaseType) {
1551   case MachO::REBASE_TYPE_POINTER:
1552     return "pointer";
1553   case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1554     return "text abs32";
1555   case MachO::REBASE_TYPE_TEXT_PCREL32:
1556     return "text rel32";
1557   }
1558   return "unknown";
1559 }
1560 
operator ==(const MachORebaseEntry & Other) const1561 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1562   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1563   return (Ptr == Other.Ptr) &&
1564          (RemainingLoopCount == Other.RemainingLoopCount) &&
1565          (Done == Other.Done);
1566 }
1567 
1568 iterator_range<rebase_iterator>
rebaseTable(ArrayRef<uint8_t> Opcodes,bool is64)1569 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1570   MachORebaseEntry Start(Opcodes, is64);
1571   Start.moveToFirst();
1572 
1573   MachORebaseEntry Finish(Opcodes, is64);
1574   Finish.moveToEnd();
1575 
1576   return make_range(rebase_iterator(Start), rebase_iterator(Finish));
1577 }
1578 
rebaseTable() const1579 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1580   return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1581 }
1582 
MachOBindEntry(ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)1583 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
1584     : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1585       Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1586       BindType(0), PointerSize(is64Bit ? 8 : 4),
1587       TableKind(BK), Malformed(false), Done(false) {}
1588 
moveToFirst()1589 void MachOBindEntry::moveToFirst() {
1590   Ptr = Opcodes.begin();
1591   moveNext();
1592 }
1593 
moveToEnd()1594 void MachOBindEntry::moveToEnd() {
1595   Ptr = Opcodes.end();
1596   RemainingLoopCount = 0;
1597   Done = true;
1598 }
1599 
moveNext()1600 void MachOBindEntry::moveNext() {
1601   // If in the middle of some loop, move to next binding in loop.
1602   SegmentOffset += AdvanceAmount;
1603   if (RemainingLoopCount) {
1604     --RemainingLoopCount;
1605     return;
1606   }
1607   if (Ptr == Opcodes.end()) {
1608     Done = true;
1609     return;
1610   }
1611   bool More = true;
1612   while (More && !Malformed) {
1613     // Parse next opcode and set up next loop.
1614     uint8_t Byte = *Ptr++;
1615     uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1616     uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1617     int8_t SignExtended;
1618     const uint8_t *SymStart;
1619     switch (Opcode) {
1620     case MachO::BIND_OPCODE_DONE:
1621       if (TableKind == Kind::Lazy) {
1622         // Lazying bindings have a DONE opcode between entries.  Need to ignore
1623         // it to advance to next entry.  But need not if this is last entry.
1624         bool NotLastEntry = false;
1625         for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1626           if (*P) {
1627             NotLastEntry = true;
1628           }
1629         }
1630         if (NotLastEntry)
1631           break;
1632       }
1633       More = false;
1634       Done = true;
1635       moveToEnd();
1636       DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1637       break;
1638     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1639       Ordinal = ImmValue;
1640       DEBUG_WITH_TYPE(
1641           "mach-o-bind",
1642           llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1643                        << "Ordinal=" << Ordinal << "\n");
1644       break;
1645     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1646       Ordinal = readULEB128();
1647       DEBUG_WITH_TYPE(
1648           "mach-o-bind",
1649           llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1650                        << "Ordinal=" << Ordinal << "\n");
1651       break;
1652     case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1653       if (ImmValue) {
1654         SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1655         Ordinal = SignExtended;
1656       } else
1657         Ordinal = 0;
1658       DEBUG_WITH_TYPE(
1659           "mach-o-bind",
1660           llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1661                        << "Ordinal=" << Ordinal << "\n");
1662       break;
1663     case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1664       Flags = ImmValue;
1665       SymStart = Ptr;
1666       while (*Ptr) {
1667         ++Ptr;
1668       }
1669       SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1670                              Ptr-SymStart);
1671       ++Ptr;
1672       DEBUG_WITH_TYPE(
1673           "mach-o-bind",
1674           llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1675                        << "SymbolName=" << SymbolName << "\n");
1676       if (TableKind == Kind::Weak) {
1677         if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1678           return;
1679       }
1680       break;
1681     case MachO::BIND_OPCODE_SET_TYPE_IMM:
1682       BindType = ImmValue;
1683       DEBUG_WITH_TYPE(
1684           "mach-o-bind",
1685           llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1686                        << "BindType=" << (int)BindType << "\n");
1687       break;
1688     case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1689       Addend = readSLEB128();
1690       if (TableKind == Kind::Lazy)
1691         Malformed = true;
1692       DEBUG_WITH_TYPE(
1693           "mach-o-bind",
1694           llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1695                        << "Addend=" << Addend << "\n");
1696       break;
1697     case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1698       SegmentIndex = ImmValue;
1699       SegmentOffset = readULEB128();
1700       DEBUG_WITH_TYPE(
1701           "mach-o-bind",
1702           llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1703                        << "SegmentIndex=" << SegmentIndex << ", "
1704                        << format("SegmentOffset=0x%06X", SegmentOffset)
1705                        << "\n");
1706       break;
1707     case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1708       SegmentOffset += readULEB128();
1709       DEBUG_WITH_TYPE("mach-o-bind",
1710                       llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1711                                    << format("SegmentOffset=0x%06X",
1712                                              SegmentOffset) << "\n");
1713       break;
1714     case MachO::BIND_OPCODE_DO_BIND:
1715       AdvanceAmount = PointerSize;
1716       RemainingLoopCount = 0;
1717       DEBUG_WITH_TYPE("mach-o-bind",
1718                       llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1719                                    << format("SegmentOffset=0x%06X",
1720                                              SegmentOffset) << "\n");
1721       return;
1722      case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1723       AdvanceAmount = readULEB128() + PointerSize;
1724       RemainingLoopCount = 0;
1725       if (TableKind == Kind::Lazy)
1726         Malformed = true;
1727       DEBUG_WITH_TYPE(
1728           "mach-o-bind",
1729           llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1730                        << format("SegmentOffset=0x%06X", SegmentOffset)
1731                        << ", AdvanceAmount=" << AdvanceAmount
1732                        << ", RemainingLoopCount=" << RemainingLoopCount
1733                        << "\n");
1734       return;
1735     case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1736       AdvanceAmount = ImmValue * PointerSize + PointerSize;
1737       RemainingLoopCount = 0;
1738       if (TableKind == Kind::Lazy)
1739         Malformed = true;
1740       DEBUG_WITH_TYPE("mach-o-bind",
1741                       llvm::dbgs()
1742                       << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1743                       << format("SegmentOffset=0x%06X",
1744                                              SegmentOffset) << "\n");
1745       return;
1746     case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1747       RemainingLoopCount = readULEB128() - 1;
1748       AdvanceAmount = readULEB128() + PointerSize;
1749       if (TableKind == Kind::Lazy)
1750         Malformed = true;
1751       DEBUG_WITH_TYPE(
1752           "mach-o-bind",
1753           llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1754                        << format("SegmentOffset=0x%06X", SegmentOffset)
1755                        << ", AdvanceAmount=" << AdvanceAmount
1756                        << ", RemainingLoopCount=" << RemainingLoopCount
1757                        << "\n");
1758       return;
1759     default:
1760       Malformed = true;
1761     }
1762   }
1763 }
1764 
readULEB128()1765 uint64_t MachOBindEntry::readULEB128() {
1766   unsigned Count;
1767   uint64_t Result = decodeULEB128(Ptr, &Count);
1768   Ptr += Count;
1769   if (Ptr > Opcodes.end()) {
1770     Ptr = Opcodes.end();
1771     Malformed = true;
1772   }
1773   return Result;
1774 }
1775 
readSLEB128()1776 int64_t MachOBindEntry::readSLEB128() {
1777   unsigned Count;
1778   int64_t Result = decodeSLEB128(Ptr, &Count);
1779   Ptr += Count;
1780   if (Ptr > Opcodes.end()) {
1781     Ptr = Opcodes.end();
1782     Malformed = true;
1783   }
1784   return Result;
1785 }
1786 
segmentIndex() const1787 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1788 
segmentOffset() const1789 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1790 
typeName() const1791 StringRef MachOBindEntry::typeName() const {
1792   switch (BindType) {
1793   case MachO::BIND_TYPE_POINTER:
1794     return "pointer";
1795   case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1796     return "text abs32";
1797   case MachO::BIND_TYPE_TEXT_PCREL32:
1798     return "text rel32";
1799   }
1800   return "unknown";
1801 }
1802 
symbolName() const1803 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1804 
addend() const1805 int64_t MachOBindEntry::addend() const { return Addend; }
1806 
flags() const1807 uint32_t MachOBindEntry::flags() const { return Flags; }
1808 
ordinal() const1809 int MachOBindEntry::ordinal() const { return Ordinal; }
1810 
operator ==(const MachOBindEntry & Other) const1811 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1812   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1813   return (Ptr == Other.Ptr) &&
1814          (RemainingLoopCount == Other.RemainingLoopCount) &&
1815          (Done == Other.Done);
1816 }
1817 
1818 iterator_range<bind_iterator>
bindTable(ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)1819 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1820                            MachOBindEntry::Kind BKind) {
1821   MachOBindEntry Start(Opcodes, is64, BKind);
1822   Start.moveToFirst();
1823 
1824   MachOBindEntry Finish(Opcodes, is64, BKind);
1825   Finish.moveToEnd();
1826 
1827   return make_range(bind_iterator(Start), bind_iterator(Finish));
1828 }
1829 
bindTable() const1830 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1831   return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1832                    MachOBindEntry::Kind::Regular);
1833 }
1834 
lazyBindTable() const1835 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1836   return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1837                    MachOBindEntry::Kind::Lazy);
1838 }
1839 
weakBindTable() const1840 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1841   return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1842                    MachOBindEntry::Kind::Weak);
1843 }
1844 
1845 MachOObjectFile::load_command_iterator
begin_load_commands() const1846 MachOObjectFile::begin_load_commands() const {
1847   return LoadCommands.begin();
1848 }
1849 
1850 MachOObjectFile::load_command_iterator
end_load_commands() const1851 MachOObjectFile::end_load_commands() const {
1852   return LoadCommands.end();
1853 }
1854 
1855 iterator_range<MachOObjectFile::load_command_iterator>
load_commands() const1856 MachOObjectFile::load_commands() const {
1857   return make_range(begin_load_commands(), end_load_commands());
1858 }
1859 
1860 StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const1861 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1862   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1863   return parseSegmentOrSectionName(Raw.data());
1864 }
1865 
1866 ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const1867 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1868   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1869   const section_base *Base =
1870     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1871   return makeArrayRef(Base->sectname);
1872 }
1873 
1874 ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const1875 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1876   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1877   const section_base *Base =
1878     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1879   return makeArrayRef(Base->segname);
1880 }
1881 
1882 bool
isRelocationScattered(const MachO::any_relocation_info & RE) const1883 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1884   const {
1885   if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1886     return false;
1887   return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1888 }
1889 
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const1890 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1891     const MachO::any_relocation_info &RE) const {
1892   if (isLittleEndian())
1893     return RE.r_word1 & 0xffffff;
1894   return RE.r_word1 >> 8;
1895 }
1896 
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const1897 bool MachOObjectFile::getPlainRelocationExternal(
1898     const MachO::any_relocation_info &RE) const {
1899   if (isLittleEndian())
1900     return (RE.r_word1 >> 27) & 1;
1901   return (RE.r_word1 >> 4) & 1;
1902 }
1903 
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const1904 bool MachOObjectFile::getScatteredRelocationScattered(
1905     const MachO::any_relocation_info &RE) const {
1906   return RE.r_word0 >> 31;
1907 }
1908 
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const1909 uint32_t MachOObjectFile::getScatteredRelocationValue(
1910     const MachO::any_relocation_info &RE) const {
1911   return RE.r_word1;
1912 }
1913 
getScatteredRelocationType(const MachO::any_relocation_info & RE) const1914 uint32_t MachOObjectFile::getScatteredRelocationType(
1915     const MachO::any_relocation_info &RE) const {
1916   return (RE.r_word0 >> 24) & 0xf;
1917 }
1918 
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const1919 unsigned MachOObjectFile::getAnyRelocationAddress(
1920     const MachO::any_relocation_info &RE) const {
1921   if (isRelocationScattered(RE))
1922     return getScatteredRelocationAddress(RE);
1923   return getPlainRelocationAddress(RE);
1924 }
1925 
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const1926 unsigned MachOObjectFile::getAnyRelocationPCRel(
1927     const MachO::any_relocation_info &RE) const {
1928   if (isRelocationScattered(RE))
1929     return getScatteredRelocationPCRel(this, RE);
1930   return getPlainRelocationPCRel(this, RE);
1931 }
1932 
getAnyRelocationLength(const MachO::any_relocation_info & RE) const1933 unsigned MachOObjectFile::getAnyRelocationLength(
1934     const MachO::any_relocation_info &RE) const {
1935   if (isRelocationScattered(RE))
1936     return getScatteredRelocationLength(RE);
1937   return getPlainRelocationLength(this, RE);
1938 }
1939 
1940 unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const1941 MachOObjectFile::getAnyRelocationType(
1942                                    const MachO::any_relocation_info &RE) const {
1943   if (isRelocationScattered(RE))
1944     return getScatteredRelocationType(RE);
1945   return getPlainRelocationType(this, RE);
1946 }
1947 
1948 SectionRef
getAnyRelocationSection(const MachO::any_relocation_info & RE) const1949 MachOObjectFile::getAnyRelocationSection(
1950                                    const MachO::any_relocation_info &RE) const {
1951   if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1952     return *section_end();
1953   unsigned SecNum = getPlainRelocationSymbolNum(RE);
1954   if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1955     return *section_end();
1956   DataRefImpl DRI;
1957   DRI.d.a = SecNum - 1;
1958   return SectionRef(DRI, this);
1959 }
1960 
getSection(DataRefImpl DRI) const1961 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1962   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1963   return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1964 }
1965 
getSection64(DataRefImpl DRI) const1966 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1967   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1968   return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1969 }
1970 
getSection(const LoadCommandInfo & L,unsigned Index) const1971 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1972                                            unsigned Index) const {
1973   const char *Sec = getSectionPtr(this, L, Index);
1974   return getStruct<MachO::section>(this, Sec);
1975 }
1976 
getSection64(const LoadCommandInfo & L,unsigned Index) const1977 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1978                                                 unsigned Index) const {
1979   const char *Sec = getSectionPtr(this, L, Index);
1980   return getStruct<MachO::section_64>(this, Sec);
1981 }
1982 
1983 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const1984 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1985   const char *P = reinterpret_cast<const char *>(DRI.p);
1986   return getStruct<MachO::nlist>(this, P);
1987 }
1988 
1989 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const1990 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1991   const char *P = reinterpret_cast<const char *>(DRI.p);
1992   return getStruct<MachO::nlist_64>(this, P);
1993 }
1994 
1995 MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const1996 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1997   return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1998 }
1999 
2000 MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const2001 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2002   return getStruct<MachO::segment_command>(this, L.Ptr);
2003 }
2004 
2005 MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const2006 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2007   return getStruct<MachO::segment_command_64>(this, L.Ptr);
2008 }
2009 
2010 MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const2011 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2012   return getStruct<MachO::linker_option_command>(this, L.Ptr);
2013 }
2014 
2015 MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const2016 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2017   return getStruct<MachO::version_min_command>(this, L.Ptr);
2018 }
2019 
2020 MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const2021 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2022   return getStruct<MachO::dylib_command>(this, L.Ptr);
2023 }
2024 
2025 MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const2026 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2027   return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2028 }
2029 
2030 MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const2031 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2032   return getStruct<MachO::dylinker_command>(this, L.Ptr);
2033 }
2034 
2035 MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const2036 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2037   return getStruct<MachO::uuid_command>(this, L.Ptr);
2038 }
2039 
2040 MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const2041 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2042   return getStruct<MachO::rpath_command>(this, L.Ptr);
2043 }
2044 
2045 MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const2046 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2047   return getStruct<MachO::source_version_command>(this, L.Ptr);
2048 }
2049 
2050 MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const2051 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2052   return getStruct<MachO::entry_point_command>(this, L.Ptr);
2053 }
2054 
2055 MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const2056 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2057   return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2058 }
2059 
2060 MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const2061 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2062   return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2063 }
2064 
2065 MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const2066 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2067   return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2068 }
2069 
2070 MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const2071 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2072   return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2073 }
2074 
2075 MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const2076 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2077   return getStruct<MachO::sub_library_command>(this, L.Ptr);
2078 }
2079 
2080 MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const2081 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2082   return getStruct<MachO::sub_client_command>(this, L.Ptr);
2083 }
2084 
2085 MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const2086 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2087   return getStruct<MachO::routines_command>(this, L.Ptr);
2088 }
2089 
2090 MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const2091 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2092   return getStruct<MachO::routines_command_64>(this, L.Ptr);
2093 }
2094 
2095 MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const2096 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2097   return getStruct<MachO::thread_command>(this, L.Ptr);
2098 }
2099 
2100 MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const2101 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2102   DataRefImpl Sec;
2103   Sec.d.a = Rel.d.a;
2104   uint32_t Offset;
2105   if (is64Bit()) {
2106     MachO::section_64 Sect = getSection64(Sec);
2107     Offset = Sect.reloff;
2108   } else {
2109     MachO::section Sect = getSection(Sec);
2110     Offset = Sect.reloff;
2111   }
2112 
2113   auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2114       getPtr(this, Offset)) + Rel.d.b;
2115   return getStruct<MachO::any_relocation_info>(
2116       this, reinterpret_cast<const char *>(P));
2117 }
2118 
2119 MachO::data_in_code_entry
getDice(DataRefImpl Rel) const2120 MachOObjectFile::getDice(DataRefImpl Rel) const {
2121   const char *P = reinterpret_cast<const char *>(Rel.p);
2122   return getStruct<MachO::data_in_code_entry>(this, P);
2123 }
2124 
getHeader() const2125 const MachO::mach_header &MachOObjectFile::getHeader() const {
2126   return Header;
2127 }
2128 
getHeader64() const2129 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2130   assert(is64Bit());
2131   return Header64;
2132 }
2133 
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const2134 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2135                                              const MachO::dysymtab_command &DLC,
2136                                              unsigned Index) const {
2137   uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2138   return getStruct<uint32_t>(this, getPtr(this, Offset));
2139 }
2140 
2141 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const2142 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2143                                          unsigned Index) const {
2144   uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2145   return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2146 }
2147 
getSymtabLoadCommand() const2148 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2149   if (SymtabLoadCmd)
2150     return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2151 
2152   // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2153   MachO::symtab_command Cmd;
2154   Cmd.cmd = MachO::LC_SYMTAB;
2155   Cmd.cmdsize = sizeof(MachO::symtab_command);
2156   Cmd.symoff = 0;
2157   Cmd.nsyms = 0;
2158   Cmd.stroff = 0;
2159   Cmd.strsize = 0;
2160   return Cmd;
2161 }
2162 
getDysymtabLoadCommand() const2163 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2164   if (DysymtabLoadCmd)
2165     return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2166 
2167   // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2168   MachO::dysymtab_command Cmd;
2169   Cmd.cmd = MachO::LC_DYSYMTAB;
2170   Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2171   Cmd.ilocalsym = 0;
2172   Cmd.nlocalsym = 0;
2173   Cmd.iextdefsym = 0;
2174   Cmd.nextdefsym = 0;
2175   Cmd.iundefsym = 0;
2176   Cmd.nundefsym = 0;
2177   Cmd.tocoff = 0;
2178   Cmd.ntoc = 0;
2179   Cmd.modtaboff = 0;
2180   Cmd.nmodtab = 0;
2181   Cmd.extrefsymoff = 0;
2182   Cmd.nextrefsyms = 0;
2183   Cmd.indirectsymoff = 0;
2184   Cmd.nindirectsyms = 0;
2185   Cmd.extreloff = 0;
2186   Cmd.nextrel = 0;
2187   Cmd.locreloff = 0;
2188   Cmd.nlocrel = 0;
2189   return Cmd;
2190 }
2191 
2192 MachO::linkedit_data_command
getDataInCodeLoadCommand() const2193 MachOObjectFile::getDataInCodeLoadCommand() const {
2194   if (DataInCodeLoadCmd)
2195     return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2196 
2197   // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2198   MachO::linkedit_data_command Cmd;
2199   Cmd.cmd = MachO::LC_DATA_IN_CODE;
2200   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2201   Cmd.dataoff = 0;
2202   Cmd.datasize = 0;
2203   return Cmd;
2204 }
2205 
2206 MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const2207 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2208   if (LinkOptHintsLoadCmd)
2209     return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2210 
2211   // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2212   // fields.
2213   MachO::linkedit_data_command Cmd;
2214   Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2215   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2216   Cmd.dataoff = 0;
2217   Cmd.datasize = 0;
2218   return Cmd;
2219 }
2220 
getDyldInfoRebaseOpcodes() const2221 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2222   if (!DyldInfoLoadCmd)
2223     return None;
2224 
2225   MachO::dyld_info_command DyldInfo =
2226       getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2227   const uint8_t *Ptr =
2228       reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
2229   return makeArrayRef(Ptr, DyldInfo.rebase_size);
2230 }
2231 
getDyldInfoBindOpcodes() const2232 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2233   if (!DyldInfoLoadCmd)
2234     return None;
2235 
2236   MachO::dyld_info_command DyldInfo =
2237       getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2238   const uint8_t *Ptr =
2239       reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
2240   return makeArrayRef(Ptr, DyldInfo.bind_size);
2241 }
2242 
getDyldInfoWeakBindOpcodes() const2243 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2244   if (!DyldInfoLoadCmd)
2245     return None;
2246 
2247   MachO::dyld_info_command DyldInfo =
2248       getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2249   const uint8_t *Ptr =
2250       reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
2251   return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
2252 }
2253 
getDyldInfoLazyBindOpcodes() const2254 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2255   if (!DyldInfoLoadCmd)
2256     return None;
2257 
2258   MachO::dyld_info_command DyldInfo =
2259       getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2260   const uint8_t *Ptr =
2261       reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
2262   return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
2263 }
2264 
getDyldInfoExportsTrie() const2265 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2266   if (!DyldInfoLoadCmd)
2267     return None;
2268 
2269   MachO::dyld_info_command DyldInfo =
2270       getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2271   const uint8_t *Ptr =
2272       reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
2273   return makeArrayRef(Ptr, DyldInfo.export_size);
2274 }
2275 
getUuid() const2276 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2277   if (!UuidLoadCmd)
2278     return None;
2279   // Returning a pointer is fine as uuid doesn't need endian swapping.
2280   const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2281   return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
2282 }
2283 
getStringTableData() const2284 StringRef MachOObjectFile::getStringTableData() const {
2285   MachO::symtab_command S = getSymtabLoadCommand();
2286   return getData().substr(S.stroff, S.strsize);
2287 }
2288 
is64Bit() const2289 bool MachOObjectFile::is64Bit() const {
2290   return getType() == getMachOType(false, true) ||
2291     getType() == getMachOType(true, true);
2292 }
2293 
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const2294 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2295                                    SmallVectorImpl<uint64_t> &Out) const {
2296   DataExtractor extractor(ObjectFile::getData(), true, 0);
2297 
2298   uint32_t offset = Index;
2299   uint64_t data = 0;
2300   while (uint64_t delta = extractor.getULEB128(&offset)) {
2301     data += delta;
2302     Out.push_back(data);
2303   }
2304 }
2305 
isRelocatableObject() const2306 bool MachOObjectFile::isRelocatableObject() const {
2307   return getHeader().filetype == MachO::MH_OBJECT;
2308 }
2309 
2310 ErrorOr<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer)2311 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2312   StringRef Magic = Buffer.getBuffer().slice(0, 4);
2313   std::error_code EC;
2314   std::unique_ptr<MachOObjectFile> Ret;
2315   if (Magic == "\xFE\xED\xFA\xCE")
2316     Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2317   else if (Magic == "\xCE\xFA\xED\xFE")
2318     Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2319   else if (Magic == "\xFE\xED\xFA\xCF")
2320     Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2321   else if (Magic == "\xCF\xFA\xED\xFE")
2322     Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2323   else
2324     return object_error::parse_failed;
2325 
2326   if (EC)
2327     return EC;
2328   return std::move(Ret);
2329 }
2330