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 template <typename T>
getStruct(const MachOObjectFile * O,const char * P)42 static T getStruct(const MachOObjectFile *O, const char *P) {
43   // Don't read before the beginning or past the end of the file
44   if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
45     report_fatal_error("Malformed MachO file.");
46 
47   T Cmd;
48   memcpy(&Cmd, P, sizeof(T));
49   if (O->isLittleEndian() != sys::IsLittleEndianHost)
50     MachO::swapStruct(Cmd);
51   return Cmd;
52 }
53 
54 template <typename SegmentCmd>
getSegmentLoadCommandNumSections(const SegmentCmd & S,uint32_t Cmdsize)55 static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
56                                                  uint32_t Cmdsize) {
57   const unsigned SectionSize = sizeof(SegmentCmd);
58   if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
59       S.nsects * SectionSize > Cmdsize - sizeof(S))
60     report_fatal_error(
61         "Number of sections too large for size of load command.");
62   return S.nsects;
63 }
64 
65 static uint32_t
getSegmentLoadCommandNumSections(const MachOObjectFile * O,const MachOObjectFile::LoadCommandInfo & L)66 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
67                                  const MachOObjectFile::LoadCommandInfo &L) {
68   if (O->is64Bit())
69     return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
70                                             L.C.cmdsize);
71 
72   return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
73                                           L.C.cmdsize);
74 }
75 
isPageZeroSegment(const MachOObjectFile * O,const MachOObjectFile::LoadCommandInfo & L)76 static bool isPageZeroSegment(const MachOObjectFile *O,
77                               const MachOObjectFile::LoadCommandInfo &L) {
78   if (O->is64Bit()) {
79     MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
80     return StringRef("__PAGEZERO").equals(S.segname);
81   }
82   MachO::segment_command S = O->getSegmentLoadCommand(L);
83   return StringRef("__PAGEZERO").equals(S.segname);
84 }
85 
86 
87 static const char *
getSectionPtr(const MachOObjectFile * O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)88 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
89               unsigned Sec) {
90   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
91 
92   bool Is64 = O->is64Bit();
93   unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
94                                     sizeof(MachO::segment_command);
95   unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
96                                 sizeof(MachO::section);
97 
98   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
99   return reinterpret_cast<const char*>(SectionAddr);
100 }
101 
getPtr(const MachOObjectFile * O,size_t Offset)102 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
103   return O->getData().substr(Offset, 1).data();
104 }
105 
106 static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile * O,DataRefImpl DRI)107 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
108   const char *P = reinterpret_cast<const char *>(DRI.p);
109   return getStruct<MachO::nlist_base>(O, P);
110 }
111 
parseSegmentOrSectionName(const char * P)112 static StringRef parseSegmentOrSectionName(const char *P) {
113   if (P[15] == 0)
114     // Null terminated.
115     return P;
116   // Not null terminated, so this is a 16 char string.
117   return StringRef(P, 16);
118 }
119 
120 // Helper to advance a section or symbol iterator multiple increments at a time.
121 template<class T>
advance(T & it,size_t Val)122 static void advance(T &it, size_t Val) {
123   while (Val--)
124     ++it;
125 }
126 
getCPUType(const MachOObjectFile * O)127 static unsigned getCPUType(const MachOObjectFile *O) {
128   return O->getHeader().cputype;
129 }
130 
printRelocationTargetName(const MachOObjectFile * O,const MachO::any_relocation_info & RE,raw_string_ostream & fmt)131 static void printRelocationTargetName(const MachOObjectFile *O,
132                                       const MachO::any_relocation_info &RE,
133                                       raw_string_ostream &fmt) {
134   bool IsScattered = O->isRelocationScattered(RE);
135 
136   // Target of a scattered relocation is an address.  In the interest of
137   // generating pretty output, scan through the symbol table looking for a
138   // symbol that aligns with that address.  If we find one, print it.
139   // Otherwise, we just print the hex address of the target.
140   if (IsScattered) {
141     uint32_t Val = O->getPlainRelocationSymbolNum(RE);
142 
143     for (const SymbolRef &Symbol : O->symbols()) {
144       std::error_code ec;
145       uint64_t Addr;
146       StringRef Name;
147 
148       if ((ec = Symbol.getAddress(Addr)))
149         report_fatal_error(ec.message());
150       if (Addr != Val)
151         continue;
152       if ((ec = Symbol.getName(Name)))
153         report_fatal_error(ec.message());
154       fmt << Name;
155       return;
156     }
157 
158     // If we couldn't find a symbol that this relocation refers to, try
159     // to find a section beginning instead.
160     for (const SectionRef &Section : O->sections()) {
161       std::error_code ec;
162 
163       StringRef Name;
164       uint64_t Addr = Section.getAddress();
165       if (Addr != Val)
166         continue;
167       if ((ec = Section.getName(Name)))
168         report_fatal_error(ec.message());
169       fmt << Name;
170       return;
171     }
172 
173     fmt << format("0x%x", Val);
174     return;
175   }
176 
177   StringRef S;
178   bool isExtern = O->getPlainRelocationExternal(RE);
179   uint64_t Val = O->getPlainRelocationSymbolNum(RE);
180 
181   if (isExtern) {
182     symbol_iterator SI = O->symbol_begin();
183     advance(SI, Val);
184     SI->getName(S);
185   } else {
186     section_iterator SI = O->section_begin();
187     // Adjust for the fact that sections are 1-indexed.
188     advance(SI, Val - 1);
189     SI->getName(S);
190   }
191 
192   fmt << S;
193 }
194 
195 static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)196 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
197   return RE.r_word0;
198 }
199 
200 static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)201 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
202   return RE.r_word0 & 0xffffff;
203 }
204 
getPlainRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)205 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
206                                     const MachO::any_relocation_info &RE) {
207   if (O->isLittleEndian())
208     return (RE.r_word1 >> 24) & 1;
209   return (RE.r_word1 >> 7) & 1;
210 }
211 
212 static bool
getScatteredRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)213 getScatteredRelocationPCRel(const MachOObjectFile *O,
214                             const MachO::any_relocation_info &RE) {
215   return (RE.r_word0 >> 30) & 1;
216 }
217 
getPlainRelocationLength(const MachOObjectFile * O,const MachO::any_relocation_info & RE)218 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
219                                          const MachO::any_relocation_info &RE) {
220   if (O->isLittleEndian())
221     return (RE.r_word1 >> 25) & 3;
222   return (RE.r_word1 >> 5) & 3;
223 }
224 
225 static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)226 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
227   return (RE.r_word0 >> 28) & 3;
228 }
229 
getPlainRelocationType(const MachOObjectFile * O,const MachO::any_relocation_info & RE)230 static unsigned getPlainRelocationType(const MachOObjectFile *O,
231                                        const MachO::any_relocation_info &RE) {
232   if (O->isLittleEndian())
233     return RE.r_word1 >> 28;
234   return RE.r_word1 & 0xf;
235 }
236 
getSectionFlags(const MachOObjectFile * O,DataRefImpl Sec)237 static uint32_t getSectionFlags(const MachOObjectFile *O,
238                                 DataRefImpl Sec) {
239   if (O->is64Bit()) {
240     MachO::section_64 Sect = O->getSection64(Sec);
241     return Sect.flags;
242   }
243   MachO::section Sect = O->getSection(Sec);
244   return Sect.flags;
245 }
246 
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,std::error_code & EC)247 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
248                                  bool Is64bits, std::error_code &EC)
249     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
250       SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
251       DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
252       DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
253       HasPageZeroSegment(false) {
254   uint32_t LoadCommandCount = this->getHeader().ncmds;
255   if (LoadCommandCount == 0)
256     return;
257 
258   MachO::LoadCommandType SegmentLoadType = is64Bit() ?
259     MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
260 
261   MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
262   for (unsigned I = 0; ; ++I) {
263     if (Load.C.cmd == MachO::LC_SYMTAB) {
264       // Multiple symbol tables
265       if (SymtabLoadCmd) {
266         EC = object_error::parse_failed;
267         return;
268       }
269       SymtabLoadCmd = Load.Ptr;
270     } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
271       // Multiple dynamic symbol tables
272       if (DysymtabLoadCmd) {
273         EC = object_error::parse_failed;
274         return;
275       }
276       DysymtabLoadCmd = Load.Ptr;
277     } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
278       // Multiple data in code tables
279       if (DataInCodeLoadCmd) {
280         EC = object_error::parse_failed;
281         return;
282       }
283       DataInCodeLoadCmd = Load.Ptr;
284     } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
285       // Multiple linker optimization hint tables
286       if (LinkOptHintsLoadCmd) {
287         EC = object_error::parse_failed;
288         return;
289       }
290       LinkOptHintsLoadCmd = Load.Ptr;
291     } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
292                Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
293       // Multiple dyldinfo load commands
294       if (DyldInfoLoadCmd) {
295         EC = object_error::parse_failed;
296         return;
297       }
298       DyldInfoLoadCmd = Load.Ptr;
299     } else if (Load.C.cmd == MachO::LC_UUID) {
300       // Multiple UUID load commands
301       if (UuidLoadCmd) {
302         EC = object_error::parse_failed;
303         return;
304       }
305       UuidLoadCmd = Load.Ptr;
306     } else if (Load.C.cmd == SegmentLoadType) {
307       const unsigned SegmentLoadSize = this->is64Bit()
308                                            ? sizeof(MachO::segment_command_64)
309                                            : sizeof(MachO::segment_command);
310       if (Load.C.cmdsize < SegmentLoadSize)
311         report_fatal_error("Segment load command size is too small.");
312 
313       uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
314       for (unsigned J = 0; J < NumSections; ++J) {
315         const char *Sec = getSectionPtr(this, Load, J);
316         Sections.push_back(Sec);
317       }
318       if (isPageZeroSegment(this, Load))
319         HasPageZeroSegment = true;
320     } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
321                Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
322                Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
323                Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
324                Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
325       Libraries.push_back(Load.Ptr);
326     }
327 
328     if (I == LoadCommandCount - 1)
329       break;
330     else
331       Load = getNextLoadCommandInfo(Load);
332   }
333 }
334 
moveSymbolNext(DataRefImpl & Symb) const335 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
336   unsigned SymbolTableEntrySize = is64Bit() ?
337     sizeof(MachO::nlist_64) :
338     sizeof(MachO::nlist);
339   Symb.p += SymbolTableEntrySize;
340 }
341 
getSymbolName(DataRefImpl Symb,StringRef & Res) const342 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
343                                                StringRef &Res) const {
344   StringRef StringTable = getStringTableData();
345   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
346   const char *Start = &StringTable.data()[Entry.n_strx];
347   if (Start < getData().begin() || Start >= getData().end())
348     report_fatal_error(
349         "Symbol name entry points before beginning or past end of file.");
350   Res = StringRef(Start);
351   return object_error::success;
352 }
353 
getSectionType(SectionRef Sec) const354 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
355   DataRefImpl DRI = Sec.getRawDataRefImpl();
356   uint32_t Flags = getSectionFlags(this, DRI);
357   return Flags & MachO::SECTION_TYPE;
358 }
359 
360 // getIndirectName() returns the name of the alias'ed symbol who's string table
361 // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const362 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
363                                                  StringRef &Res) const {
364   StringRef StringTable = getStringTableData();
365   uint64_t NValue;
366   if (is64Bit()) {
367     MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
368     NValue = Entry.n_value;
369     if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
370       return object_error::parse_failed;
371   } else {
372     MachO::nlist Entry = getSymbolTableEntry(Symb);
373     NValue = Entry.n_value;
374     if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
375       return object_error::parse_failed;
376   }
377   if (NValue >= StringTable.size())
378     return object_error::parse_failed;
379   const char *Start = &StringTable.data()[NValue];
380   Res = StringRef(Start);
381   return object_error::success;
382 }
383 
getSymbolAddress(DataRefImpl Symb,uint64_t & Res) const384 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
385                                                   uint64_t &Res) const {
386   if (is64Bit()) {
387     MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
388     if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
389         Entry.n_value == 0)
390       Res = UnknownAddressOrSize;
391     else
392       Res = Entry.n_value;
393   } else {
394     MachO::nlist Entry = getSymbolTableEntry(Symb);
395     if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
396         Entry.n_value == 0)
397       Res = UnknownAddressOrSize;
398     else
399       Res = Entry.n_value;
400   }
401   return object_error::success;
402 }
403 
getSymbolAlignment(DataRefImpl DRI,uint32_t & Result) const404 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
405                                                     uint32_t &Result) const {
406   uint32_t flags = getSymbolFlags(DRI);
407   if (flags & SymbolRef::SF_Common) {
408     MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
409     Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
410   } else {
411     Result = 0;
412   }
413   return object_error::success;
414 }
415 
getSymbolSize(DataRefImpl DRI,uint64_t & Result) const416 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
417                                                uint64_t &Result) const {
418   uint64_t BeginOffset;
419   uint64_t EndOffset = 0;
420   uint8_t SectionIndex;
421 
422   MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
423   uint64_t Value;
424   getSymbolAddress(DRI, Value);
425   if (Value == UnknownAddressOrSize) {
426     Result = UnknownAddressOrSize;
427     return object_error::success;
428   }
429 
430   BeginOffset = Value;
431 
432   SectionIndex = Entry.n_sect;
433   if (!SectionIndex) {
434     uint32_t flags = getSymbolFlags(DRI);
435     if (flags & SymbolRef::SF_Common)
436       Result = Value;
437     else
438       Result = UnknownAddressOrSize;
439     return object_error::success;
440   }
441   // Unfortunately symbols are unsorted so we need to touch all
442   // symbols from load command
443   for (const SymbolRef &Symbol : symbols()) {
444     DataRefImpl DRI = Symbol.getRawDataRefImpl();
445     Entry = getSymbolTableEntryBase(this, DRI);
446     getSymbolAddress(DRI, Value);
447     if (Value == UnknownAddressOrSize)
448       continue;
449     if (Entry.n_sect == SectionIndex && Value > BeginOffset)
450       if (!EndOffset || Value < EndOffset)
451         EndOffset = Value;
452   }
453   if (!EndOffset) {
454     DataRefImpl Sec;
455     Sec.d.a = SectionIndex-1;
456     uint64_t Size = getSectionSize(Sec);
457     EndOffset = getSectionAddress(Sec);
458     EndOffset += Size;
459   }
460   Result = EndOffset - BeginOffset;
461   return object_error::success;
462 }
463 
getSymbolType(DataRefImpl Symb,SymbolRef::Type & Res) const464 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
465                                                SymbolRef::Type &Res) const {
466   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
467   uint8_t n_type = Entry.n_type;
468 
469   Res = SymbolRef::ST_Other;
470 
471   // If this is a STAB debugging symbol, we can do nothing more.
472   if (n_type & MachO::N_STAB) {
473     Res = SymbolRef::ST_Debug;
474     return object_error::success;
475   }
476 
477   switch (n_type & MachO::N_TYPE) {
478     case MachO::N_UNDF :
479       Res = SymbolRef::ST_Unknown;
480       break;
481     case MachO::N_SECT :
482       Res = SymbolRef::ST_Function;
483       break;
484   }
485   return object_error::success;
486 }
487 
getSymbolFlags(DataRefImpl DRI) const488 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
489   MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
490 
491   uint8_t MachOType = Entry.n_type;
492   uint16_t MachOFlags = Entry.n_desc;
493 
494   uint32_t Result = SymbolRef::SF_None;
495 
496   if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
497     Result |= SymbolRef::SF_Undefined;
498 
499   if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
500     Result |= SymbolRef::SF_Indirect;
501 
502   if (MachOType & MachO::N_STAB)
503     Result |= SymbolRef::SF_FormatSpecific;
504 
505   if (MachOType & MachO::N_EXT) {
506     Result |= SymbolRef::SF_Global;
507     if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
508       uint64_t Value;
509       getSymbolAddress(DRI, Value);
510       if (Value && Value != UnknownAddressOrSize)
511         Result |= SymbolRef::SF_Common;
512     }
513 
514     if (!(MachOType & MachO::N_PEXT))
515       Result |= SymbolRef::SF_Exported;
516   }
517 
518   if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
519     Result |= SymbolRef::SF_Weak;
520 
521   if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
522     Result |= SymbolRef::SF_Thumb;
523 
524   if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
525     Result |= SymbolRef::SF_Absolute;
526 
527   return Result;
528 }
529 
getSymbolSection(DataRefImpl Symb,section_iterator & Res) const530 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
531                                                   section_iterator &Res) const {
532   MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
533   uint8_t index = Entry.n_sect;
534 
535   if (index == 0) {
536     Res = section_end();
537   } else {
538     DataRefImpl DRI;
539     DRI.d.a = index - 1;
540     Res = section_iterator(SectionRef(DRI, this));
541   }
542 
543   return object_error::success;
544 }
545 
moveSectionNext(DataRefImpl & Sec) const546 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
547   Sec.d.a++;
548 }
549 
getSectionName(DataRefImpl Sec,StringRef & Result) const550 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
551                                                 StringRef &Result) const {
552   ArrayRef<char> Raw = getSectionRawName(Sec);
553   Result = parseSegmentOrSectionName(Raw.data());
554   return object_error::success;
555 }
556 
getSectionAddress(DataRefImpl Sec) const557 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
558   if (is64Bit())
559     return getSection64(Sec).addr;
560   return getSection(Sec).addr;
561 }
562 
getSectionSize(DataRefImpl Sec) const563 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
564   if (is64Bit())
565     return getSection64(Sec).size;
566   return getSection(Sec).size;
567 }
568 
getSectionContents(DataRefImpl Sec,StringRef & Res) const569 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
570                                                     StringRef &Res) const {
571   uint32_t Offset;
572   uint64_t Size;
573 
574   if (is64Bit()) {
575     MachO::section_64 Sect = getSection64(Sec);
576     Offset = Sect.offset;
577     Size = Sect.size;
578   } else {
579     MachO::section Sect = getSection(Sec);
580     Offset = Sect.offset;
581     Size = Sect.size;
582   }
583 
584   Res = this->getData().substr(Offset, Size);
585   return object_error::success;
586 }
587 
getSectionAlignment(DataRefImpl Sec) const588 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
589   uint32_t Align;
590   if (is64Bit()) {
591     MachO::section_64 Sect = getSection64(Sec);
592     Align = Sect.align;
593   } else {
594     MachO::section Sect = getSection(Sec);
595     Align = Sect.align;
596   }
597 
598   return uint64_t(1) << Align;
599 }
600 
isSectionText(DataRefImpl Sec) const601 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
602   uint32_t Flags = getSectionFlags(this, Sec);
603   return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
604 }
605 
isSectionData(DataRefImpl Sec) const606 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
607   uint32_t Flags = getSectionFlags(this, Sec);
608   unsigned SectionType = Flags & MachO::SECTION_TYPE;
609   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
610          !(SectionType == MachO::S_ZEROFILL ||
611            SectionType == MachO::S_GB_ZEROFILL);
612 }
613 
isSectionBSS(DataRefImpl Sec) const614 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
615   uint32_t Flags = getSectionFlags(this, Sec);
616   unsigned SectionType = Flags & MachO::SECTION_TYPE;
617   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
618          (SectionType == MachO::S_ZEROFILL ||
619           SectionType == MachO::S_GB_ZEROFILL);
620 }
621 
isSectionVirtual(DataRefImpl Sec) const622 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
623   // FIXME: Unimplemented.
624   return false;
625 }
626 
sectionContainsSymbol(DataRefImpl Sec,DataRefImpl Symb) const627 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
628                                             DataRefImpl Symb) const {
629   SymbolRef::Type ST;
630   this->getSymbolType(Symb, ST);
631   if (ST == SymbolRef::ST_Unknown)
632     return false;
633 
634   uint64_t SectBegin = getSectionAddress(Sec);
635   uint64_t SectEnd = getSectionSize(Sec);
636   SectEnd += SectBegin;
637 
638   uint64_t SymAddr;
639   getSymbolAddress(Symb, SymAddr);
640   return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
641 }
642 
section_rel_begin(DataRefImpl Sec) const643 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
644   DataRefImpl Ret;
645   Ret.d.a = Sec.d.a;
646   Ret.d.b = 0;
647   return relocation_iterator(RelocationRef(Ret, this));
648 }
649 
650 relocation_iterator
section_rel_end(DataRefImpl Sec) const651 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
652   uint32_t Num;
653   if (is64Bit()) {
654     MachO::section_64 Sect = getSection64(Sec);
655     Num = Sect.nreloc;
656   } else {
657     MachO::section Sect = getSection(Sec);
658     Num = Sect.nreloc;
659   }
660 
661   DataRefImpl Ret;
662   Ret.d.a = Sec.d.a;
663   Ret.d.b = Num;
664   return relocation_iterator(RelocationRef(Ret, this));
665 }
666 
moveRelocationNext(DataRefImpl & Rel) const667 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
668   ++Rel.d.b;
669 }
670 
getRelocationAddress(DataRefImpl Rel,uint64_t & Res) const671 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
672                                                       uint64_t &Res) const {
673   uint64_t Offset;
674   getRelocationOffset(Rel, Offset);
675 
676   DataRefImpl Sec;
677   Sec.d.a = Rel.d.a;
678   uint64_t SecAddress = getSectionAddress(Sec);
679   Res = SecAddress + Offset;
680   return object_error::success;
681 }
682 
getRelocationOffset(DataRefImpl Rel,uint64_t & Res) const683 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
684                                                      uint64_t &Res) const {
685   assert(getHeader().filetype == MachO::MH_OBJECT &&
686          "Only implemented for MH_OBJECT");
687   MachO::any_relocation_info RE = getRelocation(Rel);
688   Res = getAnyRelocationAddress(RE);
689   return object_error::success;
690 }
691 
692 symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const693 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
694   MachO::any_relocation_info RE = getRelocation(Rel);
695   if (isRelocationScattered(RE))
696     return symbol_end();
697 
698   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
699   bool isExtern = getPlainRelocationExternal(RE);
700   if (!isExtern)
701     return symbol_end();
702 
703   MachO::symtab_command S = getSymtabLoadCommand();
704   unsigned SymbolTableEntrySize = is64Bit() ?
705     sizeof(MachO::nlist_64) :
706     sizeof(MachO::nlist);
707   uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
708   DataRefImpl Sym;
709   Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
710   return symbol_iterator(SymbolRef(Sym, this));
711 }
712 
getRelocationType(DataRefImpl Rel,uint64_t & Res) const713 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
714                                                    uint64_t &Res) const {
715   MachO::any_relocation_info RE = getRelocation(Rel);
716   Res = getAnyRelocationType(RE);
717   return object_error::success;
718 }
719 
720 std::error_code
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const721 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
722                                        SmallVectorImpl<char> &Result) const {
723   StringRef res;
724   uint64_t RType;
725   getRelocationType(Rel, RType);
726 
727   unsigned Arch = this->getArch();
728 
729   switch (Arch) {
730     case Triple::x86: {
731       static const char *const Table[] =  {
732         "GENERIC_RELOC_VANILLA",
733         "GENERIC_RELOC_PAIR",
734         "GENERIC_RELOC_SECTDIFF",
735         "GENERIC_RELOC_PB_LA_PTR",
736         "GENERIC_RELOC_LOCAL_SECTDIFF",
737         "GENERIC_RELOC_TLV" };
738 
739       if (RType > 5)
740         res = "Unknown";
741       else
742         res = Table[RType];
743       break;
744     }
745     case Triple::x86_64: {
746       static const char *const Table[] =  {
747         "X86_64_RELOC_UNSIGNED",
748         "X86_64_RELOC_SIGNED",
749         "X86_64_RELOC_BRANCH",
750         "X86_64_RELOC_GOT_LOAD",
751         "X86_64_RELOC_GOT",
752         "X86_64_RELOC_SUBTRACTOR",
753         "X86_64_RELOC_SIGNED_1",
754         "X86_64_RELOC_SIGNED_2",
755         "X86_64_RELOC_SIGNED_4",
756         "X86_64_RELOC_TLV" };
757 
758       if (RType > 9)
759         res = "Unknown";
760       else
761         res = Table[RType];
762       break;
763     }
764     case Triple::arm: {
765       static const char *const Table[] =  {
766         "ARM_RELOC_VANILLA",
767         "ARM_RELOC_PAIR",
768         "ARM_RELOC_SECTDIFF",
769         "ARM_RELOC_LOCAL_SECTDIFF",
770         "ARM_RELOC_PB_LA_PTR",
771         "ARM_RELOC_BR24",
772         "ARM_THUMB_RELOC_BR22",
773         "ARM_THUMB_32BIT_BRANCH",
774         "ARM_RELOC_HALF",
775         "ARM_RELOC_HALF_SECTDIFF" };
776 
777       if (RType > 9)
778         res = "Unknown";
779       else
780         res = Table[RType];
781       break;
782     }
783     case Triple::aarch64: {
784       static const char *const Table[] = {
785         "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
786         "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
787         "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
788         "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
789         "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
790         "ARM64_RELOC_ADDEND"
791       };
792 
793       if (RType >= array_lengthof(Table))
794         res = "Unknown";
795       else
796         res = Table[RType];
797       break;
798     }
799     case Triple::ppc: {
800       static const char *const Table[] =  {
801         "PPC_RELOC_VANILLA",
802         "PPC_RELOC_PAIR",
803         "PPC_RELOC_BR14",
804         "PPC_RELOC_BR24",
805         "PPC_RELOC_HI16",
806         "PPC_RELOC_LO16",
807         "PPC_RELOC_HA16",
808         "PPC_RELOC_LO14",
809         "PPC_RELOC_SECTDIFF",
810         "PPC_RELOC_PB_LA_PTR",
811         "PPC_RELOC_HI16_SECTDIFF",
812         "PPC_RELOC_LO16_SECTDIFF",
813         "PPC_RELOC_HA16_SECTDIFF",
814         "PPC_RELOC_JBSR",
815         "PPC_RELOC_LO14_SECTDIFF",
816         "PPC_RELOC_LOCAL_SECTDIFF" };
817 
818       if (RType > 15)
819         res = "Unknown";
820       else
821         res = Table[RType];
822       break;
823     }
824     case Triple::UnknownArch:
825       res = "Unknown";
826       break;
827   }
828   Result.append(res.begin(), res.end());
829   return object_error::success;
830 }
831 
832 std::error_code
getRelocationValueString(DataRefImpl Rel,SmallVectorImpl<char> & Result) const833 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
834                                           SmallVectorImpl<char> &Result) const {
835   MachO::any_relocation_info RE = getRelocation(Rel);
836 
837   unsigned Arch = this->getArch();
838 
839   std::string fmtbuf;
840   raw_string_ostream fmt(fmtbuf);
841   unsigned Type = this->getAnyRelocationType(RE);
842   bool IsPCRel = this->getAnyRelocationPCRel(RE);
843 
844   // Determine any addends that should be displayed with the relocation.
845   // These require decoding the relocation type, which is triple-specific.
846 
847   // X86_64 has entirely custom relocation types.
848   if (Arch == Triple::x86_64) {
849     bool isPCRel = getAnyRelocationPCRel(RE);
850 
851     switch (Type) {
852       case MachO::X86_64_RELOC_GOT_LOAD:
853       case MachO::X86_64_RELOC_GOT: {
854         printRelocationTargetName(this, RE, fmt);
855         fmt << "@GOT";
856         if (isPCRel) fmt << "PCREL";
857         break;
858       }
859       case MachO::X86_64_RELOC_SUBTRACTOR: {
860         DataRefImpl RelNext = Rel;
861         moveRelocationNext(RelNext);
862         MachO::any_relocation_info RENext = getRelocation(RelNext);
863 
864         // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
865         // X86_64_RELOC_UNSIGNED.
866         // NOTE: Scattered relocations don't exist on x86_64.
867         unsigned RType = getAnyRelocationType(RENext);
868         if (RType != MachO::X86_64_RELOC_UNSIGNED)
869           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
870                              "X86_64_RELOC_SUBTRACTOR.");
871 
872         // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
873         // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
874         printRelocationTargetName(this, RENext, fmt);
875         fmt << "-";
876         printRelocationTargetName(this, RE, fmt);
877         break;
878       }
879       case MachO::X86_64_RELOC_TLV:
880         printRelocationTargetName(this, RE, fmt);
881         fmt << "@TLV";
882         if (isPCRel) fmt << "P";
883         break;
884       case MachO::X86_64_RELOC_SIGNED_1:
885         printRelocationTargetName(this, RE, fmt);
886         fmt << "-1";
887         break;
888       case MachO::X86_64_RELOC_SIGNED_2:
889         printRelocationTargetName(this, RE, fmt);
890         fmt << "-2";
891         break;
892       case MachO::X86_64_RELOC_SIGNED_4:
893         printRelocationTargetName(this, RE, fmt);
894         fmt << "-4";
895         break;
896       default:
897         printRelocationTargetName(this, RE, fmt);
898         break;
899     }
900   // X86 and ARM share some relocation types in common.
901   } else if (Arch == Triple::x86 || Arch == Triple::arm ||
902              Arch == Triple::ppc) {
903     // Generic relocation types...
904     switch (Type) {
905       case MachO::GENERIC_RELOC_PAIR: // prints no info
906         return object_error::success;
907       case MachO::GENERIC_RELOC_SECTDIFF: {
908         DataRefImpl RelNext = Rel;
909         moveRelocationNext(RelNext);
910         MachO::any_relocation_info RENext = getRelocation(RelNext);
911 
912         // X86 sect diff's must be followed by a relocation of type
913         // GENERIC_RELOC_PAIR.
914         unsigned RType = getAnyRelocationType(RENext);
915 
916         if (RType != MachO::GENERIC_RELOC_PAIR)
917           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
918                              "GENERIC_RELOC_SECTDIFF.");
919 
920         printRelocationTargetName(this, RE, fmt);
921         fmt << "-";
922         printRelocationTargetName(this, RENext, fmt);
923         break;
924       }
925     }
926 
927     if (Arch == Triple::x86 || Arch == Triple::ppc) {
928       switch (Type) {
929         case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
930           DataRefImpl RelNext = Rel;
931           moveRelocationNext(RelNext);
932           MachO::any_relocation_info RENext = getRelocation(RelNext);
933 
934           // X86 sect diff's must be followed by a relocation of type
935           // GENERIC_RELOC_PAIR.
936           unsigned RType = getAnyRelocationType(RENext);
937           if (RType != MachO::GENERIC_RELOC_PAIR)
938             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
939                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
940 
941           printRelocationTargetName(this, RE, fmt);
942           fmt << "-";
943           printRelocationTargetName(this, RENext, fmt);
944           break;
945         }
946         case MachO::GENERIC_RELOC_TLV: {
947           printRelocationTargetName(this, RE, fmt);
948           fmt << "@TLV";
949           if (IsPCRel) fmt << "P";
950           break;
951         }
952         default:
953           printRelocationTargetName(this, RE, fmt);
954       }
955     } else { // ARM-specific relocations
956       switch (Type) {
957         case MachO::ARM_RELOC_HALF:
958         case MachO::ARM_RELOC_HALF_SECTDIFF: {
959           // Half relocations steal a bit from the length field to encode
960           // whether this is an upper16 or a lower16 relocation.
961           bool isUpper = getAnyRelocationLength(RE) >> 1;
962 
963           if (isUpper)
964             fmt << ":upper16:(";
965           else
966             fmt << ":lower16:(";
967           printRelocationTargetName(this, RE, fmt);
968 
969           DataRefImpl RelNext = Rel;
970           moveRelocationNext(RelNext);
971           MachO::any_relocation_info RENext = getRelocation(RelNext);
972 
973           // ARM half relocs must be followed by a relocation of type
974           // ARM_RELOC_PAIR.
975           unsigned RType = getAnyRelocationType(RENext);
976           if (RType != MachO::ARM_RELOC_PAIR)
977             report_fatal_error("Expected ARM_RELOC_PAIR after "
978                                "ARM_RELOC_HALF");
979 
980           // NOTE: The half of the target virtual address is stashed in the
981           // address field of the secondary relocation, but we can't reverse
982           // engineer the constant offset from it without decoding the movw/movt
983           // instruction to find the other half in its immediate field.
984 
985           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
986           // symbol/section pointer of the follow-on relocation.
987           if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
988             fmt << "-";
989             printRelocationTargetName(this, RENext, fmt);
990           }
991 
992           fmt << ")";
993           break;
994         }
995         default: {
996           printRelocationTargetName(this, RE, fmt);
997         }
998       }
999     }
1000   } else
1001     printRelocationTargetName(this, RE, fmt);
1002 
1003   fmt.flush();
1004   Result.append(fmtbuf.begin(), fmtbuf.end());
1005   return object_error::success;
1006 }
1007 
getRelocationHidden(DataRefImpl Rel,bool & Result) const1008 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1009                                                      bool &Result) const {
1010   unsigned Arch = getArch();
1011   uint64_t Type;
1012   getRelocationType(Rel, Type);
1013 
1014   Result = false;
1015 
1016   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1017   // is always hidden.
1018   if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
1019     if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
1020   } else if (Arch == Triple::x86_64) {
1021     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1022     // an X86_64_RELOC_SUBTRACTOR.
1023     if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1024       DataRefImpl RelPrev = Rel;
1025       RelPrev.d.a--;
1026       uint64_t PrevType;
1027       getRelocationType(RelPrev, PrevType);
1028       if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1029         Result = true;
1030     }
1031   }
1032 
1033   return object_error::success;
1034 }
1035 
1036 //
1037 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1038 // guess on what the short name is.  Then name is returned as a substring of the
1039 // StringRef Name passed in.  The name of the dynamic library is recognized as
1040 // a framework if it has one of the two following forms:
1041 //      Foo.framework/Versions/A/Foo
1042 //      Foo.framework/Foo
1043 // Where A and Foo can be any string.  And may contain a trailing suffix
1044 // starting with an underbar.  If the Name is recognized as a framework then
1045 // isFramework is set to true else it is set to false.  If the Name has a
1046 // suffix then Suffix is set to the substring in Name that contains the suffix
1047 // else it is set to a NULL StringRef.
1048 //
1049 // The Name of the dynamic library is recognized as a library name if it has
1050 // one of the two following forms:
1051 //      libFoo.A.dylib
1052 //      libFoo.dylib
1053 // The library may have a suffix trailing the name Foo of the form:
1054 //      libFoo_profile.A.dylib
1055 //      libFoo_profile.dylib
1056 //
1057 // The Name of the dynamic library is also recognized as a library name if it
1058 // has the following form:
1059 //      Foo.qtx
1060 //
1061 // If the Name of the dynamic library is none of the forms above then a NULL
1062 // StringRef is returned.
1063 //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)1064 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1065                                                  bool &isFramework,
1066                                                  StringRef &Suffix) {
1067   StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1068   size_t a, b, c, d, Idx;
1069 
1070   isFramework = false;
1071   Suffix = StringRef();
1072 
1073   // Pull off the last component and make Foo point to it
1074   a = Name.rfind('/');
1075   if (a == Name.npos || a == 0)
1076     goto guess_library;
1077   Foo = Name.slice(a+1, Name.npos);
1078 
1079   // Look for a suffix starting with a '_'
1080   Idx = Foo.rfind('_');
1081   if (Idx != Foo.npos && Foo.size() >= 2) {
1082     Suffix = Foo.slice(Idx, Foo.npos);
1083     Foo = Foo.slice(0, Idx);
1084   }
1085 
1086   // First look for the form Foo.framework/Foo
1087   b = Name.rfind('/', a);
1088   if (b == Name.npos)
1089     Idx = 0;
1090   else
1091     Idx = b+1;
1092   F = Name.slice(Idx, Idx + Foo.size());
1093   DotFramework = Name.slice(Idx + Foo.size(),
1094                             Idx + Foo.size() + sizeof(".framework/")-1);
1095   if (F == Foo && DotFramework == ".framework/") {
1096     isFramework = true;
1097     return Foo;
1098   }
1099 
1100   // Next look for the form Foo.framework/Versions/A/Foo
1101   if (b == Name.npos)
1102     goto guess_library;
1103   c =  Name.rfind('/', b);
1104   if (c == Name.npos || c == 0)
1105     goto guess_library;
1106   V = Name.slice(c+1, Name.npos);
1107   if (!V.startswith("Versions/"))
1108     goto guess_library;
1109   d =  Name.rfind('/', c);
1110   if (d == Name.npos)
1111     Idx = 0;
1112   else
1113     Idx = d+1;
1114   F = Name.slice(Idx, Idx + Foo.size());
1115   DotFramework = Name.slice(Idx + Foo.size(),
1116                             Idx + Foo.size() + sizeof(".framework/")-1);
1117   if (F == Foo && DotFramework == ".framework/") {
1118     isFramework = true;
1119     return Foo;
1120   }
1121 
1122 guess_library:
1123   // pull off the suffix after the "." and make a point to it
1124   a = Name.rfind('.');
1125   if (a == Name.npos || a == 0)
1126     return StringRef();
1127   Dylib = Name.slice(a, Name.npos);
1128   if (Dylib != ".dylib")
1129     goto guess_qtx;
1130 
1131   // First pull off the version letter for the form Foo.A.dylib if any.
1132   if (a >= 3) {
1133     Dot = Name.slice(a-2, a-1);
1134     if (Dot == ".")
1135       a = a - 2;
1136   }
1137 
1138   b = Name.rfind('/', a);
1139   if (b == Name.npos)
1140     b = 0;
1141   else
1142     b = b+1;
1143   // ignore any suffix after an underbar like Foo_profile.A.dylib
1144   Idx = Name.find('_', b);
1145   if (Idx != Name.npos && Idx != b) {
1146     Lib = Name.slice(b, Idx);
1147     Suffix = Name.slice(Idx, a);
1148   }
1149   else
1150     Lib = Name.slice(b, a);
1151   // There are incorrect library names of the form:
1152   // libATS.A_profile.dylib so check for these.
1153   if (Lib.size() >= 3) {
1154     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1155     if (Dot == ".")
1156       Lib = Lib.slice(0, Lib.size()-2);
1157   }
1158   return Lib;
1159 
1160 guess_qtx:
1161   Qtx = Name.slice(a, Name.npos);
1162   if (Qtx != ".qtx")
1163     return StringRef();
1164   b = Name.rfind('/', a);
1165   if (b == Name.npos)
1166     Lib = Name.slice(0, a);
1167   else
1168     Lib = Name.slice(b+1, a);
1169   // There are library names of the form: QT.A.qtx so check for these.
1170   if (Lib.size() >= 3) {
1171     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1172     if (Dot == ".")
1173       Lib = Lib.slice(0, Lib.size()-2);
1174   }
1175   return Lib;
1176 }
1177 
1178 // getLibraryShortNameByIndex() is used to get the short name of the library
1179 // for an undefined symbol in a linked Mach-O binary that was linked with the
1180 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1181 // It is passed the index (0 - based) of the library as translated from
1182 // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const1183 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1184                                                          StringRef &Res) const {
1185   if (Index >= Libraries.size())
1186     return object_error::parse_failed;
1187 
1188   // If the cache of LibrariesShortNames is not built up do that first for
1189   // all the Libraries.
1190   if (LibrariesShortNames.size() == 0) {
1191     for (unsigned i = 0; i < Libraries.size(); i++) {
1192       MachO::dylib_command D =
1193         getStruct<MachO::dylib_command>(this, Libraries[i]);
1194       if (D.dylib.name >= D.cmdsize)
1195         return object_error::parse_failed;
1196       const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1197       StringRef Name = StringRef(P);
1198       if (D.dylib.name+Name.size() >= D.cmdsize)
1199         return object_error::parse_failed;
1200       StringRef Suffix;
1201       bool isFramework;
1202       StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1203       if (shortName.empty())
1204         LibrariesShortNames.push_back(Name);
1205       else
1206         LibrariesShortNames.push_back(shortName);
1207     }
1208   }
1209 
1210   Res = LibrariesShortNames[Index];
1211   return object_error::success;
1212 }
1213 
symbol_begin_impl() const1214 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1215   return getSymbolByIndex(0);
1216 }
1217 
symbol_end_impl() const1218 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1219   DataRefImpl DRI;
1220   if (!SymtabLoadCmd)
1221     return basic_symbol_iterator(SymbolRef(DRI, this));
1222 
1223   MachO::symtab_command Symtab = getSymtabLoadCommand();
1224   unsigned SymbolTableEntrySize = is64Bit() ?
1225     sizeof(MachO::nlist_64) :
1226     sizeof(MachO::nlist);
1227   unsigned Offset = Symtab.symoff +
1228     Symtab.nsyms * SymbolTableEntrySize;
1229   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1230   return basic_symbol_iterator(SymbolRef(DRI, this));
1231 }
1232 
getSymbolByIndex(unsigned Index) const1233 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1234   DataRefImpl DRI;
1235   if (!SymtabLoadCmd)
1236     return basic_symbol_iterator(SymbolRef(DRI, this));
1237 
1238   MachO::symtab_command Symtab = getSymtabLoadCommand();
1239   if (Index >= Symtab.nsyms)
1240     report_fatal_error("Requested symbol index is out of range.");
1241   unsigned SymbolTableEntrySize =
1242     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1243   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1244   DRI.p += Index * SymbolTableEntrySize;
1245   return basic_symbol_iterator(SymbolRef(DRI, this));
1246 }
1247 
section_begin() const1248 section_iterator MachOObjectFile::section_begin() const {
1249   DataRefImpl DRI;
1250   return section_iterator(SectionRef(DRI, this));
1251 }
1252 
section_end() const1253 section_iterator MachOObjectFile::section_end() const {
1254   DataRefImpl DRI;
1255   DRI.d.a = Sections.size();
1256   return section_iterator(SectionRef(DRI, this));
1257 }
1258 
getBytesInAddress() const1259 uint8_t MachOObjectFile::getBytesInAddress() const {
1260   return is64Bit() ? 8 : 4;
1261 }
1262 
getFileFormatName() const1263 StringRef MachOObjectFile::getFileFormatName() const {
1264   unsigned CPUType = getCPUType(this);
1265   if (!is64Bit()) {
1266     switch (CPUType) {
1267     case llvm::MachO::CPU_TYPE_I386:
1268       return "Mach-O 32-bit i386";
1269     case llvm::MachO::CPU_TYPE_ARM:
1270       return "Mach-O arm";
1271     case llvm::MachO::CPU_TYPE_POWERPC:
1272       return "Mach-O 32-bit ppc";
1273     default:
1274       return "Mach-O 32-bit unknown";
1275     }
1276   }
1277 
1278   switch (CPUType) {
1279   case llvm::MachO::CPU_TYPE_X86_64:
1280     return "Mach-O 64-bit x86-64";
1281   case llvm::MachO::CPU_TYPE_ARM64:
1282     return "Mach-O arm64";
1283   case llvm::MachO::CPU_TYPE_POWERPC64:
1284     return "Mach-O 64-bit ppc64";
1285   default:
1286     return "Mach-O 64-bit unknown";
1287   }
1288 }
1289 
getArch(uint32_t CPUType)1290 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1291   switch (CPUType) {
1292   case llvm::MachO::CPU_TYPE_I386:
1293     return Triple::x86;
1294   case llvm::MachO::CPU_TYPE_X86_64:
1295     return Triple::x86_64;
1296   case llvm::MachO::CPU_TYPE_ARM:
1297     return Triple::arm;
1298   case llvm::MachO::CPU_TYPE_ARM64:
1299     return Triple::aarch64;
1300   case llvm::MachO::CPU_TYPE_POWERPC:
1301     return Triple::ppc;
1302   case llvm::MachO::CPU_TYPE_POWERPC64:
1303     return Triple::ppc64;
1304   default:
1305     return Triple::UnknownArch;
1306   }
1307 }
1308 
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1309 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1310                                 const char **McpuDefault) {
1311   if (McpuDefault)
1312     *McpuDefault = nullptr;
1313 
1314   switch (CPUType) {
1315   case MachO::CPU_TYPE_I386:
1316     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1317     case MachO::CPU_SUBTYPE_I386_ALL:
1318       return Triple("i386-apple-darwin");
1319     default:
1320       return Triple();
1321     }
1322   case MachO::CPU_TYPE_X86_64:
1323     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1324     case MachO::CPU_SUBTYPE_X86_64_ALL:
1325       return Triple("x86_64-apple-darwin");
1326     case MachO::CPU_SUBTYPE_X86_64_H:
1327       return Triple("x86_64h-apple-darwin");
1328     default:
1329       return Triple();
1330     }
1331   case MachO::CPU_TYPE_ARM:
1332     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1333     case MachO::CPU_SUBTYPE_ARM_V4T:
1334       return Triple("armv4t-apple-darwin");
1335     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1336       return Triple("armv5e-apple-darwin");
1337     case MachO::CPU_SUBTYPE_ARM_XSCALE:
1338       return Triple("xscale-apple-darwin");
1339     case MachO::CPU_SUBTYPE_ARM_V6:
1340       return Triple("armv6-apple-darwin");
1341     case MachO::CPU_SUBTYPE_ARM_V6M:
1342       if (McpuDefault)
1343         *McpuDefault = "cortex-m0";
1344       return Triple("armv6m-apple-darwin");
1345     case MachO::CPU_SUBTYPE_ARM_V7:
1346       return Triple("armv7-apple-darwin");
1347     case MachO::CPU_SUBTYPE_ARM_V7EM:
1348       if (McpuDefault)
1349         *McpuDefault = "cortex-m4";
1350       return Triple("armv7em-apple-darwin");
1351     case MachO::CPU_SUBTYPE_ARM_V7K:
1352       return Triple("armv7k-apple-darwin");
1353     case MachO::CPU_SUBTYPE_ARM_V7M:
1354       if (McpuDefault)
1355         *McpuDefault = "cortex-m3";
1356       return Triple("armv7m-apple-darwin");
1357     case MachO::CPU_SUBTYPE_ARM_V7S:
1358       return Triple("armv7s-apple-darwin");
1359     default:
1360       return Triple();
1361     }
1362   case MachO::CPU_TYPE_ARM64:
1363     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1364     case MachO::CPU_SUBTYPE_ARM64_ALL:
1365       return Triple("arm64-apple-darwin");
1366     default:
1367       return Triple();
1368     }
1369   case MachO::CPU_TYPE_POWERPC:
1370     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1371     case MachO::CPU_SUBTYPE_POWERPC_ALL:
1372       return Triple("ppc-apple-darwin");
1373     default:
1374       return Triple();
1375     }
1376   case MachO::CPU_TYPE_POWERPC64:
1377     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1378     case MachO::CPU_SUBTYPE_POWERPC_ALL:
1379       return Triple("ppc64-apple-darwin");
1380     default:
1381       return Triple();
1382     }
1383   default:
1384     return Triple();
1385   }
1386 }
1387 
getThumbArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1388 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1389                                      const char **McpuDefault) {
1390   if (McpuDefault)
1391     *McpuDefault = nullptr;
1392 
1393   switch (CPUType) {
1394   case MachO::CPU_TYPE_ARM:
1395     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1396     case MachO::CPU_SUBTYPE_ARM_V4T:
1397       return Triple("thumbv4t-apple-darwin");
1398     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1399       return Triple("thumbv5e-apple-darwin");
1400     case MachO::CPU_SUBTYPE_ARM_XSCALE:
1401       return Triple("xscale-apple-darwin");
1402     case MachO::CPU_SUBTYPE_ARM_V6:
1403       return Triple("thumbv6-apple-darwin");
1404     case MachO::CPU_SUBTYPE_ARM_V6M:
1405       if (McpuDefault)
1406         *McpuDefault = "cortex-m0";
1407       return Triple("thumbv6m-apple-darwin");
1408     case MachO::CPU_SUBTYPE_ARM_V7:
1409       return Triple("thumbv7-apple-darwin");
1410     case MachO::CPU_SUBTYPE_ARM_V7EM:
1411       if (McpuDefault)
1412         *McpuDefault = "cortex-m4";
1413       return Triple("thumbv7em-apple-darwin");
1414     case MachO::CPU_SUBTYPE_ARM_V7K:
1415       return Triple("thumbv7k-apple-darwin");
1416     case MachO::CPU_SUBTYPE_ARM_V7M:
1417       if (McpuDefault)
1418         *McpuDefault = "cortex-m3";
1419       return Triple("thumbv7m-apple-darwin");
1420     case MachO::CPU_SUBTYPE_ARM_V7S:
1421       return Triple("thumbv7s-apple-darwin");
1422     default:
1423       return Triple();
1424     }
1425   default:
1426     return Triple();
1427   }
1428 }
1429 
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,Triple * ThumbTriple)1430 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1431                                 const char **McpuDefault,
1432 				Triple *ThumbTriple) {
1433   Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1434   *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1435                                                McpuDefault);
1436   return T;
1437 }
1438 
getHostArch()1439 Triple MachOObjectFile::getHostArch() {
1440   return Triple(sys::getDefaultTargetTriple());
1441 }
1442 
isValidArch(StringRef ArchFlag)1443 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1444   return StringSwitch<bool>(ArchFlag)
1445       .Case("i386", true)
1446       .Case("x86_64", true)
1447       .Case("x86_64h", true)
1448       .Case("armv4t", true)
1449       .Case("arm", true)
1450       .Case("armv5e", true)
1451       .Case("armv6", true)
1452       .Case("armv6m", true)
1453       .Case("armv7em", true)
1454       .Case("armv7k", true)
1455       .Case("armv7m", true)
1456       .Case("armv7s", true)
1457       .Case("arm64", true)
1458       .Case("ppc", true)
1459       .Case("ppc64", true)
1460       .Default(false);
1461 }
1462 
getArch() const1463 unsigned MachOObjectFile::getArch() const {
1464   return getArch(getCPUType(this));
1465 }
1466 
getArch(const char ** McpuDefault,Triple * ThumbTriple) const1467 Triple MachOObjectFile::getArch(const char **McpuDefault,
1468                                 Triple *ThumbTriple) const {
1469   Triple T;
1470   if (is64Bit()) {
1471     MachO::mach_header_64 H_64;
1472     H_64 = getHeader64();
1473     T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1474     *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1475                                                  McpuDefault);
1476   } else {
1477     MachO::mach_header H;
1478     H = getHeader();
1479     T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1480     *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1481                                                  McpuDefault);
1482   }
1483   return T;
1484 }
1485 
section_rel_begin(unsigned Index) const1486 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1487   DataRefImpl DRI;
1488   DRI.d.a = Index;
1489   return section_rel_begin(DRI);
1490 }
1491 
section_rel_end(unsigned Index) const1492 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1493   DataRefImpl DRI;
1494   DRI.d.a = Index;
1495   return section_rel_end(DRI);
1496 }
1497 
begin_dices() const1498 dice_iterator MachOObjectFile::begin_dices() const {
1499   DataRefImpl DRI;
1500   if (!DataInCodeLoadCmd)
1501     return dice_iterator(DiceRef(DRI, this));
1502 
1503   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1504   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1505   return dice_iterator(DiceRef(DRI, this));
1506 }
1507 
end_dices() const1508 dice_iterator MachOObjectFile::end_dices() const {
1509   DataRefImpl DRI;
1510   if (!DataInCodeLoadCmd)
1511     return dice_iterator(DiceRef(DRI, this));
1512 
1513   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1514   unsigned Offset = DicLC.dataoff + DicLC.datasize;
1515   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1516   return dice_iterator(DiceRef(DRI, this));
1517 }
1518 
ExportEntry(ArrayRef<uint8_t> T)1519 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1520   : Trie(T), Malformed(false), Done(false) { }
1521 
moveToFirst()1522 void ExportEntry::moveToFirst() {
1523   pushNode(0);
1524   pushDownUntilBottom();
1525 }
1526 
moveToEnd()1527 void ExportEntry::moveToEnd() {
1528   Stack.clear();
1529   Done = true;
1530 }
1531 
operator ==(const ExportEntry & Other) const1532 bool ExportEntry::operator==(const ExportEntry &Other) const {
1533   // Common case, one at end, other iterating from begin.
1534   if (Done || Other.Done)
1535     return (Done == Other.Done);
1536   // Not equal if different stack sizes.
1537   if (Stack.size() != Other.Stack.size())
1538     return false;
1539   // Not equal if different cumulative strings.
1540   if (!CumulativeString.equals(Other.CumulativeString))
1541     return false;
1542   // Equal if all nodes in both stacks match.
1543   for (unsigned i=0; i < Stack.size(); ++i) {
1544     if (Stack[i].Start != Other.Stack[i].Start)
1545       return false;
1546   }
1547   return true;
1548 }
1549 
readULEB128(const uint8_t * & Ptr)1550 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1551   unsigned Count;
1552   uint64_t Result = decodeULEB128(Ptr, &Count);
1553   Ptr += Count;
1554   if (Ptr > Trie.end()) {
1555     Ptr = Trie.end();
1556     Malformed = true;
1557   }
1558   return Result;
1559 }
1560 
name() const1561 StringRef ExportEntry::name() const {
1562   return CumulativeString;
1563 }
1564 
flags() const1565 uint64_t ExportEntry::flags() const {
1566   return Stack.back().Flags;
1567 }
1568 
address() const1569 uint64_t ExportEntry::address() const {
1570   return Stack.back().Address;
1571 }
1572 
other() const1573 uint64_t ExportEntry::other() const {
1574   return Stack.back().Other;
1575 }
1576 
otherName() const1577 StringRef ExportEntry::otherName() const {
1578   const char* ImportName = Stack.back().ImportName;
1579   if (ImportName)
1580     return StringRef(ImportName);
1581   return StringRef();
1582 }
1583 
nodeOffset() const1584 uint32_t ExportEntry::nodeOffset() const {
1585   return Stack.back().Start - Trie.begin();
1586 }
1587 
NodeState(const uint8_t * Ptr)1588 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1589   : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1590     ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1591     ParentStringLength(0), IsExportNode(false) {
1592 }
1593 
pushNode(uint64_t offset)1594 void ExportEntry::pushNode(uint64_t offset) {
1595   const uint8_t *Ptr = Trie.begin() + offset;
1596   NodeState State(Ptr);
1597   uint64_t ExportInfoSize = readULEB128(State.Current);
1598   State.IsExportNode = (ExportInfoSize != 0);
1599   const uint8_t* Children = State.Current + ExportInfoSize;
1600   if (State.IsExportNode) {
1601     State.Flags = readULEB128(State.Current);
1602     if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1603       State.Address = 0;
1604       State.Other = readULEB128(State.Current); // dylib ordinal
1605       State.ImportName = reinterpret_cast<const char*>(State.Current);
1606     } else {
1607       State.Address = readULEB128(State.Current);
1608       if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1609         State.Other = readULEB128(State.Current);
1610     }
1611   }
1612   State.ChildCount = *Children;
1613   State.Current = Children + 1;
1614   State.NextChildIndex = 0;
1615   State.ParentStringLength = CumulativeString.size();
1616   Stack.push_back(State);
1617 }
1618 
pushDownUntilBottom()1619 void ExportEntry::pushDownUntilBottom() {
1620   while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1621     NodeState &Top = Stack.back();
1622     CumulativeString.resize(Top.ParentStringLength);
1623     for (;*Top.Current != 0; Top.Current++) {
1624       char C = *Top.Current;
1625       CumulativeString.push_back(C);
1626     }
1627     Top.Current += 1;
1628     uint64_t childNodeIndex = readULEB128(Top.Current);
1629     Top.NextChildIndex += 1;
1630     pushNode(childNodeIndex);
1631   }
1632   if (!Stack.back().IsExportNode) {
1633     Malformed = true;
1634     moveToEnd();
1635   }
1636 }
1637 
1638 // We have a trie data structure and need a way to walk it that is compatible
1639 // with the C++ iterator model. The solution is a non-recursive depth first
1640 // traversal where the iterator contains a stack of parent nodes along with a
1641 // string that is the accumulation of all edge strings along the parent chain
1642 // to this point.
1643 //
1644 // There is one "export" node for each exported symbol.  But because some
1645 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1646 // node may have child nodes too.
1647 //
1648 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1649 // child until hitting a node with no children (which is an export node or
1650 // else the trie is malformed). On the way down, each node is pushed on the
1651 // stack ivar.  If there is no more ways down, it pops up one and tries to go
1652 // down a sibling path until a childless node is reached.
moveNext()1653 void ExportEntry::moveNext() {
1654   if (Stack.empty() || !Stack.back().IsExportNode) {
1655     Malformed = true;
1656     moveToEnd();
1657     return;
1658   }
1659 
1660   Stack.pop_back();
1661   while (!Stack.empty()) {
1662     NodeState &Top = Stack.back();
1663     if (Top.NextChildIndex < Top.ChildCount) {
1664       pushDownUntilBottom();
1665       // Now at the next export node.
1666       return;
1667     } else {
1668       if (Top.IsExportNode) {
1669         // This node has no children but is itself an export node.
1670         CumulativeString.resize(Top.ParentStringLength);
1671         return;
1672       }
1673       Stack.pop_back();
1674     }
1675   }
1676   Done = true;
1677 }
1678 
1679 iterator_range<export_iterator>
exports(ArrayRef<uint8_t> Trie)1680 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1681   ExportEntry Start(Trie);
1682   if (Trie.size() == 0)
1683     Start.moveToEnd();
1684   else
1685     Start.moveToFirst();
1686 
1687   ExportEntry Finish(Trie);
1688   Finish.moveToEnd();
1689 
1690   return iterator_range<export_iterator>(export_iterator(Start),
1691                                          export_iterator(Finish));
1692 }
1693 
exports() const1694 iterator_range<export_iterator> MachOObjectFile::exports() const {
1695   return exports(getDyldInfoExportsTrie());
1696 }
1697 
1698 
MachORebaseEntry(ArrayRef<uint8_t> Bytes,bool is64Bit)1699 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1700     : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1701       RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1702       PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1703 
moveToFirst()1704 void MachORebaseEntry::moveToFirst() {
1705   Ptr = Opcodes.begin();
1706   moveNext();
1707 }
1708 
moveToEnd()1709 void MachORebaseEntry::moveToEnd() {
1710   Ptr = Opcodes.end();
1711   RemainingLoopCount = 0;
1712   Done = true;
1713 }
1714 
moveNext()1715 void MachORebaseEntry::moveNext() {
1716   // If in the middle of some loop, move to next rebasing in loop.
1717   SegmentOffset += AdvanceAmount;
1718   if (RemainingLoopCount) {
1719     --RemainingLoopCount;
1720     return;
1721   }
1722   if (Ptr == Opcodes.end()) {
1723     Done = true;
1724     return;
1725   }
1726   bool More = true;
1727   while (More && !Malformed) {
1728     // Parse next opcode and set up next loop.
1729     uint8_t Byte = *Ptr++;
1730     uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1731     uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1732     switch (Opcode) {
1733     case MachO::REBASE_OPCODE_DONE:
1734       More = false;
1735       Done = true;
1736       moveToEnd();
1737       DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1738       break;
1739     case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1740       RebaseType = ImmValue;
1741       DEBUG_WITH_TYPE(
1742           "mach-o-rebase",
1743           llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1744                        << "RebaseType=" << (int) RebaseType << "\n");
1745       break;
1746     case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1747       SegmentIndex = ImmValue;
1748       SegmentOffset = readULEB128();
1749       DEBUG_WITH_TYPE(
1750           "mach-o-rebase",
1751           llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1752                        << "SegmentIndex=" << SegmentIndex << ", "
1753                        << format("SegmentOffset=0x%06X", SegmentOffset)
1754                        << "\n");
1755       break;
1756     case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1757       SegmentOffset += readULEB128();
1758       DEBUG_WITH_TYPE("mach-o-rebase",
1759                       llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1760                                    << format("SegmentOffset=0x%06X",
1761                                              SegmentOffset) << "\n");
1762       break;
1763     case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1764       SegmentOffset += ImmValue * PointerSize;
1765       DEBUG_WITH_TYPE("mach-o-rebase",
1766                       llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1767                                    << format("SegmentOffset=0x%06X",
1768                                              SegmentOffset) << "\n");
1769       break;
1770     case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1771       AdvanceAmount = PointerSize;
1772       RemainingLoopCount = ImmValue - 1;
1773       DEBUG_WITH_TYPE(
1774           "mach-o-rebase",
1775           llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1776                        << format("SegmentOffset=0x%06X", SegmentOffset)
1777                        << ", AdvanceAmount=" << AdvanceAmount
1778                        << ", RemainingLoopCount=" << RemainingLoopCount
1779                        << "\n");
1780       return;
1781     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1782       AdvanceAmount = PointerSize;
1783       RemainingLoopCount = readULEB128() - 1;
1784       DEBUG_WITH_TYPE(
1785           "mach-o-rebase",
1786           llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1787                        << format("SegmentOffset=0x%06X", SegmentOffset)
1788                        << ", AdvanceAmount=" << AdvanceAmount
1789                        << ", RemainingLoopCount=" << RemainingLoopCount
1790                        << "\n");
1791       return;
1792     case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1793       AdvanceAmount = readULEB128() + PointerSize;
1794       RemainingLoopCount = 0;
1795       DEBUG_WITH_TYPE(
1796           "mach-o-rebase",
1797           llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1798                        << format("SegmentOffset=0x%06X", SegmentOffset)
1799                        << ", AdvanceAmount=" << AdvanceAmount
1800                        << ", RemainingLoopCount=" << RemainingLoopCount
1801                        << "\n");
1802       return;
1803     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1804       RemainingLoopCount = readULEB128() - 1;
1805       AdvanceAmount = readULEB128() + PointerSize;
1806       DEBUG_WITH_TYPE(
1807           "mach-o-rebase",
1808           llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1809                        << format("SegmentOffset=0x%06X", SegmentOffset)
1810                        << ", AdvanceAmount=" << AdvanceAmount
1811                        << ", RemainingLoopCount=" << RemainingLoopCount
1812                        << "\n");
1813       return;
1814     default:
1815       Malformed = true;
1816     }
1817   }
1818 }
1819 
readULEB128()1820 uint64_t MachORebaseEntry::readULEB128() {
1821   unsigned Count;
1822   uint64_t Result = decodeULEB128(Ptr, &Count);
1823   Ptr += Count;
1824   if (Ptr > Opcodes.end()) {
1825     Ptr = Opcodes.end();
1826     Malformed = true;
1827   }
1828   return Result;
1829 }
1830 
segmentIndex() const1831 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1832 
segmentOffset() const1833 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1834 
typeName() const1835 StringRef MachORebaseEntry::typeName() const {
1836   switch (RebaseType) {
1837   case MachO::REBASE_TYPE_POINTER:
1838     return "pointer";
1839   case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1840     return "text abs32";
1841   case MachO::REBASE_TYPE_TEXT_PCREL32:
1842     return "text rel32";
1843   }
1844   return "unknown";
1845 }
1846 
operator ==(const MachORebaseEntry & Other) const1847 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1848   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1849   return (Ptr == Other.Ptr) &&
1850          (RemainingLoopCount == Other.RemainingLoopCount) &&
1851          (Done == Other.Done);
1852 }
1853 
1854 iterator_range<rebase_iterator>
rebaseTable(ArrayRef<uint8_t> Opcodes,bool is64)1855 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1856   MachORebaseEntry Start(Opcodes, is64);
1857   Start.moveToFirst();
1858 
1859   MachORebaseEntry Finish(Opcodes, is64);
1860   Finish.moveToEnd();
1861 
1862   return iterator_range<rebase_iterator>(rebase_iterator(Start),
1863                                          rebase_iterator(Finish));
1864 }
1865 
rebaseTable() const1866 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1867   return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1868 }
1869 
1870 
MachOBindEntry(ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)1871 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1872                                Kind BK)
1873     : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1874       Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1875       BindType(0), PointerSize(is64Bit ? 8 : 4),
1876       TableKind(BK), Malformed(false), Done(false) {}
1877 
moveToFirst()1878 void MachOBindEntry::moveToFirst() {
1879   Ptr = Opcodes.begin();
1880   moveNext();
1881 }
1882 
moveToEnd()1883 void MachOBindEntry::moveToEnd() {
1884   Ptr = Opcodes.end();
1885   RemainingLoopCount = 0;
1886   Done = true;
1887 }
1888 
moveNext()1889 void MachOBindEntry::moveNext() {
1890   // If in the middle of some loop, move to next binding in loop.
1891   SegmentOffset += AdvanceAmount;
1892   if (RemainingLoopCount) {
1893     --RemainingLoopCount;
1894     return;
1895   }
1896   if (Ptr == Opcodes.end()) {
1897     Done = true;
1898     return;
1899   }
1900   bool More = true;
1901   while (More && !Malformed) {
1902     // Parse next opcode and set up next loop.
1903     uint8_t Byte = *Ptr++;
1904     uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1905     uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1906     int8_t SignExtended;
1907     const uint8_t *SymStart;
1908     switch (Opcode) {
1909     case MachO::BIND_OPCODE_DONE:
1910       if (TableKind == Kind::Lazy) {
1911         // Lazying bindings have a DONE opcode between entries.  Need to ignore
1912         // it to advance to next entry.  But need not if this is last entry.
1913         bool NotLastEntry = false;
1914         for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1915           if (*P) {
1916             NotLastEntry = true;
1917           }
1918         }
1919         if (NotLastEntry)
1920           break;
1921       }
1922       More = false;
1923       Done = true;
1924       moveToEnd();
1925       DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1926       break;
1927     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1928       Ordinal = ImmValue;
1929       DEBUG_WITH_TYPE(
1930           "mach-o-bind",
1931           llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1932                        << "Ordinal=" << Ordinal << "\n");
1933       break;
1934     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1935       Ordinal = readULEB128();
1936       DEBUG_WITH_TYPE(
1937           "mach-o-bind",
1938           llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1939                        << "Ordinal=" << Ordinal << "\n");
1940       break;
1941     case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1942       if (ImmValue) {
1943         SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1944         Ordinal = SignExtended;
1945       } else
1946         Ordinal = 0;
1947       DEBUG_WITH_TYPE(
1948           "mach-o-bind",
1949           llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1950                        << "Ordinal=" << Ordinal << "\n");
1951       break;
1952     case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1953       Flags = ImmValue;
1954       SymStart = Ptr;
1955       while (*Ptr) {
1956         ++Ptr;
1957       }
1958       SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1959                              Ptr-SymStart);
1960       ++Ptr;
1961       DEBUG_WITH_TYPE(
1962           "mach-o-bind",
1963           llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1964                        << "SymbolName=" << SymbolName << "\n");
1965       if (TableKind == Kind::Weak) {
1966         if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1967           return;
1968       }
1969       break;
1970     case MachO::BIND_OPCODE_SET_TYPE_IMM:
1971       BindType = ImmValue;
1972       DEBUG_WITH_TYPE(
1973           "mach-o-bind",
1974           llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1975                        << "BindType=" << (int)BindType << "\n");
1976       break;
1977     case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1978       Addend = readSLEB128();
1979       if (TableKind == Kind::Lazy)
1980         Malformed = true;
1981       DEBUG_WITH_TYPE(
1982           "mach-o-bind",
1983           llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1984                        << "Addend=" << Addend << "\n");
1985       break;
1986     case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1987       SegmentIndex = ImmValue;
1988       SegmentOffset = readULEB128();
1989       DEBUG_WITH_TYPE(
1990           "mach-o-bind",
1991           llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1992                        << "SegmentIndex=" << SegmentIndex << ", "
1993                        << format("SegmentOffset=0x%06X", SegmentOffset)
1994                        << "\n");
1995       break;
1996     case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1997       SegmentOffset += readULEB128();
1998       DEBUG_WITH_TYPE("mach-o-bind",
1999                       llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2000                                    << format("SegmentOffset=0x%06X",
2001                                              SegmentOffset) << "\n");
2002       break;
2003     case MachO::BIND_OPCODE_DO_BIND:
2004       AdvanceAmount = PointerSize;
2005       RemainingLoopCount = 0;
2006       DEBUG_WITH_TYPE("mach-o-bind",
2007                       llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2008                                    << format("SegmentOffset=0x%06X",
2009                                              SegmentOffset) << "\n");
2010       return;
2011      case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2012       AdvanceAmount = readULEB128() + PointerSize;
2013       RemainingLoopCount = 0;
2014       if (TableKind == Kind::Lazy)
2015         Malformed = true;
2016       DEBUG_WITH_TYPE(
2017           "mach-o-bind",
2018           llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
2019                        << format("SegmentOffset=0x%06X", SegmentOffset)
2020                        << ", AdvanceAmount=" << AdvanceAmount
2021                        << ", RemainingLoopCount=" << RemainingLoopCount
2022                        << "\n");
2023       return;
2024     case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2025       AdvanceAmount = ImmValue * PointerSize + PointerSize;
2026       RemainingLoopCount = 0;
2027       if (TableKind == Kind::Lazy)
2028         Malformed = true;
2029       DEBUG_WITH_TYPE("mach-o-bind",
2030                       llvm::dbgs()
2031                       << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2032                       << format("SegmentOffset=0x%06X",
2033                                              SegmentOffset) << "\n");
2034       return;
2035     case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2036       RemainingLoopCount = readULEB128() - 1;
2037       AdvanceAmount = readULEB128() + PointerSize;
2038       if (TableKind == Kind::Lazy)
2039         Malformed = true;
2040       DEBUG_WITH_TYPE(
2041           "mach-o-bind",
2042           llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2043                        << format("SegmentOffset=0x%06X", SegmentOffset)
2044                        << ", AdvanceAmount=" << AdvanceAmount
2045                        << ", RemainingLoopCount=" << RemainingLoopCount
2046                        << "\n");
2047       return;
2048     default:
2049       Malformed = true;
2050     }
2051   }
2052 }
2053 
readULEB128()2054 uint64_t MachOBindEntry::readULEB128() {
2055   unsigned Count;
2056   uint64_t Result = decodeULEB128(Ptr, &Count);
2057   Ptr += Count;
2058   if (Ptr > Opcodes.end()) {
2059     Ptr = Opcodes.end();
2060     Malformed = true;
2061   }
2062   return Result;
2063 }
2064 
readSLEB128()2065 int64_t MachOBindEntry::readSLEB128() {
2066   unsigned Count;
2067   int64_t Result = decodeSLEB128(Ptr, &Count);
2068   Ptr += Count;
2069   if (Ptr > Opcodes.end()) {
2070     Ptr = Opcodes.end();
2071     Malformed = true;
2072   }
2073   return Result;
2074 }
2075 
2076 
segmentIndex() const2077 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2078 
segmentOffset() const2079 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2080 
typeName() const2081 StringRef MachOBindEntry::typeName() const {
2082   switch (BindType) {
2083   case MachO::BIND_TYPE_POINTER:
2084     return "pointer";
2085   case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2086     return "text abs32";
2087   case MachO::BIND_TYPE_TEXT_PCREL32:
2088     return "text rel32";
2089   }
2090   return "unknown";
2091 }
2092 
symbolName() const2093 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2094 
addend() const2095 int64_t MachOBindEntry::addend() const { return Addend; }
2096 
flags() const2097 uint32_t MachOBindEntry::flags() const { return Flags; }
2098 
ordinal() const2099 int MachOBindEntry::ordinal() const { return Ordinal; }
2100 
operator ==(const MachOBindEntry & Other) const2101 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2102   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2103   return (Ptr == Other.Ptr) &&
2104          (RemainingLoopCount == Other.RemainingLoopCount) &&
2105          (Done == Other.Done);
2106 }
2107 
2108 iterator_range<bind_iterator>
bindTable(ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)2109 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2110                            MachOBindEntry::Kind BKind) {
2111   MachOBindEntry Start(Opcodes, is64, BKind);
2112   Start.moveToFirst();
2113 
2114   MachOBindEntry Finish(Opcodes, is64, BKind);
2115   Finish.moveToEnd();
2116 
2117   return iterator_range<bind_iterator>(bind_iterator(Start),
2118                                        bind_iterator(Finish));
2119 }
2120 
bindTable() const2121 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2122   return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2123                    MachOBindEntry::Kind::Regular);
2124 }
2125 
lazyBindTable() const2126 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2127   return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2128                    MachOBindEntry::Kind::Lazy);
2129 }
2130 
weakBindTable() const2131 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2132   return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2133                    MachOBindEntry::Kind::Weak);
2134 }
2135 
2136 StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const2137 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2138   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2139   return parseSegmentOrSectionName(Raw.data());
2140 }
2141 
2142 ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const2143 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2144   if (Sec.d.a >= Sections.size())
2145     report_fatal_error("getSectionRawName: Invalid section index");
2146   const section_base *Base =
2147     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2148   return makeArrayRef(Base->sectname);
2149 }
2150 
2151 ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const2152 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2153   if (Sec.d.a >= Sections.size())
2154     report_fatal_error("getSectionRawFinalSegmentName: Invalid section index");
2155   const section_base *Base =
2156     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2157   return makeArrayRef(Base->segname);
2158 }
2159 
2160 bool
isRelocationScattered(const MachO::any_relocation_info & RE) const2161 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2162   const {
2163   if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2164     return false;
2165   return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2166 }
2167 
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const2168 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2169     const MachO::any_relocation_info &RE) const {
2170   if (isLittleEndian())
2171     return RE.r_word1 & 0xffffff;
2172   return RE.r_word1 >> 8;
2173 }
2174 
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const2175 bool MachOObjectFile::getPlainRelocationExternal(
2176     const MachO::any_relocation_info &RE) const {
2177   if (isLittleEndian())
2178     return (RE.r_word1 >> 27) & 1;
2179   return (RE.r_word1 >> 4) & 1;
2180 }
2181 
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const2182 bool MachOObjectFile::getScatteredRelocationScattered(
2183     const MachO::any_relocation_info &RE) const {
2184   return RE.r_word0 >> 31;
2185 }
2186 
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const2187 uint32_t MachOObjectFile::getScatteredRelocationValue(
2188     const MachO::any_relocation_info &RE) const {
2189   return RE.r_word1;
2190 }
2191 
getScatteredRelocationType(const MachO::any_relocation_info & RE) const2192 uint32_t MachOObjectFile::getScatteredRelocationType(
2193     const MachO::any_relocation_info &RE) const {
2194   return (RE.r_word0 >> 24) & 0xf;
2195 }
2196 
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const2197 unsigned MachOObjectFile::getAnyRelocationAddress(
2198     const MachO::any_relocation_info &RE) const {
2199   if (isRelocationScattered(RE))
2200     return getScatteredRelocationAddress(RE);
2201   return getPlainRelocationAddress(RE);
2202 }
2203 
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const2204 unsigned MachOObjectFile::getAnyRelocationPCRel(
2205     const MachO::any_relocation_info &RE) const {
2206   if (isRelocationScattered(RE))
2207     return getScatteredRelocationPCRel(this, RE);
2208   return getPlainRelocationPCRel(this, RE);
2209 }
2210 
getAnyRelocationLength(const MachO::any_relocation_info & RE) const2211 unsigned MachOObjectFile::getAnyRelocationLength(
2212     const MachO::any_relocation_info &RE) const {
2213   if (isRelocationScattered(RE))
2214     return getScatteredRelocationLength(RE);
2215   return getPlainRelocationLength(this, RE);
2216 }
2217 
2218 unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const2219 MachOObjectFile::getAnyRelocationType(
2220                                    const MachO::any_relocation_info &RE) const {
2221   if (isRelocationScattered(RE))
2222     return getScatteredRelocationType(RE);
2223   return getPlainRelocationType(this, RE);
2224 }
2225 
2226 SectionRef
getRelocationSection(const MachO::any_relocation_info & RE) const2227 MachOObjectFile::getRelocationSection(
2228                                    const MachO::any_relocation_info &RE) const {
2229   if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2230     return *section_end();
2231   unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2232   DataRefImpl DRI;
2233   DRI.d.a = SecNum;
2234   return SectionRef(DRI, this);
2235 }
2236 
2237 MachOObjectFile::LoadCommandInfo
getFirstLoadCommandInfo() const2238 MachOObjectFile::getFirstLoadCommandInfo() const {
2239   MachOObjectFile::LoadCommandInfo Load;
2240 
2241   unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2242                                     sizeof(MachO::mach_header);
2243   Load.Ptr = getPtr(this, HeaderSize);
2244   Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2245   if (Load.C.cmdsize < 8)
2246     report_fatal_error("Load command with size < 8 bytes.");
2247   return Load;
2248 }
2249 
2250 MachOObjectFile::LoadCommandInfo
getNextLoadCommandInfo(const LoadCommandInfo & L) const2251 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2252   MachOObjectFile::LoadCommandInfo Next;
2253   Next.Ptr = L.Ptr + L.C.cmdsize;
2254   Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2255   if (Next.C.cmdsize < 8)
2256     report_fatal_error("Load command with size < 8 bytes.");
2257   return Next;
2258 }
2259 
getSection(DataRefImpl DRI) const2260 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2261   // TODO: What if Sections.size() == 0?
2262   if (DRI.d.a >= Sections.size())
2263     report_fatal_error("getSection: Invalid section index.");
2264   return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2265 }
2266 
getSection64(DataRefImpl DRI) const2267 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2268   // TODO: What if Sections.size() == 0?
2269   if (DRI.d.a >= Sections.size())
2270     report_fatal_error("getSection64: Invalid section index.");
2271   return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2272 }
2273 
getSection(const LoadCommandInfo & L,unsigned Index) const2274 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2275                                            unsigned Index) const {
2276   const char *Sec = getSectionPtr(this, L, Index);
2277   return getStruct<MachO::section>(this, Sec);
2278 }
2279 
getSection64(const LoadCommandInfo & L,unsigned Index) const2280 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2281                                                 unsigned Index) const {
2282   const char *Sec = getSectionPtr(this, L, Index);
2283   return getStruct<MachO::section_64>(this, Sec);
2284 }
2285 
2286 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const2287 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2288   const char *P = reinterpret_cast<const char *>(DRI.p);
2289   return getStruct<MachO::nlist>(this, P);
2290 }
2291 
2292 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const2293 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2294   const char *P = reinterpret_cast<const char *>(DRI.p);
2295   return getStruct<MachO::nlist_64>(this, P);
2296 }
2297 
2298 MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const2299 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2300   return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2301 }
2302 
2303 MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const2304 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2305   return getStruct<MachO::segment_command>(this, L.Ptr);
2306 }
2307 
2308 MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const2309 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2310   return getStruct<MachO::segment_command_64>(this, L.Ptr);
2311 }
2312 
2313 MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const2314 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2315   return getStruct<MachO::linker_option_command>(this, L.Ptr);
2316 }
2317 
2318 MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const2319 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2320   return getStruct<MachO::version_min_command>(this, L.Ptr);
2321 }
2322 
2323 MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const2324 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2325   return getStruct<MachO::dylib_command>(this, L.Ptr);
2326 }
2327 
2328 MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const2329 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2330   return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2331 }
2332 
2333 MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const2334 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2335   return getStruct<MachO::dylinker_command>(this, L.Ptr);
2336 }
2337 
2338 MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const2339 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2340   return getStruct<MachO::uuid_command>(this, L.Ptr);
2341 }
2342 
2343 MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const2344 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2345   return getStruct<MachO::rpath_command>(this, L.Ptr);
2346 }
2347 
2348 MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const2349 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2350   return getStruct<MachO::source_version_command>(this, L.Ptr);
2351 }
2352 
2353 MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const2354 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2355   return getStruct<MachO::entry_point_command>(this, L.Ptr);
2356 }
2357 
2358 MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const2359 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2360   return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2361 }
2362 
2363 MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const2364 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2365   return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2366 }
2367 
2368 MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const2369 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2370   return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2371 }
2372 
2373 MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const2374 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2375   return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2376 }
2377 
2378 MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const2379 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2380   return getStruct<MachO::sub_library_command>(this, L.Ptr);
2381 }
2382 
2383 MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const2384 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2385   return getStruct<MachO::sub_client_command>(this, L.Ptr);
2386 }
2387 
2388 MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const2389 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2390   return getStruct<MachO::routines_command>(this, L.Ptr);
2391 }
2392 
2393 MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const2394 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2395   return getStruct<MachO::routines_command_64>(this, L.Ptr);
2396 }
2397 
2398 MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const2399 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2400   return getStruct<MachO::thread_command>(this, L.Ptr);
2401 }
2402 
2403 MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const2404 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2405   DataRefImpl Sec;
2406   Sec.d.a = Rel.d.a;
2407   uint32_t Offset;
2408   if (is64Bit()) {
2409     MachO::section_64 Sect = getSection64(Sec);
2410     Offset = Sect.reloff;
2411   } else {
2412     MachO::section Sect = getSection(Sec);
2413     Offset = Sect.reloff;
2414   }
2415 
2416   auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2417       getPtr(this, Offset)) + Rel.d.b;
2418   return getStruct<MachO::any_relocation_info>(
2419       this, reinterpret_cast<const char *>(P));
2420 }
2421 
2422 MachO::data_in_code_entry
getDice(DataRefImpl Rel) const2423 MachOObjectFile::getDice(DataRefImpl Rel) const {
2424   const char *P = reinterpret_cast<const char *>(Rel.p);
2425   return getStruct<MachO::data_in_code_entry>(this, P);
2426 }
2427 
getHeader() const2428 MachO::mach_header MachOObjectFile::getHeader() const {
2429   return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2430 }
2431 
getHeader64() const2432 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2433   return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2434 }
2435 
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const2436 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2437                                              const MachO::dysymtab_command &DLC,
2438                                              unsigned Index) const {
2439   uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2440   return getStruct<uint32_t>(this, getPtr(this, Offset));
2441 }
2442 
2443 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const2444 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2445                                          unsigned Index) const {
2446   uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2447   return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2448 }
2449 
getSymtabLoadCommand() const2450 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2451   if (SymtabLoadCmd)
2452     return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2453 
2454   // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2455   MachO::symtab_command Cmd;
2456   Cmd.cmd = MachO::LC_SYMTAB;
2457   Cmd.cmdsize = sizeof(MachO::symtab_command);
2458   Cmd.symoff = 0;
2459   Cmd.nsyms = 0;
2460   Cmd.stroff = 0;
2461   Cmd.strsize = 0;
2462   return Cmd;
2463 }
2464 
getDysymtabLoadCommand() const2465 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2466   if (DysymtabLoadCmd)
2467     return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2468 
2469   // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2470   MachO::dysymtab_command Cmd;
2471   Cmd.cmd = MachO::LC_DYSYMTAB;
2472   Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2473   Cmd.ilocalsym = 0;
2474   Cmd.nlocalsym = 0;
2475   Cmd.iextdefsym = 0;
2476   Cmd.nextdefsym = 0;
2477   Cmd.iundefsym = 0;
2478   Cmd.nundefsym = 0;
2479   Cmd.tocoff = 0;
2480   Cmd.ntoc = 0;
2481   Cmd.modtaboff = 0;
2482   Cmd.nmodtab = 0;
2483   Cmd.extrefsymoff = 0;
2484   Cmd.nextrefsyms = 0;
2485   Cmd.indirectsymoff = 0;
2486   Cmd.nindirectsyms = 0;
2487   Cmd.extreloff = 0;
2488   Cmd.nextrel = 0;
2489   Cmd.locreloff = 0;
2490   Cmd.nlocrel = 0;
2491   return Cmd;
2492 }
2493 
2494 MachO::linkedit_data_command
getDataInCodeLoadCommand() const2495 MachOObjectFile::getDataInCodeLoadCommand() const {
2496   if (DataInCodeLoadCmd)
2497     return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2498 
2499   // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2500   MachO::linkedit_data_command Cmd;
2501   Cmd.cmd = MachO::LC_DATA_IN_CODE;
2502   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2503   Cmd.dataoff = 0;
2504   Cmd.datasize = 0;
2505   return Cmd;
2506 }
2507 
2508 MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const2509 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2510   if (LinkOptHintsLoadCmd)
2511     return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2512 
2513   // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2514   // fields.
2515   MachO::linkedit_data_command Cmd;
2516   Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2517   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2518   Cmd.dataoff = 0;
2519   Cmd.datasize = 0;
2520   return Cmd;
2521 }
2522 
getDyldInfoRebaseOpcodes() const2523 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2524   if (!DyldInfoLoadCmd)
2525     return ArrayRef<uint8_t>();
2526 
2527   MachO::dyld_info_command DyldInfo
2528                    = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2529   const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2530                                              getPtr(this, DyldInfo.rebase_off));
2531   return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2532 }
2533 
getDyldInfoBindOpcodes() const2534 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2535   if (!DyldInfoLoadCmd)
2536     return ArrayRef<uint8_t>();
2537 
2538   MachO::dyld_info_command DyldInfo
2539                    = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2540   const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2541                                                getPtr(this, DyldInfo.bind_off));
2542   return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2543 }
2544 
getDyldInfoWeakBindOpcodes() const2545 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2546   if (!DyldInfoLoadCmd)
2547     return ArrayRef<uint8_t>();
2548 
2549   MachO::dyld_info_command DyldInfo
2550                    = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2551   const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2552                                           getPtr(this, DyldInfo.weak_bind_off));
2553   return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2554 }
2555 
getDyldInfoLazyBindOpcodes() const2556 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2557   if (!DyldInfoLoadCmd)
2558     return ArrayRef<uint8_t>();
2559 
2560   MachO::dyld_info_command DyldInfo
2561                    = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2562   const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2563                                           getPtr(this, DyldInfo.lazy_bind_off));
2564   return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2565 }
2566 
getDyldInfoExportsTrie() const2567 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2568   if (!DyldInfoLoadCmd)
2569     return ArrayRef<uint8_t>();
2570 
2571   MachO::dyld_info_command DyldInfo
2572                    = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2573   const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2574                                              getPtr(this, DyldInfo.export_off));
2575   return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2576 }
2577 
getUuid() const2578 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2579   if (!UuidLoadCmd)
2580     return ArrayRef<uint8_t>();
2581   // Returning a pointer is fine as uuid doesn't need endian swapping.
2582   const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2583   return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2584 }
2585 
getStringTableData() const2586 StringRef MachOObjectFile::getStringTableData() const {
2587   MachO::symtab_command S = getSymtabLoadCommand();
2588   return getData().substr(S.stroff, S.strsize);
2589 }
2590 
is64Bit() const2591 bool MachOObjectFile::is64Bit() const {
2592   return getType() == getMachOType(false, true) ||
2593     getType() == getMachOType(true, true);
2594 }
2595 
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const2596 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2597                                    SmallVectorImpl<uint64_t> &Out) const {
2598   DataExtractor extractor(ObjectFile::getData(), true, 0);
2599 
2600   uint32_t offset = Index;
2601   uint64_t data = 0;
2602   while (uint64_t delta = extractor.getULEB128(&offset)) {
2603     data += delta;
2604     Out.push_back(data);
2605   }
2606 }
2607 
isRelocatableObject() const2608 bool MachOObjectFile::isRelocatableObject() const {
2609   return getHeader().filetype == MachO::MH_OBJECT;
2610 }
2611 
2612 ErrorOr<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer)2613 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2614   StringRef Magic = Buffer.getBuffer().slice(0, 4);
2615   std::error_code EC;
2616   std::unique_ptr<MachOObjectFile> Ret;
2617   if (Magic == "\xFE\xED\xFA\xCE")
2618     Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2619   else if (Magic == "\xCE\xFA\xED\xFE")
2620     Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2621   else if (Magic == "\xFE\xED\xFA\xCF")
2622     Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2623   else if (Magic == "\xCF\xFA\xED\xFE")
2624     Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2625   else
2626     return object_error::parse_failed;
2627 
2628   if (EC)
2629     return EC;
2630   return std::move(Ret);
2631 }
2632 
2633