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