151690af2SDimitry Andric //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
23b0f4066SDimitry Andric //
33b0f4066SDimitry Andric //                     The LLVM Compiler Infrastructure
43b0f4066SDimitry Andric //
53b0f4066SDimitry Andric // This file is distributed under the University of Illinois Open Source
63b0f4066SDimitry Andric // License. See LICENSE.TXT for details.
73b0f4066SDimitry Andric //
83b0f4066SDimitry Andric //===----------------------------------------------------------------------===//
93b0f4066SDimitry Andric //
103b0f4066SDimitry Andric // This file defines the MachOObjectFile class, which binds the MachOObject
113b0f4066SDimitry Andric // class to the generic ObjectFile wrapper.
123b0f4066SDimitry Andric //
133b0f4066SDimitry Andric //===----------------------------------------------------------------------===//
143b0f4066SDimitry Andric 
1551690af2SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1651690af2SDimitry Andric #include "llvm/ADT/None.h"
1791bc56edSDimitry Andric #include "llvm/ADT/STLExtras.h"
18db17bf38SDimitry Andric #include "llvm/ADT/SmallVector.h"
1951690af2SDimitry Andric #include "llvm/ADT/StringRef.h"
2039d628a0SDimitry Andric #include "llvm/ADT/StringSwitch.h"
21139f7f9bSDimitry Andric #include "llvm/ADT/Triple.h"
2251690af2SDimitry Andric #include "llvm/ADT/Twine.h"
23db17bf38SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
2451690af2SDimitry Andric #include "llvm/Object/Error.h"
2551690af2SDimitry Andric #include "llvm/Object/MachO.h"
2651690af2SDimitry Andric #include "llvm/Object/ObjectFile.h"
2751690af2SDimitry Andric #include "llvm/Object/SymbolicFile.h"
28284c1978SDimitry Andric #include "llvm/Support/DataExtractor.h"
2939d628a0SDimitry Andric #include "llvm/Support/Debug.h"
3051690af2SDimitry Andric #include "llvm/Support/Error.h"
3151690af2SDimitry Andric #include "llvm/Support/ErrorHandling.h"
32dff0c46cSDimitry Andric #include "llvm/Support/Format.h"
33284c1978SDimitry Andric #include "llvm/Support/Host.h"
3439d628a0SDimitry Andric #include "llvm/Support/LEB128.h"
353b0f4066SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
3651690af2SDimitry Andric #include "llvm/Support/SwapByteOrder.h"
37db17bf38SDimitry Andric #include "llvm/Support/raw_ostream.h"
3851690af2SDimitry Andric #include <algorithm>
3951690af2SDimitry Andric #include <cassert>
4051690af2SDimitry Andric #include <cstddef>
4151690af2SDimitry Andric #include <cstdint>
423b0f4066SDimitry Andric #include <cstring>
433b0f4066SDimitry Andric #include <limits>
44d88c1a5aSDimitry Andric #include <list>
4551690af2SDimitry Andric #include <memory>
4651690af2SDimitry Andric #include <string>
4751690af2SDimitry Andric #include <system_error>
483b0f4066SDimitry Andric 
493b0f4066SDimitry Andric using namespace llvm;
503b0f4066SDimitry Andric using namespace object;
513b0f4066SDimitry Andric 
5291bc56edSDimitry Andric namespace {
5351690af2SDimitry Andric 
54f785676fSDimitry Andric   struct section_base {
55f785676fSDimitry Andric     char sectname[16];
56f785676fSDimitry Andric     char segname[16];
57284c1978SDimitry Andric   };
5851690af2SDimitry Andric 
5951690af2SDimitry Andric } // end anonymous namespace
603b0f4066SDimitry Andric 
malformedError(const Twine & Msg)612cab237bSDimitry Andric static Error malformedError(const Twine &Msg) {
622cab237bSDimitry Andric   return make_error<GenericBinaryError>("truncated or malformed object (" +
632cab237bSDimitry Andric                                             Msg + ")",
643ca95b02SDimitry Andric                                         object_error::parse_failed);
653ca95b02SDimitry Andric }
663ca95b02SDimitry Andric 
6797bc6c73SDimitry Andric // FIXME: Replace all uses of this function with getStructOrErr.
68284c1978SDimitry Andric template <typename T>
getStruct(const MachOObjectFile & O,const char * P)69d88c1a5aSDimitry Andric static T getStruct(const MachOObjectFile &O, const char *P) {
70ff0cc061SDimitry Andric   // Don't read before the beginning or past the end of the file
71d88c1a5aSDimitry Andric   if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
72ff0cc061SDimitry Andric     report_fatal_error("Malformed MachO file.");
73ff0cc061SDimitry Andric 
74284c1978SDimitry Andric   T Cmd;
75284c1978SDimitry Andric   memcpy(&Cmd, P, sizeof(T));
76d88c1a5aSDimitry Andric   if (O.isLittleEndian() != sys::IsLittleEndianHost)
7791bc56edSDimitry Andric     MachO::swapStruct(Cmd);
78284c1978SDimitry Andric   return Cmd;
79284c1978SDimitry Andric }
80284c1978SDimitry Andric 
8197bc6c73SDimitry Andric template <typename T>
getStructOrErr(const MachOObjectFile & O,const char * P)82d88c1a5aSDimitry Andric static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
8397bc6c73SDimitry Andric   // Don't read before the beginning or past the end of the file
84d88c1a5aSDimitry Andric   if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
853ca95b02SDimitry Andric     return malformedError("Structure read out-of-range");
86ff0cc061SDimitry Andric 
8797bc6c73SDimitry Andric   T Cmd;
8897bc6c73SDimitry Andric   memcpy(&Cmd, P, sizeof(T));
89d88c1a5aSDimitry Andric   if (O.isLittleEndian() != sys::IsLittleEndianHost)
9097bc6c73SDimitry Andric     MachO::swapStruct(Cmd);
9197bc6c73SDimitry Andric   return Cmd;
92284c1978SDimitry Andric }
93284c1978SDimitry Andric 
94284c1978SDimitry Andric static const char *
getSectionPtr(const MachOObjectFile & O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)95d88c1a5aSDimitry Andric getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
96284c1978SDimitry Andric               unsigned Sec) {
97284c1978SDimitry Andric   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
98284c1978SDimitry Andric 
99d88c1a5aSDimitry Andric   bool Is64 = O.is64Bit();
100f785676fSDimitry Andric   unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
101f785676fSDimitry Andric                                     sizeof(MachO::segment_command);
102f785676fSDimitry Andric   unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
103f785676fSDimitry Andric                                 sizeof(MachO::section);
104284c1978SDimitry Andric 
105284c1978SDimitry Andric   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
106284c1978SDimitry Andric   return reinterpret_cast<const char*>(SectionAddr);
107284c1978SDimitry Andric }
108284c1978SDimitry Andric 
getPtr(const MachOObjectFile & O,size_t Offset)109d88c1a5aSDimitry Andric static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
1104ba319b5SDimitry Andric   assert(Offset <= O.getData().size());
1114ba319b5SDimitry Andric   return O.getData().data() + Offset;
112284c1978SDimitry Andric }
113284c1978SDimitry Andric 
11491bc56edSDimitry Andric static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile & O,DataRefImpl DRI)115d88c1a5aSDimitry Andric getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
116284c1978SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
11791bc56edSDimitry Andric   return getStruct<MachO::nlist_base>(O, P);
118284c1978SDimitry Andric }
119284c1978SDimitry Andric 
parseSegmentOrSectionName(const char * P)120284c1978SDimitry Andric static StringRef parseSegmentOrSectionName(const char *P) {
121284c1978SDimitry Andric   if (P[15] == 0)
122284c1978SDimitry Andric     // Null terminated.
123284c1978SDimitry Andric     return P;
124284c1978SDimitry Andric   // Not null terminated, so this is a 16 char string.
125284c1978SDimitry Andric   return StringRef(P, 16);
126284c1978SDimitry Andric }
127284c1978SDimitry Andric 
getCPUType(const MachOObjectFile & O)128d88c1a5aSDimitry Andric static unsigned getCPUType(const MachOObjectFile &O) {
129d88c1a5aSDimitry Andric   return O.getHeader().cputype;
130284c1978SDimitry Andric }
131284c1978SDimitry Andric 
132f785676fSDimitry Andric static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)133f785676fSDimitry Andric getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
134f785676fSDimitry Andric   return RE.r_word0;
135284c1978SDimitry Andric }
136284c1978SDimitry Andric 
137284c1978SDimitry Andric static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)138f785676fSDimitry Andric getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
139f785676fSDimitry Andric   return RE.r_word0 & 0xffffff;
140284c1978SDimitry Andric }
141284c1978SDimitry Andric 
getPlainRelocationPCRel(const MachOObjectFile & O,const MachO::any_relocation_info & RE)142d88c1a5aSDimitry Andric static bool getPlainRelocationPCRel(const MachOObjectFile &O,
143f785676fSDimitry Andric                                     const MachO::any_relocation_info &RE) {
144d88c1a5aSDimitry Andric   if (O.isLittleEndian())
145f785676fSDimitry Andric     return (RE.r_word1 >> 24) & 1;
146f785676fSDimitry Andric   return (RE.r_word1 >> 7) & 1;
147284c1978SDimitry Andric }
148284c1978SDimitry Andric 
149284c1978SDimitry Andric static bool
getScatteredRelocationPCRel(const MachO::any_relocation_info & RE)150d88c1a5aSDimitry Andric getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
151f785676fSDimitry Andric   return (RE.r_word0 >> 30) & 1;
152284c1978SDimitry Andric }
153284c1978SDimitry Andric 
getPlainRelocationLength(const MachOObjectFile & O,const MachO::any_relocation_info & RE)154d88c1a5aSDimitry Andric static unsigned getPlainRelocationLength(const MachOObjectFile &O,
155f785676fSDimitry Andric                                          const MachO::any_relocation_info &RE) {
156d88c1a5aSDimitry Andric   if (O.isLittleEndian())
157f785676fSDimitry Andric     return (RE.r_word1 >> 25) & 3;
158f785676fSDimitry Andric   return (RE.r_word1 >> 5) & 3;
159284c1978SDimitry Andric }
160284c1978SDimitry Andric 
161284c1978SDimitry Andric static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)162f785676fSDimitry Andric getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
163f785676fSDimitry Andric   return (RE.r_word0 >> 28) & 3;
164284c1978SDimitry Andric }
165284c1978SDimitry Andric 
getPlainRelocationType(const MachOObjectFile & O,const MachO::any_relocation_info & RE)166d88c1a5aSDimitry Andric static unsigned getPlainRelocationType(const MachOObjectFile &O,
167f785676fSDimitry Andric                                        const MachO::any_relocation_info &RE) {
168d88c1a5aSDimitry Andric   if (O.isLittleEndian())
169f785676fSDimitry Andric     return RE.r_word1 >> 28;
170f785676fSDimitry Andric   return RE.r_word1 & 0xf;
171284c1978SDimitry Andric }
172284c1978SDimitry Andric 
getSectionFlags(const MachOObjectFile & O,DataRefImpl Sec)173d88c1a5aSDimitry Andric static uint32_t getSectionFlags(const MachOObjectFile &O,
174284c1978SDimitry Andric                                 DataRefImpl Sec) {
175d88c1a5aSDimitry Andric   if (O.is64Bit()) {
176d88c1a5aSDimitry Andric     MachO::section_64 Sect = O.getSection64(Sec);
177f785676fSDimitry Andric     return Sect.flags;
178284c1978SDimitry Andric   }
179d88c1a5aSDimitry Andric   MachO::section Sect = O.getSection(Sec);
180f785676fSDimitry Andric   return Sect.flags;
181284c1978SDimitry Andric }
182284c1978SDimitry Andric 
1833ca95b02SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile & Obj,const char * Ptr,uint32_t LoadCommandIndex)184d88c1a5aSDimitry Andric getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
1853ca95b02SDimitry Andric                    uint32_t LoadCommandIndex) {
1863ca95b02SDimitry Andric   if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
1872cab237bSDimitry Andric     if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
1882cab237bSDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
1892cab237bSDimitry Andric                             " extends past end of file");
19097bc6c73SDimitry Andric     if (CmdOrErr->cmdsize < 8)
1913ca95b02SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
1923ca95b02SDimitry Andric                             " with size less than 8 bytes");
1933ca95b02SDimitry Andric     return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
1943ca95b02SDimitry Andric   } else
1953ca95b02SDimitry Andric     return CmdOrErr.takeError();
19697bc6c73SDimitry Andric }
19797bc6c73SDimitry Andric 
1983ca95b02SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getFirstLoadCommandInfo(const MachOObjectFile & Obj)199d88c1a5aSDimitry Andric getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
200d88c1a5aSDimitry Andric   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
20197bc6c73SDimitry Andric                                       : sizeof(MachO::mach_header);
202d88c1a5aSDimitry Andric   if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
2033ca95b02SDimitry Andric     return malformedError("load command 0 extends past the end all load "
2043ca95b02SDimitry Andric                           "commands in the file");
2053ca95b02SDimitry Andric   return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
20697bc6c73SDimitry Andric }
20797bc6c73SDimitry Andric 
2083ca95b02SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getNextLoadCommandInfo(const MachOObjectFile & Obj,uint32_t LoadCommandIndex,const MachOObjectFile::LoadCommandInfo & L)209d88c1a5aSDimitry Andric getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
21097bc6c73SDimitry Andric                        const MachOObjectFile::LoadCommandInfo &L) {
211d88c1a5aSDimitry Andric   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
2123ca95b02SDimitry Andric                                       : sizeof(MachO::mach_header);
213d88c1a5aSDimitry Andric   if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
214d88c1a5aSDimitry Andric       Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
2153ca95b02SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex + 1) +
2163ca95b02SDimitry Andric                           " extends past the end all load commands in the file");
2173ca95b02SDimitry Andric   return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
21897bc6c73SDimitry Andric }
21997bc6c73SDimitry Andric 
22097bc6c73SDimitry Andric template <typename T>
parseHeader(const MachOObjectFile & Obj,T & Header,Error & Err)221d88c1a5aSDimitry Andric static void parseHeader(const MachOObjectFile &Obj, T &Header,
2223ca95b02SDimitry Andric                         Error &Err) {
223d88c1a5aSDimitry Andric   if (sizeof(T) > Obj.getData().size()) {
2243ca95b02SDimitry Andric     Err = malformedError("the mach header extends past the end of the "
2253ca95b02SDimitry Andric                          "file");
2263ca95b02SDimitry Andric     return;
2273ca95b02SDimitry Andric   }
2283ca95b02SDimitry Andric   if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
2293ca95b02SDimitry Andric     Header = *HeaderOrErr;
23097bc6c73SDimitry Andric   else
2313ca95b02SDimitry Andric     Err = HeaderOrErr.takeError();
23297bc6c73SDimitry Andric }
23397bc6c73SDimitry Andric 
234d88c1a5aSDimitry Andric // This is used to check for overlapping of Mach-O elements.
235d88c1a5aSDimitry Andric struct MachOElement {
236d88c1a5aSDimitry Andric   uint64_t Offset;
237d88c1a5aSDimitry Andric   uint64_t Size;
238d88c1a5aSDimitry Andric   const char *Name;
239d88c1a5aSDimitry Andric };
240d88c1a5aSDimitry Andric 
checkOverlappingElement(std::list<MachOElement> & Elements,uint64_t Offset,uint64_t Size,const char * Name)241d88c1a5aSDimitry Andric static Error checkOverlappingElement(std::list<MachOElement> &Elements,
242d88c1a5aSDimitry Andric                                      uint64_t Offset, uint64_t Size,
243d88c1a5aSDimitry Andric                                      const char *Name) {
244d88c1a5aSDimitry Andric   if (Size == 0)
245d88c1a5aSDimitry Andric     return Error::success();
246d88c1a5aSDimitry Andric 
247d88c1a5aSDimitry Andric   for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
248d88c1a5aSDimitry Andric     auto E = *it;
249d88c1a5aSDimitry Andric     if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
250d88c1a5aSDimitry Andric         (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
251d88c1a5aSDimitry Andric         (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
252d88c1a5aSDimitry Andric       return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
253d88c1a5aSDimitry Andric                             " with a size of " + Twine(Size) + ", overlaps " +
254d88c1a5aSDimitry Andric                             E.Name + " at offset " + Twine(E.Offset) + " with "
255d88c1a5aSDimitry Andric                             "a size of " + Twine(E.Size));
256d88c1a5aSDimitry Andric     auto nt = it;
257d88c1a5aSDimitry Andric     nt++;
258d88c1a5aSDimitry Andric     if (nt != Elements.end()) {
259d88c1a5aSDimitry Andric       auto N = *nt;
260d88c1a5aSDimitry Andric       if (Offset + Size <= N.Offset) {
261d88c1a5aSDimitry Andric         Elements.insert(nt, {Offset, Size, Name});
262d88c1a5aSDimitry Andric         return Error::success();
263d88c1a5aSDimitry Andric       }
264d88c1a5aSDimitry Andric     }
265d88c1a5aSDimitry Andric   }
266d88c1a5aSDimitry Andric   Elements.push_back({Offset, Size, Name});
267d88c1a5aSDimitry Andric   return Error::success();
268d88c1a5aSDimitry Andric }
269d88c1a5aSDimitry Andric 
27097bc6c73SDimitry Andric // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
27197bc6c73SDimitry Andric // sections to \param Sections, and optionally sets
27297bc6c73SDimitry Andric // \param IsPageZeroSegment to true.
273d88c1a5aSDimitry Andric template <typename Segment, typename Section>
parseSegmentLoadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & Sections,bool & IsPageZeroSegment,uint32_t LoadCommandIndex,const char * CmdName,uint64_t SizeOfHeaders,std::list<MachOElement> & Elements)2743ca95b02SDimitry Andric static Error parseSegmentLoadCommand(
275d88c1a5aSDimitry Andric     const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
2763ca95b02SDimitry Andric     SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
277d88c1a5aSDimitry Andric     uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
278d88c1a5aSDimitry Andric     std::list<MachOElement> &Elements) {
279d88c1a5aSDimitry Andric   const unsigned SegmentLoadSize = sizeof(Segment);
28097bc6c73SDimitry Andric   if (Load.C.cmdsize < SegmentLoadSize)
2813ca95b02SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
2823ca95b02SDimitry Andric                           " " + CmdName + " cmdsize too small");
283d88c1a5aSDimitry Andric   if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
284d88c1a5aSDimitry Andric     Segment S = SegOrErr.get();
285d88c1a5aSDimitry Andric     const unsigned SectionSize = sizeof(Section);
286d88c1a5aSDimitry Andric     uint64_t FileSize = Obj.getData().size();
28797bc6c73SDimitry Andric     if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
28897bc6c73SDimitry Andric         S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
2893ca95b02SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
2903ca95b02SDimitry Andric                             " inconsistent cmdsize in " + CmdName +
2913ca95b02SDimitry Andric                             " for the number of sections");
29297bc6c73SDimitry Andric     for (unsigned J = 0; J < S.nsects; ++J) {
29397bc6c73SDimitry Andric       const char *Sec = getSectionPtr(Obj, Load, J);
29497bc6c73SDimitry Andric       Sections.push_back(Sec);
295d88c1a5aSDimitry Andric       Section s = getStruct<Section>(Obj, Sec);
296d88c1a5aSDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
297d88c1a5aSDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
298d88c1a5aSDimitry Andric           s.flags != MachO::S_ZEROFILL &&
299d88c1a5aSDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
300d88c1a5aSDimitry Andric           s.offset > FileSize)
301d88c1a5aSDimitry Andric         return malformedError("offset field of section " + Twine(J) + " in " +
302d88c1a5aSDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
303d88c1a5aSDimitry Andric                               " extends past the end of the file");
304d88c1a5aSDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
305d88c1a5aSDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
306d88c1a5aSDimitry Andric           s.flags != MachO::S_ZEROFILL &&
307d88c1a5aSDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
308d88c1a5aSDimitry Andric           s.offset < SizeOfHeaders && s.size != 0)
309d88c1a5aSDimitry Andric         return malformedError("offset field of section " + Twine(J) + " in " +
310d88c1a5aSDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
311d88c1a5aSDimitry Andric                               " not past the headers of the file");
312d88c1a5aSDimitry Andric       uint64_t BigSize = s.offset;
313d88c1a5aSDimitry Andric       BigSize += s.size;
314d88c1a5aSDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
315d88c1a5aSDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
316d88c1a5aSDimitry Andric           s.flags != MachO::S_ZEROFILL &&
317d88c1a5aSDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
318d88c1a5aSDimitry Andric           BigSize > FileSize)
319d88c1a5aSDimitry Andric         return malformedError("offset field plus size field of section " +
320d88c1a5aSDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
321d88c1a5aSDimitry Andric                               Twine(LoadCommandIndex) +
322d88c1a5aSDimitry Andric                               " extends past the end of the file");
323d88c1a5aSDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
324d88c1a5aSDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
325d88c1a5aSDimitry Andric           s.flags != MachO::S_ZEROFILL &&
326d88c1a5aSDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
327d88c1a5aSDimitry Andric           s.size > S.filesize)
328d88c1a5aSDimitry Andric         return malformedError("size field of section " +
329d88c1a5aSDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
330d88c1a5aSDimitry Andric                               Twine(LoadCommandIndex) +
331d88c1a5aSDimitry Andric                               " greater than the segment");
332d88c1a5aSDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
333d88c1a5aSDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
334d88c1a5aSDimitry Andric           s.addr < S.vmaddr)
335d88c1a5aSDimitry Andric         return malformedError("addr field of section " + Twine(J) + " in " +
336d88c1a5aSDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
337d88c1a5aSDimitry Andric                               " less than the segment's vmaddr");
338d88c1a5aSDimitry Andric       BigSize = s.addr;
339d88c1a5aSDimitry Andric       BigSize += s.size;
340d88c1a5aSDimitry Andric       uint64_t BigEnd = S.vmaddr;
341d88c1a5aSDimitry Andric       BigEnd += S.vmsize;
342d88c1a5aSDimitry Andric       if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
343d88c1a5aSDimitry Andric         return malformedError("addr field plus size of section " + Twine(J) +
344d88c1a5aSDimitry Andric                               " in " + CmdName + " command " +
345d88c1a5aSDimitry Andric                               Twine(LoadCommandIndex) +
346d88c1a5aSDimitry Andric                               " greater than than "
347d88c1a5aSDimitry Andric                               "the segment's vmaddr plus vmsize");
348d88c1a5aSDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
349d88c1a5aSDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
350d88c1a5aSDimitry Andric           s.flags != MachO::S_ZEROFILL &&
351d88c1a5aSDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
352d88c1a5aSDimitry Andric         if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
353d88c1a5aSDimitry Andric                                                 "section contents"))
354d88c1a5aSDimitry Andric           return Err;
355d88c1a5aSDimitry Andric       if (s.reloff > FileSize)
356d88c1a5aSDimitry Andric         return malformedError("reloff field of section " + Twine(J) + " in " +
357d88c1a5aSDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
358d88c1a5aSDimitry Andric                               " extends past the end of the file");
359d88c1a5aSDimitry Andric       BigSize = s.nreloc;
360d88c1a5aSDimitry Andric       BigSize *= sizeof(struct MachO::relocation_info);
361d88c1a5aSDimitry Andric       BigSize += s.reloff;
362d88c1a5aSDimitry Andric       if (BigSize > FileSize)
363d88c1a5aSDimitry Andric         return malformedError("reloff field plus nreloc field times sizeof("
364d88c1a5aSDimitry Andric                               "struct relocation_info) of section " +
365d88c1a5aSDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
366d88c1a5aSDimitry Andric                               Twine(LoadCommandIndex) +
367d88c1a5aSDimitry Andric                               " extends past the end of the file");
368d88c1a5aSDimitry Andric       if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
369d88c1a5aSDimitry Andric                                               sizeof(struct
370d88c1a5aSDimitry Andric                                               MachO::relocation_info),
371d88c1a5aSDimitry Andric                                               "section relocation entries"))
372d88c1a5aSDimitry Andric         return Err;
37397bc6c73SDimitry Andric     }
374d88c1a5aSDimitry Andric     if (S.fileoff > FileSize)
375d88c1a5aSDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
376d88c1a5aSDimitry Andric                             " fileoff field in " + CmdName +
377d88c1a5aSDimitry Andric                             " extends past the end of the file");
378d88c1a5aSDimitry Andric     uint64_t BigSize = S.fileoff;
379d88c1a5aSDimitry Andric     BigSize += S.filesize;
380d88c1a5aSDimitry Andric     if (BigSize > FileSize)
381d88c1a5aSDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
382d88c1a5aSDimitry Andric                             " fileoff field plus filesize field in " +
383d88c1a5aSDimitry Andric                             CmdName + " extends past the end of the file");
384d88c1a5aSDimitry Andric     if (S.vmsize != 0 && S.filesize > S.vmsize)
385d88c1a5aSDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
3867a7e6055SDimitry Andric                             " filesize field in " + CmdName +
387d88c1a5aSDimitry Andric                             " greater than vmsize field");
38897bc6c73SDimitry Andric     IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
3893ca95b02SDimitry Andric   } else
3903ca95b02SDimitry Andric     return SegOrErr.takeError();
3913ca95b02SDimitry Andric 
3923ca95b02SDimitry Andric   return Error::success();
3933ca95b02SDimitry Andric }
3943ca95b02SDimitry Andric 
checkSymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** SymtabLoadCmd,std::list<MachOElement> & Elements)395d88c1a5aSDimitry Andric static Error checkSymtabCommand(const MachOObjectFile &Obj,
396d88c1a5aSDimitry Andric                                 const MachOObjectFile::LoadCommandInfo &Load,
397d88c1a5aSDimitry Andric                                 uint32_t LoadCommandIndex,
398d88c1a5aSDimitry Andric                                 const char **SymtabLoadCmd,
399d88c1a5aSDimitry Andric                                 std::list<MachOElement> &Elements) {
400d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::symtab_command))
401d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
402d88c1a5aSDimitry Andric                           " LC_SYMTAB cmdsize too small");
403d88c1a5aSDimitry Andric   if (*SymtabLoadCmd != nullptr)
404d88c1a5aSDimitry Andric     return malformedError("more than one LC_SYMTAB command");
405d88c1a5aSDimitry Andric   MachO::symtab_command Symtab =
406d88c1a5aSDimitry Andric     getStruct<MachO::symtab_command>(Obj, Load.Ptr);
407d88c1a5aSDimitry Andric   if (Symtab.cmdsize != sizeof(MachO::symtab_command))
408d88c1a5aSDimitry Andric     return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
409d88c1a5aSDimitry Andric                           " has incorrect cmdsize");
410d88c1a5aSDimitry Andric   uint64_t FileSize = Obj.getData().size();
411d88c1a5aSDimitry Andric   if (Symtab.symoff > FileSize)
412d88c1a5aSDimitry Andric     return malformedError("symoff field of LC_SYMTAB command " +
413d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
414d88c1a5aSDimitry Andric                           "of the file");
415d88c1a5aSDimitry Andric   uint64_t SymtabSize = Symtab.nsyms;
416d88c1a5aSDimitry Andric   const char *struct_nlist_name;
417d88c1a5aSDimitry Andric   if (Obj.is64Bit()) {
418d88c1a5aSDimitry Andric     SymtabSize *= sizeof(MachO::nlist_64);
419d88c1a5aSDimitry Andric     struct_nlist_name = "struct nlist_64";
420d88c1a5aSDimitry Andric   } else {
421d88c1a5aSDimitry Andric     SymtabSize *= sizeof(MachO::nlist);
422d88c1a5aSDimitry Andric     struct_nlist_name = "struct nlist";
423d88c1a5aSDimitry Andric   }
424d88c1a5aSDimitry Andric   uint64_t BigSize = SymtabSize;
425d88c1a5aSDimitry Andric   BigSize += Symtab.symoff;
426d88c1a5aSDimitry Andric   if (BigSize > FileSize)
427d88c1a5aSDimitry Andric     return malformedError("symoff field plus nsyms field times sizeof(" +
428d88c1a5aSDimitry Andric                           Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
429d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
430d88c1a5aSDimitry Andric                           "of the file");
431d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
432d88c1a5aSDimitry Andric                                           "symbol table"))
433d88c1a5aSDimitry Andric     return Err;
434d88c1a5aSDimitry Andric   if (Symtab.stroff > FileSize)
435d88c1a5aSDimitry Andric     return malformedError("stroff field of LC_SYMTAB command " +
436d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
437d88c1a5aSDimitry Andric                           "of the file");
438d88c1a5aSDimitry Andric   BigSize = Symtab.stroff;
439d88c1a5aSDimitry Andric   BigSize += Symtab.strsize;
440d88c1a5aSDimitry Andric   if (BigSize > FileSize)
441d88c1a5aSDimitry Andric     return malformedError("stroff field plus strsize field of LC_SYMTAB "
442d88c1a5aSDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
443d88c1a5aSDimitry Andric                           "past the end of the file");
444d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
445d88c1a5aSDimitry Andric                                           Symtab.strsize, "string table"))
446d88c1a5aSDimitry Andric     return Err;
447d88c1a5aSDimitry Andric   *SymtabLoadCmd = Load.Ptr;
448d88c1a5aSDimitry Andric   return Error::success();
449d88c1a5aSDimitry Andric }
450d88c1a5aSDimitry Andric 
checkDysymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** DysymtabLoadCmd,std::list<MachOElement> & Elements)451d88c1a5aSDimitry Andric static Error checkDysymtabCommand(const MachOObjectFile &Obj,
452d88c1a5aSDimitry Andric                                   const MachOObjectFile::LoadCommandInfo &Load,
453d88c1a5aSDimitry Andric                                   uint32_t LoadCommandIndex,
454d88c1a5aSDimitry Andric                                   const char **DysymtabLoadCmd,
455d88c1a5aSDimitry Andric                                   std::list<MachOElement> &Elements) {
456d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
457d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
458d88c1a5aSDimitry Andric                           " LC_DYSYMTAB cmdsize too small");
459d88c1a5aSDimitry Andric   if (*DysymtabLoadCmd != nullptr)
460d88c1a5aSDimitry Andric     return malformedError("more than one LC_DYSYMTAB command");
461d88c1a5aSDimitry Andric   MachO::dysymtab_command Dysymtab =
462d88c1a5aSDimitry Andric     getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
463d88c1a5aSDimitry Andric   if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
464d88c1a5aSDimitry Andric     return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
465d88c1a5aSDimitry Andric                           " has incorrect cmdsize");
466d88c1a5aSDimitry Andric   uint64_t FileSize = Obj.getData().size();
467d88c1a5aSDimitry Andric   if (Dysymtab.tocoff > FileSize)
468d88c1a5aSDimitry Andric     return malformedError("tocoff field of LC_DYSYMTAB command " +
469d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
470d88c1a5aSDimitry Andric                           "the file");
471d88c1a5aSDimitry Andric   uint64_t BigSize = Dysymtab.ntoc;
472d88c1a5aSDimitry Andric   BigSize *= sizeof(MachO::dylib_table_of_contents);
473d88c1a5aSDimitry Andric   BigSize += Dysymtab.tocoff;
474d88c1a5aSDimitry Andric   if (BigSize > FileSize)
475d88c1a5aSDimitry Andric     return malformedError("tocoff field plus ntoc field times sizeof(struct "
476d88c1a5aSDimitry Andric                           "dylib_table_of_contents) of LC_DYSYMTAB command " +
477d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
478d88c1a5aSDimitry Andric                           "the file");
479d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
480d88c1a5aSDimitry Andric                                           Dysymtab.ntoc * sizeof(struct
481d88c1a5aSDimitry Andric                                           MachO::dylib_table_of_contents),
482d88c1a5aSDimitry Andric                                           "table of contents"))
483d88c1a5aSDimitry Andric     return Err;
484d88c1a5aSDimitry Andric   if (Dysymtab.modtaboff > FileSize)
485d88c1a5aSDimitry Andric     return malformedError("modtaboff field of LC_DYSYMTAB command " +
486d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
487d88c1a5aSDimitry Andric                           "the file");
488d88c1a5aSDimitry Andric   BigSize = Dysymtab.nmodtab;
489d88c1a5aSDimitry Andric   const char *struct_dylib_module_name;
490d88c1a5aSDimitry Andric   uint64_t sizeof_modtab;
491d88c1a5aSDimitry Andric   if (Obj.is64Bit()) {
492d88c1a5aSDimitry Andric     sizeof_modtab = sizeof(MachO::dylib_module_64);
493d88c1a5aSDimitry Andric     struct_dylib_module_name = "struct dylib_module_64";
494d88c1a5aSDimitry Andric   } else {
495d88c1a5aSDimitry Andric     sizeof_modtab = sizeof(MachO::dylib_module);
496d88c1a5aSDimitry Andric     struct_dylib_module_name = "struct dylib_module";
497d88c1a5aSDimitry Andric   }
498d88c1a5aSDimitry Andric   BigSize *= sizeof_modtab;
499d88c1a5aSDimitry Andric   BigSize += Dysymtab.modtaboff;
500d88c1a5aSDimitry Andric   if (BigSize > FileSize)
501d88c1a5aSDimitry Andric     return malformedError("modtaboff field plus nmodtab field times sizeof(" +
502d88c1a5aSDimitry Andric                           Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
503d88c1a5aSDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
504d88c1a5aSDimitry Andric                           "past the end of the file");
505d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
506d88c1a5aSDimitry Andric                                           Dysymtab.nmodtab * sizeof_modtab,
507d88c1a5aSDimitry Andric                                           "module table"))
508d88c1a5aSDimitry Andric     return Err;
509d88c1a5aSDimitry Andric   if (Dysymtab.extrefsymoff > FileSize)
510d88c1a5aSDimitry Andric     return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
511d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
512d88c1a5aSDimitry Andric                           "the file");
513d88c1a5aSDimitry Andric   BigSize = Dysymtab.nextrefsyms;
514d88c1a5aSDimitry Andric   BigSize *= sizeof(MachO::dylib_reference);
515d88c1a5aSDimitry Andric   BigSize += Dysymtab.extrefsymoff;
516d88c1a5aSDimitry Andric   if (BigSize > FileSize)
517d88c1a5aSDimitry Andric     return malformedError("extrefsymoff field plus nextrefsyms field times "
518d88c1a5aSDimitry Andric                           "sizeof(struct dylib_reference) of LC_DYSYMTAB "
519d88c1a5aSDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
520d88c1a5aSDimitry Andric                           "past the end of the file");
521d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
522d88c1a5aSDimitry Andric                                           Dysymtab.nextrefsyms *
523d88c1a5aSDimitry Andric                                               sizeof(MachO::dylib_reference),
524d88c1a5aSDimitry Andric                                           "reference table"))
525d88c1a5aSDimitry Andric     return Err;
526d88c1a5aSDimitry Andric   if (Dysymtab.indirectsymoff > FileSize)
527d88c1a5aSDimitry Andric     return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
528d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
529d88c1a5aSDimitry Andric                           "the file");
530d88c1a5aSDimitry Andric   BigSize = Dysymtab.nindirectsyms;
531d88c1a5aSDimitry Andric   BigSize *= sizeof(uint32_t);
532d88c1a5aSDimitry Andric   BigSize += Dysymtab.indirectsymoff;
533d88c1a5aSDimitry Andric   if (BigSize > FileSize)
534d88c1a5aSDimitry Andric     return malformedError("indirectsymoff field plus nindirectsyms field times "
535d88c1a5aSDimitry Andric                           "sizeof(uint32_t) of LC_DYSYMTAB command " +
536d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
537d88c1a5aSDimitry Andric                           "the file");
538d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
539d88c1a5aSDimitry Andric                                           Dysymtab.nindirectsyms *
540d88c1a5aSDimitry Andric                                           sizeof(uint32_t),
541d88c1a5aSDimitry Andric                                           "indirect table"))
542d88c1a5aSDimitry Andric     return Err;
543d88c1a5aSDimitry Andric   if (Dysymtab.extreloff > FileSize)
544d88c1a5aSDimitry Andric     return malformedError("extreloff field of LC_DYSYMTAB command " +
545d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
546d88c1a5aSDimitry Andric                           "the file");
547d88c1a5aSDimitry Andric   BigSize = Dysymtab.nextrel;
548d88c1a5aSDimitry Andric   BigSize *= sizeof(MachO::relocation_info);
549d88c1a5aSDimitry Andric   BigSize += Dysymtab.extreloff;
550d88c1a5aSDimitry Andric   if (BigSize > FileSize)
551d88c1a5aSDimitry Andric     return malformedError("extreloff field plus nextrel field times sizeof"
552d88c1a5aSDimitry Andric                           "(struct relocation_info) of LC_DYSYMTAB command " +
553d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
554d88c1a5aSDimitry Andric                           "the file");
555d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
556d88c1a5aSDimitry Andric                                           Dysymtab.nextrel *
557d88c1a5aSDimitry Andric                                               sizeof(MachO::relocation_info),
558d88c1a5aSDimitry Andric                                           "external relocation table"))
559d88c1a5aSDimitry Andric     return Err;
560d88c1a5aSDimitry Andric   if (Dysymtab.locreloff > FileSize)
561d88c1a5aSDimitry Andric     return malformedError("locreloff field of LC_DYSYMTAB command " +
562d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
563d88c1a5aSDimitry Andric                           "the file");
564d88c1a5aSDimitry Andric   BigSize = Dysymtab.nlocrel;
565d88c1a5aSDimitry Andric   BigSize *= sizeof(MachO::relocation_info);
566d88c1a5aSDimitry Andric   BigSize += Dysymtab.locreloff;
567d88c1a5aSDimitry Andric   if (BigSize > FileSize)
568d88c1a5aSDimitry Andric     return malformedError("locreloff field plus nlocrel field times sizeof"
569d88c1a5aSDimitry Andric                           "(struct relocation_info) of LC_DYSYMTAB command " +
570d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
571d88c1a5aSDimitry Andric                           "the file");
572d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
573d88c1a5aSDimitry Andric                                           Dysymtab.nlocrel *
574d88c1a5aSDimitry Andric                                               sizeof(MachO::relocation_info),
575d88c1a5aSDimitry Andric                                           "local relocation table"))
576d88c1a5aSDimitry Andric     return Err;
577d88c1a5aSDimitry Andric   *DysymtabLoadCmd = Load.Ptr;
578d88c1a5aSDimitry Andric   return Error::success();
579d88c1a5aSDimitry Andric }
580d88c1a5aSDimitry Andric 
checkLinkeditDataCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements,const char * ElementName)581d88c1a5aSDimitry Andric static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
582d88c1a5aSDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
583d88c1a5aSDimitry Andric                                  uint32_t LoadCommandIndex,
584d88c1a5aSDimitry Andric                                  const char **LoadCmd, const char *CmdName,
585d88c1a5aSDimitry Andric                                  std::list<MachOElement> &Elements,
586d88c1a5aSDimitry Andric                                  const char *ElementName) {
587d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
588d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
589d88c1a5aSDimitry Andric                           CmdName + " cmdsize too small");
590d88c1a5aSDimitry Andric   if (*LoadCmd != nullptr)
591d88c1a5aSDimitry Andric     return malformedError("more than one " + Twine(CmdName) + " command");
592d88c1a5aSDimitry Andric   MachO::linkedit_data_command LinkData =
593d88c1a5aSDimitry Andric     getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
594d88c1a5aSDimitry Andric   if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
595d88c1a5aSDimitry Andric     return malformedError(Twine(CmdName) + " command " +
596d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " has incorrect cmdsize");
597d88c1a5aSDimitry Andric   uint64_t FileSize = Obj.getData().size();
598d88c1a5aSDimitry Andric   if (LinkData.dataoff > FileSize)
599d88c1a5aSDimitry Andric     return malformedError("dataoff field of " + Twine(CmdName) + " command " +
600d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
601d88c1a5aSDimitry Andric                           "the file");
602d88c1a5aSDimitry Andric   uint64_t BigSize = LinkData.dataoff;
603d88c1a5aSDimitry Andric   BigSize += LinkData.datasize;
604d88c1a5aSDimitry Andric   if (BigSize > FileSize)
605d88c1a5aSDimitry Andric     return malformedError("dataoff field plus datasize field of " +
606d88c1a5aSDimitry Andric                           Twine(CmdName) + " command " +
607d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
608d88c1a5aSDimitry Andric                           "the file");
609d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
610d88c1a5aSDimitry Andric                                           LinkData.datasize, ElementName))
611d88c1a5aSDimitry Andric     return Err;
612d88c1a5aSDimitry Andric   *LoadCmd = Load.Ptr;
613d88c1a5aSDimitry Andric   return Error::success();
614d88c1a5aSDimitry Andric }
615d88c1a5aSDimitry Andric 
checkDyldInfoCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements)616d88c1a5aSDimitry Andric static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
617d88c1a5aSDimitry Andric                                   const MachOObjectFile::LoadCommandInfo &Load,
618d88c1a5aSDimitry Andric                                   uint32_t LoadCommandIndex,
619d88c1a5aSDimitry Andric                                   const char **LoadCmd, const char *CmdName,
620d88c1a5aSDimitry Andric                                   std::list<MachOElement> &Elements) {
621d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
622d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
623d88c1a5aSDimitry Andric                           CmdName + " cmdsize too small");
624d88c1a5aSDimitry Andric   if (*LoadCmd != nullptr)
625d88c1a5aSDimitry Andric     return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
626d88c1a5aSDimitry Andric                           "command");
627d88c1a5aSDimitry Andric   MachO::dyld_info_command DyldInfo =
628d88c1a5aSDimitry Andric     getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
629d88c1a5aSDimitry Andric   if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
630d88c1a5aSDimitry Andric     return malformedError(Twine(CmdName) + " command " +
631d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " has incorrect cmdsize");
632d88c1a5aSDimitry Andric   uint64_t FileSize = Obj.getData().size();
633d88c1a5aSDimitry Andric   if (DyldInfo.rebase_off > FileSize)
634d88c1a5aSDimitry Andric     return malformedError("rebase_off field of " + Twine(CmdName) +
635d88c1a5aSDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
636d88c1a5aSDimitry Andric                           "past the end of the file");
637d88c1a5aSDimitry Andric   uint64_t BigSize = DyldInfo.rebase_off;
638d88c1a5aSDimitry Andric   BigSize += DyldInfo.rebase_size;
639d88c1a5aSDimitry Andric   if (BigSize > FileSize)
640d88c1a5aSDimitry Andric     return malformedError("rebase_off field plus rebase_size field of " +
641d88c1a5aSDimitry Andric                           Twine(CmdName) + " command " +
642d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
643d88c1a5aSDimitry Andric                           "the file");
644d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
645d88c1a5aSDimitry Andric                                           DyldInfo.rebase_size,
646d88c1a5aSDimitry Andric                                           "dyld rebase info"))
647d88c1a5aSDimitry Andric     return Err;
648d88c1a5aSDimitry Andric   if (DyldInfo.bind_off > FileSize)
649d88c1a5aSDimitry Andric     return malformedError("bind_off field of " + Twine(CmdName) +
650d88c1a5aSDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
651d88c1a5aSDimitry Andric                           "past the end of the file");
652d88c1a5aSDimitry Andric   BigSize = DyldInfo.bind_off;
653d88c1a5aSDimitry Andric   BigSize += DyldInfo.bind_size;
654d88c1a5aSDimitry Andric   if (BigSize > FileSize)
655d88c1a5aSDimitry Andric     return malformedError("bind_off field plus bind_size field of " +
656d88c1a5aSDimitry Andric                           Twine(CmdName) + " command " +
657d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
658d88c1a5aSDimitry Andric                           "the file");
659d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
660d88c1a5aSDimitry Andric                                           DyldInfo.bind_size,
661d88c1a5aSDimitry Andric                                           "dyld bind info"))
662d88c1a5aSDimitry Andric     return Err;
663d88c1a5aSDimitry Andric   if (DyldInfo.weak_bind_off > FileSize)
664d88c1a5aSDimitry Andric     return malformedError("weak_bind_off field of " + Twine(CmdName) +
665d88c1a5aSDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
666d88c1a5aSDimitry Andric                           "past the end of the file");
667d88c1a5aSDimitry Andric   BigSize = DyldInfo.weak_bind_off;
668d88c1a5aSDimitry Andric   BigSize += DyldInfo.weak_bind_size;
669d88c1a5aSDimitry Andric   if (BigSize > FileSize)
670d88c1a5aSDimitry Andric     return malformedError("weak_bind_off field plus weak_bind_size field of " +
671d88c1a5aSDimitry Andric                           Twine(CmdName) + " command " +
672d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
673d88c1a5aSDimitry Andric                           "the file");
674d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
675d88c1a5aSDimitry Andric                                           DyldInfo.weak_bind_size,
676d88c1a5aSDimitry Andric                                           "dyld weak bind info"))
677d88c1a5aSDimitry Andric     return Err;
678d88c1a5aSDimitry Andric   if (DyldInfo.lazy_bind_off > FileSize)
679d88c1a5aSDimitry Andric     return malformedError("lazy_bind_off field of " + Twine(CmdName) +
680d88c1a5aSDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
681d88c1a5aSDimitry Andric                           "past the end of the file");
682d88c1a5aSDimitry Andric   BigSize = DyldInfo.lazy_bind_off;
683d88c1a5aSDimitry Andric   BigSize += DyldInfo.lazy_bind_size;
684d88c1a5aSDimitry Andric   if (BigSize > FileSize)
685d88c1a5aSDimitry Andric     return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
686d88c1a5aSDimitry Andric                           Twine(CmdName) + " command " +
687d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
688d88c1a5aSDimitry Andric                           "the file");
689d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
690d88c1a5aSDimitry Andric                                           DyldInfo.lazy_bind_size,
691d88c1a5aSDimitry Andric                                           "dyld lazy bind info"))
692d88c1a5aSDimitry Andric     return Err;
693d88c1a5aSDimitry Andric   if (DyldInfo.export_off > FileSize)
694d88c1a5aSDimitry Andric     return malformedError("export_off field of " + Twine(CmdName) +
695d88c1a5aSDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
696d88c1a5aSDimitry Andric                           "past the end of the file");
697d88c1a5aSDimitry Andric   BigSize = DyldInfo.export_off;
698d88c1a5aSDimitry Andric   BigSize += DyldInfo.export_size;
699d88c1a5aSDimitry Andric   if (BigSize > FileSize)
700d88c1a5aSDimitry Andric     return malformedError("export_off field plus export_size field of " +
701d88c1a5aSDimitry Andric                           Twine(CmdName) + " command " +
702d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
703d88c1a5aSDimitry Andric                           "the file");
704d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
705d88c1a5aSDimitry Andric                                           DyldInfo.export_size,
706d88c1a5aSDimitry Andric                                           "dyld export info"))
707d88c1a5aSDimitry Andric     return Err;
708d88c1a5aSDimitry Andric   *LoadCmd = Load.Ptr;
709d88c1a5aSDimitry Andric   return Error::success();
710d88c1a5aSDimitry Andric }
711d88c1a5aSDimitry Andric 
checkDylibCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)712d88c1a5aSDimitry Andric static Error checkDylibCommand(const MachOObjectFile &Obj,
713d88c1a5aSDimitry Andric                                const MachOObjectFile::LoadCommandInfo &Load,
714d88c1a5aSDimitry Andric                                uint32_t LoadCommandIndex, const char *CmdName) {
715d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dylib_command))
716d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
717d88c1a5aSDimitry Andric                           CmdName + " cmdsize too small");
718d88c1a5aSDimitry Andric   MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
719d88c1a5aSDimitry Andric   if (D.dylib.name < sizeof(MachO::dylib_command))
720d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
721d88c1a5aSDimitry Andric                           CmdName + " name.offset field too small, not past "
722d88c1a5aSDimitry Andric                           "the end of the dylib_command struct");
723d88c1a5aSDimitry Andric   if (D.dylib.name >= D.cmdsize)
724d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
725d88c1a5aSDimitry Andric                           CmdName + " name.offset field extends past the end "
726d88c1a5aSDimitry Andric                           "of the load command");
727d88c1a5aSDimitry Andric   // Make sure there is a null between the starting offset of the name and
728d88c1a5aSDimitry Andric   // the end of the load command.
729d88c1a5aSDimitry Andric   uint32_t i;
730d88c1a5aSDimitry Andric   const char *P = (const char *)Load.Ptr;
731d88c1a5aSDimitry Andric   for (i = D.dylib.name; i < D.cmdsize; i++)
732d88c1a5aSDimitry Andric     if (P[i] == '\0')
733d88c1a5aSDimitry Andric       break;
734d88c1a5aSDimitry Andric   if (i >= D.cmdsize)
735d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
736d88c1a5aSDimitry Andric                           CmdName + " library name extends past the end of the "
737d88c1a5aSDimitry Andric                           "load command");
738d88c1a5aSDimitry Andric   return Error::success();
739d88c1a5aSDimitry Andric }
740d88c1a5aSDimitry Andric 
checkDylibIdCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd)741d88c1a5aSDimitry Andric static Error checkDylibIdCommand(const MachOObjectFile &Obj,
742d88c1a5aSDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
743d88c1a5aSDimitry Andric                                  uint32_t LoadCommandIndex,
744d88c1a5aSDimitry Andric                                  const char **LoadCmd) {
745d88c1a5aSDimitry Andric   if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
746d88c1a5aSDimitry Andric                                      "LC_ID_DYLIB"))
747d88c1a5aSDimitry Andric     return Err;
748d88c1a5aSDimitry Andric   if (*LoadCmd != nullptr)
749d88c1a5aSDimitry Andric     return malformedError("more than one LC_ID_DYLIB command");
750d88c1a5aSDimitry Andric   if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
751d88c1a5aSDimitry Andric       Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
752d88c1a5aSDimitry Andric     return malformedError("LC_ID_DYLIB load command in non-dynamic library "
753d88c1a5aSDimitry Andric                           "file type");
754d88c1a5aSDimitry Andric   *LoadCmd = Load.Ptr;
755d88c1a5aSDimitry Andric   return Error::success();
756d88c1a5aSDimitry Andric }
757d88c1a5aSDimitry Andric 
checkDyldCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)758d88c1a5aSDimitry Andric static Error checkDyldCommand(const MachOObjectFile &Obj,
759d88c1a5aSDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
760d88c1a5aSDimitry Andric                               uint32_t LoadCommandIndex, const char *CmdName) {
761d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
762d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
763d88c1a5aSDimitry Andric                           CmdName + " cmdsize too small");
764d88c1a5aSDimitry Andric   MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
765d88c1a5aSDimitry Andric   if (D.name < sizeof(MachO::dylinker_command))
766d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
767d88c1a5aSDimitry Andric                           CmdName + " name.offset field too small, not past "
768d88c1a5aSDimitry Andric                           "the end of the dylinker_command struct");
769d88c1a5aSDimitry Andric   if (D.name >= D.cmdsize)
770d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
771d88c1a5aSDimitry Andric                           CmdName + " name.offset field extends past the end "
772d88c1a5aSDimitry Andric                           "of the load command");
773d88c1a5aSDimitry Andric   // Make sure there is a null between the starting offset of the name and
774d88c1a5aSDimitry Andric   // the end of the load command.
775d88c1a5aSDimitry Andric   uint32_t i;
776d88c1a5aSDimitry Andric   const char *P = (const char *)Load.Ptr;
777d88c1a5aSDimitry Andric   for (i = D.name; i < D.cmdsize; i++)
778d88c1a5aSDimitry Andric     if (P[i] == '\0')
779d88c1a5aSDimitry Andric       break;
780d88c1a5aSDimitry Andric   if (i >= D.cmdsize)
781d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
782d88c1a5aSDimitry Andric                           CmdName + " dyld name extends past the end of the "
783d88c1a5aSDimitry Andric                           "load command");
784d88c1a5aSDimitry Andric   return Error::success();
785d88c1a5aSDimitry Andric }
786d88c1a5aSDimitry Andric 
checkVersCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName)787d88c1a5aSDimitry Andric static Error checkVersCommand(const MachOObjectFile &Obj,
788d88c1a5aSDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
789d88c1a5aSDimitry Andric                               uint32_t LoadCommandIndex,
790d88c1a5aSDimitry Andric                               const char **LoadCmd, const char *CmdName) {
791d88c1a5aSDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::version_min_command))
792d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
793d88c1a5aSDimitry Andric                           CmdName + " has incorrect cmdsize");
794d88c1a5aSDimitry Andric   if (*LoadCmd != nullptr)
795d88c1a5aSDimitry Andric     return malformedError("more than one LC_VERSION_MIN_MACOSX, "
796d88c1a5aSDimitry Andric                           "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
797d88c1a5aSDimitry Andric                           "LC_VERSION_MIN_WATCHOS command");
798d88c1a5aSDimitry Andric   *LoadCmd = Load.Ptr;
799d88c1a5aSDimitry Andric   return Error::success();
800d88c1a5aSDimitry Andric }
801d88c1a5aSDimitry Andric 
checkNoteCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,std::list<MachOElement> & Elements)8027a7e6055SDimitry Andric static Error checkNoteCommand(const MachOObjectFile &Obj,
8037a7e6055SDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
8047a7e6055SDimitry Andric                               uint32_t LoadCommandIndex,
8057a7e6055SDimitry Andric                               std::list<MachOElement> &Elements) {
8067a7e6055SDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::note_command))
8077a7e6055SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8087a7e6055SDimitry Andric                           " LC_NOTE has incorrect cmdsize");
8097a7e6055SDimitry Andric   MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
8107a7e6055SDimitry Andric   uint64_t FileSize = Obj.getData().size();
8117a7e6055SDimitry Andric   if (Nt.offset > FileSize)
8127a7e6055SDimitry Andric     return malformedError("offset field of LC_NOTE command " +
8137a7e6055SDimitry Andric                           Twine(LoadCommandIndex) + " extends "
8147a7e6055SDimitry Andric                           "past the end of the file");
8157a7e6055SDimitry Andric   uint64_t BigSize = Nt.offset;
8167a7e6055SDimitry Andric   BigSize += Nt.size;
8177a7e6055SDimitry Andric   if (BigSize > FileSize)
8187a7e6055SDimitry Andric     return malformedError("size field plus offset field of LC_NOTE command " +
8197a7e6055SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
8207a7e6055SDimitry Andric                           "the file");
8217a7e6055SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
8227a7e6055SDimitry Andric                                           "LC_NOTE data"))
8237a7e6055SDimitry Andric     return Err;
8247a7e6055SDimitry Andric   return Error::success();
8257a7e6055SDimitry Andric }
8267a7e6055SDimitry Andric 
8277a7e6055SDimitry Andric static Error
parseBuildVersionCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & BuildTools,uint32_t LoadCommandIndex)8287a7e6055SDimitry Andric parseBuildVersionCommand(const MachOObjectFile &Obj,
8297a7e6055SDimitry Andric                          const MachOObjectFile::LoadCommandInfo &Load,
8307a7e6055SDimitry Andric                          SmallVectorImpl<const char*> &BuildTools,
8317a7e6055SDimitry Andric                          uint32_t LoadCommandIndex) {
8327a7e6055SDimitry Andric   MachO::build_version_command BVC =
8337a7e6055SDimitry Andric       getStruct<MachO::build_version_command>(Obj, Load.Ptr);
8347a7e6055SDimitry Andric   if (Load.C.cmdsize !=
8357a7e6055SDimitry Andric       sizeof(MachO::build_version_command) +
8367a7e6055SDimitry Andric           BVC.ntools * sizeof(MachO::build_tool_version))
8377a7e6055SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8387a7e6055SDimitry Andric                           " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
8397a7e6055SDimitry Andric 
8407a7e6055SDimitry Andric   auto Start = Load.Ptr + sizeof(MachO::build_version_command);
8417a7e6055SDimitry Andric   BuildTools.resize(BVC.ntools);
8427a7e6055SDimitry Andric   for (unsigned i = 0; i < BVC.ntools; ++i)
8437a7e6055SDimitry Andric     BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
8447a7e6055SDimitry Andric 
8457a7e6055SDimitry Andric   return Error::success();
8467a7e6055SDimitry Andric }
8477a7e6055SDimitry Andric 
checkRpathCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)848d88c1a5aSDimitry Andric static Error checkRpathCommand(const MachOObjectFile &Obj,
849d88c1a5aSDimitry Andric                                const MachOObjectFile::LoadCommandInfo &Load,
850d88c1a5aSDimitry Andric                                uint32_t LoadCommandIndex) {
851d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::rpath_command))
852d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
853d88c1a5aSDimitry Andric                           " LC_RPATH cmdsize too small");
854d88c1a5aSDimitry Andric   MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
855d88c1a5aSDimitry Andric   if (R.path < sizeof(MachO::rpath_command))
856d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
857d88c1a5aSDimitry Andric                           " LC_RPATH path.offset field too small, not past "
858d88c1a5aSDimitry Andric                           "the end of the rpath_command struct");
859d88c1a5aSDimitry Andric   if (R.path >= R.cmdsize)
860d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
861d88c1a5aSDimitry Andric                           " LC_RPATH path.offset field extends past the end "
862d88c1a5aSDimitry Andric                           "of the load command");
863d88c1a5aSDimitry Andric   // Make sure there is a null between the starting offset of the path and
864d88c1a5aSDimitry Andric   // the end of the load command.
865d88c1a5aSDimitry Andric   uint32_t i;
866d88c1a5aSDimitry Andric   const char *P = (const char *)Load.Ptr;
867d88c1a5aSDimitry Andric   for (i = R.path; i < R.cmdsize; i++)
868d88c1a5aSDimitry Andric     if (P[i] == '\0')
869d88c1a5aSDimitry Andric       break;
870d88c1a5aSDimitry Andric   if (i >= R.cmdsize)
871d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
872d88c1a5aSDimitry Andric                           " LC_RPATH library name extends past the end of the "
873d88c1a5aSDimitry Andric                           "load command");
874d88c1a5aSDimitry Andric   return Error::success();
875d88c1a5aSDimitry Andric }
876d88c1a5aSDimitry Andric 
checkEncryptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,uint64_t cryptoff,uint64_t cryptsize,const char ** LoadCmd,const char * CmdName)877d88c1a5aSDimitry Andric static Error checkEncryptCommand(const MachOObjectFile &Obj,
878d88c1a5aSDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
879d88c1a5aSDimitry Andric                                  uint32_t LoadCommandIndex,
880d88c1a5aSDimitry Andric                                  uint64_t cryptoff, uint64_t cryptsize,
881d88c1a5aSDimitry Andric                                  const char **LoadCmd, const char *CmdName) {
882d88c1a5aSDimitry Andric   if (*LoadCmd != nullptr)
883d88c1a5aSDimitry Andric     return malformedError("more than one LC_ENCRYPTION_INFO and or "
884d88c1a5aSDimitry Andric                           "LC_ENCRYPTION_INFO_64 command");
885d88c1a5aSDimitry Andric   uint64_t FileSize = Obj.getData().size();
886d88c1a5aSDimitry Andric   if (cryptoff > FileSize)
887d88c1a5aSDimitry Andric     return malformedError("cryptoff field of " + Twine(CmdName) +
888d88c1a5aSDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
889d88c1a5aSDimitry Andric                           "past the end of the file");
890d88c1a5aSDimitry Andric   uint64_t BigSize = cryptoff;
891d88c1a5aSDimitry Andric   BigSize += cryptsize;
892d88c1a5aSDimitry Andric   if (BigSize > FileSize)
893d88c1a5aSDimitry Andric     return malformedError("cryptoff field plus cryptsize field of " +
894d88c1a5aSDimitry Andric                           Twine(CmdName) + " command " +
895d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
896d88c1a5aSDimitry Andric                           "the file");
897d88c1a5aSDimitry Andric   *LoadCmd = Load.Ptr;
898d88c1a5aSDimitry Andric   return Error::success();
899d88c1a5aSDimitry Andric }
900d88c1a5aSDimitry Andric 
checkLinkerOptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)901d88c1a5aSDimitry Andric static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
902d88c1a5aSDimitry Andric                                    const MachOObjectFile::LoadCommandInfo &Load,
903d88c1a5aSDimitry Andric                                    uint32_t LoadCommandIndex) {
904d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
905d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
906d88c1a5aSDimitry Andric                           " LC_LINKER_OPTION cmdsize too small");
907d88c1a5aSDimitry Andric   MachO::linker_option_command L =
908d88c1a5aSDimitry Andric     getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
909d88c1a5aSDimitry Andric   // Make sure the count of strings is correct.
910d88c1a5aSDimitry Andric   const char *string = (const char *)Load.Ptr +
911d88c1a5aSDimitry Andric                        sizeof(struct MachO::linker_option_command);
912d88c1a5aSDimitry Andric   uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
913d88c1a5aSDimitry Andric   uint32_t i = 0;
914d88c1a5aSDimitry Andric   while (left > 0) {
915d88c1a5aSDimitry Andric     while (*string == '\0' && left > 0) {
916d88c1a5aSDimitry Andric       string++;
917d88c1a5aSDimitry Andric       left--;
918d88c1a5aSDimitry Andric     }
919d88c1a5aSDimitry Andric     if (left > 0) {
920d88c1a5aSDimitry Andric       i++;
921d88c1a5aSDimitry Andric       uint32_t NullPos = StringRef(string, left).find('\0');
922d88c1a5aSDimitry Andric       uint32_t len = std::min(NullPos, left) + 1;
923d88c1a5aSDimitry Andric       string += len;
924d88c1a5aSDimitry Andric       left -= len;
925d88c1a5aSDimitry Andric     }
926d88c1a5aSDimitry Andric   }
927d88c1a5aSDimitry Andric   if (L.count != i)
928d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
929d88c1a5aSDimitry Andric                           " LC_LINKER_OPTION string count " + Twine(L.count) +
930d88c1a5aSDimitry Andric                           " does not match number of strings");
931d88c1a5aSDimitry Andric   return Error::success();
932d88c1a5aSDimitry Andric }
933d88c1a5aSDimitry Andric 
checkSubCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName,size_t SizeOfCmd,const char * CmdStructName,uint32_t PathOffset,const char * PathFieldName)934d88c1a5aSDimitry Andric static Error checkSubCommand(const MachOObjectFile &Obj,
935d88c1a5aSDimitry Andric                              const MachOObjectFile::LoadCommandInfo &Load,
936d88c1a5aSDimitry Andric                              uint32_t LoadCommandIndex, const char *CmdName,
937d88c1a5aSDimitry Andric                              size_t SizeOfCmd, const char *CmdStructName,
938d88c1a5aSDimitry Andric                              uint32_t PathOffset, const char *PathFieldName) {
939d88c1a5aSDimitry Andric   if (PathOffset < SizeOfCmd)
940d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
941d88c1a5aSDimitry Andric                           CmdName + " " + PathFieldName + ".offset field too "
942d88c1a5aSDimitry Andric                           "small, not past the end of the " + CmdStructName);
943d88c1a5aSDimitry Andric   if (PathOffset >= Load.C.cmdsize)
944d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
945d88c1a5aSDimitry Andric                           CmdName + " " + PathFieldName + ".offset field "
946d88c1a5aSDimitry Andric                           "extends past the end of the load command");
947d88c1a5aSDimitry Andric   // Make sure there is a null between the starting offset of the path and
948d88c1a5aSDimitry Andric   // the end of the load command.
949d88c1a5aSDimitry Andric   uint32_t i;
950d88c1a5aSDimitry Andric   const char *P = (const char *)Load.Ptr;
951d88c1a5aSDimitry Andric   for (i = PathOffset; i < Load.C.cmdsize; i++)
952d88c1a5aSDimitry Andric     if (P[i] == '\0')
953d88c1a5aSDimitry Andric       break;
954d88c1a5aSDimitry Andric   if (i >= Load.C.cmdsize)
955d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
956d88c1a5aSDimitry Andric                           CmdName + " " + PathFieldName + " name extends past "
957d88c1a5aSDimitry Andric                           "the end of the load command");
958d88c1a5aSDimitry Andric   return Error::success();
959d88c1a5aSDimitry Andric }
960d88c1a5aSDimitry Andric 
checkThreadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)961d88c1a5aSDimitry Andric static Error checkThreadCommand(const MachOObjectFile &Obj,
962d88c1a5aSDimitry Andric                                 const MachOObjectFile::LoadCommandInfo &Load,
963d88c1a5aSDimitry Andric                                 uint32_t LoadCommandIndex,
964d88c1a5aSDimitry Andric                                 const char *CmdName) {
965d88c1a5aSDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::thread_command))
966d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
967d88c1a5aSDimitry Andric                           CmdName + " cmdsize too small");
968d88c1a5aSDimitry Andric   MachO::thread_command T =
969d88c1a5aSDimitry Andric     getStruct<MachO::thread_command>(Obj, Load.Ptr);
970d88c1a5aSDimitry Andric   const char *state = Load.Ptr + sizeof(MachO::thread_command);
971d88c1a5aSDimitry Andric   const char *end = Load.Ptr + T.cmdsize;
972d88c1a5aSDimitry Andric   uint32_t nflavor = 0;
973d88c1a5aSDimitry Andric   uint32_t cputype = getCPUType(Obj);
974d88c1a5aSDimitry Andric   while (state < end) {
975d88c1a5aSDimitry Andric     if(state + sizeof(uint32_t) > end)
976d88c1a5aSDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
977d88c1a5aSDimitry Andric                             "flavor in " + CmdName + " extends past end of "
978d88c1a5aSDimitry Andric                             "command");
979d88c1a5aSDimitry Andric     uint32_t flavor;
980d88c1a5aSDimitry Andric     memcpy(&flavor, state, sizeof(uint32_t));
981d88c1a5aSDimitry Andric     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
982d88c1a5aSDimitry Andric       sys::swapByteOrder(flavor);
983d88c1a5aSDimitry Andric     state += sizeof(uint32_t);
984d88c1a5aSDimitry Andric 
985d88c1a5aSDimitry Andric     if(state + sizeof(uint32_t) > end)
986d88c1a5aSDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
987d88c1a5aSDimitry Andric                             " count in " + CmdName + " extends past end of "
988d88c1a5aSDimitry Andric                             "command");
989d88c1a5aSDimitry Andric     uint32_t count;
990d88c1a5aSDimitry Andric     memcpy(&count, state, sizeof(uint32_t));
991d88c1a5aSDimitry Andric     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
992d88c1a5aSDimitry Andric       sys::swapByteOrder(count);
993d88c1a5aSDimitry Andric     state += sizeof(uint32_t);
994d88c1a5aSDimitry Andric 
9957a7e6055SDimitry Andric     if (cputype == MachO::CPU_TYPE_I386) {
9967a7e6055SDimitry Andric       if (flavor == MachO::x86_THREAD_STATE32) {
9977a7e6055SDimitry Andric         if (count != MachO::x86_THREAD_STATE32_COUNT)
9987a7e6055SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
9997a7e6055SDimitry Andric                                 " count not x86_THREAD_STATE32_COUNT for "
10007a7e6055SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10017a7e6055SDimitry Andric                                 "a x86_THREAD_STATE32 flavor in " + CmdName +
10027a7e6055SDimitry Andric                                 " command");
10037a7e6055SDimitry Andric         if (state + sizeof(MachO::x86_thread_state32_t) > end)
10047a7e6055SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10057a7e6055SDimitry Andric                                 " x86_THREAD_STATE32 extends past end of "
10067a7e6055SDimitry Andric                                 "command in " + CmdName + " command");
10077a7e6055SDimitry Andric         state += sizeof(MachO::x86_thread_state32_t);
10087a7e6055SDimitry Andric       } else {
10097a7e6055SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
10107a7e6055SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
10117a7e6055SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
10127a7e6055SDimitry Andric                               CmdName + " command");
10137a7e6055SDimitry Andric       }
10147a7e6055SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_X86_64) {
10154ba319b5SDimitry Andric       if (flavor == MachO::x86_THREAD_STATE) {
10164ba319b5SDimitry Andric         if (count != MachO::x86_THREAD_STATE_COUNT)
10174ba319b5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10184ba319b5SDimitry Andric                                 " count not x86_THREAD_STATE_COUNT for "
10194ba319b5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10204ba319b5SDimitry Andric                                 "a x86_THREAD_STATE flavor in " + CmdName +
10214ba319b5SDimitry Andric                                 " command");
10224ba319b5SDimitry Andric         if (state + sizeof(MachO::x86_thread_state_t) > end)
10234ba319b5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10244ba319b5SDimitry Andric                                 " x86_THREAD_STATE extends past end of "
10254ba319b5SDimitry Andric                                 "command in " + CmdName + " command");
10264ba319b5SDimitry Andric         state += sizeof(MachO::x86_thread_state_t);
10274ba319b5SDimitry Andric       } else if (flavor == MachO::x86_FLOAT_STATE) {
10284ba319b5SDimitry Andric         if (count != MachO::x86_FLOAT_STATE_COUNT)
10294ba319b5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10304ba319b5SDimitry Andric                                 " count not x86_FLOAT_STATE_COUNT for "
10314ba319b5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10324ba319b5SDimitry Andric                                 "a x86_FLOAT_STATE flavor in " + CmdName +
10334ba319b5SDimitry Andric                                 " command");
10344ba319b5SDimitry Andric         if (state + sizeof(MachO::x86_float_state_t) > end)
10354ba319b5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10364ba319b5SDimitry Andric                                 " x86_FLOAT_STATE extends past end of "
10374ba319b5SDimitry Andric                                 "command in " + CmdName + " command");
10384ba319b5SDimitry Andric         state += sizeof(MachO::x86_float_state_t);
10394ba319b5SDimitry Andric       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
10404ba319b5SDimitry Andric         if (count != MachO::x86_EXCEPTION_STATE_COUNT)
10414ba319b5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10424ba319b5SDimitry Andric                                 " count not x86_EXCEPTION_STATE_COUNT for "
10434ba319b5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10444ba319b5SDimitry Andric                                 "a x86_EXCEPTION_STATE flavor in " + CmdName +
10454ba319b5SDimitry Andric                                 " command");
10464ba319b5SDimitry Andric         if (state + sizeof(MachO::x86_exception_state_t) > end)
10474ba319b5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10484ba319b5SDimitry Andric                                 " x86_EXCEPTION_STATE extends past end of "
10494ba319b5SDimitry Andric                                 "command in " + CmdName + " command");
10504ba319b5SDimitry Andric         state += sizeof(MachO::x86_exception_state_t);
10514ba319b5SDimitry Andric       } else if (flavor == MachO::x86_THREAD_STATE64) {
1052d88c1a5aSDimitry Andric         if (count != MachO::x86_THREAD_STATE64_COUNT)
1053d88c1a5aSDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
1054d88c1a5aSDimitry Andric                                 " count not x86_THREAD_STATE64_COUNT for "
1055d88c1a5aSDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
1056d88c1a5aSDimitry Andric                                 "a x86_THREAD_STATE64 flavor in " + CmdName +
1057d88c1a5aSDimitry Andric                                 " command");
1058d88c1a5aSDimitry Andric         if (state + sizeof(MachO::x86_thread_state64_t) > end)
1059d88c1a5aSDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
1060d88c1a5aSDimitry Andric                                 " x86_THREAD_STATE64 extends past end of "
1061d88c1a5aSDimitry Andric                                 "command in " + CmdName + " command");
1062d88c1a5aSDimitry Andric         state += sizeof(MachO::x86_thread_state64_t);
10634ba319b5SDimitry Andric       } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
10644ba319b5SDimitry Andric         if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
10654ba319b5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10664ba319b5SDimitry Andric                                 " count not x86_EXCEPTION_STATE64_COUNT for "
10674ba319b5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10684ba319b5SDimitry Andric                                 "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
10694ba319b5SDimitry Andric                                 " command");
10704ba319b5SDimitry Andric         if (state + sizeof(MachO::x86_exception_state64_t) > end)
10714ba319b5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10724ba319b5SDimitry Andric                                 " x86_EXCEPTION_STATE64 extends past end of "
10734ba319b5SDimitry Andric                                 "command in " + CmdName + " command");
10744ba319b5SDimitry Andric         state += sizeof(MachO::x86_exception_state64_t);
1075d88c1a5aSDimitry Andric       } else {
1076d88c1a5aSDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
1077d88c1a5aSDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
1078d88c1a5aSDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
1079d88c1a5aSDimitry Andric                               CmdName + " command");
1080d88c1a5aSDimitry Andric       }
1081d88c1a5aSDimitry Andric     } else if (cputype == MachO::CPU_TYPE_ARM) {
1082d88c1a5aSDimitry Andric       if (flavor == MachO::ARM_THREAD_STATE) {
1083d88c1a5aSDimitry Andric         if (count != MachO::ARM_THREAD_STATE_COUNT)
1084d88c1a5aSDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
1085d88c1a5aSDimitry Andric                                 " count not ARM_THREAD_STATE_COUNT for "
1086d88c1a5aSDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
1087d88c1a5aSDimitry Andric                                 "a ARM_THREAD_STATE flavor in " + CmdName +
1088d88c1a5aSDimitry Andric                                 " command");
1089d88c1a5aSDimitry Andric         if (state + sizeof(MachO::arm_thread_state32_t) > end)
1090d88c1a5aSDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
1091d88c1a5aSDimitry Andric                                 " ARM_THREAD_STATE extends past end of "
1092d88c1a5aSDimitry Andric                                 "command in " + CmdName + " command");
1093d88c1a5aSDimitry Andric         state += sizeof(MachO::arm_thread_state32_t);
1094d88c1a5aSDimitry Andric       } else {
1095d88c1a5aSDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
1096d88c1a5aSDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
1097d88c1a5aSDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
1098d88c1a5aSDimitry Andric                               CmdName + " command");
1099d88c1a5aSDimitry Andric       }
1100d88c1a5aSDimitry Andric     } else if (cputype == MachO::CPU_TYPE_ARM64) {
1101d88c1a5aSDimitry Andric       if (flavor == MachO::ARM_THREAD_STATE64) {
1102d88c1a5aSDimitry Andric         if (count != MachO::ARM_THREAD_STATE64_COUNT)
1103d88c1a5aSDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
1104d88c1a5aSDimitry Andric                                 " count not ARM_THREAD_STATE64_COUNT for "
1105d88c1a5aSDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
1106d88c1a5aSDimitry Andric                                 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1107d88c1a5aSDimitry Andric                                 " command");
1108d88c1a5aSDimitry Andric         if (state + sizeof(MachO::arm_thread_state64_t) > end)
1109d88c1a5aSDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
1110d88c1a5aSDimitry Andric                                 " ARM_THREAD_STATE64 extends past end of "
1111d88c1a5aSDimitry Andric                                 "command in " + CmdName + " command");
1112d88c1a5aSDimitry Andric         state += sizeof(MachO::arm_thread_state64_t);
1113d88c1a5aSDimitry Andric       } else {
1114d88c1a5aSDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
1115d88c1a5aSDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
1116d88c1a5aSDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
1117d88c1a5aSDimitry Andric                               CmdName + " command");
1118d88c1a5aSDimitry Andric       }
1119d88c1a5aSDimitry Andric     } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1120d88c1a5aSDimitry Andric       if (flavor == MachO::PPC_THREAD_STATE) {
1121d88c1a5aSDimitry Andric         if (count != MachO::PPC_THREAD_STATE_COUNT)
1122d88c1a5aSDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
1123d88c1a5aSDimitry Andric                                 " count not PPC_THREAD_STATE_COUNT for "
1124d88c1a5aSDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
1125d88c1a5aSDimitry Andric                                 "a PPC_THREAD_STATE flavor in " + CmdName +
1126d88c1a5aSDimitry Andric                                 " command");
1127d88c1a5aSDimitry Andric         if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1128d88c1a5aSDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
1129d88c1a5aSDimitry Andric                                 " PPC_THREAD_STATE extends past end of "
1130d88c1a5aSDimitry Andric                                 "command in " + CmdName + " command");
1131d88c1a5aSDimitry Andric         state += sizeof(MachO::ppc_thread_state32_t);
1132d88c1a5aSDimitry Andric       } else {
1133d88c1a5aSDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
1134d88c1a5aSDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
1135d88c1a5aSDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
1136d88c1a5aSDimitry Andric                               CmdName + " command");
1137d88c1a5aSDimitry Andric       }
1138d88c1a5aSDimitry Andric     } else {
1139d88c1a5aSDimitry Andric       return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1140d88c1a5aSDimitry Andric                             "command " + Twine(LoadCommandIndex) + " for " +
1141d88c1a5aSDimitry Andric                             CmdName + " command can't be checked");
1142d88c1a5aSDimitry Andric     }
1143d88c1a5aSDimitry Andric     nflavor++;
1144d88c1a5aSDimitry Andric   }
1145d88c1a5aSDimitry Andric   return Error::success();
1146d88c1a5aSDimitry Andric }
1147d88c1a5aSDimitry Andric 
checkTwoLevelHintsCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,std::list<MachOElement> & Elements)1148d88c1a5aSDimitry Andric static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1149d88c1a5aSDimitry Andric                                        const MachOObjectFile::LoadCommandInfo
1150d88c1a5aSDimitry Andric                                          &Load,
1151d88c1a5aSDimitry Andric                                        uint32_t LoadCommandIndex,
1152d88c1a5aSDimitry Andric                                        const char **LoadCmd,
1153d88c1a5aSDimitry Andric                                        std::list<MachOElement> &Elements) {
1154d88c1a5aSDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1155d88c1a5aSDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
1156d88c1a5aSDimitry Andric                           " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1157d88c1a5aSDimitry Andric   if (*LoadCmd != nullptr)
1158d88c1a5aSDimitry Andric     return malformedError("more than one LC_TWOLEVEL_HINTS command");
1159d88c1a5aSDimitry Andric   MachO::twolevel_hints_command Hints =
1160d88c1a5aSDimitry Andric     getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1161d88c1a5aSDimitry Andric   uint64_t FileSize = Obj.getData().size();
1162d88c1a5aSDimitry Andric   if (Hints.offset > FileSize)
1163d88c1a5aSDimitry Andric     return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1164d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
1165d88c1a5aSDimitry Andric                           "the file");
1166d88c1a5aSDimitry Andric   uint64_t BigSize = Hints.nhints;
11672cab237bSDimitry Andric   BigSize *= sizeof(MachO::twolevel_hint);
1168d88c1a5aSDimitry Andric   BigSize += Hints.offset;
1169d88c1a5aSDimitry Andric   if (BigSize > FileSize)
1170d88c1a5aSDimitry Andric     return malformedError("offset field plus nhints times sizeof(struct "
1171d88c1a5aSDimitry Andric                           "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1172d88c1a5aSDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
1173d88c1a5aSDimitry Andric                           "the file");
1174d88c1a5aSDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1175d88c1a5aSDimitry Andric                                           sizeof(MachO::twolevel_hint),
1176d88c1a5aSDimitry Andric                                           "two level hints"))
1177d88c1a5aSDimitry Andric     return Err;
1178d88c1a5aSDimitry Andric   *LoadCmd = Load.Ptr;
1179d88c1a5aSDimitry Andric   return Error::success();
1180d88c1a5aSDimitry Andric }
1181d88c1a5aSDimitry Andric 
1182d88c1a5aSDimitry Andric // Returns true if the libObject code does not support the load command and its
1183d88c1a5aSDimitry Andric // contents.  The cmd value it is treated as an unknown load command but with
1184d88c1a5aSDimitry Andric // an error message that says the cmd value is obsolete.
isLoadCommandObsolete(uint32_t cmd)1185d88c1a5aSDimitry Andric static bool isLoadCommandObsolete(uint32_t cmd) {
1186d88c1a5aSDimitry Andric   if (cmd == MachO::LC_SYMSEG ||
1187d88c1a5aSDimitry Andric       cmd == MachO::LC_LOADFVMLIB ||
1188d88c1a5aSDimitry Andric       cmd == MachO::LC_IDFVMLIB ||
1189d88c1a5aSDimitry Andric       cmd == MachO::LC_IDENT ||
1190d88c1a5aSDimitry Andric       cmd == MachO::LC_FVMFILE ||
1191d88c1a5aSDimitry Andric       cmd == MachO::LC_PREPAGE ||
1192d88c1a5aSDimitry Andric       cmd == MachO::LC_PREBOUND_DYLIB ||
1193d88c1a5aSDimitry Andric       cmd == MachO::LC_TWOLEVEL_HINTS ||
1194d88c1a5aSDimitry Andric       cmd == MachO::LC_PREBIND_CKSUM)
1195d88c1a5aSDimitry Andric     return true;
1196d88c1a5aSDimitry Andric   return false;
1197d88c1a5aSDimitry Andric }
1198d88c1a5aSDimitry Andric 
11993ca95b02SDimitry Andric Expected<std::unique_ptr<MachOObjectFile>>
create(MemoryBufferRef Object,bool IsLittleEndian,bool Is64Bits,uint32_t UniversalCputype,uint32_t UniversalIndex)12003ca95b02SDimitry Andric MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1201d88c1a5aSDimitry Andric                         bool Is64Bits, uint32_t UniversalCputype,
1202d88c1a5aSDimitry Andric                         uint32_t UniversalIndex) {
1203d88c1a5aSDimitry Andric   Error Err = Error::success();
12043ca95b02SDimitry Andric   std::unique_ptr<MachOObjectFile> Obj(
12053ca95b02SDimitry Andric       new MachOObjectFile(std::move(Object), IsLittleEndian,
1206d88c1a5aSDimitry Andric                           Is64Bits, Err, UniversalCputype,
1207d88c1a5aSDimitry Andric                           UniversalIndex));
12083ca95b02SDimitry Andric   if (Err)
12093ca95b02SDimitry Andric     return std::move(Err);
12103ca95b02SDimitry Andric   return std::move(Obj);
121197bc6c73SDimitry Andric }
121297bc6c73SDimitry Andric 
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,Error & Err,uint32_t UniversalCputype,uint32_t UniversalIndex)121339d628a0SDimitry Andric MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1214d88c1a5aSDimitry Andric                                  bool Is64bits, Error &Err,
1215d88c1a5aSDimitry Andric                                  uint32_t UniversalCputype,
1216d88c1a5aSDimitry Andric                                  uint32_t UniversalIndex)
121751690af2SDimitry Andric     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
1218d88c1a5aSDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
1219d88c1a5aSDimitry Andric   uint64_t SizeOfHeaders;
1220d88c1a5aSDimitry Andric   uint32_t cputype;
12213ca95b02SDimitry Andric   if (is64Bit()) {
1222d88c1a5aSDimitry Andric     parseHeader(*this, Header64, Err);
1223d88c1a5aSDimitry Andric     SizeOfHeaders = sizeof(MachO::mach_header_64);
1224d88c1a5aSDimitry Andric     cputype = Header64.cputype;
12253ca95b02SDimitry Andric   } else {
1226d88c1a5aSDimitry Andric     parseHeader(*this, Header, Err);
1227d88c1a5aSDimitry Andric     SizeOfHeaders = sizeof(MachO::mach_header);
1228d88c1a5aSDimitry Andric     cputype = Header.cputype;
12293ca95b02SDimitry Andric   }
12303ca95b02SDimitry Andric   if (Err)
123197bc6c73SDimitry Andric     return;
1232d88c1a5aSDimitry Andric   SizeOfHeaders += getHeader().sizeofcmds;
1233d88c1a5aSDimitry Andric   if (getData().data() + SizeOfHeaders > getData().end()) {
12343ca95b02SDimitry Andric     Err = malformedError("load commands extend past the end of the file");
12353ca95b02SDimitry Andric     return;
12363ca95b02SDimitry Andric   }
1237d88c1a5aSDimitry Andric   if (UniversalCputype != 0 && cputype != UniversalCputype) {
1238d88c1a5aSDimitry Andric     Err = malformedError("universal header architecture: " +
1239d88c1a5aSDimitry Andric                          Twine(UniversalIndex) + "'s cputype does not match "
1240d88c1a5aSDimitry Andric                          "object file's mach header");
1241d88c1a5aSDimitry Andric     return;
1242d88c1a5aSDimitry Andric   }
1243d88c1a5aSDimitry Andric   std::list<MachOElement> Elements;
1244d88c1a5aSDimitry Andric   Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
124597bc6c73SDimitry Andric 
124697bc6c73SDimitry Andric   uint32_t LoadCommandCount = getHeader().ncmds;
12473ca95b02SDimitry Andric   LoadCommandInfo Load;
1248d88c1a5aSDimitry Andric   if (LoadCommandCount != 0) {
1249d88c1a5aSDimitry Andric     if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
12503ca95b02SDimitry Andric       Load = *LoadOrErr;
12513ca95b02SDimitry Andric     else {
12523ca95b02SDimitry Andric       Err = LoadOrErr.takeError();
125397bc6c73SDimitry Andric       return;
125497bc6c73SDimitry Andric     }
1255d88c1a5aSDimitry Andric   }
12563ca95b02SDimitry Andric 
1257d88c1a5aSDimitry Andric   const char *DyldIdLoadCmd = nullptr;
1258d88c1a5aSDimitry Andric   const char *FuncStartsLoadCmd = nullptr;
1259d88c1a5aSDimitry Andric   const char *SplitInfoLoadCmd = nullptr;
1260d88c1a5aSDimitry Andric   const char *CodeSignDrsLoadCmd = nullptr;
1261d88c1a5aSDimitry Andric   const char *CodeSignLoadCmd = nullptr;
1262d88c1a5aSDimitry Andric   const char *VersLoadCmd = nullptr;
1263d88c1a5aSDimitry Andric   const char *SourceLoadCmd = nullptr;
1264d88c1a5aSDimitry Andric   const char *EntryPointLoadCmd = nullptr;
1265d88c1a5aSDimitry Andric   const char *EncryptLoadCmd = nullptr;
1266d88c1a5aSDimitry Andric   const char *RoutinesLoadCmd = nullptr;
1267d88c1a5aSDimitry Andric   const char *UnixThreadLoadCmd = nullptr;
1268d88c1a5aSDimitry Andric   const char *TwoLevelHintsLoadCmd = nullptr;
126997bc6c73SDimitry Andric   for (unsigned I = 0; I < LoadCommandCount; ++I) {
12703ca95b02SDimitry Andric     if (is64Bit()) {
12713ca95b02SDimitry Andric       if (Load.C.cmdsize % 8 != 0) {
12723ca95b02SDimitry Andric         // We have a hack here to allow 64-bit Mach-O core files to have
12733ca95b02SDimitry Andric         // LC_THREAD commands that are only a multiple of 4 and not 8 to be
12743ca95b02SDimitry Andric         // allowed since the macOS kernel produces them.
12753ca95b02SDimitry Andric         if (getHeader().filetype != MachO::MH_CORE ||
12763ca95b02SDimitry Andric             Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
12773ca95b02SDimitry Andric           Err = malformedError("load command " + Twine(I) + " cmdsize not a "
12783ca95b02SDimitry Andric                                "multiple of 8");
12793ca95b02SDimitry Andric           return;
12803ca95b02SDimitry Andric         }
12813ca95b02SDimitry Andric       }
12823ca95b02SDimitry Andric     } else {
12833ca95b02SDimitry Andric       if (Load.C.cmdsize % 4 != 0) {
12843ca95b02SDimitry Andric         Err = malformedError("load command " + Twine(I) + " cmdsize not a "
12853ca95b02SDimitry Andric                              "multiple of 4");
12863ca95b02SDimitry Andric         return;
12873ca95b02SDimitry Andric       }
12883ca95b02SDimitry Andric     }
128997bc6c73SDimitry Andric     LoadCommands.push_back(Load);
1290f785676fSDimitry Andric     if (Load.C.cmd == MachO::LC_SYMTAB) {
1291d88c1a5aSDimitry Andric       if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
129239d628a0SDimitry Andric         return;
1293f785676fSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1294d88c1a5aSDimitry Andric       if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1295d88c1a5aSDimitry Andric                                       Elements)))
129639d628a0SDimitry Andric         return;
1297f785676fSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1298d88c1a5aSDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1299d88c1a5aSDimitry Andric                                           "LC_DATA_IN_CODE", Elements,
1300d88c1a5aSDimitry Andric                                           "data in code info")))
130139d628a0SDimitry Andric         return;
1302ff0cc061SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1303d88c1a5aSDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1304d88c1a5aSDimitry Andric                                           "LC_LINKER_OPTIMIZATION_HINT",
1305d88c1a5aSDimitry Andric                                           Elements, "linker optimization "
1306d88c1a5aSDimitry Andric                                           "hints")))
1307ff0cc061SDimitry Andric         return;
1308d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1309d88c1a5aSDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1310d88c1a5aSDimitry Andric                                           "LC_FUNCTION_STARTS", Elements,
1311d88c1a5aSDimitry Andric                                           "function starts data")))
131239d628a0SDimitry Andric         return;
1313d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1314d88c1a5aSDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1315d88c1a5aSDimitry Andric                                           "LC_SEGMENT_SPLIT_INFO", Elements,
1316d88c1a5aSDimitry Andric                                           "split info data")))
1317d88c1a5aSDimitry Andric         return;
1318d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1319d88c1a5aSDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1320d88c1a5aSDimitry Andric                                           "LC_DYLIB_CODE_SIGN_DRS", Elements,
1321d88c1a5aSDimitry Andric                                           "code signing RDs data")))
1322d88c1a5aSDimitry Andric         return;
1323d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1324d88c1a5aSDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1325d88c1a5aSDimitry Andric                                           "LC_CODE_SIGNATURE", Elements,
1326d88c1a5aSDimitry Andric                                           "code signature data")))
1327d88c1a5aSDimitry Andric         return;
1328d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1329d88c1a5aSDimitry Andric       if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1330d88c1a5aSDimitry Andric                                       "LC_DYLD_INFO", Elements)))
1331d88c1a5aSDimitry Andric         return;
1332d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1333d88c1a5aSDimitry Andric       if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1334d88c1a5aSDimitry Andric                                       "LC_DYLD_INFO_ONLY", Elements)))
1335d88c1a5aSDimitry Andric         return;
133639d628a0SDimitry Andric     } else if (Load.C.cmd == MachO::LC_UUID) {
1337d88c1a5aSDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1338d88c1a5aSDimitry Andric         Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1339d88c1a5aSDimitry Andric                              "cmdsize");
1340d88c1a5aSDimitry Andric         return;
1341d88c1a5aSDimitry Andric       }
134239d628a0SDimitry Andric       if (UuidLoadCmd) {
1343d88c1a5aSDimitry Andric         Err = malformedError("more than one LC_UUID command");
134439d628a0SDimitry Andric         return;
134539d628a0SDimitry Andric       }
134639d628a0SDimitry Andric       UuidLoadCmd = Load.Ptr;
134797bc6c73SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1348d88c1a5aSDimitry Andric       if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1349d88c1a5aSDimitry Andric                                          MachO::section_64>(
1350d88c1a5aSDimitry Andric                    *this, Load, Sections, HasPageZeroSegment, I,
1351d88c1a5aSDimitry Andric                    "LC_SEGMENT_64", SizeOfHeaders, Elements)))
135297bc6c73SDimitry Andric         return;
135397bc6c73SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1354d88c1a5aSDimitry Andric       if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1355d88c1a5aSDimitry Andric                                          MachO::section>(
1356d88c1a5aSDimitry Andric                    *this, Load, Sections, HasPageZeroSegment, I,
1357d88c1a5aSDimitry Andric                    "LC_SEGMENT", SizeOfHeaders, Elements)))
135897bc6c73SDimitry Andric         return;
1359d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1360d88c1a5aSDimitry Andric       if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1361d88c1a5aSDimitry Andric         return;
1362d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1363d88c1a5aSDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1364d88c1a5aSDimitry Andric         return;
136591bc56edSDimitry Andric       Libraries.push_back(Load.Ptr);
1366d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1367d88c1a5aSDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1368d88c1a5aSDimitry Andric         return;
1369d88c1a5aSDimitry Andric       Libraries.push_back(Load.Ptr);
1370d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1371d88c1a5aSDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1372d88c1a5aSDimitry Andric         return;
1373d88c1a5aSDimitry Andric       Libraries.push_back(Load.Ptr);
1374d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1375d88c1a5aSDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1376d88c1a5aSDimitry Andric         return;
1377d88c1a5aSDimitry Andric       Libraries.push_back(Load.Ptr);
1378d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1379d88c1a5aSDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1380d88c1a5aSDimitry Andric         return;
1381d88c1a5aSDimitry Andric       Libraries.push_back(Load.Ptr);
1382d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1383d88c1a5aSDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1384d88c1a5aSDimitry Andric         return;
1385d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1386d88c1a5aSDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1387d88c1a5aSDimitry Andric         return;
1388d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1389d88c1a5aSDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1390d88c1a5aSDimitry Andric         return;
1391d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1392d88c1a5aSDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1393d88c1a5aSDimitry Andric                                   "LC_VERSION_MIN_MACOSX")))
1394d88c1a5aSDimitry Andric         return;
1395d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1396d88c1a5aSDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1397d88c1a5aSDimitry Andric                                   "LC_VERSION_MIN_IPHONEOS")))
1398d88c1a5aSDimitry Andric         return;
1399d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1400d88c1a5aSDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1401d88c1a5aSDimitry Andric                                   "LC_VERSION_MIN_TVOS")))
1402d88c1a5aSDimitry Andric         return;
1403d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1404d88c1a5aSDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1405d88c1a5aSDimitry Andric                                   "LC_VERSION_MIN_WATCHOS")))
1406d88c1a5aSDimitry Andric         return;
14077a7e6055SDimitry Andric     } else if (Load.C.cmd == MachO::LC_NOTE) {
14087a7e6055SDimitry Andric       if ((Err = checkNoteCommand(*this, Load, I, Elements)))
14097a7e6055SDimitry Andric         return;
14107a7e6055SDimitry Andric     } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
14117a7e6055SDimitry Andric       if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
14127a7e6055SDimitry Andric         return;
1413d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_RPATH) {
1414d88c1a5aSDimitry Andric       if ((Err = checkRpathCommand(*this, Load, I)))
1415d88c1a5aSDimitry Andric         return;
1416d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1417d88c1a5aSDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1418d88c1a5aSDimitry Andric         Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1419d88c1a5aSDimitry Andric                              " has incorrect cmdsize");
1420d88c1a5aSDimitry Andric         return;
14213b0f4066SDimitry Andric       }
1422d88c1a5aSDimitry Andric       if (SourceLoadCmd) {
1423d88c1a5aSDimitry Andric         Err = malformedError("more than one LC_SOURCE_VERSION command");
1424d88c1a5aSDimitry Andric         return;
1425d88c1a5aSDimitry Andric       }
1426d88c1a5aSDimitry Andric       SourceLoadCmd = Load.Ptr;
1427d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_MAIN) {
1428d88c1a5aSDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1429d88c1a5aSDimitry Andric         Err = malformedError("LC_MAIN command " + Twine(I) +
1430d88c1a5aSDimitry Andric                              " has incorrect cmdsize");
1431d88c1a5aSDimitry Andric         return;
1432d88c1a5aSDimitry Andric       }
1433d88c1a5aSDimitry Andric       if (EntryPointLoadCmd) {
1434d88c1a5aSDimitry Andric         Err = malformedError("more than one LC_MAIN command");
1435d88c1a5aSDimitry Andric         return;
1436d88c1a5aSDimitry Andric       }
1437d88c1a5aSDimitry Andric       EntryPointLoadCmd = Load.Ptr;
1438d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1439d88c1a5aSDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1440d88c1a5aSDimitry Andric         Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1441d88c1a5aSDimitry Andric                              " has incorrect cmdsize");
1442d88c1a5aSDimitry Andric         return;
1443d88c1a5aSDimitry Andric       }
1444d88c1a5aSDimitry Andric       MachO::encryption_info_command E =
1445d88c1a5aSDimitry Andric         getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1446d88c1a5aSDimitry Andric       if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1447d88c1a5aSDimitry Andric                                      &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1448d88c1a5aSDimitry Andric         return;
1449d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1450d88c1a5aSDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1451d88c1a5aSDimitry Andric         Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1452d88c1a5aSDimitry Andric                              " has incorrect cmdsize");
1453d88c1a5aSDimitry Andric         return;
1454d88c1a5aSDimitry Andric       }
1455d88c1a5aSDimitry Andric       MachO::encryption_info_command_64 E =
1456d88c1a5aSDimitry Andric         getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1457d88c1a5aSDimitry Andric       if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1458d88c1a5aSDimitry Andric                                      &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1459d88c1a5aSDimitry Andric         return;
1460d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1461d88c1a5aSDimitry Andric       if ((Err = checkLinkerOptCommand(*this, Load, I)))
1462d88c1a5aSDimitry Andric         return;
1463d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1464d88c1a5aSDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1465d88c1a5aSDimitry Andric         Err =  malformedError("load command " + Twine(I) +
1466d88c1a5aSDimitry Andric                               " LC_SUB_FRAMEWORK cmdsize too small");
1467d88c1a5aSDimitry Andric         return;
1468d88c1a5aSDimitry Andric       }
1469d88c1a5aSDimitry Andric       MachO::sub_framework_command S =
1470d88c1a5aSDimitry Andric         getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1471d88c1a5aSDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1472d88c1a5aSDimitry Andric                                  sizeof(MachO::sub_framework_command),
1473d88c1a5aSDimitry Andric                                  "sub_framework_command", S.umbrella,
1474d88c1a5aSDimitry Andric                                  "umbrella")))
1475d88c1a5aSDimitry Andric         return;
1476d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1477d88c1a5aSDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1478d88c1a5aSDimitry Andric         Err =  malformedError("load command " + Twine(I) +
1479d88c1a5aSDimitry Andric                               " LC_SUB_UMBRELLA cmdsize too small");
1480d88c1a5aSDimitry Andric         return;
1481d88c1a5aSDimitry Andric       }
1482d88c1a5aSDimitry Andric       MachO::sub_umbrella_command S =
1483d88c1a5aSDimitry Andric         getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1484d88c1a5aSDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1485d88c1a5aSDimitry Andric                                  sizeof(MachO::sub_umbrella_command),
1486d88c1a5aSDimitry Andric                                  "sub_umbrella_command", S.sub_umbrella,
1487d88c1a5aSDimitry Andric                                  "sub_umbrella")))
1488d88c1a5aSDimitry Andric         return;
1489d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1490d88c1a5aSDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1491d88c1a5aSDimitry Andric         Err =  malformedError("load command " + Twine(I) +
1492d88c1a5aSDimitry Andric                               " LC_SUB_LIBRARY cmdsize too small");
1493d88c1a5aSDimitry Andric         return;
1494d88c1a5aSDimitry Andric       }
1495d88c1a5aSDimitry Andric       MachO::sub_library_command S =
1496d88c1a5aSDimitry Andric         getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1497d88c1a5aSDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1498d88c1a5aSDimitry Andric                                  sizeof(MachO::sub_library_command),
1499d88c1a5aSDimitry Andric                                  "sub_library_command", S.sub_library,
1500d88c1a5aSDimitry Andric                                  "sub_library")))
1501d88c1a5aSDimitry Andric         return;
1502d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1503d88c1a5aSDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1504d88c1a5aSDimitry Andric         Err =  malformedError("load command " + Twine(I) +
1505d88c1a5aSDimitry Andric                               " LC_SUB_CLIENT cmdsize too small");
1506d88c1a5aSDimitry Andric         return;
1507d88c1a5aSDimitry Andric       }
1508d88c1a5aSDimitry Andric       MachO::sub_client_command S =
1509d88c1a5aSDimitry Andric         getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1510d88c1a5aSDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1511d88c1a5aSDimitry Andric                                  sizeof(MachO::sub_client_command),
1512d88c1a5aSDimitry Andric                                  "sub_client_command", S.client, "client")))
1513d88c1a5aSDimitry Andric         return;
1514d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1515d88c1a5aSDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1516d88c1a5aSDimitry Andric         Err = malformedError("LC_ROUTINES command " + Twine(I) +
1517d88c1a5aSDimitry Andric                              " has incorrect cmdsize");
1518d88c1a5aSDimitry Andric         return;
1519d88c1a5aSDimitry Andric       }
1520d88c1a5aSDimitry Andric       if (RoutinesLoadCmd) {
1521d88c1a5aSDimitry Andric         Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1522d88c1a5aSDimitry Andric                              "command");
1523d88c1a5aSDimitry Andric         return;
1524d88c1a5aSDimitry Andric       }
1525d88c1a5aSDimitry Andric       RoutinesLoadCmd = Load.Ptr;
1526d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1527d88c1a5aSDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1528d88c1a5aSDimitry Andric         Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1529d88c1a5aSDimitry Andric                              " has incorrect cmdsize");
1530d88c1a5aSDimitry Andric         return;
1531d88c1a5aSDimitry Andric       }
1532d88c1a5aSDimitry Andric       if (RoutinesLoadCmd) {
1533d88c1a5aSDimitry Andric         Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1534d88c1a5aSDimitry Andric                              "command");
1535d88c1a5aSDimitry Andric         return;
1536d88c1a5aSDimitry Andric       }
1537d88c1a5aSDimitry Andric       RoutinesLoadCmd = Load.Ptr;
1538d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1539d88c1a5aSDimitry Andric       if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1540d88c1a5aSDimitry Andric         return;
1541d88c1a5aSDimitry Andric       if (UnixThreadLoadCmd) {
1542d88c1a5aSDimitry Andric         Err = malformedError("more than one LC_UNIXTHREAD command");
1543d88c1a5aSDimitry Andric         return;
1544d88c1a5aSDimitry Andric       }
1545d88c1a5aSDimitry Andric       UnixThreadLoadCmd = Load.Ptr;
1546d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_THREAD) {
1547d88c1a5aSDimitry Andric       if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1548d88c1a5aSDimitry Andric         return;
1549d88c1a5aSDimitry Andric     // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1550d88c1a5aSDimitry Andric     } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1551d88c1a5aSDimitry Andric        if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1552d88c1a5aSDimitry Andric                                             &TwoLevelHintsLoadCmd, Elements)))
1553d88c1a5aSDimitry Andric          return;
1554d88c1a5aSDimitry Andric     } else if (isLoadCommandObsolete(Load.C.cmd)) {
1555d88c1a5aSDimitry Andric       Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1556d88c1a5aSDimitry Andric                            Twine(Load.C.cmd) + " is obsolete and not "
1557d88c1a5aSDimitry Andric                            "supported");
1558d88c1a5aSDimitry Andric       return;
1559d88c1a5aSDimitry Andric     }
1560d88c1a5aSDimitry Andric     // TODO: generate a error for unknown load commands by default.  But still
1561d88c1a5aSDimitry Andric     // need work out an approach to allow or not allow unknown values like this
1562d88c1a5aSDimitry Andric     // as an option for some uses like lldb.
156397bc6c73SDimitry Andric     if (I < LoadCommandCount - 1) {
1564d88c1a5aSDimitry Andric       if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
15653ca95b02SDimitry Andric         Load = *LoadOrErr;
15663ca95b02SDimitry Andric       else {
15673ca95b02SDimitry Andric         Err = LoadOrErr.takeError();
156897bc6c73SDimitry Andric         return;
1569284c1978SDimitry Andric       }
15703ca95b02SDimitry Andric     }
15713ca95b02SDimitry Andric   }
15723ca95b02SDimitry Andric   if (!SymtabLoadCmd) {
15733ca95b02SDimitry Andric     if (DysymtabLoadCmd) {
15743ca95b02SDimitry Andric       Err = malformedError("contains LC_DYSYMTAB load command without a "
15753ca95b02SDimitry Andric                            "LC_SYMTAB load command");
15763ca95b02SDimitry Andric       return;
15773ca95b02SDimitry Andric     }
15783ca95b02SDimitry Andric   } else if (DysymtabLoadCmd) {
15793ca95b02SDimitry Andric     MachO::symtab_command Symtab =
1580d88c1a5aSDimitry Andric       getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
15813ca95b02SDimitry Andric     MachO::dysymtab_command Dysymtab =
1582d88c1a5aSDimitry Andric       getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
15833ca95b02SDimitry Andric     if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
15843ca95b02SDimitry Andric       Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
15853ca95b02SDimitry Andric                            "extends past the end of the symbol table");
15863ca95b02SDimitry Andric       return;
15873ca95b02SDimitry Andric     }
15883ca95b02SDimitry Andric     uint64_t BigSize = Dysymtab.ilocalsym;
15893ca95b02SDimitry Andric     BigSize += Dysymtab.nlocalsym;
15903ca95b02SDimitry Andric     if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
15913ca95b02SDimitry Andric       Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
15923ca95b02SDimitry Andric                            "command extends past the end of the symbol table");
15933ca95b02SDimitry Andric       return;
15943ca95b02SDimitry Andric     }
1595*b5893f02SDimitry Andric     if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
1596*b5893f02SDimitry Andric       Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
15973ca95b02SDimitry Andric                            "extends past the end of the symbol table");
15983ca95b02SDimitry Andric       return;
15993ca95b02SDimitry Andric     }
16003ca95b02SDimitry Andric     BigSize = Dysymtab.iextdefsym;
16013ca95b02SDimitry Andric     BigSize += Dysymtab.nextdefsym;
16023ca95b02SDimitry Andric     if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
16033ca95b02SDimitry Andric       Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
16043ca95b02SDimitry Andric                            "load command extends past the end of the symbol "
16053ca95b02SDimitry Andric                            "table");
16063ca95b02SDimitry Andric       return;
16073ca95b02SDimitry Andric     }
16083ca95b02SDimitry Andric     if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
1609*b5893f02SDimitry Andric       Err = malformedError("iundefsym in LC_DYSYMTAB load command "
16103ca95b02SDimitry Andric                            "extends past the end of the symbol table");
16113ca95b02SDimitry Andric       return;
16123ca95b02SDimitry Andric     }
16133ca95b02SDimitry Andric     BigSize = Dysymtab.iundefsym;
16143ca95b02SDimitry Andric     BigSize += Dysymtab.nundefsym;
16153ca95b02SDimitry Andric     if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
16163ca95b02SDimitry Andric       Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
16173ca95b02SDimitry Andric                            " command extends past the end of the symbol table");
16183ca95b02SDimitry Andric       return;
161997bc6c73SDimitry Andric     }
162097bc6c73SDimitry Andric   }
1621d88c1a5aSDimitry Andric   if ((getHeader().filetype == MachO::MH_DYLIB ||
1622d88c1a5aSDimitry Andric        getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1623d88c1a5aSDimitry Andric        DyldIdLoadCmd == nullptr) {
1624d88c1a5aSDimitry Andric     Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1625d88c1a5aSDimitry Andric                          "filetype");
1626d88c1a5aSDimitry Andric     return;
1627d88c1a5aSDimitry Andric   }
162897bc6c73SDimitry Andric   assert(LoadCommands.size() == LoadCommandCount);
16293ca95b02SDimitry Andric 
16303ca95b02SDimitry Andric   Err = Error::success();
16313b0f4066SDimitry Andric }
16323b0f4066SDimitry Andric 
checkSymbolTable() const1633d88c1a5aSDimitry Andric Error MachOObjectFile::checkSymbolTable() const {
1634d88c1a5aSDimitry Andric   uint32_t Flags = 0;
1635d88c1a5aSDimitry Andric   if (is64Bit()) {
1636d88c1a5aSDimitry Andric     MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1637d88c1a5aSDimitry Andric     Flags = H_64.flags;
1638d88c1a5aSDimitry Andric   } else {
1639d88c1a5aSDimitry Andric     MachO::mach_header H = MachOObjectFile::getHeader();
1640d88c1a5aSDimitry Andric     Flags = H.flags;
1641d88c1a5aSDimitry Andric   }
1642d88c1a5aSDimitry Andric   uint8_t NType = 0;
1643d88c1a5aSDimitry Andric   uint8_t NSect = 0;
1644d88c1a5aSDimitry Andric   uint16_t NDesc = 0;
1645d88c1a5aSDimitry Andric   uint32_t NStrx = 0;
1646d88c1a5aSDimitry Andric   uint64_t NValue = 0;
1647d88c1a5aSDimitry Andric   uint32_t SymbolIndex = 0;
1648d88c1a5aSDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
1649d88c1a5aSDimitry Andric   for (const SymbolRef &Symbol : symbols()) {
1650d88c1a5aSDimitry Andric     DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1651d88c1a5aSDimitry Andric     if (is64Bit()) {
1652d88c1a5aSDimitry Andric       MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1653d88c1a5aSDimitry Andric       NType = STE_64.n_type;
1654d88c1a5aSDimitry Andric       NSect = STE_64.n_sect;
1655d88c1a5aSDimitry Andric       NDesc = STE_64.n_desc;
1656d88c1a5aSDimitry Andric       NStrx = STE_64.n_strx;
1657d88c1a5aSDimitry Andric       NValue = STE_64.n_value;
1658d88c1a5aSDimitry Andric     } else {
1659d88c1a5aSDimitry Andric       MachO::nlist STE = getSymbolTableEntry(SymDRI);
1660d88c1a5aSDimitry Andric       NType = STE.n_type;
1661d88c1a5aSDimitry Andric       NType = STE.n_type;
1662d88c1a5aSDimitry Andric       NSect = STE.n_sect;
1663d88c1a5aSDimitry Andric       NDesc = STE.n_desc;
1664d88c1a5aSDimitry Andric       NStrx = STE.n_strx;
1665d88c1a5aSDimitry Andric       NValue = STE.n_value;
1666d88c1a5aSDimitry Andric     }
1667d88c1a5aSDimitry Andric     if ((NType & MachO::N_STAB) == 0 &&
1668d88c1a5aSDimitry Andric         (NType & MachO::N_TYPE) == MachO::N_SECT) {
1669d88c1a5aSDimitry Andric       if (NSect == 0 || NSect > Sections.size())
1670d88c1a5aSDimitry Andric         return malformedError("bad section index: " + Twine((int)NSect) +
1671d88c1a5aSDimitry Andric                               " for symbol at index " + Twine(SymbolIndex));
1672d88c1a5aSDimitry Andric     }
1673d88c1a5aSDimitry Andric     if ((NType & MachO::N_STAB) == 0 &&
1674d88c1a5aSDimitry Andric         (NType & MachO::N_TYPE) == MachO::N_INDR) {
1675d88c1a5aSDimitry Andric       if (NValue >= S.strsize)
1676d88c1a5aSDimitry Andric         return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1677d88c1a5aSDimitry Andric                               "the end of string table, for N_INDR symbol at "
1678d88c1a5aSDimitry Andric                               "index " + Twine(SymbolIndex));
1679d88c1a5aSDimitry Andric     }
1680d88c1a5aSDimitry Andric     if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1681d88c1a5aSDimitry Andric         (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1682d88c1a5aSDimitry Andric          (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1683d88c1a5aSDimitry Andric       uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1684d88c1a5aSDimitry Andric       if (LibraryOrdinal != 0 &&
1685d88c1a5aSDimitry Andric           LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1686d88c1a5aSDimitry Andric           LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1687d88c1a5aSDimitry Andric           LibraryOrdinal - 1 >= Libraries.size() ) {
1688d88c1a5aSDimitry Andric         return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1689d88c1a5aSDimitry Andric                             " for symbol at index " + Twine(SymbolIndex));
1690d88c1a5aSDimitry Andric       }
1691d88c1a5aSDimitry Andric     }
1692d88c1a5aSDimitry Andric     if (NStrx >= S.strsize)
1693d88c1a5aSDimitry Andric       return malformedError("bad string table index: " + Twine((int)NStrx) +
1694d88c1a5aSDimitry Andric                             " past the end of string table, for symbol at "
1695d88c1a5aSDimitry Andric                             "index " + Twine(SymbolIndex));
1696d88c1a5aSDimitry Andric     SymbolIndex++;
1697d88c1a5aSDimitry Andric   }
1698d88c1a5aSDimitry Andric   return Error::success();
1699d88c1a5aSDimitry Andric }
1700d88c1a5aSDimitry Andric 
moveSymbolNext(DataRefImpl & Symb) const170191bc56edSDimitry Andric void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1702284c1978SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
1703f785676fSDimitry Andric     sizeof(MachO::nlist_64) :
1704f785676fSDimitry Andric     sizeof(MachO::nlist);
1705284c1978SDimitry Andric   Symb.p += SymbolTableEntrySize;
17063b0f4066SDimitry Andric }
17073b0f4066SDimitry Andric 
getSymbolName(DataRefImpl Symb) const17083ca95b02SDimitry Andric Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1709284c1978SDimitry Andric   StringRef StringTable = getStringTableData();
1710d88c1a5aSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
17114ba319b5SDimitry Andric   if (Entry.n_strx == 0)
17124ba319b5SDimitry Andric     // A n_strx value of 0 indicates that no name is associated with a
17134ba319b5SDimitry Andric     // particular symbol table entry.
17144ba319b5SDimitry Andric     return StringRef();
1715f785676fSDimitry Andric   const char *Start = &StringTable.data()[Entry.n_strx];
17163ca95b02SDimitry Andric   if (Start < getData().begin() || Start >= getData().end()) {
17173ca95b02SDimitry Andric     return malformedError("bad string index: " + Twine(Entry.n_strx) +
17183ca95b02SDimitry Andric                           " for symbol at index " + Twine(getSymbolIndex(Symb)));
17193ca95b02SDimitry Andric   }
17203dac3a9bSDimitry Andric   return StringRef(Start);
1721284c1978SDimitry Andric }
1722284c1978SDimitry Andric 
getSectionType(SectionRef Sec) const172339d628a0SDimitry Andric unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
172439d628a0SDimitry Andric   DataRefImpl DRI = Sec.getRawDataRefImpl();
1725d88c1a5aSDimitry Andric   uint32_t Flags = getSectionFlags(*this, DRI);
172639d628a0SDimitry Andric   return Flags & MachO::SECTION_TYPE;
172739d628a0SDimitry Andric }
172839d628a0SDimitry Andric 
getNValue(DataRefImpl Sym) const17293dac3a9bSDimitry Andric uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
17303dac3a9bSDimitry Andric   if (is64Bit()) {
17313dac3a9bSDimitry Andric     MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
17323dac3a9bSDimitry Andric     return Entry.n_value;
17333dac3a9bSDimitry Andric   }
17343dac3a9bSDimitry Andric   MachO::nlist Entry = getSymbolTableEntry(Sym);
17353dac3a9bSDimitry Andric   return Entry.n_value;
17363dac3a9bSDimitry Andric }
17373dac3a9bSDimitry Andric 
173891bc56edSDimitry Andric // getIndirectName() returns the name of the alias'ed symbol who's string table
173991bc56edSDimitry Andric // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const174091bc56edSDimitry Andric std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
174191bc56edSDimitry Andric                                                  StringRef &Res) const {
174291bc56edSDimitry Andric   StringRef StringTable = getStringTableData();
1743d88c1a5aSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
174491bc56edSDimitry Andric   if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
174591bc56edSDimitry Andric     return object_error::parse_failed;
17463dac3a9bSDimitry Andric   uint64_t NValue = getNValue(Symb);
174791bc56edSDimitry Andric   if (NValue >= StringTable.size())
174891bc56edSDimitry Andric     return object_error::parse_failed;
174991bc56edSDimitry Andric   const char *Start = &StringTable.data()[NValue];
175091bc56edSDimitry Andric   Res = StringRef(Start);
175197bc6c73SDimitry Andric   return std::error_code();
175291bc56edSDimitry Andric }
175391bc56edSDimitry Andric 
getSymbolValueImpl(DataRefImpl Sym) const1754875ed548SDimitry Andric uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1755875ed548SDimitry Andric   return getNValue(Sym);
175617a519f9SDimitry Andric }
17573dac3a9bSDimitry Andric 
getSymbolAddress(DataRefImpl Sym) const17583ca95b02SDimitry Andric Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1759875ed548SDimitry Andric   return getSymbolValue(Sym);
17603b0f4066SDimitry Andric }
17613b0f4066SDimitry Andric 
getSymbolAlignment(DataRefImpl DRI) const176297bc6c73SDimitry Andric uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
176391bc56edSDimitry Andric   uint32_t flags = getSymbolFlags(DRI);
1764284c1978SDimitry Andric   if (flags & SymbolRef::SF_Common) {
1765d88c1a5aSDimitry Andric     MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
176697bc6c73SDimitry Andric     return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
176717a519f9SDimitry Andric   }
176897bc6c73SDimitry Andric   return 0;
17693b0f4066SDimitry Andric }
17703b0f4066SDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl DRI) const17713dac3a9bSDimitry Andric uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1772875ed548SDimitry Andric   return getNValue(DRI);
17733b0f4066SDimitry Andric }
17743b0f4066SDimitry Andric 
17753ca95b02SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const17763ca95b02SDimitry Andric MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1777d88c1a5aSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1778f785676fSDimitry Andric   uint8_t n_type = Entry.n_type;
1779284c1978SDimitry Andric 
17806122f3e6SDimitry Andric   // If this is a STAB debugging symbol, we can do nothing more.
17813dac3a9bSDimitry Andric   if (n_type & MachO::N_STAB)
17823dac3a9bSDimitry Andric     return SymbolRef::ST_Debug;
17836122f3e6SDimitry Andric 
1784f785676fSDimitry Andric   switch (n_type & MachO::N_TYPE) {
1785f785676fSDimitry Andric     case MachO::N_UNDF :
17863dac3a9bSDimitry Andric       return SymbolRef::ST_Unknown;
1787f785676fSDimitry Andric     case MachO::N_SECT :
17883ca95b02SDimitry Andric       Expected<section_iterator> SecOrError = getSymbolSection(Symb);
17893ca95b02SDimitry Andric       if (!SecOrError)
17903ca95b02SDimitry Andric         return SecOrError.takeError();
17913ca95b02SDimitry Andric       section_iterator Sec = *SecOrError;
17927d523365SDimitry Andric       if (Sec->isData() || Sec->isBSS())
17937d523365SDimitry Andric         return SymbolRef::ST_Data;
17943dac3a9bSDimitry Andric       return SymbolRef::ST_Function;
17956122f3e6SDimitry Andric   }
17963dac3a9bSDimitry Andric   return SymbolRef::ST_Other;
17976122f3e6SDimitry Andric }
17986122f3e6SDimitry Andric 
getSymbolFlags(DataRefImpl DRI) const179991bc56edSDimitry Andric uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1800d88c1a5aSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1801284c1978SDimitry Andric 
1802f785676fSDimitry Andric   uint8_t MachOType = Entry.n_type;
1803f785676fSDimitry Andric   uint16_t MachOFlags = Entry.n_desc;
1804284c1978SDimitry Andric 
180591bc56edSDimitry Andric   uint32_t Result = SymbolRef::SF_None;
1806284c1978SDimitry Andric 
180791bc56edSDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
180891bc56edSDimitry Andric     Result |= SymbolRef::SF_Indirect;
180991bc56edSDimitry Andric 
1810f785676fSDimitry Andric   if (MachOType & MachO::N_STAB)
1811284c1978SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
1812284c1978SDimitry Andric 
1813f785676fSDimitry Andric   if (MachOType & MachO::N_EXT) {
1814284c1978SDimitry Andric     Result |= SymbolRef::SF_Global;
1815f785676fSDimitry Andric     if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1816875ed548SDimitry Andric       if (getNValue(DRI))
1817284c1978SDimitry Andric         Result |= SymbolRef::SF_Common;
1818875ed548SDimitry Andric       else
1819875ed548SDimitry Andric         Result |= SymbolRef::SF_Undefined;
1820284c1978SDimitry Andric     }
1821ff0cc061SDimitry Andric 
1822ff0cc061SDimitry Andric     if (!(MachOType & MachO::N_PEXT))
1823ff0cc061SDimitry Andric       Result |= SymbolRef::SF_Exported;
1824284c1978SDimitry Andric   }
1825284c1978SDimitry Andric 
1826f785676fSDimitry Andric   if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1827284c1978SDimitry Andric     Result |= SymbolRef::SF_Weak;
1828284c1978SDimitry Andric 
182939d628a0SDimitry Andric   if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
183039d628a0SDimitry Andric     Result |= SymbolRef::SF_Thumb;
183139d628a0SDimitry Andric 
1832f785676fSDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1833284c1978SDimitry Andric     Result |= SymbolRef::SF_Absolute;
1834284c1978SDimitry Andric 
183591bc56edSDimitry Andric   return Result;
1836284c1978SDimitry Andric }
1837284c1978SDimitry Andric 
18383ca95b02SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const18397d523365SDimitry Andric MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1840d88c1a5aSDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1841f785676fSDimitry Andric   uint8_t index = Entry.n_sect;
1842284c1978SDimitry Andric 
18437d523365SDimitry Andric   if (index == 0)
18447d523365SDimitry Andric     return section_end();
1845284c1978SDimitry Andric   DataRefImpl DRI;
1846284c1978SDimitry Andric   DRI.d.a = index - 1;
18473ca95b02SDimitry Andric   if (DRI.d.a >= Sections.size()){
18483ca95b02SDimitry Andric     return malformedError("bad section index: " + Twine((int)index) +
18493ca95b02SDimitry Andric                           " for symbol at index " + Twine(getSymbolIndex(Symb)));
18503ca95b02SDimitry Andric   }
18517d523365SDimitry Andric   return section_iterator(SectionRef(DRI, this));
1852284c1978SDimitry Andric }
1853284c1978SDimitry Andric 
getSymbolSectionID(SymbolRef Sym) const18543dac3a9bSDimitry Andric unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
18553dac3a9bSDimitry Andric   MachO::nlist_base Entry =
1856d88c1a5aSDimitry Andric       getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
18573dac3a9bSDimitry Andric   return Entry.n_sect - 1;
18583dac3a9bSDimitry Andric }
18593dac3a9bSDimitry Andric 
moveSectionNext(DataRefImpl & Sec) const186091bc56edSDimitry Andric void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1861284c1978SDimitry Andric   Sec.d.a++;
18623b0f4066SDimitry Andric }
18633b0f4066SDimitry Andric 
getSectionName(DataRefImpl Sec,StringRef & Result) const186491bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
186591bc56edSDimitry Andric                                                 StringRef &Result) const {
1866284c1978SDimitry Andric   ArrayRef<char> Raw = getSectionRawName(Sec);
1867284c1978SDimitry Andric   Result = parseSegmentOrSectionName(Raw.data());
186897bc6c73SDimitry Andric   return std::error_code();
18693b0f4066SDimitry Andric }
18703b0f4066SDimitry Andric 
getSectionAddress(DataRefImpl Sec) const187139d628a0SDimitry Andric uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
187239d628a0SDimitry Andric   if (is64Bit())
187339d628a0SDimitry Andric     return getSection64(Sec).addr;
187439d628a0SDimitry Andric   return getSection(Sec).addr;
1875139f7f9bSDimitry Andric }
1876139f7f9bSDimitry Andric 
getSectionIndex(DataRefImpl Sec) const1877302affcbSDimitry Andric uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1878302affcbSDimitry Andric   return Sec.d.a;
1879302affcbSDimitry Andric }
1880302affcbSDimitry Andric 
getSectionSize(DataRefImpl Sec) const188139d628a0SDimitry Andric uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
18827d523365SDimitry Andric   // In the case if a malformed Mach-O file where the section offset is past
18837d523365SDimitry Andric   // the end of the file or some part of the section size is past the end of
18847d523365SDimitry Andric   // the file return a size of zero or a size that covers the rest of the file
18857d523365SDimitry Andric   // but does not extend past the end of the file.
18867d523365SDimitry Andric   uint32_t SectOffset, SectType;
18877d523365SDimitry Andric   uint64_t SectSize;
18887d523365SDimitry Andric 
18897d523365SDimitry Andric   if (is64Bit()) {
18907d523365SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
18917d523365SDimitry Andric     SectOffset = Sect.offset;
18927d523365SDimitry Andric     SectSize = Sect.size;
18937d523365SDimitry Andric     SectType = Sect.flags & MachO::SECTION_TYPE;
18947d523365SDimitry Andric   } else {
18957d523365SDimitry Andric     MachO::section Sect = getSection(Sec);
18967d523365SDimitry Andric     SectOffset = Sect.offset;
18977d523365SDimitry Andric     SectSize = Sect.size;
18987d523365SDimitry Andric     SectType = Sect.flags & MachO::SECTION_TYPE;
18997d523365SDimitry Andric   }
19007d523365SDimitry Andric   if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
19017d523365SDimitry Andric     return SectSize;
19027d523365SDimitry Andric   uint64_t FileSize = getData().size();
19037d523365SDimitry Andric   if (SectOffset > FileSize)
19047d523365SDimitry Andric     return 0;
19057d523365SDimitry Andric   if (FileSize - SectOffset < SectSize)
19067d523365SDimitry Andric     return FileSize - SectOffset;
19077d523365SDimitry Andric   return SectSize;
19083b0f4066SDimitry Andric }
19093b0f4066SDimitry Andric 
getSectionContents(DataRefImpl Sec,StringRef & Res) const191091bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
191191bc56edSDimitry Andric                                                     StringRef &Res) const {
1912284c1978SDimitry Andric   uint32_t Offset;
1913284c1978SDimitry Andric   uint64_t Size;
1914284c1978SDimitry Andric 
1915284c1978SDimitry Andric   if (is64Bit()) {
1916f785676fSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
1917f785676fSDimitry Andric     Offset = Sect.offset;
1918f785676fSDimitry Andric     Size = Sect.size;
191917a519f9SDimitry Andric   } else {
1920f785676fSDimitry Andric     MachO::section Sect = getSection(Sec);
1921f785676fSDimitry Andric     Offset = Sect.offset;
1922f785676fSDimitry Andric     Size = Sect.size;
192317a519f9SDimitry Andric   }
1924284c1978SDimitry Andric 
1925284c1978SDimitry Andric   Res = this->getData().substr(Offset, Size);
192697bc6c73SDimitry Andric   return std::error_code();
19273b0f4066SDimitry Andric }
19283b0f4066SDimitry Andric 
getSectionAlignment(DataRefImpl Sec) const192939d628a0SDimitry Andric uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1930284c1978SDimitry Andric   uint32_t Align;
1931284c1978SDimitry Andric   if (is64Bit()) {
1932f785676fSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
1933f785676fSDimitry Andric     Align = Sect.align;
193417a519f9SDimitry Andric   } else {
1935f785676fSDimitry Andric     MachO::section Sect = getSection(Sec);
1936f785676fSDimitry Andric     Align = Sect.align;
193717a519f9SDimitry Andric   }
1938284c1978SDimitry Andric 
193939d628a0SDimitry Andric   return uint64_t(1) << Align;
19403b0f4066SDimitry Andric }
19413b0f4066SDimitry Andric 
getSection(unsigned SectionIndex) const19424ba319b5SDimitry Andric Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
19434ba319b5SDimitry Andric   if (SectionIndex < 1 || SectionIndex > Sections.size())
19444ba319b5SDimitry Andric     return malformedError("bad section index: " + Twine((int)SectionIndex));
19454ba319b5SDimitry Andric 
19464ba319b5SDimitry Andric   DataRefImpl DRI;
19474ba319b5SDimitry Andric   DRI.d.a = SectionIndex - 1;
19484ba319b5SDimitry Andric   return SectionRef(DRI, this);
19494ba319b5SDimitry Andric }
19504ba319b5SDimitry Andric 
getSection(StringRef SectionName) const19514ba319b5SDimitry Andric Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
19524ba319b5SDimitry Andric   StringRef SecName;
19534ba319b5SDimitry Andric   for (const SectionRef &Section : sections()) {
19544ba319b5SDimitry Andric     if (std::error_code E = Section.getName(SecName))
19554ba319b5SDimitry Andric       return errorCodeToError(E);
19564ba319b5SDimitry Andric     if (SecName == SectionName) {
19574ba319b5SDimitry Andric       return Section;
19584ba319b5SDimitry Andric     }
19594ba319b5SDimitry Andric   }
19604ba319b5SDimitry Andric   return errorCodeToError(object_error::parse_failed);
19614ba319b5SDimitry Andric }
19624ba319b5SDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const19633ca95b02SDimitry Andric bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
19643ca95b02SDimitry Andric   return false;
19653ca95b02SDimitry Andric }
19663ca95b02SDimitry Andric 
isSectionText(DataRefImpl Sec) const196739d628a0SDimitry Andric bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
1968d88c1a5aSDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
196939d628a0SDimitry Andric   return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
19703b0f4066SDimitry Andric }
19713b0f4066SDimitry Andric 
isSectionData(DataRefImpl Sec) const197239d628a0SDimitry Andric bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
1973d88c1a5aSDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
197491bc56edSDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
197539d628a0SDimitry Andric   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
197691bc56edSDimitry Andric          !(SectionType == MachO::S_ZEROFILL ||
197791bc56edSDimitry Andric            SectionType == MachO::S_GB_ZEROFILL);
19783b0f4066SDimitry Andric }
19793b0f4066SDimitry Andric 
isSectionBSS(DataRefImpl Sec) const198039d628a0SDimitry Andric bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
1981d88c1a5aSDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
198291bc56edSDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
198339d628a0SDimitry Andric   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
198491bc56edSDimitry Andric          (SectionType == MachO::S_ZEROFILL ||
198591bc56edSDimitry Andric           SectionType == MachO::S_GB_ZEROFILL);
19866122f3e6SDimitry Andric }
19876122f3e6SDimitry Andric 
getSectionID(SectionRef Sec) const19883dac3a9bSDimitry Andric unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
19893dac3a9bSDimitry Andric   return Sec.getRawDataRefImpl().d.a;
19903dac3a9bSDimitry Andric }
19913dac3a9bSDimitry Andric 
isSectionVirtual(DataRefImpl Sec) const199239d628a0SDimitry Andric bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
19934ba319b5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
19944ba319b5SDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
19954ba319b5SDimitry Andric   return SectionType == MachO::S_ZEROFILL ||
19964ba319b5SDimitry Andric          SectionType == MachO::S_GB_ZEROFILL;
1997dff0c46cSDimitry Andric }
1998dff0c46cSDimitry Andric 
isSectionBitcode(DataRefImpl Sec) const19993ca95b02SDimitry Andric bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
20003ca95b02SDimitry Andric   StringRef SegmentName = getSectionFinalSegmentName(Sec);
20013ca95b02SDimitry Andric   StringRef SectName;
20023ca95b02SDimitry Andric   if (!getSectionName(Sec, SectName))
20033ca95b02SDimitry Andric     return (SegmentName == "__LLVM" && SectName == "__bitcode");
20043ca95b02SDimitry Andric   return false;
20053ca95b02SDimitry Andric }
20063ca95b02SDimitry Andric 
isSectionStripped(DataRefImpl Sec) const20072cab237bSDimitry Andric bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
20082cab237bSDimitry Andric   if (is64Bit())
20092cab237bSDimitry Andric     return getSection64(Sec).offset == 0;
20102cab237bSDimitry Andric   return getSection(Sec).offset == 0;
20112cab237bSDimitry Andric }
20122cab237bSDimitry Andric 
section_rel_begin(DataRefImpl Sec) const2013f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
2014284c1978SDimitry Andric   DataRefImpl Ret;
201591bc56edSDimitry Andric   Ret.d.a = Sec.d.a;
201691bc56edSDimitry Andric   Ret.d.b = 0;
2017284c1978SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
20183b0f4066SDimitry Andric }
20193b0f4066SDimitry Andric 
2020284c1978SDimitry Andric relocation_iterator
section_rel_end(DataRefImpl Sec) const2021f785676fSDimitry Andric MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
2022284c1978SDimitry Andric   uint32_t Num;
2023284c1978SDimitry Andric   if (is64Bit()) {
2024f785676fSDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
2025f785676fSDimitry Andric     Num = Sect.nreloc;
20266122f3e6SDimitry Andric   } else {
2027f785676fSDimitry Andric     MachO::section Sect = getSection(Sec);
2028f785676fSDimitry Andric     Num = Sect.nreloc;
20296122f3e6SDimitry Andric   }
2030284c1978SDimitry Andric 
2031284c1978SDimitry Andric   DataRefImpl Ret;
203291bc56edSDimitry Andric   Ret.d.a = Sec.d.a;
203391bc56edSDimitry Andric   Ret.d.b = Num;
2034284c1978SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
20356122f3e6SDimitry Andric }
2036284c1978SDimitry Andric 
extrel_begin() const2037edd7eaddSDimitry Andric relocation_iterator MachOObjectFile::extrel_begin() const {
2038edd7eaddSDimitry Andric   DataRefImpl Ret;
20392cab237bSDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2040edd7eaddSDimitry Andric   Ret.d.a = 0; // Would normally be a section index.
2041edd7eaddSDimitry Andric   Ret.d.b = 0; // Index into the external relocations
2042edd7eaddSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
2043edd7eaddSDimitry Andric }
2044edd7eaddSDimitry Andric 
extrel_end() const2045edd7eaddSDimitry Andric relocation_iterator MachOObjectFile::extrel_end() const {
2046edd7eaddSDimitry Andric   MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2047edd7eaddSDimitry Andric   DataRefImpl Ret;
20482cab237bSDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2049edd7eaddSDimitry Andric   Ret.d.a = 0; // Would normally be a section index.
2050edd7eaddSDimitry Andric   Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2051edd7eaddSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
2052edd7eaddSDimitry Andric }
2053edd7eaddSDimitry Andric 
locrel_begin() const20542cab237bSDimitry Andric relocation_iterator MachOObjectFile::locrel_begin() const {
20552cab237bSDimitry Andric   DataRefImpl Ret;
20562cab237bSDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
20572cab237bSDimitry Andric   Ret.d.a = 1; // Would normally be a section index.
20582cab237bSDimitry Andric   Ret.d.b = 0; // Index into the local relocations
20592cab237bSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
20602cab237bSDimitry Andric }
20612cab237bSDimitry Andric 
locrel_end() const20622cab237bSDimitry Andric relocation_iterator MachOObjectFile::locrel_end() const {
20632cab237bSDimitry Andric   MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
20642cab237bSDimitry Andric   DataRefImpl Ret;
20652cab237bSDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
20662cab237bSDimitry Andric   Ret.d.a = 1; // Would normally be a section index.
20672cab237bSDimitry Andric   Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
20682cab237bSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
20692cab237bSDimitry Andric }
20702cab237bSDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const207191bc56edSDimitry Andric void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
207291bc56edSDimitry Andric   ++Rel.d.b;
207391bc56edSDimitry Andric }
207491bc56edSDimitry Andric 
getRelocationOffset(DataRefImpl Rel) const20753dac3a9bSDimitry Andric uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
2076edd7eaddSDimitry Andric   assert((getHeader().filetype == MachO::MH_OBJECT ||
2077edd7eaddSDimitry Andric           getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2078edd7eaddSDimitry Andric          "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2079f785676fSDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
20803dac3a9bSDimitry Andric   return getAnyRelocationAddress(RE);
20816122f3e6SDimitry Andric }
20826122f3e6SDimitry Andric 
2083f785676fSDimitry Andric symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const2084f785676fSDimitry Andric MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
2085f785676fSDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
208691bc56edSDimitry Andric   if (isRelocationScattered(RE))
208791bc56edSDimitry Andric     return symbol_end();
208891bc56edSDimitry Andric 
2089284c1978SDimitry Andric   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2090284c1978SDimitry Andric   bool isExtern = getPlainRelocationExternal(RE);
2091f785676fSDimitry Andric   if (!isExtern)
209291bc56edSDimitry Andric     return symbol_end();
2093284c1978SDimitry Andric 
2094f785676fSDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
2095284c1978SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
2096f785676fSDimitry Andric     sizeof(MachO::nlist_64) :
2097f785676fSDimitry Andric     sizeof(MachO::nlist);
2098f785676fSDimitry Andric   uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
20996122f3e6SDimitry Andric   DataRefImpl Sym;
2100d88c1a5aSDimitry Andric   Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2101f785676fSDimitry Andric   return symbol_iterator(SymbolRef(Sym, this));
21026122f3e6SDimitry Andric }
2103284c1978SDimitry Andric 
2104ff0cc061SDimitry Andric section_iterator
getRelocationSection(DataRefImpl Rel) const2105ff0cc061SDimitry Andric MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2106ff0cc061SDimitry Andric   return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2107ff0cc061SDimitry Andric }
2108ff0cc061SDimitry Andric 
getRelocationType(DataRefImpl Rel) const21093dac3a9bSDimitry Andric uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
2110f785676fSDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
21113dac3a9bSDimitry Andric   return getAnyRelocationType(RE);
21126122f3e6SDimitry Andric }
2113284c1978SDimitry Andric 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const21143dac3a9bSDimitry Andric void MachOObjectFile::getRelocationTypeName(
21153dac3a9bSDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
2116dff0c46cSDimitry Andric   StringRef res;
21173dac3a9bSDimitry Andric   uint64_t RType = getRelocationType(Rel);
2118dff0c46cSDimitry Andric 
2119284c1978SDimitry Andric   unsigned Arch = this->getArch();
2120dff0c46cSDimitry Andric 
2121dff0c46cSDimitry Andric   switch (Arch) {
2122dff0c46cSDimitry Andric     case Triple::x86: {
21237ae0e2c9SDimitry Andric       static const char *const Table[] =  {
2124dff0c46cSDimitry Andric         "GENERIC_RELOC_VANILLA",
2125dff0c46cSDimitry Andric         "GENERIC_RELOC_PAIR",
2126dff0c46cSDimitry Andric         "GENERIC_RELOC_SECTDIFF",
2127dff0c46cSDimitry Andric         "GENERIC_RELOC_PB_LA_PTR",
2128dff0c46cSDimitry Andric         "GENERIC_RELOC_LOCAL_SECTDIFF",
2129dff0c46cSDimitry Andric         "GENERIC_RELOC_TLV" };
2130dff0c46cSDimitry Andric 
213191bc56edSDimitry Andric       if (RType > 5)
2132dff0c46cSDimitry Andric         res = "Unknown";
2133dff0c46cSDimitry Andric       else
2134284c1978SDimitry Andric         res = Table[RType];
2135dff0c46cSDimitry Andric       break;
2136dff0c46cSDimitry Andric     }
2137dff0c46cSDimitry Andric     case Triple::x86_64: {
21387ae0e2c9SDimitry Andric       static const char *const Table[] =  {
2139dff0c46cSDimitry Andric         "X86_64_RELOC_UNSIGNED",
2140dff0c46cSDimitry Andric         "X86_64_RELOC_SIGNED",
2141dff0c46cSDimitry Andric         "X86_64_RELOC_BRANCH",
2142dff0c46cSDimitry Andric         "X86_64_RELOC_GOT_LOAD",
2143dff0c46cSDimitry Andric         "X86_64_RELOC_GOT",
2144dff0c46cSDimitry Andric         "X86_64_RELOC_SUBTRACTOR",
2145dff0c46cSDimitry Andric         "X86_64_RELOC_SIGNED_1",
2146dff0c46cSDimitry Andric         "X86_64_RELOC_SIGNED_2",
2147dff0c46cSDimitry Andric         "X86_64_RELOC_SIGNED_4",
2148dff0c46cSDimitry Andric         "X86_64_RELOC_TLV" };
2149dff0c46cSDimitry Andric 
2150284c1978SDimitry Andric       if (RType > 9)
2151dff0c46cSDimitry Andric         res = "Unknown";
2152dff0c46cSDimitry Andric       else
2153284c1978SDimitry Andric         res = Table[RType];
2154dff0c46cSDimitry Andric       break;
2155dff0c46cSDimitry Andric     }
2156dff0c46cSDimitry Andric     case Triple::arm: {
21577ae0e2c9SDimitry Andric       static const char *const Table[] =  {
2158dff0c46cSDimitry Andric         "ARM_RELOC_VANILLA",
2159dff0c46cSDimitry Andric         "ARM_RELOC_PAIR",
2160dff0c46cSDimitry Andric         "ARM_RELOC_SECTDIFF",
2161dff0c46cSDimitry Andric         "ARM_RELOC_LOCAL_SECTDIFF",
2162dff0c46cSDimitry Andric         "ARM_RELOC_PB_LA_PTR",
2163dff0c46cSDimitry Andric         "ARM_RELOC_BR24",
2164dff0c46cSDimitry Andric         "ARM_THUMB_RELOC_BR22",
2165dff0c46cSDimitry Andric         "ARM_THUMB_32BIT_BRANCH",
2166dff0c46cSDimitry Andric         "ARM_RELOC_HALF",
2167dff0c46cSDimitry Andric         "ARM_RELOC_HALF_SECTDIFF" };
2168dff0c46cSDimitry Andric 
2169284c1978SDimitry Andric       if (RType > 9)
2170dff0c46cSDimitry Andric         res = "Unknown";
2171dff0c46cSDimitry Andric       else
2172284c1978SDimitry Andric         res = Table[RType];
2173dff0c46cSDimitry Andric       break;
2174dff0c46cSDimitry Andric     }
217591bc56edSDimitry Andric     case Triple::aarch64: {
217691bc56edSDimitry Andric       static const char *const Table[] = {
217791bc56edSDimitry Andric         "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
217891bc56edSDimitry Andric         "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
217991bc56edSDimitry Andric         "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
218091bc56edSDimitry Andric         "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
218191bc56edSDimitry Andric         "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
218291bc56edSDimitry Andric         "ARM64_RELOC_ADDEND"
218391bc56edSDimitry Andric       };
218491bc56edSDimitry Andric 
218591bc56edSDimitry Andric       if (RType >= array_lengthof(Table))
218691bc56edSDimitry Andric         res = "Unknown";
218791bc56edSDimitry Andric       else
218891bc56edSDimitry Andric         res = Table[RType];
218991bc56edSDimitry Andric       break;
219091bc56edSDimitry Andric     }
2191dff0c46cSDimitry Andric     case Triple::ppc: {
21927ae0e2c9SDimitry Andric       static const char *const Table[] =  {
2193dff0c46cSDimitry Andric         "PPC_RELOC_VANILLA",
2194dff0c46cSDimitry Andric         "PPC_RELOC_PAIR",
2195dff0c46cSDimitry Andric         "PPC_RELOC_BR14",
2196dff0c46cSDimitry Andric         "PPC_RELOC_BR24",
2197dff0c46cSDimitry Andric         "PPC_RELOC_HI16",
2198dff0c46cSDimitry Andric         "PPC_RELOC_LO16",
2199dff0c46cSDimitry Andric         "PPC_RELOC_HA16",
2200dff0c46cSDimitry Andric         "PPC_RELOC_LO14",
2201dff0c46cSDimitry Andric         "PPC_RELOC_SECTDIFF",
2202dff0c46cSDimitry Andric         "PPC_RELOC_PB_LA_PTR",
2203dff0c46cSDimitry Andric         "PPC_RELOC_HI16_SECTDIFF",
2204dff0c46cSDimitry Andric         "PPC_RELOC_LO16_SECTDIFF",
2205dff0c46cSDimitry Andric         "PPC_RELOC_HA16_SECTDIFF",
2206dff0c46cSDimitry Andric         "PPC_RELOC_JBSR",
2207dff0c46cSDimitry Andric         "PPC_RELOC_LO14_SECTDIFF",
2208dff0c46cSDimitry Andric         "PPC_RELOC_LOCAL_SECTDIFF" };
2209dff0c46cSDimitry Andric 
221091bc56edSDimitry Andric       if (RType > 15)
221191bc56edSDimitry Andric         res = "Unknown";
221291bc56edSDimitry Andric       else
2213284c1978SDimitry Andric         res = Table[RType];
2214dff0c46cSDimitry Andric       break;
2215dff0c46cSDimitry Andric     }
2216dff0c46cSDimitry Andric     case Triple::UnknownArch:
2217dff0c46cSDimitry Andric       res = "Unknown";
2218dff0c46cSDimitry Andric       break;
2219dff0c46cSDimitry Andric   }
2220dff0c46cSDimitry Andric   Result.append(res.begin(), res.end());
222197bc6c73SDimitry Andric }
222297bc6c73SDimitry Andric 
getRelocationLength(DataRefImpl Rel) const222397bc6c73SDimitry Andric uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
222497bc6c73SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
222597bc6c73SDimitry Andric   return getAnyRelocationLength(RE);
2226dff0c46cSDimitry Andric }
2227dff0c46cSDimitry Andric 
222891bc56edSDimitry Andric //
222991bc56edSDimitry Andric // guessLibraryShortName() is passed a name of a dynamic library and returns a
223091bc56edSDimitry Andric // guess on what the short name is.  Then name is returned as a substring of the
223191bc56edSDimitry Andric // StringRef Name passed in.  The name of the dynamic library is recognized as
223291bc56edSDimitry Andric // a framework if it has one of the two following forms:
223391bc56edSDimitry Andric //      Foo.framework/Versions/A/Foo
223491bc56edSDimitry Andric //      Foo.framework/Foo
223591bc56edSDimitry Andric // Where A and Foo can be any string.  And may contain a trailing suffix
223691bc56edSDimitry Andric // starting with an underbar.  If the Name is recognized as a framework then
223791bc56edSDimitry Andric // isFramework is set to true else it is set to false.  If the Name has a
223891bc56edSDimitry Andric // suffix then Suffix is set to the substring in Name that contains the suffix
223991bc56edSDimitry Andric // else it is set to a NULL StringRef.
224091bc56edSDimitry Andric //
224191bc56edSDimitry Andric // The Name of the dynamic library is recognized as a library name if it has
224291bc56edSDimitry Andric // one of the two following forms:
224391bc56edSDimitry Andric //      libFoo.A.dylib
224491bc56edSDimitry Andric //      libFoo.dylib
224591bc56edSDimitry Andric // The library may have a suffix trailing the name Foo of the form:
224691bc56edSDimitry Andric //      libFoo_profile.A.dylib
224791bc56edSDimitry Andric //      libFoo_profile.dylib
224891bc56edSDimitry Andric //
224991bc56edSDimitry Andric // The Name of the dynamic library is also recognized as a library name if it
225091bc56edSDimitry Andric // has the following form:
225191bc56edSDimitry Andric //      Foo.qtx
225291bc56edSDimitry Andric //
225391bc56edSDimitry Andric // If the Name of the dynamic library is none of the forms above then a NULL
225491bc56edSDimitry Andric // StringRef is returned.
225591bc56edSDimitry Andric //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)225691bc56edSDimitry Andric StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
225791bc56edSDimitry Andric                                                  bool &isFramework,
225891bc56edSDimitry Andric                                                  StringRef &Suffix) {
225991bc56edSDimitry Andric   StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
226091bc56edSDimitry Andric   size_t a, b, c, d, Idx;
2261dff0c46cSDimitry Andric 
226291bc56edSDimitry Andric   isFramework = false;
226391bc56edSDimitry Andric   Suffix = StringRef();
226491bc56edSDimitry Andric 
226591bc56edSDimitry Andric   // Pull off the last component and make Foo point to it
226691bc56edSDimitry Andric   a = Name.rfind('/');
226791bc56edSDimitry Andric   if (a == Name.npos || a == 0)
226891bc56edSDimitry Andric     goto guess_library;
226991bc56edSDimitry Andric   Foo = Name.slice(a+1, Name.npos);
227091bc56edSDimitry Andric 
227191bc56edSDimitry Andric   // Look for a suffix starting with a '_'
227291bc56edSDimitry Andric   Idx = Foo.rfind('_');
227391bc56edSDimitry Andric   if (Idx != Foo.npos && Foo.size() >= 2) {
227491bc56edSDimitry Andric     Suffix = Foo.slice(Idx, Foo.npos);
227591bc56edSDimitry Andric     Foo = Foo.slice(0, Idx);
2276284c1978SDimitry Andric   }
2277284c1978SDimitry Andric 
227891bc56edSDimitry Andric   // First look for the form Foo.framework/Foo
227991bc56edSDimitry Andric   b = Name.rfind('/', a);
228091bc56edSDimitry Andric   if (b == Name.npos)
228191bc56edSDimitry Andric     Idx = 0;
228291bc56edSDimitry Andric   else
228391bc56edSDimitry Andric     Idx = b+1;
228491bc56edSDimitry Andric   F = Name.slice(Idx, Idx + Foo.size());
228591bc56edSDimitry Andric   DotFramework = Name.slice(Idx + Foo.size(),
228691bc56edSDimitry Andric                             Idx + Foo.size() + sizeof(".framework/")-1);
228791bc56edSDimitry Andric   if (F == Foo && DotFramework == ".framework/") {
228891bc56edSDimitry Andric     isFramework = true;
228991bc56edSDimitry Andric     return Foo;
229091bc56edSDimitry Andric   }
229191bc56edSDimitry Andric 
229291bc56edSDimitry Andric   // Next look for the form Foo.framework/Versions/A/Foo
229391bc56edSDimitry Andric   if (b == Name.npos)
229491bc56edSDimitry Andric     goto guess_library;
229591bc56edSDimitry Andric   c =  Name.rfind('/', b);
229691bc56edSDimitry Andric   if (c == Name.npos || c == 0)
229791bc56edSDimitry Andric     goto guess_library;
229891bc56edSDimitry Andric   V = Name.slice(c+1, Name.npos);
229991bc56edSDimitry Andric   if (!V.startswith("Versions/"))
230091bc56edSDimitry Andric     goto guess_library;
230191bc56edSDimitry Andric   d =  Name.rfind('/', c);
230291bc56edSDimitry Andric   if (d == Name.npos)
230391bc56edSDimitry Andric     Idx = 0;
230491bc56edSDimitry Andric   else
230591bc56edSDimitry Andric     Idx = d+1;
230691bc56edSDimitry Andric   F = Name.slice(Idx, Idx + Foo.size());
230791bc56edSDimitry Andric   DotFramework = Name.slice(Idx + Foo.size(),
230891bc56edSDimitry Andric                             Idx + Foo.size() + sizeof(".framework/")-1);
230991bc56edSDimitry Andric   if (F == Foo && DotFramework == ".framework/") {
231091bc56edSDimitry Andric     isFramework = true;
231191bc56edSDimitry Andric     return Foo;
231291bc56edSDimitry Andric   }
231391bc56edSDimitry Andric 
231491bc56edSDimitry Andric guess_library:
231591bc56edSDimitry Andric   // pull off the suffix after the "." and make a point to it
231691bc56edSDimitry Andric   a = Name.rfind('.');
231791bc56edSDimitry Andric   if (a == Name.npos || a == 0)
231891bc56edSDimitry Andric     return StringRef();
231991bc56edSDimitry Andric   Dylib = Name.slice(a, Name.npos);
232091bc56edSDimitry Andric   if (Dylib != ".dylib")
232191bc56edSDimitry Andric     goto guess_qtx;
232291bc56edSDimitry Andric 
232391bc56edSDimitry Andric   // First pull off the version letter for the form Foo.A.dylib if any.
232491bc56edSDimitry Andric   if (a >= 3) {
232591bc56edSDimitry Andric     Dot = Name.slice(a-2, a-1);
232691bc56edSDimitry Andric     if (Dot == ".")
232791bc56edSDimitry Andric       a = a - 2;
232891bc56edSDimitry Andric   }
232991bc56edSDimitry Andric 
233091bc56edSDimitry Andric   b = Name.rfind('/', a);
233191bc56edSDimitry Andric   if (b == Name.npos)
233291bc56edSDimitry Andric     b = 0;
233391bc56edSDimitry Andric   else
233491bc56edSDimitry Andric     b = b+1;
233591bc56edSDimitry Andric   // ignore any suffix after an underbar like Foo_profile.A.dylib
233691bc56edSDimitry Andric   Idx = Name.find('_', b);
233791bc56edSDimitry Andric   if (Idx != Name.npos && Idx != b) {
233891bc56edSDimitry Andric     Lib = Name.slice(b, Idx);
233991bc56edSDimitry Andric     Suffix = Name.slice(Idx, a);
234091bc56edSDimitry Andric   }
234191bc56edSDimitry Andric   else
234291bc56edSDimitry Andric     Lib = Name.slice(b, a);
234391bc56edSDimitry Andric   // There are incorrect library names of the form:
234491bc56edSDimitry Andric   // libATS.A_profile.dylib so check for these.
234591bc56edSDimitry Andric   if (Lib.size() >= 3) {
234691bc56edSDimitry Andric     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
234791bc56edSDimitry Andric     if (Dot == ".")
234891bc56edSDimitry Andric       Lib = Lib.slice(0, Lib.size()-2);
234991bc56edSDimitry Andric   }
235091bc56edSDimitry Andric   return Lib;
235191bc56edSDimitry Andric 
235291bc56edSDimitry Andric guess_qtx:
235391bc56edSDimitry Andric   Qtx = Name.slice(a, Name.npos);
235491bc56edSDimitry Andric   if (Qtx != ".qtx")
235591bc56edSDimitry Andric     return StringRef();
235691bc56edSDimitry Andric   b = Name.rfind('/', a);
235791bc56edSDimitry Andric   if (b == Name.npos)
235891bc56edSDimitry Andric     Lib = Name.slice(0, a);
235991bc56edSDimitry Andric   else
236091bc56edSDimitry Andric     Lib = Name.slice(b+1, a);
236191bc56edSDimitry Andric   // There are library names of the form: QT.A.qtx so check for these.
236291bc56edSDimitry Andric   if (Lib.size() >= 3) {
236391bc56edSDimitry Andric     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
236491bc56edSDimitry Andric     if (Dot == ".")
236591bc56edSDimitry Andric       Lib = Lib.slice(0, Lib.size()-2);
236691bc56edSDimitry Andric   }
236791bc56edSDimitry Andric   return Lib;
236891bc56edSDimitry Andric }
236991bc56edSDimitry Andric 
237091bc56edSDimitry Andric // getLibraryShortNameByIndex() is used to get the short name of the library
237191bc56edSDimitry Andric // for an undefined symbol in a linked Mach-O binary that was linked with the
237291bc56edSDimitry Andric // normal two-level namespace default (that is MH_TWOLEVEL in the header).
237391bc56edSDimitry Andric // It is passed the index (0 - based) of the library as translated from
237491bc56edSDimitry Andric // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const237591bc56edSDimitry Andric std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
237639d628a0SDimitry Andric                                                          StringRef &Res) const {
237791bc56edSDimitry Andric   if (Index >= Libraries.size())
237891bc56edSDimitry Andric     return object_error::parse_failed;
237991bc56edSDimitry Andric 
238091bc56edSDimitry Andric   // If the cache of LibrariesShortNames is not built up do that first for
238191bc56edSDimitry Andric   // all the Libraries.
238291bc56edSDimitry Andric   if (LibrariesShortNames.size() == 0) {
238391bc56edSDimitry Andric     for (unsigned i = 0; i < Libraries.size(); i++) {
238491bc56edSDimitry Andric       MachO::dylib_command D =
2385d88c1a5aSDimitry Andric         getStruct<MachO::dylib_command>(*this, Libraries[i]);
238639d628a0SDimitry Andric       if (D.dylib.name >= D.cmdsize)
238739d628a0SDimitry Andric         return object_error::parse_failed;
238891bc56edSDimitry Andric       const char *P = (const char *)(Libraries[i]) + D.dylib.name;
238991bc56edSDimitry Andric       StringRef Name = StringRef(P);
239039d628a0SDimitry Andric       if (D.dylib.name+Name.size() >= D.cmdsize)
239139d628a0SDimitry Andric         return object_error::parse_failed;
239291bc56edSDimitry Andric       StringRef Suffix;
239391bc56edSDimitry Andric       bool isFramework;
239491bc56edSDimitry Andric       StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
239539d628a0SDimitry Andric       if (shortName.empty())
239691bc56edSDimitry Andric         LibrariesShortNames.push_back(Name);
239791bc56edSDimitry Andric       else
239891bc56edSDimitry Andric         LibrariesShortNames.push_back(shortName);
239991bc56edSDimitry Andric     }
240091bc56edSDimitry Andric   }
240191bc56edSDimitry Andric 
240291bc56edSDimitry Andric   Res = LibrariesShortNames[Index];
240397bc6c73SDimitry Andric   return std::error_code();
240491bc56edSDimitry Andric }
240591bc56edSDimitry Andric 
getLibraryCount() const24067a7e6055SDimitry Andric uint32_t MachOObjectFile::getLibraryCount() const {
24077a7e6055SDimitry Andric   return Libraries.size();
24087a7e6055SDimitry Andric }
24097a7e6055SDimitry Andric 
2410875ed548SDimitry Andric section_iterator
getRelocationRelocatedSection(relocation_iterator Rel) const2411875ed548SDimitry Andric MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2412875ed548SDimitry Andric   DataRefImpl Sec;
2413875ed548SDimitry Andric   Sec.d.a = Rel->getRawDataRefImpl().d.a;
2414875ed548SDimitry Andric   return section_iterator(SectionRef(Sec, this));
2415875ed548SDimitry Andric }
2416875ed548SDimitry Andric 
symbol_begin() const2417d88c1a5aSDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_begin() const {
24183ca95b02SDimitry Andric   DataRefImpl DRI;
24193ca95b02SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
24203ca95b02SDimitry Andric   if (!SymtabLoadCmd || Symtab.nsyms == 0)
24213ca95b02SDimitry Andric     return basic_symbol_iterator(SymbolRef(DRI, this));
24223ca95b02SDimitry Andric 
242391bc56edSDimitry Andric   return getSymbolByIndex(0);
242491bc56edSDimitry Andric }
242591bc56edSDimitry Andric 
symbol_end() const2426d88c1a5aSDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_end() const {
2427284c1978SDimitry Andric   DataRefImpl DRI;
24283ca95b02SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
24293ca95b02SDimitry Andric   if (!SymtabLoadCmd || Symtab.nsyms == 0)
243091bc56edSDimitry Andric     return basic_symbol_iterator(SymbolRef(DRI, this));
2431284c1978SDimitry Andric 
2432284c1978SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
2433f785676fSDimitry Andric     sizeof(MachO::nlist_64) :
2434f785676fSDimitry Andric     sizeof(MachO::nlist);
2435f785676fSDimitry Andric   unsigned Offset = Symtab.symoff +
2436f785676fSDimitry Andric     Symtab.nsyms * SymbolTableEntrySize;
2437d88c1a5aSDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
243891bc56edSDimitry Andric   return basic_symbol_iterator(SymbolRef(DRI, this));
2439284c1978SDimitry Andric }
2440284c1978SDimitry Andric 
getSymbolByIndex(unsigned Index) const2441*b5893f02SDimitry Andric symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
244291bc56edSDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
24433ca95b02SDimitry Andric   if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2444ff0cc061SDimitry Andric     report_fatal_error("Requested symbol index is out of range.");
244591bc56edSDimitry Andric   unsigned SymbolTableEntrySize =
244691bc56edSDimitry Andric     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
24473ca95b02SDimitry Andric   DataRefImpl DRI;
2448d88c1a5aSDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
244991bc56edSDimitry Andric   DRI.p += Index * SymbolTableEntrySize;
245091bc56edSDimitry Andric   return basic_symbol_iterator(SymbolRef(DRI, this));
2451284c1978SDimitry Andric }
2452284c1978SDimitry Andric 
getSymbolIndex(DataRefImpl Symb) const24533ca95b02SDimitry Andric uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
24543ca95b02SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
24553ca95b02SDimitry Andric   if (!SymtabLoadCmd)
24563ca95b02SDimitry Andric     report_fatal_error("getSymbolIndex() called with no symbol table symbol");
24573ca95b02SDimitry Andric   unsigned SymbolTableEntrySize =
24583ca95b02SDimitry Andric     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
24593ca95b02SDimitry Andric   DataRefImpl DRIstart;
2460d88c1a5aSDimitry Andric   DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
24613ca95b02SDimitry Andric   uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
24623ca95b02SDimitry Andric   return Index;
24633ca95b02SDimitry Andric }
24643ca95b02SDimitry Andric 
section_begin() const246591bc56edSDimitry Andric section_iterator MachOObjectFile::section_begin() const {
2466284c1978SDimitry Andric   DataRefImpl DRI;
2467284c1978SDimitry Andric   return section_iterator(SectionRef(DRI, this));
2468284c1978SDimitry Andric }
2469284c1978SDimitry Andric 
section_end() const247091bc56edSDimitry Andric section_iterator MachOObjectFile::section_end() const {
2471284c1978SDimitry Andric   DataRefImpl DRI;
2472284c1978SDimitry Andric   DRI.d.a = Sections.size();
2473284c1978SDimitry Andric   return section_iterator(SectionRef(DRI, this));
2474284c1978SDimitry Andric }
2475284c1978SDimitry Andric 
getBytesInAddress() const24763b0f4066SDimitry Andric uint8_t MachOObjectFile::getBytesInAddress() const {
2477284c1978SDimitry Andric   return is64Bit() ? 8 : 4;
24783b0f4066SDimitry Andric }
24793b0f4066SDimitry Andric 
getFileFormatName() const24803b0f4066SDimitry Andric StringRef MachOObjectFile::getFileFormatName() const {
2481d88c1a5aSDimitry Andric   unsigned CPUType = getCPUType(*this);
2482284c1978SDimitry Andric   if (!is64Bit()) {
2483284c1978SDimitry Andric     switch (CPUType) {
248451690af2SDimitry Andric     case MachO::CPU_TYPE_I386:
24853b0f4066SDimitry Andric       return "Mach-O 32-bit i386";
248651690af2SDimitry Andric     case MachO::CPU_TYPE_ARM:
24873b0f4066SDimitry Andric       return "Mach-O arm";
248851690af2SDimitry Andric     case MachO::CPU_TYPE_POWERPC:
24893b0f4066SDimitry Andric       return "Mach-O 32-bit ppc";
24903b0f4066SDimitry Andric     default:
24913b0f4066SDimitry Andric       return "Mach-O 32-bit unknown";
24923b0f4066SDimitry Andric     }
24933b0f4066SDimitry Andric   }
24943b0f4066SDimitry Andric 
2495284c1978SDimitry Andric   switch (CPUType) {
249651690af2SDimitry Andric   case MachO::CPU_TYPE_X86_64:
24973b0f4066SDimitry Andric     return "Mach-O 64-bit x86-64";
249851690af2SDimitry Andric   case MachO::CPU_TYPE_ARM64:
249991bc56edSDimitry Andric     return "Mach-O arm64";
250051690af2SDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
25013b0f4066SDimitry Andric     return "Mach-O 64-bit ppc64";
25023b0f4066SDimitry Andric   default:
25033b0f4066SDimitry Andric     return "Mach-O 64-bit unknown";
25043b0f4066SDimitry Andric   }
25053b0f4066SDimitry Andric }
25063b0f4066SDimitry Andric 
getArch(uint32_t CPUType)2507f785676fSDimitry Andric Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2508f785676fSDimitry Andric   switch (CPUType) {
250951690af2SDimitry Andric   case MachO::CPU_TYPE_I386:
25103b0f4066SDimitry Andric     return Triple::x86;
251151690af2SDimitry Andric   case MachO::CPU_TYPE_X86_64:
25123b0f4066SDimitry Andric     return Triple::x86_64;
251351690af2SDimitry Andric   case MachO::CPU_TYPE_ARM:
25143b0f4066SDimitry Andric     return Triple::arm;
251551690af2SDimitry Andric   case MachO::CPU_TYPE_ARM64:
251639d628a0SDimitry Andric     return Triple::aarch64;
251751690af2SDimitry Andric   case MachO::CPU_TYPE_POWERPC:
25183b0f4066SDimitry Andric     return Triple::ppc;
251951690af2SDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
25203b0f4066SDimitry Andric     return Triple::ppc64;
25213b0f4066SDimitry Andric   default:
25223b0f4066SDimitry Andric     return Triple::UnknownArch;
25233b0f4066SDimitry Andric   }
25243b0f4066SDimitry Andric }
25253b0f4066SDimitry Andric 
getArchTriple(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,const char ** ArchFlag)25263ca95b02SDimitry Andric Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2527d88c1a5aSDimitry Andric                                       const char **McpuDefault,
2528d88c1a5aSDimitry Andric                                       const char **ArchFlag) {
252939d628a0SDimitry Andric   if (McpuDefault)
253039d628a0SDimitry Andric     *McpuDefault = nullptr;
2531d88c1a5aSDimitry Andric   if (ArchFlag)
2532d88c1a5aSDimitry Andric     *ArchFlag = nullptr;
253339d628a0SDimitry Andric 
253491bc56edSDimitry Andric   switch (CPUType) {
253591bc56edSDimitry Andric   case MachO::CPU_TYPE_I386:
253691bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
253791bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_I386_ALL:
2538d88c1a5aSDimitry Andric       if (ArchFlag)
2539d88c1a5aSDimitry Andric         *ArchFlag = "i386";
254091bc56edSDimitry Andric       return Triple("i386-apple-darwin");
254191bc56edSDimitry Andric     default:
254291bc56edSDimitry Andric       return Triple();
254391bc56edSDimitry Andric     }
254491bc56edSDimitry Andric   case MachO::CPU_TYPE_X86_64:
254591bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
254691bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_X86_64_ALL:
2547d88c1a5aSDimitry Andric       if (ArchFlag)
2548d88c1a5aSDimitry Andric         *ArchFlag = "x86_64";
254991bc56edSDimitry Andric       return Triple("x86_64-apple-darwin");
255091bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_X86_64_H:
2551d88c1a5aSDimitry Andric       if (ArchFlag)
2552d88c1a5aSDimitry Andric         *ArchFlag = "x86_64h";
255391bc56edSDimitry Andric       return Triple("x86_64h-apple-darwin");
255491bc56edSDimitry Andric     default:
255591bc56edSDimitry Andric       return Triple();
255691bc56edSDimitry Andric     }
255791bc56edSDimitry Andric   case MachO::CPU_TYPE_ARM:
255891bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
255991bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V4T:
2560d88c1a5aSDimitry Andric       if (ArchFlag)
2561d88c1a5aSDimitry Andric         *ArchFlag = "armv4t";
256291bc56edSDimitry Andric       return Triple("armv4t-apple-darwin");
256391bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2564d88c1a5aSDimitry Andric       if (ArchFlag)
2565d88c1a5aSDimitry Andric         *ArchFlag = "armv5e";
256691bc56edSDimitry Andric       return Triple("armv5e-apple-darwin");
256739d628a0SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_XSCALE:
2568d88c1a5aSDimitry Andric       if (ArchFlag)
2569d88c1a5aSDimitry Andric         *ArchFlag = "xscale";
257039d628a0SDimitry Andric       return Triple("xscale-apple-darwin");
257191bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V6:
2572d88c1a5aSDimitry Andric       if (ArchFlag)
2573d88c1a5aSDimitry Andric         *ArchFlag = "armv6";
257491bc56edSDimitry Andric       return Triple("armv6-apple-darwin");
257591bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V6M:
257639d628a0SDimitry Andric       if (McpuDefault)
257739d628a0SDimitry Andric         *McpuDefault = "cortex-m0";
2578d88c1a5aSDimitry Andric       if (ArchFlag)
2579d88c1a5aSDimitry Andric         *ArchFlag = "armv6m";
258091bc56edSDimitry Andric       return Triple("armv6m-apple-darwin");
258139d628a0SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7:
2582d88c1a5aSDimitry Andric       if (ArchFlag)
2583d88c1a5aSDimitry Andric         *ArchFlag = "armv7";
258439d628a0SDimitry Andric       return Triple("armv7-apple-darwin");
258591bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7EM:
258639d628a0SDimitry Andric       if (McpuDefault)
258739d628a0SDimitry Andric         *McpuDefault = "cortex-m4";
2588d88c1a5aSDimitry Andric       if (ArchFlag)
2589d88c1a5aSDimitry Andric         *ArchFlag = "armv7em";
25903ca95b02SDimitry Andric       return Triple("thumbv7em-apple-darwin");
259191bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7K:
25927a7e6055SDimitry Andric       if (McpuDefault)
25937a7e6055SDimitry Andric         *McpuDefault = "cortex-a7";
2594d88c1a5aSDimitry Andric       if (ArchFlag)
2595d88c1a5aSDimitry Andric         *ArchFlag = "armv7k";
259691bc56edSDimitry Andric       return Triple("armv7k-apple-darwin");
259791bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7M:
259839d628a0SDimitry Andric       if (McpuDefault)
259939d628a0SDimitry Andric         *McpuDefault = "cortex-m3";
2600d88c1a5aSDimitry Andric       if (ArchFlag)
2601d88c1a5aSDimitry Andric         *ArchFlag = "armv7m";
26023ca95b02SDimitry Andric       return Triple("thumbv7m-apple-darwin");
260391bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7S:
26047a7e6055SDimitry Andric       if (McpuDefault)
26057a7e6055SDimitry Andric         *McpuDefault = "cortex-a7";
2606d88c1a5aSDimitry Andric       if (ArchFlag)
2607d88c1a5aSDimitry Andric         *ArchFlag = "armv7s";
260891bc56edSDimitry Andric       return Triple("armv7s-apple-darwin");
260991bc56edSDimitry Andric     default:
261091bc56edSDimitry Andric       return Triple();
261191bc56edSDimitry Andric     }
261291bc56edSDimitry Andric   case MachO::CPU_TYPE_ARM64:
261391bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
261491bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_ARM64_ALL:
26157a7e6055SDimitry Andric       if (McpuDefault)
26167a7e6055SDimitry Andric         *McpuDefault = "cyclone";
2617d88c1a5aSDimitry Andric       if (ArchFlag)
2618d88c1a5aSDimitry Andric         *ArchFlag = "arm64";
261991bc56edSDimitry Andric       return Triple("arm64-apple-darwin");
262091bc56edSDimitry Andric     default:
262191bc56edSDimitry Andric       return Triple();
262291bc56edSDimitry Andric     }
262391bc56edSDimitry Andric   case MachO::CPU_TYPE_POWERPC:
262491bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
262591bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_POWERPC_ALL:
2626d88c1a5aSDimitry Andric       if (ArchFlag)
2627d88c1a5aSDimitry Andric         *ArchFlag = "ppc";
262891bc56edSDimitry Andric       return Triple("ppc-apple-darwin");
262991bc56edSDimitry Andric     default:
263091bc56edSDimitry Andric       return Triple();
263191bc56edSDimitry Andric     }
263291bc56edSDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
263391bc56edSDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
263491bc56edSDimitry Andric     case MachO::CPU_SUBTYPE_POWERPC_ALL:
2635d88c1a5aSDimitry Andric       if (ArchFlag)
2636d88c1a5aSDimitry Andric         *ArchFlag = "ppc64";
263791bc56edSDimitry Andric       return Triple("ppc64-apple-darwin");
263891bc56edSDimitry Andric     default:
263991bc56edSDimitry Andric       return Triple();
264091bc56edSDimitry Andric     }
264191bc56edSDimitry Andric   default:
264291bc56edSDimitry Andric     return Triple();
264391bc56edSDimitry Andric   }
264491bc56edSDimitry Andric }
264591bc56edSDimitry Andric 
getHostArch()264691bc56edSDimitry Andric Triple MachOObjectFile::getHostArch() {
264791bc56edSDimitry Andric   return Triple(sys::getDefaultTargetTriple());
264891bc56edSDimitry Andric }
264991bc56edSDimitry Andric 
isValidArch(StringRef ArchFlag)265039d628a0SDimitry Andric bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
265139d628a0SDimitry Andric   return StringSwitch<bool>(ArchFlag)
265239d628a0SDimitry Andric       .Case("i386", true)
265339d628a0SDimitry Andric       .Case("x86_64", true)
265439d628a0SDimitry Andric       .Case("x86_64h", true)
265539d628a0SDimitry Andric       .Case("armv4t", true)
265639d628a0SDimitry Andric       .Case("arm", true)
265739d628a0SDimitry Andric       .Case("armv5e", true)
265839d628a0SDimitry Andric       .Case("armv6", true)
265939d628a0SDimitry Andric       .Case("armv6m", true)
26608f0fd8f6SDimitry Andric       .Case("armv7", true)
266139d628a0SDimitry Andric       .Case("armv7em", true)
266239d628a0SDimitry Andric       .Case("armv7k", true)
266339d628a0SDimitry Andric       .Case("armv7m", true)
266439d628a0SDimitry Andric       .Case("armv7s", true)
266539d628a0SDimitry Andric       .Case("arm64", true)
266639d628a0SDimitry Andric       .Case("ppc", true)
266739d628a0SDimitry Andric       .Case("ppc64", true)
266839d628a0SDimitry Andric       .Default(false);
266991bc56edSDimitry Andric }
267091bc56edSDimitry Andric 
getArch() const26712cab237bSDimitry Andric Triple::ArchType MachOObjectFile::getArch() const {
2672d88c1a5aSDimitry Andric   return getArch(getCPUType(*this));
2673f785676fSDimitry Andric }
2674f785676fSDimitry Andric 
getArchTriple(const char ** McpuDefault) const26753ca95b02SDimitry Andric Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
26763ca95b02SDimitry Andric   return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2677284c1978SDimitry Andric }
2678284c1978SDimitry Andric 
section_rel_begin(unsigned Index) const2679f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2680284c1978SDimitry Andric   DataRefImpl DRI;
2681284c1978SDimitry Andric   DRI.d.a = Index;
2682f785676fSDimitry Andric   return section_rel_begin(DRI);
2683284c1978SDimitry Andric }
2684284c1978SDimitry Andric 
section_rel_end(unsigned Index) const2685f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2686284c1978SDimitry Andric   DataRefImpl DRI;
2687284c1978SDimitry Andric   DRI.d.a = Index;
2688f785676fSDimitry Andric   return section_rel_end(DRI);
2689f785676fSDimitry Andric }
2690f785676fSDimitry Andric 
begin_dices() const2691f785676fSDimitry Andric dice_iterator MachOObjectFile::begin_dices() const {
2692f785676fSDimitry Andric   DataRefImpl DRI;
2693f785676fSDimitry Andric   if (!DataInCodeLoadCmd)
2694f785676fSDimitry Andric     return dice_iterator(DiceRef(DRI, this));
2695f785676fSDimitry Andric 
2696f785676fSDimitry Andric   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2697d88c1a5aSDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2698f785676fSDimitry Andric   return dice_iterator(DiceRef(DRI, this));
2699f785676fSDimitry Andric }
2700f785676fSDimitry Andric 
end_dices() const2701f785676fSDimitry Andric dice_iterator MachOObjectFile::end_dices() const {
2702f785676fSDimitry Andric   DataRefImpl DRI;
2703f785676fSDimitry Andric   if (!DataInCodeLoadCmd)
2704f785676fSDimitry Andric     return dice_iterator(DiceRef(DRI, this));
2705f785676fSDimitry Andric 
2706f785676fSDimitry Andric   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2707f785676fSDimitry Andric   unsigned Offset = DicLC.dataoff + DicLC.datasize;
2708d88c1a5aSDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2709f785676fSDimitry Andric   return dice_iterator(DiceRef(DRI, this));
2710284c1978SDimitry Andric }
2711284c1978SDimitry Andric 
ExportEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> T)27122cab237bSDimitry Andric ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
27132cab237bSDimitry Andric                          ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
271439d628a0SDimitry Andric 
moveToFirst()271539d628a0SDimitry Andric void ExportEntry::moveToFirst() {
27162cab237bSDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
271739d628a0SDimitry Andric   pushNode(0);
27182cab237bSDimitry Andric   if (*E)
27192cab237bSDimitry Andric     return;
272039d628a0SDimitry Andric   pushDownUntilBottom();
272139d628a0SDimitry Andric }
272239d628a0SDimitry Andric 
moveToEnd()272339d628a0SDimitry Andric void ExportEntry::moveToEnd() {
272439d628a0SDimitry Andric   Stack.clear();
272539d628a0SDimitry Andric   Done = true;
272639d628a0SDimitry Andric }
272739d628a0SDimitry Andric 
operator ==(const ExportEntry & Other) const272839d628a0SDimitry Andric bool ExportEntry::operator==(const ExportEntry &Other) const {
272939d628a0SDimitry Andric   // Common case, one at end, other iterating from begin.
273039d628a0SDimitry Andric   if (Done || Other.Done)
273139d628a0SDimitry Andric     return (Done == Other.Done);
273239d628a0SDimitry Andric   // Not equal if different stack sizes.
273339d628a0SDimitry Andric   if (Stack.size() != Other.Stack.size())
273439d628a0SDimitry Andric     return false;
273539d628a0SDimitry Andric   // Not equal if different cumulative strings.
2736ff0cc061SDimitry Andric   if (!CumulativeString.equals(Other.CumulativeString))
273739d628a0SDimitry Andric     return false;
273839d628a0SDimitry Andric   // Equal if all nodes in both stacks match.
273939d628a0SDimitry Andric   for (unsigned i=0; i < Stack.size(); ++i) {
274039d628a0SDimitry Andric     if (Stack[i].Start != Other.Stack[i].Start)
274139d628a0SDimitry Andric       return false;
274239d628a0SDimitry Andric   }
274339d628a0SDimitry Andric   return true;
274439d628a0SDimitry Andric }
274539d628a0SDimitry Andric 
readULEB128(const uint8_t * & Ptr,const char ** error)27462cab237bSDimitry Andric uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
274739d628a0SDimitry Andric   unsigned Count;
27482cab237bSDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
274939d628a0SDimitry Andric   Ptr += Count;
27502cab237bSDimitry Andric   if (Ptr > Trie.end())
275139d628a0SDimitry Andric     Ptr = Trie.end();
275239d628a0SDimitry Andric   return Result;
275339d628a0SDimitry Andric }
275439d628a0SDimitry Andric 
name() const275539d628a0SDimitry Andric StringRef ExportEntry::name() const {
2756ff0cc061SDimitry Andric   return CumulativeString;
275739d628a0SDimitry Andric }
275839d628a0SDimitry Andric 
flags() const275939d628a0SDimitry Andric uint64_t ExportEntry::flags() const {
276039d628a0SDimitry Andric   return Stack.back().Flags;
276139d628a0SDimitry Andric }
276239d628a0SDimitry Andric 
address() const276339d628a0SDimitry Andric uint64_t ExportEntry::address() const {
276439d628a0SDimitry Andric   return Stack.back().Address;
276539d628a0SDimitry Andric }
276639d628a0SDimitry Andric 
other() const276739d628a0SDimitry Andric uint64_t ExportEntry::other() const {
276839d628a0SDimitry Andric   return Stack.back().Other;
276939d628a0SDimitry Andric }
277039d628a0SDimitry Andric 
otherName() const277139d628a0SDimitry Andric StringRef ExportEntry::otherName() const {
277239d628a0SDimitry Andric   const char* ImportName = Stack.back().ImportName;
277339d628a0SDimitry Andric   if (ImportName)
277439d628a0SDimitry Andric     return StringRef(ImportName);
277539d628a0SDimitry Andric   return StringRef();
277639d628a0SDimitry Andric }
277739d628a0SDimitry Andric 
nodeOffset() const277839d628a0SDimitry Andric uint32_t ExportEntry::nodeOffset() const {
277939d628a0SDimitry Andric   return Stack.back().Start - Trie.begin();
278039d628a0SDimitry Andric }
278139d628a0SDimitry Andric 
NodeState(const uint8_t * Ptr)278239d628a0SDimitry Andric ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
278351690af2SDimitry Andric     : Start(Ptr), Current(Ptr) {}
278439d628a0SDimitry Andric 
pushNode(uint64_t offset)278539d628a0SDimitry Andric void ExportEntry::pushNode(uint64_t offset) {
27862cab237bSDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
278739d628a0SDimitry Andric   const uint8_t *Ptr = Trie.begin() + offset;
278839d628a0SDimitry Andric   NodeState State(Ptr);
27892cab237bSDimitry Andric   const char *error;
27902cab237bSDimitry Andric   uint64_t ExportInfoSize = readULEB128(State.Current, &error);
27912cab237bSDimitry Andric   if (error) {
27922cab237bSDimitry Andric     *E = malformedError("export info size " + Twine(error) +
27932cab237bSDimitry Andric                         " in export trie data at node: 0x" +
27942cab237bSDimitry Andric                         Twine::utohexstr(offset));
27952cab237bSDimitry Andric     moveToEnd();
27962cab237bSDimitry Andric     return;
27972cab237bSDimitry Andric   }
279839d628a0SDimitry Andric   State.IsExportNode = (ExportInfoSize != 0);
279939d628a0SDimitry Andric   const uint8_t* Children = State.Current + ExportInfoSize;
28002cab237bSDimitry Andric   if (Children > Trie.end()) {
28012cab237bSDimitry Andric     *E = malformedError(
28022cab237bSDimitry Andric         "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
28032cab237bSDimitry Andric         " in export trie data at node: 0x" + Twine::utohexstr(offset) +
28042cab237bSDimitry Andric         " too big and extends past end of trie data");
28052cab237bSDimitry Andric     moveToEnd();
28062cab237bSDimitry Andric     return;
28072cab237bSDimitry Andric   }
280839d628a0SDimitry Andric   if (State.IsExportNode) {
28092cab237bSDimitry Andric     const uint8_t *ExportStart = State.Current;
28102cab237bSDimitry Andric     State.Flags = readULEB128(State.Current, &error);
28112cab237bSDimitry Andric     if (error) {
28122cab237bSDimitry Andric       *E = malformedError("flags " + Twine(error) +
28132cab237bSDimitry Andric                           " in export trie data at node: 0x" +
28142cab237bSDimitry Andric                           Twine::utohexstr(offset));
28152cab237bSDimitry Andric       moveToEnd();
28162cab237bSDimitry Andric       return;
28172cab237bSDimitry Andric     }
28182cab237bSDimitry Andric     uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
28192cab237bSDimitry Andric     if (State.Flags != 0 &&
28202cab237bSDimitry Andric         (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
28212cab237bSDimitry Andric          Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
28222cab237bSDimitry Andric          Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
28232cab237bSDimitry Andric       *E = malformedError(
28242cab237bSDimitry Andric           "unsupported exported symbol kind: " + Twine((int)Kind) +
28252cab237bSDimitry Andric           " in flags: 0x" + Twine::utohexstr(State.Flags) +
28262cab237bSDimitry Andric           " in export trie data at node: 0x" + Twine::utohexstr(offset));
28272cab237bSDimitry Andric       moveToEnd();
28282cab237bSDimitry Andric       return;
28292cab237bSDimitry Andric     }
283039d628a0SDimitry Andric     if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
283139d628a0SDimitry Andric       State.Address = 0;
28322cab237bSDimitry Andric       State.Other = readULEB128(State.Current, &error); // dylib ordinal
28332cab237bSDimitry Andric       if (error) {
28342cab237bSDimitry Andric         *E = malformedError("dylib ordinal of re-export " + Twine(error) +
28352cab237bSDimitry Andric                             " in export trie data at node: 0x" +
28362cab237bSDimitry Andric                             Twine::utohexstr(offset));
28372cab237bSDimitry Andric         moveToEnd();
28382cab237bSDimitry Andric         return;
28392cab237bSDimitry Andric       }
28402cab237bSDimitry Andric       if (O != nullptr) {
28412cab237bSDimitry Andric         if (State.Other > O->getLibraryCount()) {
28422cab237bSDimitry Andric           *E = malformedError(
28432cab237bSDimitry Andric               "bad library ordinal: " + Twine((int)State.Other) + " (max " +
28442cab237bSDimitry Andric               Twine((int)O->getLibraryCount()) +
28452cab237bSDimitry Andric               ") in export trie data at node: 0x" + Twine::utohexstr(offset));
28462cab237bSDimitry Andric           moveToEnd();
28472cab237bSDimitry Andric           return;
28482cab237bSDimitry Andric         }
28492cab237bSDimitry Andric       }
285039d628a0SDimitry Andric       State.ImportName = reinterpret_cast<const char*>(State.Current);
28512cab237bSDimitry Andric       if (*State.ImportName == '\0') {
28522cab237bSDimitry Andric         State.Current++;
285339d628a0SDimitry Andric       } else {
28542cab237bSDimitry Andric         const uint8_t *End = State.Current + 1;
28552cab237bSDimitry Andric         if (End >= Trie.end()) {
28562cab237bSDimitry Andric           *E = malformedError("import name of re-export in export trie data at "
28572cab237bSDimitry Andric                               "node: 0x" +
28582cab237bSDimitry Andric                               Twine::utohexstr(offset) +
28592cab237bSDimitry Andric                               " starts past end of trie data");
28602cab237bSDimitry Andric           moveToEnd();
28612cab237bSDimitry Andric           return;
28622cab237bSDimitry Andric         }
28632cab237bSDimitry Andric         while(*End != '\0' && End < Trie.end())
28642cab237bSDimitry Andric           End++;
28652cab237bSDimitry Andric         if (*End != '\0') {
28662cab237bSDimitry Andric           *E = malformedError("import name of re-export in export trie data at "
28672cab237bSDimitry Andric                               "node: 0x" +
28682cab237bSDimitry Andric                               Twine::utohexstr(offset) +
28692cab237bSDimitry Andric                               " extends past end of trie data");
28702cab237bSDimitry Andric           moveToEnd();
28712cab237bSDimitry Andric           return;
28722cab237bSDimitry Andric         }
28732cab237bSDimitry Andric         State.Current = End + 1;
28742cab237bSDimitry Andric       }
28752cab237bSDimitry Andric     } else {
28762cab237bSDimitry Andric       State.Address = readULEB128(State.Current, &error);
28772cab237bSDimitry Andric       if (error) {
28782cab237bSDimitry Andric         *E = malformedError("address " + Twine(error) +
28792cab237bSDimitry Andric                             " in export trie data at node: 0x" +
28802cab237bSDimitry Andric                             Twine::utohexstr(offset));
28812cab237bSDimitry Andric         moveToEnd();
28822cab237bSDimitry Andric         return;
28832cab237bSDimitry Andric       }
28842cab237bSDimitry Andric       if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
28852cab237bSDimitry Andric         State.Other = readULEB128(State.Current, &error);
28862cab237bSDimitry Andric         if (error) {
28872cab237bSDimitry Andric           *E = malformedError("resolver of stub and resolver " + Twine(error) +
28882cab237bSDimitry Andric                               " in export trie data at node: 0x" +
28892cab237bSDimitry Andric                               Twine::utohexstr(offset));
28902cab237bSDimitry Andric           moveToEnd();
28912cab237bSDimitry Andric           return;
28922cab237bSDimitry Andric         }
28932cab237bSDimitry Andric       }
28942cab237bSDimitry Andric     }
28952cab237bSDimitry Andric     if(ExportStart + ExportInfoSize != State.Current) {
28962cab237bSDimitry Andric       *E = malformedError(
28972cab237bSDimitry Andric           "inconsistant export info size: 0x" +
28982cab237bSDimitry Andric           Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
28992cab237bSDimitry Andric           Twine::utohexstr(State.Current - ExportStart) +
29002cab237bSDimitry Andric           " in export trie data at node: 0x" + Twine::utohexstr(offset));
29012cab237bSDimitry Andric       moveToEnd();
29022cab237bSDimitry Andric       return;
290339d628a0SDimitry Andric     }
290439d628a0SDimitry Andric   }
290539d628a0SDimitry Andric   State.ChildCount = *Children;
29062cab237bSDimitry Andric   if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
29072cab237bSDimitry Andric     *E = malformedError("byte for count of childern in export trie data at "
29082cab237bSDimitry Andric                         "node: 0x" +
29092cab237bSDimitry Andric                         Twine::utohexstr(offset) +
29102cab237bSDimitry Andric                         " extends past end of trie data");
29112cab237bSDimitry Andric     moveToEnd();
29122cab237bSDimitry Andric     return;
29132cab237bSDimitry Andric   }
291439d628a0SDimitry Andric   State.Current = Children + 1;
291539d628a0SDimitry Andric   State.NextChildIndex = 0;
291639d628a0SDimitry Andric   State.ParentStringLength = CumulativeString.size();
291739d628a0SDimitry Andric   Stack.push_back(State);
291839d628a0SDimitry Andric }
291939d628a0SDimitry Andric 
pushDownUntilBottom()292039d628a0SDimitry Andric void ExportEntry::pushDownUntilBottom() {
29212cab237bSDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
29222cab237bSDimitry Andric   const char *error;
292339d628a0SDimitry Andric   while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
292439d628a0SDimitry Andric     NodeState &Top = Stack.back();
292539d628a0SDimitry Andric     CumulativeString.resize(Top.ParentStringLength);
29262cab237bSDimitry Andric     for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
292739d628a0SDimitry Andric       char C = *Top.Current;
292839d628a0SDimitry Andric       CumulativeString.push_back(C);
292939d628a0SDimitry Andric     }
29302cab237bSDimitry Andric     if (Top.Current >= Trie.end()) {
29312cab237bSDimitry Andric       *E = malformedError("edge sub-string in export trie data at node: 0x" +
29322cab237bSDimitry Andric                           Twine::utohexstr(Top.Start - Trie.begin()) +
29332cab237bSDimitry Andric                           " for child #" + Twine((int)Top.NextChildIndex) +
29342cab237bSDimitry Andric                           " extends past end of trie data");
29352cab237bSDimitry Andric       moveToEnd();
29362cab237bSDimitry Andric       return;
29372cab237bSDimitry Andric     }
293839d628a0SDimitry Andric     Top.Current += 1;
29392cab237bSDimitry Andric     uint64_t childNodeIndex = readULEB128(Top.Current, &error);
29402cab237bSDimitry Andric     if (error) {
29412cab237bSDimitry Andric       *E = malformedError("child node offset " + Twine(error) +
29422cab237bSDimitry Andric                           " in export trie data at node: 0x" +
29432cab237bSDimitry Andric                           Twine::utohexstr(Top.Start - Trie.begin()));
29442cab237bSDimitry Andric       moveToEnd();
29452cab237bSDimitry Andric       return;
29462cab237bSDimitry Andric     }
29472cab237bSDimitry Andric     for (const NodeState &node : nodes()) {
29482cab237bSDimitry Andric       if (node.Start == Trie.begin() + childNodeIndex){
29492cab237bSDimitry Andric         *E = malformedError("loop in childern in export trie data at node: 0x" +
29502cab237bSDimitry Andric                             Twine::utohexstr(Top.Start - Trie.begin()) +
29512cab237bSDimitry Andric                             " back to node: 0x" +
29522cab237bSDimitry Andric                             Twine::utohexstr(childNodeIndex));
29532cab237bSDimitry Andric         moveToEnd();
29542cab237bSDimitry Andric         return;
29552cab237bSDimitry Andric       }
29562cab237bSDimitry Andric     }
295739d628a0SDimitry Andric     Top.NextChildIndex += 1;
295839d628a0SDimitry Andric     pushNode(childNodeIndex);
29592cab237bSDimitry Andric     if (*E)
29602cab237bSDimitry Andric       return;
296139d628a0SDimitry Andric   }
296239d628a0SDimitry Andric   if (!Stack.back().IsExportNode) {
29632cab237bSDimitry Andric     *E = malformedError("node is not an export node in export trie data at "
29642cab237bSDimitry Andric                         "node: 0x" +
29652cab237bSDimitry Andric                         Twine::utohexstr(Stack.back().Start - Trie.begin()));
296639d628a0SDimitry Andric     moveToEnd();
29672cab237bSDimitry Andric     return;
296839d628a0SDimitry Andric   }
296939d628a0SDimitry Andric }
297039d628a0SDimitry Andric 
297139d628a0SDimitry Andric // We have a trie data structure and need a way to walk it that is compatible
297239d628a0SDimitry Andric // with the C++ iterator model. The solution is a non-recursive depth first
297339d628a0SDimitry Andric // traversal where the iterator contains a stack of parent nodes along with a
297439d628a0SDimitry Andric // string that is the accumulation of all edge strings along the parent chain
297539d628a0SDimitry Andric // to this point.
297639d628a0SDimitry Andric //
297739d628a0SDimitry Andric // There is one "export" node for each exported symbol.  But because some
297839d628a0SDimitry Andric // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
297939d628a0SDimitry Andric // node may have child nodes too.
298039d628a0SDimitry Andric //
298139d628a0SDimitry Andric // The algorithm for moveNext() is to keep moving down the leftmost unvisited
298239d628a0SDimitry Andric // child until hitting a node with no children (which is an export node or
298339d628a0SDimitry Andric // else the trie is malformed). On the way down, each node is pushed on the
298439d628a0SDimitry Andric // stack ivar.  If there is no more ways down, it pops up one and tries to go
298539d628a0SDimitry Andric // down a sibling path until a childless node is reached.
moveNext()298639d628a0SDimitry Andric void ExportEntry::moveNext() {
29872cab237bSDimitry Andric   assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
29882cab237bSDimitry Andric   if (!Stack.back().IsExportNode) {
29892cab237bSDimitry Andric     *E = malformedError("node is not an export node in export trie data at "
29902cab237bSDimitry Andric                         "node: 0x" +
29912cab237bSDimitry Andric                         Twine::utohexstr(Stack.back().Start - Trie.begin()));
299239d628a0SDimitry Andric     moveToEnd();
299339d628a0SDimitry Andric     return;
299439d628a0SDimitry Andric   }
299539d628a0SDimitry Andric 
299639d628a0SDimitry Andric   Stack.pop_back();
299739d628a0SDimitry Andric   while (!Stack.empty()) {
299839d628a0SDimitry Andric     NodeState &Top = Stack.back();
299939d628a0SDimitry Andric     if (Top.NextChildIndex < Top.ChildCount) {
300039d628a0SDimitry Andric       pushDownUntilBottom();
300139d628a0SDimitry Andric       // Now at the next export node.
300239d628a0SDimitry Andric       return;
300339d628a0SDimitry Andric     } else {
300439d628a0SDimitry Andric       if (Top.IsExportNode) {
300539d628a0SDimitry Andric         // This node has no children but is itself an export node.
300639d628a0SDimitry Andric         CumulativeString.resize(Top.ParentStringLength);
300739d628a0SDimitry Andric         return;
300839d628a0SDimitry Andric       }
300939d628a0SDimitry Andric       Stack.pop_back();
301039d628a0SDimitry Andric     }
301139d628a0SDimitry Andric   }
301239d628a0SDimitry Andric   Done = true;
301339d628a0SDimitry Andric }
301439d628a0SDimitry Andric 
301539d628a0SDimitry Andric iterator_range<export_iterator>
exports(Error & E,ArrayRef<uint8_t> Trie,const MachOObjectFile * O)30162cab237bSDimitry Andric MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
30172cab237bSDimitry Andric                          const MachOObjectFile *O) {
30182cab237bSDimitry Andric   ExportEntry Start(&E, O, Trie);
301951690af2SDimitry Andric   if (Trie.empty())
302039d628a0SDimitry Andric     Start.moveToEnd();
302139d628a0SDimitry Andric   else
302239d628a0SDimitry Andric     Start.moveToFirst();
302339d628a0SDimitry Andric 
30242cab237bSDimitry Andric   ExportEntry Finish(&E, O, Trie);
302539d628a0SDimitry Andric   Finish.moveToEnd();
302639d628a0SDimitry Andric 
30277d523365SDimitry Andric   return make_range(export_iterator(Start), export_iterator(Finish));
302839d628a0SDimitry Andric }
302939d628a0SDimitry Andric 
exports(Error & Err) const30302cab237bSDimitry Andric iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
30312cab237bSDimitry Andric   return exports(Err, getDyldInfoExportsTrie(), this);
303239d628a0SDimitry Andric }
303339d628a0SDimitry Andric 
MachORebaseEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit)30347a7e6055SDimitry Andric MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
30357a7e6055SDimitry Andric                                    ArrayRef<uint8_t> Bytes, bool is64Bit)
303651690af2SDimitry Andric     : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
303751690af2SDimitry Andric       PointerSize(is64Bit ? 8 : 4) {}
303839d628a0SDimitry Andric 
moveToFirst()303939d628a0SDimitry Andric void MachORebaseEntry::moveToFirst() {
304039d628a0SDimitry Andric   Ptr = Opcodes.begin();
304139d628a0SDimitry Andric   moveNext();
304239d628a0SDimitry Andric }
304339d628a0SDimitry Andric 
moveToEnd()304439d628a0SDimitry Andric void MachORebaseEntry::moveToEnd() {
304539d628a0SDimitry Andric   Ptr = Opcodes.end();
304639d628a0SDimitry Andric   RemainingLoopCount = 0;
304739d628a0SDimitry Andric   Done = true;
304839d628a0SDimitry Andric }
304939d628a0SDimitry Andric 
moveNext()305039d628a0SDimitry Andric void MachORebaseEntry::moveNext() {
30517a7e6055SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
305239d628a0SDimitry Andric   // If in the middle of some loop, move to next rebasing in loop.
305339d628a0SDimitry Andric   SegmentOffset += AdvanceAmount;
305439d628a0SDimitry Andric   if (RemainingLoopCount) {
305539d628a0SDimitry Andric     --RemainingLoopCount;
305639d628a0SDimitry Andric     return;
305739d628a0SDimitry Andric   }
30587a7e6055SDimitry Andric   // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
30597a7e6055SDimitry Andric   // pointer size. Therefore it is possible to reach the end without ever having
30607a7e6055SDimitry Andric   // seen REBASE_OPCODE_DONE.
306139d628a0SDimitry Andric   if (Ptr == Opcodes.end()) {
306239d628a0SDimitry Andric     Done = true;
306339d628a0SDimitry Andric     return;
306439d628a0SDimitry Andric   }
306539d628a0SDimitry Andric   bool More = true;
30667a7e6055SDimitry Andric   while (More) {
306739d628a0SDimitry Andric     // Parse next opcode and set up next loop.
30687a7e6055SDimitry Andric     const uint8_t *OpcodeStart = Ptr;
306939d628a0SDimitry Andric     uint8_t Byte = *Ptr++;
307039d628a0SDimitry Andric     uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
307139d628a0SDimitry Andric     uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
30727a7e6055SDimitry Andric     uint32_t Count, Skip;
30737a7e6055SDimitry Andric     const char *error = nullptr;
307439d628a0SDimitry Andric     switch (Opcode) {
307539d628a0SDimitry Andric     case MachO::REBASE_OPCODE_DONE:
307639d628a0SDimitry Andric       More = false;
307739d628a0SDimitry Andric       Done = true;
307839d628a0SDimitry Andric       moveToEnd();
307951690af2SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
308039d628a0SDimitry Andric       break;
308139d628a0SDimitry Andric     case MachO::REBASE_OPCODE_SET_TYPE_IMM:
308239d628a0SDimitry Andric       RebaseType = ImmValue;
30837a7e6055SDimitry Andric       if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
30847a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
30857a7e6055SDimitry Andric                             Twine((int)RebaseType) + " for opcode at: 0x" +
30862cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
30877a7e6055SDimitry Andric         moveToEnd();
30887a7e6055SDimitry Andric         return;
30897a7e6055SDimitry Andric       }
309039d628a0SDimitry Andric       DEBUG_WITH_TYPE(
309139d628a0SDimitry Andric           "mach-o-rebase",
309251690af2SDimitry Andric           dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
309339d628a0SDimitry Andric                  << "RebaseType=" << (int) RebaseType << "\n");
309439d628a0SDimitry Andric       break;
309539d628a0SDimitry Andric     case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
309639d628a0SDimitry Andric       SegmentIndex = ImmValue;
30977a7e6055SDimitry Andric       SegmentOffset = readULEB128(&error);
30987a7e6055SDimitry Andric       if (error) {
30997a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
31007a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
31012cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31027a7e6055SDimitry Andric         moveToEnd();
31037a7e6055SDimitry Andric         return;
31047a7e6055SDimitry Andric       }
31057a7e6055SDimitry Andric       error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31067a7e6055SDimitry Andric                                               true);
31077a7e6055SDimitry Andric       if (error) {
31087a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
31097a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
31102cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31117a7e6055SDimitry Andric         moveToEnd();
31127a7e6055SDimitry Andric         return;
31137a7e6055SDimitry Andric       }
311439d628a0SDimitry Andric       DEBUG_WITH_TYPE(
311539d628a0SDimitry Andric           "mach-o-rebase",
311651690af2SDimitry Andric           dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
311739d628a0SDimitry Andric                  << "SegmentIndex=" << SegmentIndex << ", "
311839d628a0SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
311939d628a0SDimitry Andric                  << "\n");
312039d628a0SDimitry Andric       break;
312139d628a0SDimitry Andric     case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
31227a7e6055SDimitry Andric       SegmentOffset += readULEB128(&error);
31237a7e6055SDimitry Andric       if (error) {
31242cab237bSDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
31252cab237bSDimitry Andric                             " for opcode at: 0x" +
31262cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31277a7e6055SDimitry Andric         moveToEnd();
31287a7e6055SDimitry Andric         return;
31297a7e6055SDimitry Andric       }
31307a7e6055SDimitry Andric       error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31317a7e6055SDimitry Andric                                               true);
31327a7e6055SDimitry Andric       if (error) {
31332cab237bSDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
31342cab237bSDimitry Andric                             " for opcode at: 0x" +
31352cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31367a7e6055SDimitry Andric         moveToEnd();
31377a7e6055SDimitry Andric         return;
31387a7e6055SDimitry Andric       }
313939d628a0SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase",
314051690af2SDimitry Andric                       dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
314139d628a0SDimitry Andric                              << format("SegmentOffset=0x%06X",
314239d628a0SDimitry Andric                                        SegmentOffset) << "\n");
314339d628a0SDimitry Andric       break;
314439d628a0SDimitry Andric     case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
31457a7e6055SDimitry Andric       error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31467a7e6055SDimitry Andric                                               true);
31477a7e6055SDimitry Andric       if (error) {
31487a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
31497a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
31502cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31517a7e6055SDimitry Andric         moveToEnd();
31527a7e6055SDimitry Andric         return;
31537a7e6055SDimitry Andric       }
315439d628a0SDimitry Andric       SegmentOffset += ImmValue * PointerSize;
31557a7e6055SDimitry Andric       error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31567a7e6055SDimitry Andric                                               false);
31577a7e6055SDimitry Andric       if (error) {
31582cab237bSDimitry Andric         *E =
31592cab237bSDimitry Andric             malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
31607a7e6055SDimitry Andric                            " (after adding immediate times the pointer size) " +
31617a7e6055SDimitry Andric                            Twine(error) + " for opcode at: 0x" +
31622cab237bSDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31637a7e6055SDimitry Andric         moveToEnd();
31647a7e6055SDimitry Andric         return;
31657a7e6055SDimitry Andric       }
316639d628a0SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase",
316751690af2SDimitry Andric                       dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
316839d628a0SDimitry Andric                              << format("SegmentOffset=0x%06X",
316939d628a0SDimitry Andric                                        SegmentOffset) << "\n");
317039d628a0SDimitry Andric       break;
317139d628a0SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
31727a7e6055SDimitry Andric       error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31737a7e6055SDimitry Andric                                               true);
31747a7e6055SDimitry Andric       if (error) {
31757a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
31767a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
31772cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31787a7e6055SDimitry Andric         moveToEnd();
31797a7e6055SDimitry Andric         return;
31807a7e6055SDimitry Andric       }
318139d628a0SDimitry Andric       AdvanceAmount = PointerSize;
31827a7e6055SDimitry Andric       Skip = 0;
31837a7e6055SDimitry Andric       Count = ImmValue;
31847a7e6055SDimitry Andric       if (ImmValue != 0)
318539d628a0SDimitry Andric         RemainingLoopCount = ImmValue - 1;
31867a7e6055SDimitry Andric       else
31877a7e6055SDimitry Andric         RemainingLoopCount = 0;
31887a7e6055SDimitry Andric       error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
31897a7e6055SDimitry Andric                                               SegmentIndex, SegmentOffset);
31907a7e6055SDimitry Andric       if (error) {
31912cab237bSDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
31922cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
31932cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31947a7e6055SDimitry Andric         moveToEnd();
31957a7e6055SDimitry Andric         return;
31967a7e6055SDimitry Andric       }
319739d628a0SDimitry Andric       DEBUG_WITH_TYPE(
319839d628a0SDimitry Andric           "mach-o-rebase",
319951690af2SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
320039d628a0SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
320139d628a0SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
320239d628a0SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
320339d628a0SDimitry Andric                  << "\n");
320439d628a0SDimitry Andric       return;
320539d628a0SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
32067a7e6055SDimitry Andric       error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
32077a7e6055SDimitry Andric                                               true);
32087a7e6055SDimitry Andric       if (error) {
32097a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
32107a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32112cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32127a7e6055SDimitry Andric         moveToEnd();
32137a7e6055SDimitry Andric         return;
32147a7e6055SDimitry Andric       }
321539d628a0SDimitry Andric       AdvanceAmount = PointerSize;
32167a7e6055SDimitry Andric       Skip = 0;
32177a7e6055SDimitry Andric       Count = readULEB128(&error);
32187a7e6055SDimitry Andric       if (error) {
32197a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
32207a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32212cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32227a7e6055SDimitry Andric         moveToEnd();
32237a7e6055SDimitry Andric         return;
32247a7e6055SDimitry Andric       }
32257a7e6055SDimitry Andric       if (Count != 0)
32267a7e6055SDimitry Andric         RemainingLoopCount = Count - 1;
32277a7e6055SDimitry Andric       else
32287a7e6055SDimitry Andric         RemainingLoopCount = 0;
32297a7e6055SDimitry Andric       error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
32307a7e6055SDimitry Andric                                               SegmentIndex, SegmentOffset);
32317a7e6055SDimitry Andric       if (error) {
32322cab237bSDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
32332cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32342cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32357a7e6055SDimitry Andric         moveToEnd();
32367a7e6055SDimitry Andric         return;
32377a7e6055SDimitry Andric       }
323839d628a0SDimitry Andric       DEBUG_WITH_TYPE(
323939d628a0SDimitry Andric           "mach-o-rebase",
324051690af2SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
324139d628a0SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
324239d628a0SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
324339d628a0SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
324439d628a0SDimitry Andric                  << "\n");
324539d628a0SDimitry Andric       return;
324639d628a0SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
32477a7e6055SDimitry Andric       error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
32487a7e6055SDimitry Andric                                               true);
32497a7e6055SDimitry Andric       if (error) {
32507a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
32517a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32522cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32537a7e6055SDimitry Andric         moveToEnd();
32547a7e6055SDimitry Andric         return;
32557a7e6055SDimitry Andric       }
32567a7e6055SDimitry Andric       Skip = readULEB128(&error);
32577a7e6055SDimitry Andric       if (error) {
32587a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
32597a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32602cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32617a7e6055SDimitry Andric         moveToEnd();
32627a7e6055SDimitry Andric         return;
32637a7e6055SDimitry Andric       }
32647a7e6055SDimitry Andric       AdvanceAmount = Skip + PointerSize;
32657a7e6055SDimitry Andric       Count = 1;
326639d628a0SDimitry Andric       RemainingLoopCount = 0;
32677a7e6055SDimitry Andric       error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
32687a7e6055SDimitry Andric                                               SegmentIndex, SegmentOffset);
32697a7e6055SDimitry Andric       if (error) {
32702cab237bSDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
32712cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32722cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32737a7e6055SDimitry Andric         moveToEnd();
32747a7e6055SDimitry Andric         return;
32757a7e6055SDimitry Andric       }
327639d628a0SDimitry Andric       DEBUG_WITH_TYPE(
327739d628a0SDimitry Andric           "mach-o-rebase",
327851690af2SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
327939d628a0SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
328039d628a0SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
328139d628a0SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
328239d628a0SDimitry Andric                  << "\n");
328339d628a0SDimitry Andric       return;
328439d628a0SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
32857a7e6055SDimitry Andric       error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
32867a7e6055SDimitry Andric                                               true);
32877a7e6055SDimitry Andric       if (error) {
32887a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
32892cab237bSDimitry Andric                             "ULEB " +
32902cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32912cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32927a7e6055SDimitry Andric         moveToEnd();
32937a7e6055SDimitry Andric         return;
32947a7e6055SDimitry Andric       }
32957a7e6055SDimitry Andric       Count = readULEB128(&error);
32967a7e6055SDimitry Andric       if (error) {
32977a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
32982cab237bSDimitry Andric                             "ULEB " +
32992cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33002cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33017a7e6055SDimitry Andric         moveToEnd();
33027a7e6055SDimitry Andric         return;
33037a7e6055SDimitry Andric       }
33047a7e6055SDimitry Andric       if (Count != 0)
33057a7e6055SDimitry Andric         RemainingLoopCount = Count - 1;
33067a7e6055SDimitry Andric       else
33077a7e6055SDimitry Andric         RemainingLoopCount = 0;
33087a7e6055SDimitry Andric       Skip = readULEB128(&error);
33097a7e6055SDimitry Andric       if (error) {
33107a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
33112cab237bSDimitry Andric                             "ULEB " +
33122cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33132cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33147a7e6055SDimitry Andric         moveToEnd();
33157a7e6055SDimitry Andric         return;
33167a7e6055SDimitry Andric       }
33177a7e6055SDimitry Andric       AdvanceAmount = Skip + PointerSize;
33187a7e6055SDimitry Andric 
33197a7e6055SDimitry Andric       error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
33207a7e6055SDimitry Andric                                               SegmentIndex, SegmentOffset);
33217a7e6055SDimitry Andric       if (error) {
33227a7e6055SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
33232cab237bSDimitry Andric                             "ULEB " +
33242cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33252cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33267a7e6055SDimitry Andric         moveToEnd();
33277a7e6055SDimitry Andric         return;
33287a7e6055SDimitry Andric       }
332939d628a0SDimitry Andric       DEBUG_WITH_TYPE(
333039d628a0SDimitry Andric           "mach-o-rebase",
333151690af2SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
333239d628a0SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
333339d628a0SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
333439d628a0SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
333539d628a0SDimitry Andric                  << "\n");
333639d628a0SDimitry Andric       return;
333739d628a0SDimitry Andric     default:
33387a7e6055SDimitry Andric       *E = malformedError("bad rebase info (bad opcode value 0x" +
33392cab237bSDimitry Andric                           Twine::utohexstr(Opcode) + " for opcode at: 0x" +
33402cab237bSDimitry Andric                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33417a7e6055SDimitry Andric       moveToEnd();
33427a7e6055SDimitry Andric       return;
334339d628a0SDimitry Andric     }
334439d628a0SDimitry Andric   }
334539d628a0SDimitry Andric }
334639d628a0SDimitry Andric 
readULEB128(const char ** error)33477a7e6055SDimitry Andric uint64_t MachORebaseEntry::readULEB128(const char **error) {
334839d628a0SDimitry Andric   unsigned Count;
33497a7e6055SDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
335039d628a0SDimitry Andric   Ptr += Count;
33517a7e6055SDimitry Andric   if (Ptr > Opcodes.end())
335239d628a0SDimitry Andric     Ptr = Opcodes.end();
335339d628a0SDimitry Andric   return Result;
335439d628a0SDimitry Andric }
335539d628a0SDimitry Andric 
segmentIndex() const33567a7e6055SDimitry Andric int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
335739d628a0SDimitry Andric 
segmentOffset() const335839d628a0SDimitry Andric uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
335939d628a0SDimitry Andric 
typeName() const336039d628a0SDimitry Andric StringRef MachORebaseEntry::typeName() const {
336139d628a0SDimitry Andric   switch (RebaseType) {
336239d628a0SDimitry Andric   case MachO::REBASE_TYPE_POINTER:
336339d628a0SDimitry Andric     return "pointer";
336439d628a0SDimitry Andric   case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
336539d628a0SDimitry Andric     return "text abs32";
336639d628a0SDimitry Andric   case MachO::REBASE_TYPE_TEXT_PCREL32:
336739d628a0SDimitry Andric     return "text rel32";
336839d628a0SDimitry Andric   }
336939d628a0SDimitry Andric   return "unknown";
337039d628a0SDimitry Andric }
337139d628a0SDimitry Andric 
33727a7e6055SDimitry Andric // For use with the SegIndex of a checked Mach-O Rebase entry
33737a7e6055SDimitry Andric // to get the segment name.
segmentName() const33747a7e6055SDimitry Andric StringRef MachORebaseEntry::segmentName() const {
33757a7e6055SDimitry Andric   return O->BindRebaseSegmentName(SegmentIndex);
33767a7e6055SDimitry Andric }
33777a7e6055SDimitry Andric 
33787a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
33797a7e6055SDimitry Andric // to get the section name.
sectionName() const33807a7e6055SDimitry Andric StringRef MachORebaseEntry::sectionName() const {
33817a7e6055SDimitry Andric   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
33827a7e6055SDimitry Andric }
33837a7e6055SDimitry Andric 
33847a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
33857a7e6055SDimitry Andric // to get the address.
address() const33867a7e6055SDimitry Andric uint64_t MachORebaseEntry::address() const {
33877a7e6055SDimitry Andric   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
33887a7e6055SDimitry Andric }
33897a7e6055SDimitry Andric 
operator ==(const MachORebaseEntry & Other) const339039d628a0SDimitry Andric bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
339124e2fe98SDimitry Andric #ifdef EXPENSIVE_CHECKS
339239d628a0SDimitry Andric   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
339324e2fe98SDimitry Andric #else
339424e2fe98SDimitry Andric   assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
339524e2fe98SDimitry Andric #endif
339639d628a0SDimitry Andric   return (Ptr == Other.Ptr) &&
339739d628a0SDimitry Andric          (RemainingLoopCount == Other.RemainingLoopCount) &&
339839d628a0SDimitry Andric          (Done == Other.Done);
339939d628a0SDimitry Andric }
340039d628a0SDimitry Andric 
340139d628a0SDimitry Andric iterator_range<rebase_iterator>
rebaseTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64)34027a7e6055SDimitry Andric MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
34037a7e6055SDimitry Andric                              ArrayRef<uint8_t> Opcodes, bool is64) {
34047a7e6055SDimitry Andric   if (O->BindRebaseSectionTable == nullptr)
34057a7e6055SDimitry Andric     O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
34067a7e6055SDimitry Andric   MachORebaseEntry Start(&Err, O, Opcodes, is64);
340739d628a0SDimitry Andric   Start.moveToFirst();
340839d628a0SDimitry Andric 
34097a7e6055SDimitry Andric   MachORebaseEntry Finish(&Err, O, Opcodes, is64);
341039d628a0SDimitry Andric   Finish.moveToEnd();
341139d628a0SDimitry Andric 
34127d523365SDimitry Andric   return make_range(rebase_iterator(Start), rebase_iterator(Finish));
341339d628a0SDimitry Andric }
341439d628a0SDimitry Andric 
rebaseTable(Error & Err)34157a7e6055SDimitry Andric iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
34167a7e6055SDimitry Andric   return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
341739d628a0SDimitry Andric }
341839d628a0SDimitry Andric 
MachOBindEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)34197a7e6055SDimitry Andric MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
34207a7e6055SDimitry Andric                                ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
342151690af2SDimitry Andric     : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
342251690af2SDimitry Andric       PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
342339d628a0SDimitry Andric 
moveToFirst()342439d628a0SDimitry Andric void MachOBindEntry::moveToFirst() {
342539d628a0SDimitry Andric   Ptr = Opcodes.begin();
342639d628a0SDimitry Andric   moveNext();
342739d628a0SDimitry Andric }
342839d628a0SDimitry Andric 
moveToEnd()342939d628a0SDimitry Andric void MachOBindEntry::moveToEnd() {
343039d628a0SDimitry Andric   Ptr = Opcodes.end();
343139d628a0SDimitry Andric   RemainingLoopCount = 0;
343239d628a0SDimitry Andric   Done = true;
343339d628a0SDimitry Andric }
343439d628a0SDimitry Andric 
moveNext()343539d628a0SDimitry Andric void MachOBindEntry::moveNext() {
34367a7e6055SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
343739d628a0SDimitry Andric   // If in the middle of some loop, move to next binding in loop.
343839d628a0SDimitry Andric   SegmentOffset += AdvanceAmount;
343939d628a0SDimitry Andric   if (RemainingLoopCount) {
344039d628a0SDimitry Andric     --RemainingLoopCount;
344139d628a0SDimitry Andric     return;
344239d628a0SDimitry Andric   }
34437a7e6055SDimitry Andric   // BIND_OPCODE_DONE is only used for padding if we are not aligned to
34447a7e6055SDimitry Andric   // pointer size. Therefore it is possible to reach the end without ever having
34457a7e6055SDimitry Andric   // seen BIND_OPCODE_DONE.
344639d628a0SDimitry Andric   if (Ptr == Opcodes.end()) {
344739d628a0SDimitry Andric     Done = true;
344839d628a0SDimitry Andric     return;
344939d628a0SDimitry Andric   }
345039d628a0SDimitry Andric   bool More = true;
34517a7e6055SDimitry Andric   while (More) {
345239d628a0SDimitry Andric     // Parse next opcode and set up next loop.
34537a7e6055SDimitry Andric     const uint8_t *OpcodeStart = Ptr;
345439d628a0SDimitry Andric     uint8_t Byte = *Ptr++;
345539d628a0SDimitry Andric     uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
345639d628a0SDimitry Andric     uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
345739d628a0SDimitry Andric     int8_t SignExtended;
345839d628a0SDimitry Andric     const uint8_t *SymStart;
34597a7e6055SDimitry Andric     uint32_t Count, Skip;
34607a7e6055SDimitry Andric     const char *error = nullptr;
346139d628a0SDimitry Andric     switch (Opcode) {
346239d628a0SDimitry Andric     case MachO::BIND_OPCODE_DONE:
346339d628a0SDimitry Andric       if (TableKind == Kind::Lazy) {
346439d628a0SDimitry Andric         // Lazying bindings have a DONE opcode between entries.  Need to ignore
346539d628a0SDimitry Andric         // it to advance to next entry.  But need not if this is last entry.
346639d628a0SDimitry Andric         bool NotLastEntry = false;
346739d628a0SDimitry Andric         for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
346839d628a0SDimitry Andric           if (*P) {
346939d628a0SDimitry Andric             NotLastEntry = true;
347039d628a0SDimitry Andric           }
347139d628a0SDimitry Andric         }
347239d628a0SDimitry Andric         if (NotLastEntry)
347339d628a0SDimitry Andric           break;
347439d628a0SDimitry Andric       }
347539d628a0SDimitry Andric       More = false;
347639d628a0SDimitry Andric       moveToEnd();
347751690af2SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
347839d628a0SDimitry Andric       break;
347939d628a0SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
34807a7e6055SDimitry Andric       if (TableKind == Kind::Weak) {
34817a7e6055SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
34827a7e6055SDimitry Andric                             "weak bind table for opcode at: 0x" +
34832cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
34847a7e6055SDimitry Andric         moveToEnd();
34857a7e6055SDimitry Andric         return;
34867a7e6055SDimitry Andric       }
348739d628a0SDimitry Andric       Ordinal = ImmValue;
34887a7e6055SDimitry Andric       LibraryOrdinalSet = true;
34897a7e6055SDimitry Andric       if (ImmValue > O->getLibraryCount()) {
34907a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
34912cab237bSDimitry Andric                             "library ordinal: " +
34922cab237bSDimitry Andric                             Twine((int)ImmValue) + " (max " +
34932cab237bSDimitry Andric                             Twine((int)O->getLibraryCount()) +
34942cab237bSDimitry Andric                             ") for opcode at: 0x" +
34952cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
34967a7e6055SDimitry Andric         moveToEnd();
34977a7e6055SDimitry Andric         return;
34987a7e6055SDimitry Andric       }
349939d628a0SDimitry Andric       DEBUG_WITH_TYPE(
350039d628a0SDimitry Andric           "mach-o-bind",
350151690af2SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
350239d628a0SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
350339d628a0SDimitry Andric       break;
350439d628a0SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
35057a7e6055SDimitry Andric       if (TableKind == Kind::Weak) {
35067a7e6055SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
35077a7e6055SDimitry Andric                             "weak bind table for opcode at: 0x" +
35082cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35097a7e6055SDimitry Andric         moveToEnd();
35107a7e6055SDimitry Andric         return;
35117a7e6055SDimitry Andric       }
35127a7e6055SDimitry Andric       Ordinal = readULEB128(&error);
35137a7e6055SDimitry Andric       LibraryOrdinalSet = true;
35147a7e6055SDimitry Andric       if (error) {
35157a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
35167a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
35172cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35187a7e6055SDimitry Andric         moveToEnd();
35197a7e6055SDimitry Andric         return;
35207a7e6055SDimitry Andric       }
35217a7e6055SDimitry Andric       if (Ordinal > (int)O->getLibraryCount()) {
35227a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
35232cab237bSDimitry Andric                             "library ordinal: " +
35242cab237bSDimitry Andric                             Twine((int)Ordinal) + " (max " +
35252cab237bSDimitry Andric                             Twine((int)O->getLibraryCount()) +
35262cab237bSDimitry Andric                             ") for opcode at: 0x" +
35272cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35287a7e6055SDimitry Andric         moveToEnd();
35297a7e6055SDimitry Andric         return;
35307a7e6055SDimitry Andric       }
353139d628a0SDimitry Andric       DEBUG_WITH_TYPE(
353239d628a0SDimitry Andric           "mach-o-bind",
353351690af2SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
353439d628a0SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
353539d628a0SDimitry Andric       break;
353639d628a0SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
35377a7e6055SDimitry Andric       if (TableKind == Kind::Weak) {
35387a7e6055SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
35397a7e6055SDimitry Andric                             "weak bind table for opcode at: 0x" +
35402cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35417a7e6055SDimitry Andric         moveToEnd();
35427a7e6055SDimitry Andric         return;
35437a7e6055SDimitry Andric       }
354439d628a0SDimitry Andric       if (ImmValue) {
354539d628a0SDimitry Andric         SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
354639d628a0SDimitry Andric         Ordinal = SignExtended;
35477a7e6055SDimitry Andric         if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
35487a7e6055SDimitry Andric           *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
35492cab237bSDimitry Andric                               "special ordinal: " +
35502cab237bSDimitry Andric                               Twine((int)Ordinal) + " for opcode at: 0x" +
35512cab237bSDimitry Andric                               Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35527a7e6055SDimitry Andric           moveToEnd();
35537a7e6055SDimitry Andric           return;
35547a7e6055SDimitry Andric         }
355539d628a0SDimitry Andric       } else
355639d628a0SDimitry Andric         Ordinal = 0;
3557f9448bf3SDimitry Andric       LibraryOrdinalSet = true;
355839d628a0SDimitry Andric       DEBUG_WITH_TYPE(
355939d628a0SDimitry Andric           "mach-o-bind",
356051690af2SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
356139d628a0SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
356239d628a0SDimitry Andric       break;
356339d628a0SDimitry Andric     case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
356439d628a0SDimitry Andric       Flags = ImmValue;
356539d628a0SDimitry Andric       SymStart = Ptr;
35667a7e6055SDimitry Andric       while (*Ptr && (Ptr < Opcodes.end())) {
356739d628a0SDimitry Andric         ++Ptr;
356839d628a0SDimitry Andric       }
35697a7e6055SDimitry Andric       if (Ptr == Opcodes.end()) {
35702cab237bSDimitry Andric         *E = malformedError(
35712cab237bSDimitry Andric             "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
35727a7e6055SDimitry Andric             "symbol name extends past opcodes for opcode at: 0x" +
35732cab237bSDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35747a7e6055SDimitry Andric         moveToEnd();
35757a7e6055SDimitry Andric         return;
35767a7e6055SDimitry Andric       }
357739d628a0SDimitry Andric       SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
357839d628a0SDimitry Andric                              Ptr-SymStart);
357939d628a0SDimitry Andric       ++Ptr;
358039d628a0SDimitry Andric       DEBUG_WITH_TYPE(
358139d628a0SDimitry Andric           "mach-o-bind",
358251690af2SDimitry Andric           dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
358339d628a0SDimitry Andric                  << "SymbolName=" << SymbolName << "\n");
358439d628a0SDimitry Andric       if (TableKind == Kind::Weak) {
358539d628a0SDimitry Andric         if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
358639d628a0SDimitry Andric           return;
358739d628a0SDimitry Andric       }
358839d628a0SDimitry Andric       break;
358939d628a0SDimitry Andric     case MachO::BIND_OPCODE_SET_TYPE_IMM:
359039d628a0SDimitry Andric       BindType = ImmValue;
35917a7e6055SDimitry Andric       if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
35927a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
35937a7e6055SDimitry Andric                             Twine((int)ImmValue) + " for opcode at: 0x" +
35942cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35957a7e6055SDimitry Andric         moveToEnd();
35967a7e6055SDimitry Andric         return;
35977a7e6055SDimitry Andric       }
359839d628a0SDimitry Andric       DEBUG_WITH_TYPE(
359939d628a0SDimitry Andric           "mach-o-bind",
360051690af2SDimitry Andric           dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
360139d628a0SDimitry Andric                  << "BindType=" << (int)BindType << "\n");
360239d628a0SDimitry Andric       break;
360339d628a0SDimitry Andric     case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
36047a7e6055SDimitry Andric       Addend = readSLEB128(&error);
36057a7e6055SDimitry Andric       if (error) {
36062cab237bSDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
36072cab237bSDimitry Andric                             " for opcode at: 0x" +
36082cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36097a7e6055SDimitry Andric         moveToEnd();
36107a7e6055SDimitry Andric         return;
36117a7e6055SDimitry Andric       }
361239d628a0SDimitry Andric       DEBUG_WITH_TYPE(
361339d628a0SDimitry Andric           "mach-o-bind",
361451690af2SDimitry Andric           dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
361539d628a0SDimitry Andric                  << "Addend=" << Addend << "\n");
361639d628a0SDimitry Andric       break;
361739d628a0SDimitry Andric     case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
361839d628a0SDimitry Andric       SegmentIndex = ImmValue;
36197a7e6055SDimitry Andric       SegmentOffset = readULEB128(&error);
36207a7e6055SDimitry Andric       if (error) {
36217a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
36227a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36232cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36247a7e6055SDimitry Andric         moveToEnd();
36257a7e6055SDimitry Andric         return;
36267a7e6055SDimitry Andric       }
36277a7e6055SDimitry Andric       error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
36287a7e6055SDimitry Andric       if (error) {
36297a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
36307a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36312cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36327a7e6055SDimitry Andric         moveToEnd();
36337a7e6055SDimitry Andric         return;
36347a7e6055SDimitry Andric       }
363539d628a0SDimitry Andric       DEBUG_WITH_TYPE(
363639d628a0SDimitry Andric           "mach-o-bind",
363751690af2SDimitry Andric           dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
363839d628a0SDimitry Andric                  << "SegmentIndex=" << SegmentIndex << ", "
363939d628a0SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
364039d628a0SDimitry Andric                  << "\n");
364139d628a0SDimitry Andric       break;
364239d628a0SDimitry Andric     case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
36437a7e6055SDimitry Andric       SegmentOffset += readULEB128(&error);
36447a7e6055SDimitry Andric       if (error) {
36452cab237bSDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
36462cab237bSDimitry Andric                             " for opcode at: 0x" +
36472cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36487a7e6055SDimitry Andric         moveToEnd();
36497a7e6055SDimitry Andric         return;
36507a7e6055SDimitry Andric       }
36517a7e6055SDimitry Andric       error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
36527a7e6055SDimitry Andric       if (error) {
36532cab237bSDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
36542cab237bSDimitry Andric                             " for opcode at: 0x" +
36552cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36567a7e6055SDimitry Andric         moveToEnd();
36577a7e6055SDimitry Andric         return;
36587a7e6055SDimitry Andric       }
365939d628a0SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
366051690af2SDimitry Andric                       dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
366139d628a0SDimitry Andric                              << format("SegmentOffset=0x%06X",
366239d628a0SDimitry Andric                                        SegmentOffset) << "\n");
366339d628a0SDimitry Andric       break;
366439d628a0SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND:
366539d628a0SDimitry Andric       AdvanceAmount = PointerSize;
366639d628a0SDimitry Andric       RemainingLoopCount = 0;
36677a7e6055SDimitry Andric       error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
36687a7e6055SDimitry Andric       if (error) {
36697a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
36702cab237bSDimitry Andric                             " for opcode at: 0x" +
36712cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36727a7e6055SDimitry Andric         moveToEnd();
36737a7e6055SDimitry Andric         return;
36747a7e6055SDimitry Andric       }
36757a7e6055SDimitry Andric       if (SymbolName == StringRef()) {
36762cab237bSDimitry Andric         *E = malformedError(
36772cab237bSDimitry Andric             "for BIND_OPCODE_DO_BIND missing preceding "
36787a7e6055SDimitry Andric             "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
36792cab237bSDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36807a7e6055SDimitry Andric         moveToEnd();
36817a7e6055SDimitry Andric         return;
36827a7e6055SDimitry Andric       }
36837a7e6055SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
36842cab237bSDimitry Andric         *E =
36852cab237bSDimitry Andric             malformedError("for BIND_OPCODE_DO_BIND missing preceding "
36867a7e6055SDimitry Andric                            "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
36872cab237bSDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36887a7e6055SDimitry Andric         moveToEnd();
36897a7e6055SDimitry Andric         return;
36907a7e6055SDimitry Andric       }
369139d628a0SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
369251690af2SDimitry Andric                       dbgs() << "BIND_OPCODE_DO_BIND: "
369339d628a0SDimitry Andric                              << format("SegmentOffset=0x%06X",
369439d628a0SDimitry Andric                                        SegmentOffset) << "\n");
369539d628a0SDimitry Andric       return;
369639d628a0SDimitry Andric      case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
36977a7e6055SDimitry Andric       if (TableKind == Kind::Lazy) {
36987a7e6055SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
36997a7e6055SDimitry Andric                             "lazy bind table for opcode at: 0x" +
37002cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37017a7e6055SDimitry Andric         moveToEnd();
37027a7e6055SDimitry Andric         return;
37037a7e6055SDimitry Andric       }
37047a7e6055SDimitry Andric       error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
37057a7e6055SDimitry Andric       if (error) {
37067a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
37077a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
37082cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37097a7e6055SDimitry Andric         moveToEnd();
37107a7e6055SDimitry Andric         return;
37117a7e6055SDimitry Andric       }
37127a7e6055SDimitry Andric       if (SymbolName == StringRef()) {
37132cab237bSDimitry Andric         *E = malformedError(
37142cab237bSDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
37157a7e6055SDimitry Andric             "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
37162cab237bSDimitry Andric             "at: 0x" +
37172cab237bSDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37187a7e6055SDimitry Andric         moveToEnd();
37197a7e6055SDimitry Andric         return;
37207a7e6055SDimitry Andric       }
37217a7e6055SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
37222cab237bSDimitry Andric         *E = malformedError(
37232cab237bSDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
37247a7e6055SDimitry Andric             "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
37252cab237bSDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37267a7e6055SDimitry Andric         moveToEnd();
37277a7e6055SDimitry Andric         return;
37287a7e6055SDimitry Andric       }
37297a7e6055SDimitry Andric       AdvanceAmount = readULEB128(&error) + PointerSize;
37307a7e6055SDimitry Andric       if (error) {
37317a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
37327a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
37332cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37347a7e6055SDimitry Andric         moveToEnd();
37357a7e6055SDimitry Andric         return;
37367a7e6055SDimitry Andric       }
37377a7e6055SDimitry Andric       // Note, this is not really an error until the next bind but make no sense
37387a7e6055SDimitry Andric       // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
37397a7e6055SDimitry Andric       // bind operation.
37407a7e6055SDimitry Andric       error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
37417a7e6055SDimitry Andric                                             AdvanceAmount, false);
37427a7e6055SDimitry Andric       if (error) {
37437a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
37442cab237bSDimitry Andric                             "ULEB) " +
37452cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
37462cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37477a7e6055SDimitry Andric         moveToEnd();
37487a7e6055SDimitry Andric         return;
37497a7e6055SDimitry Andric       }
375039d628a0SDimitry Andric       RemainingLoopCount = 0;
375139d628a0SDimitry Andric       DEBUG_WITH_TYPE(
375239d628a0SDimitry Andric           "mach-o-bind",
375351690af2SDimitry Andric           dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
375439d628a0SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
375539d628a0SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
375639d628a0SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
375739d628a0SDimitry Andric                  << "\n");
375839d628a0SDimitry Andric       return;
375939d628a0SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
37607a7e6055SDimitry Andric       if (TableKind == Kind::Lazy) {
37617a7e6055SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
37627a7e6055SDimitry Andric                             "allowed in lazy bind table for opcode at: 0x" +
37632cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37647a7e6055SDimitry Andric         moveToEnd();
37657a7e6055SDimitry Andric         return;
37667a7e6055SDimitry Andric       }
37677a7e6055SDimitry Andric       error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
37687a7e6055SDimitry Andric       if (error) {
37697a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
37707a7e6055SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
37712cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37727a7e6055SDimitry Andric         moveToEnd();
37737a7e6055SDimitry Andric         return;
37747a7e6055SDimitry Andric       }
37757a7e6055SDimitry Andric       if (SymbolName == StringRef()) {
37762cab237bSDimitry Andric         *E = malformedError(
37772cab237bSDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
37787a7e6055SDimitry Andric             "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
37792cab237bSDimitry Andric             "opcode at: 0x" +
37802cab237bSDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37817a7e6055SDimitry Andric         moveToEnd();
37827a7e6055SDimitry Andric         return;
37837a7e6055SDimitry Andric       }
37847a7e6055SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
37852cab237bSDimitry Andric         *E = malformedError(
37862cab237bSDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
37877a7e6055SDimitry Andric             "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
37882cab237bSDimitry Andric             "at: 0x" +
37892cab237bSDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37907a7e6055SDimitry Andric         moveToEnd();
37917a7e6055SDimitry Andric         return;
37927a7e6055SDimitry Andric       }
379339d628a0SDimitry Andric       AdvanceAmount = ImmValue * PointerSize + PointerSize;
379439d628a0SDimitry Andric       RemainingLoopCount = 0;
37957a7e6055SDimitry Andric       error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
37967a7e6055SDimitry Andric                                             AdvanceAmount, false);
37977a7e6055SDimitry Andric       if (error) {
37982cab237bSDimitry Andric         *E =
37992cab237bSDimitry Andric             malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
38007a7e6055SDimitry Andric                            " (after adding immediate times the pointer size) " +
38017a7e6055SDimitry Andric                            Twine(error) + " for opcode at: 0x" +
38022cab237bSDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38037a7e6055SDimitry Andric         moveToEnd();
38047a7e6055SDimitry Andric         return;
38057a7e6055SDimitry Andric       }
380639d628a0SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
380751690af2SDimitry Andric                       dbgs()
380839d628a0SDimitry Andric                       << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
380951690af2SDimitry Andric                       << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
381039d628a0SDimitry Andric       return;
381139d628a0SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
38127a7e6055SDimitry Andric       if (TableKind == Kind::Lazy) {
38137a7e6055SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
38147a7e6055SDimitry Andric                             "allowed in lazy bind table for opcode at: 0x" +
38152cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38167a7e6055SDimitry Andric         moveToEnd();
38177a7e6055SDimitry Andric         return;
38187a7e6055SDimitry Andric       }
38197a7e6055SDimitry Andric       Count = readULEB128(&error);
38207a7e6055SDimitry Andric       if (Count != 0)
38217a7e6055SDimitry Andric         RemainingLoopCount = Count - 1;
38227a7e6055SDimitry Andric       else
38237a7e6055SDimitry Andric         RemainingLoopCount = 0;
38247a7e6055SDimitry Andric       if (error) {
38257a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38262cab237bSDimitry Andric                             " (count value) " +
38272cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
38282cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38297a7e6055SDimitry Andric         moveToEnd();
38307a7e6055SDimitry Andric         return;
38317a7e6055SDimitry Andric       }
38327a7e6055SDimitry Andric       Skip = readULEB128(&error);
38337a7e6055SDimitry Andric       AdvanceAmount = Skip + PointerSize;
38347a7e6055SDimitry Andric       if (error) {
38357a7e6055SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38362cab237bSDimitry Andric                             " (skip value) " +
38372cab237bSDimitry Andric                             Twine(error) + " for opcode at: 0x" +
38382cab237bSDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38397a7e6055SDimitry Andric         moveToEnd();
38407a7e6055SDimitry Andric         return;
38417a7e6055SDimitry Andric       }
38427a7e6055SDimitry Andric       error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
38437a7e6055SDimitry Andric       if (error) {
38442cab237bSDimitry Andric         *E =
38452cab237bSDimitry Andric             malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
38462cab237bSDimitry Andric                            Twine(error) + " for opcode at: 0x" +
38472cab237bSDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38487a7e6055SDimitry Andric         moveToEnd();
38497a7e6055SDimitry Andric         return;
38507a7e6055SDimitry Andric       }
38517a7e6055SDimitry Andric       if (SymbolName == StringRef()) {
38522cab237bSDimitry Andric         *E = malformedError(
38532cab237bSDimitry Andric             "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38547a7e6055SDimitry Andric             "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
38552cab237bSDimitry Andric             "opcode at: 0x" +
38562cab237bSDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38577a7e6055SDimitry Andric         moveToEnd();
38587a7e6055SDimitry Andric         return;
38597a7e6055SDimitry Andric       }
38607a7e6055SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
38612cab237bSDimitry Andric         *E = malformedError(
38622cab237bSDimitry Andric             "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38637a7e6055SDimitry Andric             "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
38642cab237bSDimitry Andric             "at: 0x" +
38652cab237bSDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38667a7e6055SDimitry Andric         moveToEnd();
38677a7e6055SDimitry Andric         return;
38687a7e6055SDimitry Andric       }
38697a7e6055SDimitry Andric       error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
38707a7e6055SDimitry Andric                                             SegmentIndex, SegmentOffset);
38717a7e6055SDimitry Andric       if (error) {
38722cab237bSDimitry Andric         *E =
38732cab237bSDimitry Andric             malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
38742cab237bSDimitry Andric                            Twine(error) + " for opcode at: 0x" +
38752cab237bSDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38767a7e6055SDimitry Andric         moveToEnd();
38777a7e6055SDimitry Andric         return;
38787a7e6055SDimitry Andric       }
387939d628a0SDimitry Andric       DEBUG_WITH_TYPE(
388039d628a0SDimitry Andric           "mach-o-bind",
388151690af2SDimitry Andric           dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
388239d628a0SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
388339d628a0SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
388439d628a0SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
388539d628a0SDimitry Andric                  << "\n");
388639d628a0SDimitry Andric       return;
388739d628a0SDimitry Andric     default:
38887a7e6055SDimitry Andric       *E = malformedError("bad bind info (bad opcode value 0x" +
38892cab237bSDimitry Andric                           Twine::utohexstr(Opcode) + " for opcode at: 0x" +
38902cab237bSDimitry Andric                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38917a7e6055SDimitry Andric       moveToEnd();
38927a7e6055SDimitry Andric       return;
389339d628a0SDimitry Andric     }
389439d628a0SDimitry Andric   }
389539d628a0SDimitry Andric }
389639d628a0SDimitry Andric 
readULEB128(const char ** error)38977a7e6055SDimitry Andric uint64_t MachOBindEntry::readULEB128(const char **error) {
389839d628a0SDimitry Andric   unsigned Count;
38997a7e6055SDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
390039d628a0SDimitry Andric   Ptr += Count;
39017a7e6055SDimitry Andric   if (Ptr > Opcodes.end())
390239d628a0SDimitry Andric     Ptr = Opcodes.end();
390339d628a0SDimitry Andric   return Result;
390439d628a0SDimitry Andric }
390539d628a0SDimitry Andric 
readSLEB128(const char ** error)39067a7e6055SDimitry Andric int64_t MachOBindEntry::readSLEB128(const char **error) {
390739d628a0SDimitry Andric   unsigned Count;
39087a7e6055SDimitry Andric   int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
390939d628a0SDimitry Andric   Ptr += Count;
39107a7e6055SDimitry Andric   if (Ptr > Opcodes.end())
391139d628a0SDimitry Andric     Ptr = Opcodes.end();
391239d628a0SDimitry Andric   return Result;
391339d628a0SDimitry Andric }
391439d628a0SDimitry Andric 
segmentIndex() const39157a7e6055SDimitry Andric int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
391639d628a0SDimitry Andric 
segmentOffset() const391739d628a0SDimitry Andric uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
391839d628a0SDimitry Andric 
typeName() const391939d628a0SDimitry Andric StringRef MachOBindEntry::typeName() const {
392039d628a0SDimitry Andric   switch (BindType) {
392139d628a0SDimitry Andric   case MachO::BIND_TYPE_POINTER:
392239d628a0SDimitry Andric     return "pointer";
392339d628a0SDimitry Andric   case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
392439d628a0SDimitry Andric     return "text abs32";
392539d628a0SDimitry Andric   case MachO::BIND_TYPE_TEXT_PCREL32:
392639d628a0SDimitry Andric     return "text rel32";
392739d628a0SDimitry Andric   }
392839d628a0SDimitry Andric   return "unknown";
392939d628a0SDimitry Andric }
393039d628a0SDimitry Andric 
symbolName() const393139d628a0SDimitry Andric StringRef MachOBindEntry::symbolName() const { return SymbolName; }
393239d628a0SDimitry Andric 
addend() const393339d628a0SDimitry Andric int64_t MachOBindEntry::addend() const { return Addend; }
393439d628a0SDimitry Andric 
flags() const393539d628a0SDimitry Andric uint32_t MachOBindEntry::flags() const { return Flags; }
393639d628a0SDimitry Andric 
ordinal() const393739d628a0SDimitry Andric int MachOBindEntry::ordinal() const { return Ordinal; }
393839d628a0SDimitry Andric 
39397a7e6055SDimitry Andric // For use with the SegIndex of a checked Mach-O Bind entry
39407a7e6055SDimitry Andric // to get the segment name.
segmentName() const39417a7e6055SDimitry Andric StringRef MachOBindEntry::segmentName() const {
39427a7e6055SDimitry Andric   return O->BindRebaseSegmentName(SegmentIndex);
39437a7e6055SDimitry Andric }
39447a7e6055SDimitry Andric 
39457a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
39467a7e6055SDimitry Andric // to get the section name.
sectionName() const39477a7e6055SDimitry Andric StringRef MachOBindEntry::sectionName() const {
39487a7e6055SDimitry Andric   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
39497a7e6055SDimitry Andric }
39507a7e6055SDimitry Andric 
39517a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
39527a7e6055SDimitry Andric // to get the address.
address() const39537a7e6055SDimitry Andric uint64_t MachOBindEntry::address() const {
39547a7e6055SDimitry Andric   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
39557a7e6055SDimitry Andric }
39567a7e6055SDimitry Andric 
operator ==(const MachOBindEntry & Other) const395739d628a0SDimitry Andric bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
395824e2fe98SDimitry Andric #ifdef EXPENSIVE_CHECKS
395939d628a0SDimitry Andric   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
396024e2fe98SDimitry Andric #else
396124e2fe98SDimitry Andric   assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
396224e2fe98SDimitry Andric #endif
396339d628a0SDimitry Andric   return (Ptr == Other.Ptr) &&
396439d628a0SDimitry Andric          (RemainingLoopCount == Other.RemainingLoopCount) &&
396539d628a0SDimitry Andric          (Done == Other.Done);
396639d628a0SDimitry Andric }
396739d628a0SDimitry Andric 
39687a7e6055SDimitry Andric // Build table of sections so SegIndex/SegOffset pairs can be translated.
BindRebaseSegInfo(const object::MachOObjectFile * Obj)39697a7e6055SDimitry Andric BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
39707a7e6055SDimitry Andric   uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
39717a7e6055SDimitry Andric   StringRef CurSegName;
39727a7e6055SDimitry Andric   uint64_t CurSegAddress;
39737a7e6055SDimitry Andric   for (const SectionRef &Section : Obj->sections()) {
39747a7e6055SDimitry Andric     SectionInfo Info;
39757a7e6055SDimitry Andric     Section.getName(Info.SectionName);
39767a7e6055SDimitry Andric     Info.Address = Section.getAddress();
39777a7e6055SDimitry Andric     Info.Size = Section.getSize();
39787a7e6055SDimitry Andric     Info.SegmentName =
39797a7e6055SDimitry Andric         Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
39807a7e6055SDimitry Andric     if (!Info.SegmentName.equals(CurSegName)) {
39817a7e6055SDimitry Andric       ++CurSegIndex;
39827a7e6055SDimitry Andric       CurSegName = Info.SegmentName;
39837a7e6055SDimitry Andric       CurSegAddress = Info.Address;
39847a7e6055SDimitry Andric     }
39857a7e6055SDimitry Andric     Info.SegmentIndex = CurSegIndex - 1;
39867a7e6055SDimitry Andric     Info.OffsetInSegment = Info.Address - CurSegAddress;
39877a7e6055SDimitry Andric     Info.SegmentStartAddress = CurSegAddress;
39887a7e6055SDimitry Andric     Sections.push_back(Info);
39897a7e6055SDimitry Andric   }
39907a7e6055SDimitry Andric   MaxSegIndex = CurSegIndex;
39917a7e6055SDimitry Andric }
39927a7e6055SDimitry Andric 
39937a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
39947a7e6055SDimitry Andric // validate a MachOBindEntry or MachORebaseEntry.
checkSegAndOffset(int32_t SegIndex,uint64_t SegOffset,bool endInvalid)39957a7e6055SDimitry Andric const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
39967a7e6055SDimitry Andric                                                   uint64_t SegOffset,
39977a7e6055SDimitry Andric                                                   bool endInvalid) {
39987a7e6055SDimitry Andric   if (SegIndex == -1)
39997a7e6055SDimitry Andric     return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
40007a7e6055SDimitry Andric   if (SegIndex >= MaxSegIndex)
40017a7e6055SDimitry Andric     return "bad segIndex (too large)";
40027a7e6055SDimitry Andric   for (const SectionInfo &SI : Sections) {
40037a7e6055SDimitry Andric     if (SI.SegmentIndex != SegIndex)
40047a7e6055SDimitry Andric       continue;
40057a7e6055SDimitry Andric     if (SI.OffsetInSegment > SegOffset)
40067a7e6055SDimitry Andric       continue;
40077a7e6055SDimitry Andric     if (SegOffset > (SI.OffsetInSegment + SI.Size))
40087a7e6055SDimitry Andric       continue;
40097a7e6055SDimitry Andric     if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
40107a7e6055SDimitry Andric       continue;
40117a7e6055SDimitry Andric     return nullptr;
40127a7e6055SDimitry Andric   }
40137a7e6055SDimitry Andric   return "bad segOffset, too large";
40147a7e6055SDimitry Andric }
40157a7e6055SDimitry Andric 
40167a7e6055SDimitry Andric // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
40177a7e6055SDimitry Andric // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
40187a7e6055SDimitry Andric // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
40197a7e6055SDimitry Andric // REBASE_OPCODE_DO_*_TIMES* opcodes.  The SegIndex and SegOffset must have
40207a7e6055SDimitry Andric // been already checked.
checkCountAndSkip(uint32_t Count,uint32_t Skip,uint8_t PointerSize,int32_t SegIndex,uint64_t SegOffset)40217a7e6055SDimitry Andric const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
40227a7e6055SDimitry Andric                                                   uint8_t PointerSize,
40237a7e6055SDimitry Andric                                                   int32_t SegIndex,
40247a7e6055SDimitry Andric                                                   uint64_t SegOffset) {
40257a7e6055SDimitry Andric   const SectionInfo &SI = findSection(SegIndex, SegOffset);
40267a7e6055SDimitry Andric   uint64_t addr = SI.SegmentStartAddress + SegOffset;
40277a7e6055SDimitry Andric   if (addr >= SI.Address + SI.Size)
40287a7e6055SDimitry Andric     return "bad segOffset, too large";
40297a7e6055SDimitry Andric   uint64_t i = 0;
40307a7e6055SDimitry Andric   if (Count > 1)
40317a7e6055SDimitry Andric     i = (Skip + PointerSize) * (Count - 1);
40327a7e6055SDimitry Andric   else if (Count == 1)
40337a7e6055SDimitry Andric     i = Skip + PointerSize;
40347a7e6055SDimitry Andric   if (addr + i >= SI.Address + SI.Size) {
40357a7e6055SDimitry Andric     // For rebase opcodes they can step from one section to another.
40367a7e6055SDimitry Andric     uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
40377a7e6055SDimitry Andric     const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
40387a7e6055SDimitry Andric     if (error)
40397a7e6055SDimitry Andric       return "bad count and skip, too large";
40407a7e6055SDimitry Andric   }
40417a7e6055SDimitry Andric   return nullptr;
40427a7e6055SDimitry Andric }
40437a7e6055SDimitry Andric 
40447a7e6055SDimitry Andric // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
40457a7e6055SDimitry Andric // to get the segment name.
segmentName(int32_t SegIndex)40467a7e6055SDimitry Andric StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
40477a7e6055SDimitry Andric   for (const SectionInfo &SI : Sections) {
40487a7e6055SDimitry Andric     if (SI.SegmentIndex == SegIndex)
40497a7e6055SDimitry Andric       return SI.SegmentName;
40507a7e6055SDimitry Andric   }
40517a7e6055SDimitry Andric   llvm_unreachable("invalid SegIndex");
40527a7e6055SDimitry Andric }
40537a7e6055SDimitry Andric 
40547a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
40557a7e6055SDimitry Andric // to get the SectionInfo.
findSection(int32_t SegIndex,uint64_t SegOffset)40567a7e6055SDimitry Andric const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
40577a7e6055SDimitry Andric                                      int32_t SegIndex, uint64_t SegOffset) {
40587a7e6055SDimitry Andric   for (const SectionInfo &SI : Sections) {
40597a7e6055SDimitry Andric     if (SI.SegmentIndex != SegIndex)
40607a7e6055SDimitry Andric       continue;
40617a7e6055SDimitry Andric     if (SI.OffsetInSegment > SegOffset)
40627a7e6055SDimitry Andric       continue;
40637a7e6055SDimitry Andric     if (SegOffset >= (SI.OffsetInSegment + SI.Size))
40647a7e6055SDimitry Andric       continue;
40657a7e6055SDimitry Andric     return SI;
40667a7e6055SDimitry Andric   }
40677a7e6055SDimitry Andric   llvm_unreachable("SegIndex and SegOffset not in any section");
40687a7e6055SDimitry Andric }
40697a7e6055SDimitry Andric 
40707a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
40717a7e6055SDimitry Andric // entry to get the section name.
sectionName(int32_t SegIndex,uint64_t SegOffset)40727a7e6055SDimitry Andric StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
40737a7e6055SDimitry Andric                                          uint64_t SegOffset) {
40747a7e6055SDimitry Andric   return findSection(SegIndex, SegOffset).SectionName;
40757a7e6055SDimitry Andric }
40767a7e6055SDimitry Andric 
40777a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
40787a7e6055SDimitry Andric // entry to get the address.
address(uint32_t SegIndex,uint64_t OffsetInSeg)40797a7e6055SDimitry Andric uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
40807a7e6055SDimitry Andric   const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
40817a7e6055SDimitry Andric   return SI.SegmentStartAddress + OffsetInSeg;
40827a7e6055SDimitry Andric }
40837a7e6055SDimitry Andric 
408439d628a0SDimitry Andric iterator_range<bind_iterator>
bindTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)40857a7e6055SDimitry Andric MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
40867a7e6055SDimitry Andric                            ArrayRef<uint8_t> Opcodes, bool is64,
408739d628a0SDimitry Andric                            MachOBindEntry::Kind BKind) {
40887a7e6055SDimitry Andric   if (O->BindRebaseSectionTable == nullptr)
40897a7e6055SDimitry Andric     O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
40907a7e6055SDimitry Andric   MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
409139d628a0SDimitry Andric   Start.moveToFirst();
409239d628a0SDimitry Andric 
40937a7e6055SDimitry Andric   MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
409439d628a0SDimitry Andric   Finish.moveToEnd();
409539d628a0SDimitry Andric 
40967d523365SDimitry Andric   return make_range(bind_iterator(Start), bind_iterator(Finish));
409739d628a0SDimitry Andric }
409839d628a0SDimitry Andric 
bindTable(Error & Err)40997a7e6055SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
41007a7e6055SDimitry Andric   return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
410139d628a0SDimitry Andric                    MachOBindEntry::Kind::Regular);
410239d628a0SDimitry Andric }
410339d628a0SDimitry Andric 
lazyBindTable(Error & Err)41047a7e6055SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
41057a7e6055SDimitry Andric   return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
410639d628a0SDimitry Andric                    MachOBindEntry::Kind::Lazy);
410739d628a0SDimitry Andric }
410839d628a0SDimitry Andric 
weakBindTable(Error & Err)41097a7e6055SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
41107a7e6055SDimitry Andric   return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
411139d628a0SDimitry Andric                    MachOBindEntry::Kind::Weak);
411239d628a0SDimitry Andric }
411339d628a0SDimitry Andric 
411497bc6c73SDimitry Andric MachOObjectFile::load_command_iterator
begin_load_commands() const411597bc6c73SDimitry Andric MachOObjectFile::begin_load_commands() const {
411697bc6c73SDimitry Andric   return LoadCommands.begin();
411797bc6c73SDimitry Andric }
411897bc6c73SDimitry Andric 
411997bc6c73SDimitry Andric MachOObjectFile::load_command_iterator
end_load_commands() const412097bc6c73SDimitry Andric MachOObjectFile::end_load_commands() const {
412197bc6c73SDimitry Andric   return LoadCommands.end();
412297bc6c73SDimitry Andric }
412397bc6c73SDimitry Andric 
412497bc6c73SDimitry Andric iterator_range<MachOObjectFile::load_command_iterator>
load_commands() const412597bc6c73SDimitry Andric MachOObjectFile::load_commands() const {
41267d523365SDimitry Andric   return make_range(begin_load_commands(), end_load_commands());
412797bc6c73SDimitry Andric }
412897bc6c73SDimitry Andric 
4129284c1978SDimitry Andric StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const4130284c1978SDimitry Andric MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4131284c1978SDimitry Andric   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4132284c1978SDimitry Andric   return parseSegmentOrSectionName(Raw.data());
4133284c1978SDimitry Andric }
4134284c1978SDimitry Andric 
4135284c1978SDimitry Andric ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const4136284c1978SDimitry Andric MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
4137ff0cc061SDimitry Andric   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4138f785676fSDimitry Andric   const section_base *Base =
4139f785676fSDimitry Andric     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
414039d628a0SDimitry Andric   return makeArrayRef(Base->sectname);
4141284c1978SDimitry Andric }
4142284c1978SDimitry Andric 
4143284c1978SDimitry Andric ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const4144284c1978SDimitry Andric MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
4145ff0cc061SDimitry Andric   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4146f785676fSDimitry Andric   const section_base *Base =
4147f785676fSDimitry Andric     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
414839d628a0SDimitry Andric   return makeArrayRef(Base->segname);
4149284c1978SDimitry Andric }
4150284c1978SDimitry Andric 
4151284c1978SDimitry Andric bool
isRelocationScattered(const MachO::any_relocation_info & RE) const4152f785676fSDimitry Andric MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
4153284c1978SDimitry Andric   const {
4154d88c1a5aSDimitry Andric   if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
4155284c1978SDimitry Andric     return false;
4156f785676fSDimitry Andric   return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
4157284c1978SDimitry Andric }
4158284c1978SDimitry Andric 
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const4159f785676fSDimitry Andric unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4160f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
4161284c1978SDimitry Andric   if (isLittleEndian())
4162f785676fSDimitry Andric     return RE.r_word1 & 0xffffff;
4163f785676fSDimitry Andric   return RE.r_word1 >> 8;
4164284c1978SDimitry Andric }
4165284c1978SDimitry Andric 
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const4166f785676fSDimitry Andric bool MachOObjectFile::getPlainRelocationExternal(
4167f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
4168284c1978SDimitry Andric   if (isLittleEndian())
4169f785676fSDimitry Andric     return (RE.r_word1 >> 27) & 1;
4170f785676fSDimitry Andric   return (RE.r_word1 >> 4) & 1;
4171284c1978SDimitry Andric }
4172284c1978SDimitry Andric 
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const4173f785676fSDimitry Andric bool MachOObjectFile::getScatteredRelocationScattered(
4174f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
4175f785676fSDimitry Andric   return RE.r_word0 >> 31;
4176284c1978SDimitry Andric }
4177284c1978SDimitry Andric 
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const4178f785676fSDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationValue(
4179f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
4180f785676fSDimitry Andric   return RE.r_word1;
4181284c1978SDimitry Andric }
4182284c1978SDimitry Andric 
getScatteredRelocationType(const MachO::any_relocation_info & RE) const418339d628a0SDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationType(
418439d628a0SDimitry Andric     const MachO::any_relocation_info &RE) const {
418539d628a0SDimitry Andric   return (RE.r_word0 >> 24) & 0xf;
418639d628a0SDimitry Andric }
418739d628a0SDimitry Andric 
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const4188f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationAddress(
4189f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
4190284c1978SDimitry Andric   if (isRelocationScattered(RE))
4191284c1978SDimitry Andric     return getScatteredRelocationAddress(RE);
4192284c1978SDimitry Andric   return getPlainRelocationAddress(RE);
4193284c1978SDimitry Andric }
4194284c1978SDimitry Andric 
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const4195f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationPCRel(
4196f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
4197284c1978SDimitry Andric   if (isRelocationScattered(RE))
4198d88c1a5aSDimitry Andric     return getScatteredRelocationPCRel(RE);
4199d88c1a5aSDimitry Andric   return getPlainRelocationPCRel(*this, RE);
4200284c1978SDimitry Andric }
4201284c1978SDimitry Andric 
getAnyRelocationLength(const MachO::any_relocation_info & RE) const4202f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationLength(
4203f785676fSDimitry Andric     const MachO::any_relocation_info &RE) const {
4204284c1978SDimitry Andric   if (isRelocationScattered(RE))
4205284c1978SDimitry Andric     return getScatteredRelocationLength(RE);
4206d88c1a5aSDimitry Andric   return getPlainRelocationLength(*this, RE);
4207284c1978SDimitry Andric }
4208284c1978SDimitry Andric 
4209284c1978SDimitry Andric unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const4210f785676fSDimitry Andric MachOObjectFile::getAnyRelocationType(
4211f785676fSDimitry Andric                                    const MachO::any_relocation_info &RE) const {
4212284c1978SDimitry Andric   if (isRelocationScattered(RE))
4213284c1978SDimitry Andric     return getScatteredRelocationType(RE);
4214d88c1a5aSDimitry Andric   return getPlainRelocationType(*this, RE);
4215284c1978SDimitry Andric }
4216284c1978SDimitry Andric 
4217284c1978SDimitry Andric SectionRef
getAnyRelocationSection(const MachO::any_relocation_info & RE) const4218ff0cc061SDimitry Andric MachOObjectFile::getAnyRelocationSection(
4219f785676fSDimitry Andric                                    const MachO::any_relocation_info &RE) const {
4220284c1978SDimitry Andric   if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
422191bc56edSDimitry Andric     return *section_end();
42228f0fd8f6SDimitry Andric   unsigned SecNum = getPlainRelocationSymbolNum(RE);
42238f0fd8f6SDimitry Andric   if (SecNum == MachO::R_ABS || SecNum > Sections.size())
42248f0fd8f6SDimitry Andric     return *section_end();
4225284c1978SDimitry Andric   DataRefImpl DRI;
42268f0fd8f6SDimitry Andric   DRI.d.a = SecNum - 1;
4227284c1978SDimitry Andric   return SectionRef(DRI, this);
4228284c1978SDimitry Andric }
4229284c1978SDimitry Andric 
getSection(DataRefImpl DRI) const4230f785676fSDimitry Andric MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
4231ff0cc061SDimitry Andric   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4232d88c1a5aSDimitry Andric   return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
4233284c1978SDimitry Andric }
4234284c1978SDimitry Andric 
getSection64(DataRefImpl DRI) const4235f785676fSDimitry Andric MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
4236ff0cc061SDimitry Andric   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4237d88c1a5aSDimitry Andric   return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
4238284c1978SDimitry Andric }
4239284c1978SDimitry Andric 
getSection(const LoadCommandInfo & L,unsigned Index) const4240f785676fSDimitry Andric MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
4241284c1978SDimitry Andric                                            unsigned Index) const {
4242d88c1a5aSDimitry Andric   const char *Sec = getSectionPtr(*this, L, Index);
4243d88c1a5aSDimitry Andric   return getStruct<MachO::section>(*this, Sec);
4244284c1978SDimitry Andric }
4245284c1978SDimitry Andric 
getSection64(const LoadCommandInfo & L,unsigned Index) const4246f785676fSDimitry Andric MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4247284c1978SDimitry Andric                                                 unsigned Index) const {
4248d88c1a5aSDimitry Andric   const char *Sec = getSectionPtr(*this, L, Index);
4249d88c1a5aSDimitry Andric   return getStruct<MachO::section_64>(*this, Sec);
4250284c1978SDimitry Andric }
4251284c1978SDimitry Andric 
4252f785676fSDimitry Andric MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const4253284c1978SDimitry Andric MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
4254284c1978SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
4255d88c1a5aSDimitry Andric   return getStruct<MachO::nlist>(*this, P);
4256284c1978SDimitry Andric }
4257284c1978SDimitry Andric 
4258f785676fSDimitry Andric MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const4259284c1978SDimitry Andric MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
4260284c1978SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
4261d88c1a5aSDimitry Andric   return getStruct<MachO::nlist_64>(*this, P);
4262284c1978SDimitry Andric }
4263284c1978SDimitry Andric 
4264f785676fSDimitry Andric MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const4265f785676fSDimitry Andric MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
4266d88c1a5aSDimitry Andric   return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
4267284c1978SDimitry Andric }
4268284c1978SDimitry Andric 
4269f785676fSDimitry Andric MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const4270284c1978SDimitry Andric MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
4271d88c1a5aSDimitry Andric   return getStruct<MachO::segment_command>(*this, L.Ptr);
4272284c1978SDimitry Andric }
4273284c1978SDimitry Andric 
4274f785676fSDimitry Andric MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const4275284c1978SDimitry Andric MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
4276d88c1a5aSDimitry Andric   return getStruct<MachO::segment_command_64>(*this, L.Ptr);
4277284c1978SDimitry Andric }
4278284c1978SDimitry Andric 
427939d628a0SDimitry Andric MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const428039d628a0SDimitry Andric MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
4281d88c1a5aSDimitry Andric   return getStruct<MachO::linker_option_command>(*this, L.Ptr);
4282284c1978SDimitry Andric }
4283284c1978SDimitry Andric 
428491bc56edSDimitry Andric MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const428591bc56edSDimitry Andric MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
4286d88c1a5aSDimitry Andric   return getStruct<MachO::version_min_command>(*this, L.Ptr);
428791bc56edSDimitry Andric }
428891bc56edSDimitry Andric 
42897a7e6055SDimitry Andric MachO::note_command
getNoteLoadCommand(const LoadCommandInfo & L) const42907a7e6055SDimitry Andric MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
42917a7e6055SDimitry Andric   return getStruct<MachO::note_command>(*this, L.Ptr);
42927a7e6055SDimitry Andric }
42937a7e6055SDimitry Andric 
42947a7e6055SDimitry Andric MachO::build_version_command
getBuildVersionLoadCommand(const LoadCommandInfo & L) const42957a7e6055SDimitry Andric MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
42967a7e6055SDimitry Andric   return getStruct<MachO::build_version_command>(*this, L.Ptr);
42977a7e6055SDimitry Andric }
42987a7e6055SDimitry Andric 
42997a7e6055SDimitry Andric MachO::build_tool_version
getBuildToolVersion(unsigned index) const43007a7e6055SDimitry Andric MachOObjectFile::getBuildToolVersion(unsigned index) const {
43017a7e6055SDimitry Andric   return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
43027a7e6055SDimitry Andric }
43037a7e6055SDimitry Andric 
430491bc56edSDimitry Andric MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const430591bc56edSDimitry Andric MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
4306d88c1a5aSDimitry Andric   return getStruct<MachO::dylib_command>(*this, L.Ptr);
430791bc56edSDimitry Andric }
430891bc56edSDimitry Andric 
430939d628a0SDimitry Andric MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const431039d628a0SDimitry Andric MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
4311d88c1a5aSDimitry Andric   return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
431239d628a0SDimitry Andric }
431339d628a0SDimitry Andric 
431439d628a0SDimitry Andric MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const431539d628a0SDimitry Andric MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
4316d88c1a5aSDimitry Andric   return getStruct<MachO::dylinker_command>(*this, L.Ptr);
431739d628a0SDimitry Andric }
431839d628a0SDimitry Andric 
431939d628a0SDimitry Andric MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const432039d628a0SDimitry Andric MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
4321d88c1a5aSDimitry Andric   return getStruct<MachO::uuid_command>(*this, L.Ptr);
432239d628a0SDimitry Andric }
432339d628a0SDimitry Andric 
432439d628a0SDimitry Andric MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const432539d628a0SDimitry Andric MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
4326d88c1a5aSDimitry Andric   return getStruct<MachO::rpath_command>(*this, L.Ptr);
432739d628a0SDimitry Andric }
432839d628a0SDimitry Andric 
432939d628a0SDimitry Andric MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const433039d628a0SDimitry Andric MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
4331d88c1a5aSDimitry Andric   return getStruct<MachO::source_version_command>(*this, L.Ptr);
433239d628a0SDimitry Andric }
433339d628a0SDimitry Andric 
433439d628a0SDimitry Andric MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const433539d628a0SDimitry Andric MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
4336d88c1a5aSDimitry Andric   return getStruct<MachO::entry_point_command>(*this, L.Ptr);
433739d628a0SDimitry Andric }
433839d628a0SDimitry Andric 
433939d628a0SDimitry Andric MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const434039d628a0SDimitry Andric MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
4341d88c1a5aSDimitry Andric   return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
434239d628a0SDimitry Andric }
434339d628a0SDimitry Andric 
434439d628a0SDimitry Andric MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const434539d628a0SDimitry Andric MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
4346d88c1a5aSDimitry Andric   return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
434739d628a0SDimitry Andric }
434839d628a0SDimitry Andric 
434939d628a0SDimitry Andric MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const435039d628a0SDimitry Andric MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
4351d88c1a5aSDimitry Andric   return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
435239d628a0SDimitry Andric }
435339d628a0SDimitry Andric 
435439d628a0SDimitry Andric MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const435539d628a0SDimitry Andric MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
4356d88c1a5aSDimitry Andric   return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
435739d628a0SDimitry Andric }
435839d628a0SDimitry Andric 
435939d628a0SDimitry Andric MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const436039d628a0SDimitry Andric MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
4361d88c1a5aSDimitry Andric   return getStruct<MachO::sub_library_command>(*this, L.Ptr);
436239d628a0SDimitry Andric }
436339d628a0SDimitry Andric 
436439d628a0SDimitry Andric MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const436539d628a0SDimitry Andric MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
4366d88c1a5aSDimitry Andric   return getStruct<MachO::sub_client_command>(*this, L.Ptr);
436739d628a0SDimitry Andric }
436839d628a0SDimitry Andric 
436939d628a0SDimitry Andric MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const437039d628a0SDimitry Andric MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
4371d88c1a5aSDimitry Andric   return getStruct<MachO::routines_command>(*this, L.Ptr);
437239d628a0SDimitry Andric }
437339d628a0SDimitry Andric 
437439d628a0SDimitry Andric MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const437539d628a0SDimitry Andric MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
4376d88c1a5aSDimitry Andric   return getStruct<MachO::routines_command_64>(*this, L.Ptr);
437739d628a0SDimitry Andric }
437839d628a0SDimitry Andric 
437939d628a0SDimitry Andric MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const438039d628a0SDimitry Andric MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
4381d88c1a5aSDimitry Andric   return getStruct<MachO::thread_command>(*this, L.Ptr);
438239d628a0SDimitry Andric }
438391bc56edSDimitry Andric 
4384f785676fSDimitry Andric MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const4385284c1978SDimitry Andric MachOObjectFile::getRelocation(DataRefImpl Rel) const {
4386edd7eaddSDimitry Andric   uint32_t Offset;
4387edd7eaddSDimitry Andric   if (getHeader().filetype == MachO::MH_OBJECT) {
438891bc56edSDimitry Andric     DataRefImpl Sec;
438991bc56edSDimitry Andric     Sec.d.a = Rel.d.a;
439091bc56edSDimitry Andric     if (is64Bit()) {
439191bc56edSDimitry Andric       MachO::section_64 Sect = getSection64(Sec);
439291bc56edSDimitry Andric       Offset = Sect.reloff;
439391bc56edSDimitry Andric     } else {
439491bc56edSDimitry Andric       MachO::section Sect = getSection(Sec);
439591bc56edSDimitry Andric       Offset = Sect.reloff;
439691bc56edSDimitry Andric     }
4397edd7eaddSDimitry Andric   } else {
4398edd7eaddSDimitry Andric     MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
43992cab237bSDimitry Andric     if (Rel.d.a == 0)
4400edd7eaddSDimitry Andric       Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
44012cab237bSDimitry Andric     else
44022cab237bSDimitry Andric       Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
4403edd7eaddSDimitry Andric   }
440491bc56edSDimitry Andric 
440591bc56edSDimitry Andric   auto P = reinterpret_cast<const MachO::any_relocation_info *>(
4406d88c1a5aSDimitry Andric       getPtr(*this, Offset)) + Rel.d.b;
440791bc56edSDimitry Andric   return getStruct<MachO::any_relocation_info>(
4408d88c1a5aSDimitry Andric       *this, reinterpret_cast<const char *>(P));
4409284c1978SDimitry Andric }
4410284c1978SDimitry Andric 
4411f785676fSDimitry Andric MachO::data_in_code_entry
getDice(DataRefImpl Rel) const4412f785676fSDimitry Andric MachOObjectFile::getDice(DataRefImpl Rel) const {
4413f785676fSDimitry Andric   const char *P = reinterpret_cast<const char *>(Rel.p);
4414d88c1a5aSDimitry Andric   return getStruct<MachO::data_in_code_entry>(*this, P);
4415284c1978SDimitry Andric }
4416284c1978SDimitry Andric 
getHeader() const441797bc6c73SDimitry Andric const MachO::mach_header &MachOObjectFile::getHeader() const {
441897bc6c73SDimitry Andric   return Header;
4419284c1978SDimitry Andric }
4420284c1978SDimitry Andric 
getHeader64() const442197bc6c73SDimitry Andric const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
442297bc6c73SDimitry Andric   assert(is64Bit());
442397bc6c73SDimitry Andric   return Header64;
4424f785676fSDimitry Andric }
4425f785676fSDimitry Andric 
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const4426f785676fSDimitry Andric uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4427f785676fSDimitry Andric                                              const MachO::dysymtab_command &DLC,
4428284c1978SDimitry Andric                                              unsigned Index) const {
4429f785676fSDimitry Andric   uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
4430d88c1a5aSDimitry Andric   return getStruct<uint32_t>(*this, getPtr(*this, Offset));
4431284c1978SDimitry Andric }
4432284c1978SDimitry Andric 
4433f785676fSDimitry Andric MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const4434284c1978SDimitry Andric MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4435284c1978SDimitry Andric                                          unsigned Index) const {
4436f785676fSDimitry Andric   uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
4437d88c1a5aSDimitry Andric   return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
4438284c1978SDimitry Andric }
4439284c1978SDimitry Andric 
getSymtabLoadCommand() const4440f785676fSDimitry Andric MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
444139d628a0SDimitry Andric   if (SymtabLoadCmd)
4442d88c1a5aSDimitry Andric     return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
444339d628a0SDimitry Andric 
444439d628a0SDimitry Andric   // If there is no SymtabLoadCmd return a load command with zero'ed fields.
444539d628a0SDimitry Andric   MachO::symtab_command Cmd;
444639d628a0SDimitry Andric   Cmd.cmd = MachO::LC_SYMTAB;
444739d628a0SDimitry Andric   Cmd.cmdsize = sizeof(MachO::symtab_command);
444839d628a0SDimitry Andric   Cmd.symoff = 0;
444939d628a0SDimitry Andric   Cmd.nsyms = 0;
445039d628a0SDimitry Andric   Cmd.stroff = 0;
445139d628a0SDimitry Andric   Cmd.strsize = 0;
445239d628a0SDimitry Andric   return Cmd;
4453284c1978SDimitry Andric }
4454284c1978SDimitry Andric 
getDysymtabLoadCommand() const4455f785676fSDimitry Andric MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
445639d628a0SDimitry Andric   if (DysymtabLoadCmd)
4457d88c1a5aSDimitry Andric     return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
445839d628a0SDimitry Andric 
445939d628a0SDimitry Andric   // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
446039d628a0SDimitry Andric   MachO::dysymtab_command Cmd;
446139d628a0SDimitry Andric   Cmd.cmd = MachO::LC_DYSYMTAB;
446239d628a0SDimitry Andric   Cmd.cmdsize = sizeof(MachO::dysymtab_command);
446339d628a0SDimitry Andric   Cmd.ilocalsym = 0;
446439d628a0SDimitry Andric   Cmd.nlocalsym = 0;
446539d628a0SDimitry Andric   Cmd.iextdefsym = 0;
446639d628a0SDimitry Andric   Cmd.nextdefsym = 0;
446739d628a0SDimitry Andric   Cmd.iundefsym = 0;
446839d628a0SDimitry Andric   Cmd.nundefsym = 0;
446939d628a0SDimitry Andric   Cmd.tocoff = 0;
447039d628a0SDimitry Andric   Cmd.ntoc = 0;
447139d628a0SDimitry Andric   Cmd.modtaboff = 0;
447239d628a0SDimitry Andric   Cmd.nmodtab = 0;
447339d628a0SDimitry Andric   Cmd.extrefsymoff = 0;
447439d628a0SDimitry Andric   Cmd.nextrefsyms = 0;
447539d628a0SDimitry Andric   Cmd.indirectsymoff = 0;
447639d628a0SDimitry Andric   Cmd.nindirectsyms = 0;
447739d628a0SDimitry Andric   Cmd.extreloff = 0;
447839d628a0SDimitry Andric   Cmd.nextrel = 0;
447939d628a0SDimitry Andric   Cmd.locreloff = 0;
448039d628a0SDimitry Andric   Cmd.nlocrel = 0;
448139d628a0SDimitry Andric   return Cmd;
4482f785676fSDimitry Andric }
4483f785676fSDimitry Andric 
4484f785676fSDimitry Andric MachO::linkedit_data_command
getDataInCodeLoadCommand() const4485f785676fSDimitry Andric MachOObjectFile::getDataInCodeLoadCommand() const {
4486f785676fSDimitry Andric   if (DataInCodeLoadCmd)
4487d88c1a5aSDimitry Andric     return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
4488f785676fSDimitry Andric 
4489f785676fSDimitry Andric   // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4490f785676fSDimitry Andric   MachO::linkedit_data_command Cmd;
4491f785676fSDimitry Andric   Cmd.cmd = MachO::LC_DATA_IN_CODE;
4492f785676fSDimitry Andric   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4493f785676fSDimitry Andric   Cmd.dataoff = 0;
4494f785676fSDimitry Andric   Cmd.datasize = 0;
4495f785676fSDimitry Andric   return Cmd;
4496284c1978SDimitry Andric }
4497284c1978SDimitry Andric 
4498ff0cc061SDimitry Andric MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const4499ff0cc061SDimitry Andric MachOObjectFile::getLinkOptHintsLoadCommand() const {
4500ff0cc061SDimitry Andric   if (LinkOptHintsLoadCmd)
4501d88c1a5aSDimitry Andric     return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
4502ff0cc061SDimitry Andric 
4503ff0cc061SDimitry Andric   // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4504ff0cc061SDimitry Andric   // fields.
4505ff0cc061SDimitry Andric   MachO::linkedit_data_command Cmd;
4506ff0cc061SDimitry Andric   Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4507ff0cc061SDimitry Andric   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4508ff0cc061SDimitry Andric   Cmd.dataoff = 0;
4509ff0cc061SDimitry Andric   Cmd.datasize = 0;
4510ff0cc061SDimitry Andric   return Cmd;
4511ff0cc061SDimitry Andric }
4512ff0cc061SDimitry Andric 
getDyldInfoRebaseOpcodes() const451339d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
451439d628a0SDimitry Andric   if (!DyldInfoLoadCmd)
45157d523365SDimitry Andric     return None;
451639d628a0SDimitry Andric 
45177d523365SDimitry Andric   MachO::dyld_info_command DyldInfo =
4518d88c1a5aSDimitry Andric       getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45197d523365SDimitry Andric   const uint8_t *Ptr =
4520d88c1a5aSDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
45217d523365SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.rebase_size);
452239d628a0SDimitry Andric }
452339d628a0SDimitry Andric 
getDyldInfoBindOpcodes() const452439d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
452539d628a0SDimitry Andric   if (!DyldInfoLoadCmd)
45267d523365SDimitry Andric     return None;
452739d628a0SDimitry Andric 
45287d523365SDimitry Andric   MachO::dyld_info_command DyldInfo =
4529d88c1a5aSDimitry Andric       getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45307d523365SDimitry Andric   const uint8_t *Ptr =
4531d88c1a5aSDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
45327d523365SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.bind_size);
453339d628a0SDimitry Andric }
453439d628a0SDimitry Andric 
getDyldInfoWeakBindOpcodes() const453539d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
453639d628a0SDimitry Andric   if (!DyldInfoLoadCmd)
45377d523365SDimitry Andric     return None;
453839d628a0SDimitry Andric 
45397d523365SDimitry Andric   MachO::dyld_info_command DyldInfo =
4540d88c1a5aSDimitry Andric       getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45417d523365SDimitry Andric   const uint8_t *Ptr =
4542d88c1a5aSDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
45437d523365SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
454439d628a0SDimitry Andric }
454539d628a0SDimitry Andric 
getDyldInfoLazyBindOpcodes() const454639d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
454739d628a0SDimitry Andric   if (!DyldInfoLoadCmd)
45487d523365SDimitry Andric     return None;
454939d628a0SDimitry Andric 
45507d523365SDimitry Andric   MachO::dyld_info_command DyldInfo =
4551d88c1a5aSDimitry Andric       getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45527d523365SDimitry Andric   const uint8_t *Ptr =
4553d88c1a5aSDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
45547d523365SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
455539d628a0SDimitry Andric }
455639d628a0SDimitry Andric 
getDyldInfoExportsTrie() const455739d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
455839d628a0SDimitry Andric   if (!DyldInfoLoadCmd)
45597d523365SDimitry Andric     return None;
456039d628a0SDimitry Andric 
45617d523365SDimitry Andric   MachO::dyld_info_command DyldInfo =
4562d88c1a5aSDimitry Andric       getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45637d523365SDimitry Andric   const uint8_t *Ptr =
4564d88c1a5aSDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
45657d523365SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.export_size);
456639d628a0SDimitry Andric }
456739d628a0SDimitry Andric 
getUuid() const456839d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
456939d628a0SDimitry Andric   if (!UuidLoadCmd)
45707d523365SDimitry Andric     return None;
457139d628a0SDimitry Andric   // Returning a pointer is fine as uuid doesn't need endian swapping.
457239d628a0SDimitry Andric   const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
45737d523365SDimitry Andric   return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
457439d628a0SDimitry Andric }
457539d628a0SDimitry Andric 
getStringTableData() const4576284c1978SDimitry Andric StringRef MachOObjectFile::getStringTableData() const {
4577f785676fSDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
4578f785676fSDimitry Andric   return getData().substr(S.stroff, S.strsize);
4579284c1978SDimitry Andric }
4580284c1978SDimitry Andric 
is64Bit() const4581284c1978SDimitry Andric bool MachOObjectFile::is64Bit() const {
4582284c1978SDimitry Andric   return getType() == getMachOType(false, true) ||
4583284c1978SDimitry Andric     getType() == getMachOType(true, true);
4584284c1978SDimitry Andric }
4585284c1978SDimitry Andric 
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const4586284c1978SDimitry Andric void MachOObjectFile::ReadULEB128s(uint64_t Index,
4587284c1978SDimitry Andric                                    SmallVectorImpl<uint64_t> &Out) const {
4588284c1978SDimitry Andric   DataExtractor extractor(ObjectFile::getData(), true, 0);
4589284c1978SDimitry Andric 
4590284c1978SDimitry Andric   uint32_t offset = Index;
4591284c1978SDimitry Andric   uint64_t data = 0;
4592284c1978SDimitry Andric   while (uint64_t delta = extractor.getULEB128(&offset)) {
4593284c1978SDimitry Andric     data += delta;
4594284c1978SDimitry Andric     Out.push_back(data);
4595284c1978SDimitry Andric   }
4596284c1978SDimitry Andric }
4597284c1978SDimitry Andric 
isRelocatableObject() const459839d628a0SDimitry Andric bool MachOObjectFile::isRelocatableObject() const {
459939d628a0SDimitry Andric   return getHeader().filetype == MachO::MH_OBJECT;
460039d628a0SDimitry Andric }
460139d628a0SDimitry Andric 
46023ca95b02SDimitry Andric Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer,uint32_t UniversalCputype,uint32_t UniversalIndex)4603d88c1a5aSDimitry Andric ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4604d88c1a5aSDimitry Andric                                   uint32_t UniversalCputype,
4605d88c1a5aSDimitry Andric                                   uint32_t UniversalIndex) {
460639d628a0SDimitry Andric   StringRef Magic = Buffer.getBuffer().slice(0, 4);
4607284c1978SDimitry Andric   if (Magic == "\xFE\xED\xFA\xCE")
4608d88c1a5aSDimitry Andric     return MachOObjectFile::create(Buffer, false, false,
4609d88c1a5aSDimitry Andric                                    UniversalCputype, UniversalIndex);
46103ca95b02SDimitry Andric   if (Magic == "\xCE\xFA\xED\xFE")
4611d88c1a5aSDimitry Andric     return MachOObjectFile::create(Buffer, true, false,
4612d88c1a5aSDimitry Andric                                    UniversalCputype, UniversalIndex);
46133ca95b02SDimitry Andric   if (Magic == "\xFE\xED\xFA\xCF")
4614d88c1a5aSDimitry Andric     return MachOObjectFile::create(Buffer, false, true,
4615d88c1a5aSDimitry Andric                                    UniversalCputype, UniversalIndex);
46163ca95b02SDimitry Andric   if (Magic == "\xCF\xFA\xED\xFE")
4617d88c1a5aSDimitry Andric     return MachOObjectFile::create(Buffer, true, true,
4618d88c1a5aSDimitry Andric                                    UniversalCputype, UniversalIndex);
46193ca95b02SDimitry Andric   return make_error<GenericBinaryError>("Unrecognized MachO magic number",
46203ca95b02SDimitry Andric                                         object_error::invalid_file_type);
4621f785676fSDimitry Andric }
4622db17bf38SDimitry Andric 
mapDebugSectionName(StringRef Name) const4623db17bf38SDimitry Andric StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4624db17bf38SDimitry Andric   return StringSwitch<StringRef>(Name)
4625db17bf38SDimitry Andric       .Case("debug_str_offs", "debug_str_offsets")
4626db17bf38SDimitry Andric       .Default(Name);
4627db17bf38SDimitry Andric }
4628