• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file defines the MachOObjectFile class, which binds the MachOObject
10  // class to the generic ObjectFile wrapper.
11  //
12  //===----------------------------------------------------------------------===//
13  
14  #include "llvm/ADT/ArrayRef.h"
15  #include "llvm/ADT/None.h"
16  #include "llvm/ADT/STLExtras.h"
17  #include "llvm/ADT/SmallVector.h"
18  #include "llvm/ADT/StringRef.h"
19  #include "llvm/ADT/StringSwitch.h"
20  #include "llvm/ADT/Triple.h"
21  #include "llvm/ADT/Twine.h"
22  #include "llvm/BinaryFormat/MachO.h"
23  #include "llvm/Object/Error.h"
24  #include "llvm/Object/MachO.h"
25  #include "llvm/Object/ObjectFile.h"
26  #include "llvm/Object/SymbolicFile.h"
27  #include "llvm/Support/DataExtractor.h"
28  #include "llvm/Support/Debug.h"
29  #include "llvm/Support/Error.h"
30  #include "llvm/Support/ErrorHandling.h"
31  #include "llvm/Support/Format.h"
32  #include "llvm/Support/Host.h"
33  #include "llvm/Support/LEB128.h"
34  #include "llvm/Support/MemoryBuffer.h"
35  #include "llvm/Support/SwapByteOrder.h"
36  #include "llvm/Support/raw_ostream.h"
37  #include <algorithm>
38  #include <cassert>
39  #include <cstddef>
40  #include <cstdint>
41  #include <cstring>
42  #include <limits>
43  #include <list>
44  #include <memory>
45  #include <string>
46  #include <system_error>
47  
48  using namespace llvm;
49  using namespace object;
50  
51  namespace {
52  
53    struct section_base {
54      char sectname[16];
55      char segname[16];
56    };
57  
58  } // end anonymous namespace
59  
malformedError(const Twine & Msg)60  static Error malformedError(const Twine &Msg) {
61    return make_error<GenericBinaryError>("truncated or malformed object (" +
62                                              Msg + ")",
63                                          object_error::parse_failed);
64  }
65  
66  // FIXME: Replace all uses of this function with getStructOrErr.
67  template <typename T>
getStruct(const MachOObjectFile & O,const char * P)68  static T getStruct(const MachOObjectFile &O, const char *P) {
69    // Don't read before the beginning or past the end of the file
70    if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71      report_fatal_error("Malformed MachO file.");
72  
73    T Cmd;
74    memcpy(&Cmd, P, sizeof(T));
75    if (O.isLittleEndian() != sys::IsLittleEndianHost)
76      MachO::swapStruct(Cmd);
77    return Cmd;
78  }
79  
80  template <typename T>
getStructOrErr(const MachOObjectFile & O,const char * P)81  static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82    // Don't read before the beginning or past the end of the file
83    if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84      return malformedError("Structure read out-of-range");
85  
86    T Cmd;
87    memcpy(&Cmd, P, sizeof(T));
88    if (O.isLittleEndian() != sys::IsLittleEndianHost)
89      MachO::swapStruct(Cmd);
90    return Cmd;
91  }
92  
93  static const char *
getSectionPtr(const MachOObjectFile & O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)94  getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
95                unsigned Sec) {
96    uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
97  
98    bool Is64 = O.is64Bit();
99    unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
100                                      sizeof(MachO::segment_command);
101    unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
102                                  sizeof(MachO::section);
103  
104    uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
105    return reinterpret_cast<const char*>(SectionAddr);
106  }
107  
getPtr(const MachOObjectFile & O,size_t Offset)108  static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
109    assert(Offset <= O.getData().size());
110    return O.getData().data() + Offset;
111  }
112  
113  static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile & O,DataRefImpl DRI)114  getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
115    const char *P = reinterpret_cast<const char *>(DRI.p);
116    return getStruct<MachO::nlist_base>(O, P);
117  }
118  
parseSegmentOrSectionName(const char * P)119  static StringRef parseSegmentOrSectionName(const char *P) {
120    if (P[15] == 0)
121      // Null terminated.
122      return P;
123    // Not null terminated, so this is a 16 char string.
124    return StringRef(P, 16);
125  }
126  
getCPUType(const MachOObjectFile & O)127  static unsigned getCPUType(const MachOObjectFile &O) {
128    return O.getHeader().cputype;
129  }
130  
getCPUSubType(const MachOObjectFile & O)131  static unsigned getCPUSubType(const MachOObjectFile &O) {
132    return O.getHeader().cpusubtype;
133  }
134  
135  static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)136  getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
137    return RE.r_word0;
138  }
139  
140  static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)141  getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
142    return RE.r_word0 & 0xffffff;
143  }
144  
getPlainRelocationPCRel(const MachOObjectFile & O,const MachO::any_relocation_info & RE)145  static bool getPlainRelocationPCRel(const MachOObjectFile &O,
146                                      const MachO::any_relocation_info &RE) {
147    if (O.isLittleEndian())
148      return (RE.r_word1 >> 24) & 1;
149    return (RE.r_word1 >> 7) & 1;
150  }
151  
152  static bool
getScatteredRelocationPCRel(const MachO::any_relocation_info & RE)153  getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
154    return (RE.r_word0 >> 30) & 1;
155  }
156  
getPlainRelocationLength(const MachOObjectFile & O,const MachO::any_relocation_info & RE)157  static unsigned getPlainRelocationLength(const MachOObjectFile &O,
158                                           const MachO::any_relocation_info &RE) {
159    if (O.isLittleEndian())
160      return (RE.r_word1 >> 25) & 3;
161    return (RE.r_word1 >> 5) & 3;
162  }
163  
164  static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)165  getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
166    return (RE.r_word0 >> 28) & 3;
167  }
168  
getPlainRelocationType(const MachOObjectFile & O,const MachO::any_relocation_info & RE)169  static unsigned getPlainRelocationType(const MachOObjectFile &O,
170                                         const MachO::any_relocation_info &RE) {
171    if (O.isLittleEndian())
172      return RE.r_word1 >> 28;
173    return RE.r_word1 & 0xf;
174  }
175  
getSectionFlags(const MachOObjectFile & O,DataRefImpl Sec)176  static uint32_t getSectionFlags(const MachOObjectFile &O,
177                                  DataRefImpl Sec) {
178    if (O.is64Bit()) {
179      MachO::section_64 Sect = O.getSection64(Sec);
180      return Sect.flags;
181    }
182    MachO::section Sect = O.getSection(Sec);
183    return Sect.flags;
184  }
185  
186  static Expected<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile & Obj,const char * Ptr,uint32_t LoadCommandIndex)187  getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
188                     uint32_t LoadCommandIndex) {
189    if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
190      if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
191        return malformedError("load command " + Twine(LoadCommandIndex) +
192                              " extends past end of file");
193      if (CmdOrErr->cmdsize < 8)
194        return malformedError("load command " + Twine(LoadCommandIndex) +
195                              " with size less than 8 bytes");
196      return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
197    } else
198      return CmdOrErr.takeError();
199  }
200  
201  static Expected<MachOObjectFile::LoadCommandInfo>
getFirstLoadCommandInfo(const MachOObjectFile & Obj)202  getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
203    unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
204                                        : sizeof(MachO::mach_header);
205    if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
206      return malformedError("load command 0 extends past the end all load "
207                            "commands in the file");
208    return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
209  }
210  
211  static Expected<MachOObjectFile::LoadCommandInfo>
getNextLoadCommandInfo(const MachOObjectFile & Obj,uint32_t LoadCommandIndex,const MachOObjectFile::LoadCommandInfo & L)212  getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
213                         const MachOObjectFile::LoadCommandInfo &L) {
214    unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
215                                        : sizeof(MachO::mach_header);
216    if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
217        Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
218      return malformedError("load command " + Twine(LoadCommandIndex + 1) +
219                            " extends past the end all load commands in the file");
220    return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
221  }
222  
223  template <typename T>
parseHeader(const MachOObjectFile & Obj,T & Header,Error & Err)224  static void parseHeader(const MachOObjectFile &Obj, T &Header,
225                          Error &Err) {
226    if (sizeof(T) > Obj.getData().size()) {
227      Err = malformedError("the mach header extends past the end of the "
228                           "file");
229      return;
230    }
231    if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
232      Header = *HeaderOrErr;
233    else
234      Err = HeaderOrErr.takeError();
235  }
236  
237  // This is used to check for overlapping of Mach-O elements.
238  struct MachOElement {
239    uint64_t Offset;
240    uint64_t Size;
241    const char *Name;
242  };
243  
checkOverlappingElement(std::list<MachOElement> & Elements,uint64_t Offset,uint64_t Size,const char * Name)244  static Error checkOverlappingElement(std::list<MachOElement> &Elements,
245                                       uint64_t Offset, uint64_t Size,
246                                       const char *Name) {
247    if (Size == 0)
248      return Error::success();
249  
250    for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
251      auto E = *it;
252      if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
253          (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
254          (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
255        return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
256                              " with a size of " + Twine(Size) + ", overlaps " +
257                              E.Name + " at offset " + Twine(E.Offset) + " with "
258                              "a size of " + Twine(E.Size));
259      auto nt = it;
260      nt++;
261      if (nt != Elements.end()) {
262        auto N = *nt;
263        if (Offset + Size <= N.Offset) {
264          Elements.insert(nt, {Offset, Size, Name});
265          return Error::success();
266        }
267      }
268    }
269    Elements.push_back({Offset, Size, Name});
270    return Error::success();
271  }
272  
273  // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
274  // sections to \param Sections, and optionally sets
275  // \param IsPageZeroSegment to true.
276  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)277  static Error parseSegmentLoadCommand(
278      const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
279      SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
280      uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
281      std::list<MachOElement> &Elements) {
282    const unsigned SegmentLoadSize = sizeof(Segment);
283    if (Load.C.cmdsize < SegmentLoadSize)
284      return malformedError("load command " + Twine(LoadCommandIndex) +
285                            " " + CmdName + " cmdsize too small");
286    if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
287      Segment S = SegOrErr.get();
288      const unsigned SectionSize = sizeof(Section);
289      uint64_t FileSize = Obj.getData().size();
290      if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
291          S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
292        return malformedError("load command " + Twine(LoadCommandIndex) +
293                              " inconsistent cmdsize in " + CmdName +
294                              " for the number of sections");
295      for (unsigned J = 0; J < S.nsects; ++J) {
296        const char *Sec = getSectionPtr(Obj, Load, J);
297        Sections.push_back(Sec);
298        auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
299        if (!SectionOrErr)
300          return SectionOrErr.takeError();
301        Section s = SectionOrErr.get();
302        if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
303            Obj.getHeader().filetype != MachO::MH_DSYM &&
304            s.flags != MachO::S_ZEROFILL &&
305            s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
306            s.offset > FileSize)
307          return malformedError("offset field of section " + Twine(J) + " in " +
308                                CmdName + " command " + Twine(LoadCommandIndex) +
309                                " extends past the end of the file");
310        if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
311            Obj.getHeader().filetype != MachO::MH_DSYM &&
312            s.flags != MachO::S_ZEROFILL &&
313            s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
314            s.offset < SizeOfHeaders && s.size != 0)
315          return malformedError("offset field of section " + Twine(J) + " in " +
316                                CmdName + " command " + Twine(LoadCommandIndex) +
317                                " not past the headers of the file");
318        uint64_t BigSize = s.offset;
319        BigSize += s.size;
320        if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
321            Obj.getHeader().filetype != MachO::MH_DSYM &&
322            s.flags != MachO::S_ZEROFILL &&
323            s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
324            BigSize > FileSize)
325          return malformedError("offset field plus size field of section " +
326                                Twine(J) + " in " + CmdName + " command " +
327                                Twine(LoadCommandIndex) +
328                                " extends past the end of the file");
329        if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
330            Obj.getHeader().filetype != MachO::MH_DSYM &&
331            s.flags != MachO::S_ZEROFILL &&
332            s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
333            s.size > S.filesize)
334          return malformedError("size field of section " +
335                                Twine(J) + " in " + CmdName + " command " +
336                                Twine(LoadCommandIndex) +
337                                " greater than the segment");
338        if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
339            Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
340            s.addr < S.vmaddr)
341          return malformedError("addr field of section " + Twine(J) + " in " +
342                                CmdName + " command " + Twine(LoadCommandIndex) +
343                                " less than the segment's vmaddr");
344        BigSize = s.addr;
345        BigSize += s.size;
346        uint64_t BigEnd = S.vmaddr;
347        BigEnd += S.vmsize;
348        if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
349          return malformedError("addr field plus size of section " + Twine(J) +
350                                " in " + CmdName + " command " +
351                                Twine(LoadCommandIndex) +
352                                " greater than than "
353                                "the segment's vmaddr plus vmsize");
354        if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
355            Obj.getHeader().filetype != MachO::MH_DSYM &&
356            s.flags != MachO::S_ZEROFILL &&
357            s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
358          if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
359                                                  "section contents"))
360            return Err;
361        if (s.reloff > FileSize)
362          return malformedError("reloff field of section " + Twine(J) + " in " +
363                                CmdName + " command " + Twine(LoadCommandIndex) +
364                                " extends past the end of the file");
365        BigSize = s.nreloc;
366        BigSize *= sizeof(struct MachO::relocation_info);
367        BigSize += s.reloff;
368        if (BigSize > FileSize)
369          return malformedError("reloff field plus nreloc field times sizeof("
370                                "struct relocation_info) of section " +
371                                Twine(J) + " in " + CmdName + " command " +
372                                Twine(LoadCommandIndex) +
373                                " extends past the end of the file");
374        if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
375                                                sizeof(struct
376                                                MachO::relocation_info),
377                                                "section relocation entries"))
378          return Err;
379      }
380      if (S.fileoff > FileSize)
381        return malformedError("load command " + Twine(LoadCommandIndex) +
382                              " fileoff field in " + CmdName +
383                              " extends past the end of the file");
384      uint64_t BigSize = S.fileoff;
385      BigSize += S.filesize;
386      if (BigSize > FileSize)
387        return malformedError("load command " + Twine(LoadCommandIndex) +
388                              " fileoff field plus filesize field in " +
389                              CmdName + " extends past the end of the file");
390      if (S.vmsize != 0 && S.filesize > S.vmsize)
391        return malformedError("load command " + Twine(LoadCommandIndex) +
392                              " filesize field in " + CmdName +
393                              " greater than vmsize field");
394      IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
395    } else
396      return SegOrErr.takeError();
397  
398    return Error::success();
399  }
400  
checkSymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** SymtabLoadCmd,std::list<MachOElement> & Elements)401  static Error checkSymtabCommand(const MachOObjectFile &Obj,
402                                  const MachOObjectFile::LoadCommandInfo &Load,
403                                  uint32_t LoadCommandIndex,
404                                  const char **SymtabLoadCmd,
405                                  std::list<MachOElement> &Elements) {
406    if (Load.C.cmdsize < sizeof(MachO::symtab_command))
407      return malformedError("load command " + Twine(LoadCommandIndex) +
408                            " LC_SYMTAB cmdsize too small");
409    if (*SymtabLoadCmd != nullptr)
410      return malformedError("more than one LC_SYMTAB command");
411    auto SymtabOrErr = getStructOrErr<MachO::symtab_command>(Obj, Load.Ptr);
412    if (!SymtabOrErr)
413      return SymtabOrErr.takeError();
414    MachO::symtab_command Symtab = SymtabOrErr.get();
415    if (Symtab.cmdsize != sizeof(MachO::symtab_command))
416      return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
417                            " has incorrect cmdsize");
418    uint64_t FileSize = Obj.getData().size();
419    if (Symtab.symoff > FileSize)
420      return malformedError("symoff field of LC_SYMTAB command " +
421                            Twine(LoadCommandIndex) + " extends past the end "
422                            "of the file");
423    uint64_t SymtabSize = Symtab.nsyms;
424    const char *struct_nlist_name;
425    if (Obj.is64Bit()) {
426      SymtabSize *= sizeof(MachO::nlist_64);
427      struct_nlist_name = "struct nlist_64";
428    } else {
429      SymtabSize *= sizeof(MachO::nlist);
430      struct_nlist_name = "struct nlist";
431    }
432    uint64_t BigSize = SymtabSize;
433    BigSize += Symtab.symoff;
434    if (BigSize > FileSize)
435      return malformedError("symoff field plus nsyms field times sizeof(" +
436                            Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
437                            Twine(LoadCommandIndex) + " extends past the end "
438                            "of the file");
439    if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
440                                            "symbol table"))
441      return Err;
442    if (Symtab.stroff > FileSize)
443      return malformedError("stroff field of LC_SYMTAB command " +
444                            Twine(LoadCommandIndex) + " extends past the end "
445                            "of the file");
446    BigSize = Symtab.stroff;
447    BigSize += Symtab.strsize;
448    if (BigSize > FileSize)
449      return malformedError("stroff field plus strsize field of LC_SYMTAB "
450                            "command " + Twine(LoadCommandIndex) + " extends "
451                            "past the end of the file");
452    if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
453                                            Symtab.strsize, "string table"))
454      return Err;
455    *SymtabLoadCmd = Load.Ptr;
456    return Error::success();
457  }
458  
checkDysymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** DysymtabLoadCmd,std::list<MachOElement> & Elements)459  static Error checkDysymtabCommand(const MachOObjectFile &Obj,
460                                    const MachOObjectFile::LoadCommandInfo &Load,
461                                    uint32_t LoadCommandIndex,
462                                    const char **DysymtabLoadCmd,
463                                    std::list<MachOElement> &Elements) {
464    if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
465      return malformedError("load command " + Twine(LoadCommandIndex) +
466                            " LC_DYSYMTAB cmdsize too small");
467    if (*DysymtabLoadCmd != nullptr)
468      return malformedError("more than one LC_DYSYMTAB command");
469    auto DysymtabOrErr =
470      getStructOrErr<MachO::dysymtab_command>(Obj, Load.Ptr);
471    if (!DysymtabOrErr)
472      return DysymtabOrErr.takeError();
473    MachO::dysymtab_command Dysymtab = DysymtabOrErr.get();
474    if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
475      return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
476                            " has incorrect cmdsize");
477    uint64_t FileSize = Obj.getData().size();
478    if (Dysymtab.tocoff > FileSize)
479      return malformedError("tocoff field of LC_DYSYMTAB command " +
480                            Twine(LoadCommandIndex) + " extends past the end of "
481                            "the file");
482    uint64_t BigSize = Dysymtab.ntoc;
483    BigSize *= sizeof(MachO::dylib_table_of_contents);
484    BigSize += Dysymtab.tocoff;
485    if (BigSize > FileSize)
486      return malformedError("tocoff field plus ntoc field times sizeof(struct "
487                            "dylib_table_of_contents) of LC_DYSYMTAB command " +
488                            Twine(LoadCommandIndex) + " extends past the end of "
489                            "the file");
490    if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
491                                            Dysymtab.ntoc * sizeof(struct
492                                            MachO::dylib_table_of_contents),
493                                            "table of contents"))
494      return Err;
495    if (Dysymtab.modtaboff > FileSize)
496      return malformedError("modtaboff field of LC_DYSYMTAB command " +
497                            Twine(LoadCommandIndex) + " extends past the end of "
498                            "the file");
499    BigSize = Dysymtab.nmodtab;
500    const char *struct_dylib_module_name;
501    uint64_t sizeof_modtab;
502    if (Obj.is64Bit()) {
503      sizeof_modtab = sizeof(MachO::dylib_module_64);
504      struct_dylib_module_name = "struct dylib_module_64";
505    } else {
506      sizeof_modtab = sizeof(MachO::dylib_module);
507      struct_dylib_module_name = "struct dylib_module";
508    }
509    BigSize *= sizeof_modtab;
510    BigSize += Dysymtab.modtaboff;
511    if (BigSize > FileSize)
512      return malformedError("modtaboff field plus nmodtab field times sizeof(" +
513                            Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
514                            "command " + Twine(LoadCommandIndex) + " extends "
515                            "past the end of the file");
516    if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
517                                            Dysymtab.nmodtab * sizeof_modtab,
518                                            "module table"))
519      return Err;
520    if (Dysymtab.extrefsymoff > FileSize)
521      return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
522                            Twine(LoadCommandIndex) + " extends past the end of "
523                            "the file");
524    BigSize = Dysymtab.nextrefsyms;
525    BigSize *= sizeof(MachO::dylib_reference);
526    BigSize += Dysymtab.extrefsymoff;
527    if (BigSize > FileSize)
528      return malformedError("extrefsymoff field plus nextrefsyms field times "
529                            "sizeof(struct dylib_reference) of LC_DYSYMTAB "
530                            "command " + Twine(LoadCommandIndex) + " extends "
531                            "past the end of the file");
532    if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
533                                            Dysymtab.nextrefsyms *
534                                                sizeof(MachO::dylib_reference),
535                                            "reference table"))
536      return Err;
537    if (Dysymtab.indirectsymoff > FileSize)
538      return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
539                            Twine(LoadCommandIndex) + " extends past the end of "
540                            "the file");
541    BigSize = Dysymtab.nindirectsyms;
542    BigSize *= sizeof(uint32_t);
543    BigSize += Dysymtab.indirectsymoff;
544    if (BigSize > FileSize)
545      return malformedError("indirectsymoff field plus nindirectsyms field times "
546                            "sizeof(uint32_t) of LC_DYSYMTAB command " +
547                            Twine(LoadCommandIndex) + " extends past the end of "
548                            "the file");
549    if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
550                                            Dysymtab.nindirectsyms *
551                                            sizeof(uint32_t),
552                                            "indirect table"))
553      return Err;
554    if (Dysymtab.extreloff > FileSize)
555      return malformedError("extreloff field of LC_DYSYMTAB command " +
556                            Twine(LoadCommandIndex) + " extends past the end of "
557                            "the file");
558    BigSize = Dysymtab.nextrel;
559    BigSize *= sizeof(MachO::relocation_info);
560    BigSize += Dysymtab.extreloff;
561    if (BigSize > FileSize)
562      return malformedError("extreloff field plus nextrel field times sizeof"
563                            "(struct relocation_info) of LC_DYSYMTAB command " +
564                            Twine(LoadCommandIndex) + " extends past the end of "
565                            "the file");
566    if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
567                                            Dysymtab.nextrel *
568                                                sizeof(MachO::relocation_info),
569                                            "external relocation table"))
570      return Err;
571    if (Dysymtab.locreloff > FileSize)
572      return malformedError("locreloff field of LC_DYSYMTAB command " +
573                            Twine(LoadCommandIndex) + " extends past the end of "
574                            "the file");
575    BigSize = Dysymtab.nlocrel;
576    BigSize *= sizeof(MachO::relocation_info);
577    BigSize += Dysymtab.locreloff;
578    if (BigSize > FileSize)
579      return malformedError("locreloff field plus nlocrel field times sizeof"
580                            "(struct relocation_info) of LC_DYSYMTAB command " +
581                            Twine(LoadCommandIndex) + " extends past the end of "
582                            "the file");
583    if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
584                                            Dysymtab.nlocrel *
585                                                sizeof(MachO::relocation_info),
586                                            "local relocation table"))
587      return Err;
588    *DysymtabLoadCmd = Load.Ptr;
589    return Error::success();
590  }
591  
checkLinkeditDataCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements,const char * ElementName)592  static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
593                                   const MachOObjectFile::LoadCommandInfo &Load,
594                                   uint32_t LoadCommandIndex,
595                                   const char **LoadCmd, const char *CmdName,
596                                   std::list<MachOElement> &Elements,
597                                   const char *ElementName) {
598    if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
599      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
600                            CmdName + " cmdsize too small");
601    if (*LoadCmd != nullptr)
602      return malformedError("more than one " + Twine(CmdName) + " command");
603    auto LinkDataOrError =
604      getStructOrErr<MachO::linkedit_data_command>(Obj, Load.Ptr);
605    if (!LinkDataOrError)
606      return LinkDataOrError.takeError();
607    MachO::linkedit_data_command LinkData = LinkDataOrError.get();
608    if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
609      return malformedError(Twine(CmdName) + " command " +
610                            Twine(LoadCommandIndex) + " has incorrect cmdsize");
611    uint64_t FileSize = Obj.getData().size();
612    if (LinkData.dataoff > FileSize)
613      return malformedError("dataoff field of " + Twine(CmdName) + " command " +
614                            Twine(LoadCommandIndex) + " extends past the end of "
615                            "the file");
616    uint64_t BigSize = LinkData.dataoff;
617    BigSize += LinkData.datasize;
618    if (BigSize > FileSize)
619      return malformedError("dataoff field plus datasize field of " +
620                            Twine(CmdName) + " command " +
621                            Twine(LoadCommandIndex) + " extends past the end of "
622                            "the file");
623    if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
624                                            LinkData.datasize, ElementName))
625      return Err;
626    *LoadCmd = Load.Ptr;
627    return Error::success();
628  }
629  
checkDyldInfoCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements)630  static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
631                                    const MachOObjectFile::LoadCommandInfo &Load,
632                                    uint32_t LoadCommandIndex,
633                                    const char **LoadCmd, const char *CmdName,
634                                    std::list<MachOElement> &Elements) {
635    if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
636      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
637                            CmdName + " cmdsize too small");
638    if (*LoadCmd != nullptr)
639      return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
640                            "command");
641    auto DyldInfoOrErr =
642      getStructOrErr<MachO::dyld_info_command>(Obj, Load.Ptr);
643    if (!DyldInfoOrErr)
644      return DyldInfoOrErr.takeError();
645    MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
646    if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
647      return malformedError(Twine(CmdName) + " command " +
648                            Twine(LoadCommandIndex) + " has incorrect cmdsize");
649    uint64_t FileSize = Obj.getData().size();
650    if (DyldInfo.rebase_off > FileSize)
651      return malformedError("rebase_off field of " + Twine(CmdName) +
652                            " command " + Twine(LoadCommandIndex) + " extends "
653                            "past the end of the file");
654    uint64_t BigSize = DyldInfo.rebase_off;
655    BigSize += DyldInfo.rebase_size;
656    if (BigSize > FileSize)
657      return malformedError("rebase_off field plus rebase_size field of " +
658                            Twine(CmdName) + " command " +
659                            Twine(LoadCommandIndex) + " extends past the end of "
660                            "the file");
661    if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
662                                            DyldInfo.rebase_size,
663                                            "dyld rebase info"))
664      return Err;
665    if (DyldInfo.bind_off > FileSize)
666      return malformedError("bind_off field of " + Twine(CmdName) +
667                            " command " + Twine(LoadCommandIndex) + " extends "
668                            "past the end of the file");
669    BigSize = DyldInfo.bind_off;
670    BigSize += DyldInfo.bind_size;
671    if (BigSize > FileSize)
672      return malformedError("bind_off field plus bind_size field of " +
673                            Twine(CmdName) + " command " +
674                            Twine(LoadCommandIndex) + " extends past the end of "
675                            "the file");
676    if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
677                                            DyldInfo.bind_size,
678                                            "dyld bind info"))
679      return Err;
680    if (DyldInfo.weak_bind_off > FileSize)
681      return malformedError("weak_bind_off field of " + Twine(CmdName) +
682                            " command " + Twine(LoadCommandIndex) + " extends "
683                            "past the end of the file");
684    BigSize = DyldInfo.weak_bind_off;
685    BigSize += DyldInfo.weak_bind_size;
686    if (BigSize > FileSize)
687      return malformedError("weak_bind_off field plus weak_bind_size field of " +
688                            Twine(CmdName) + " command " +
689                            Twine(LoadCommandIndex) + " extends past the end of "
690                            "the file");
691    if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
692                                            DyldInfo.weak_bind_size,
693                                            "dyld weak bind info"))
694      return Err;
695    if (DyldInfo.lazy_bind_off > FileSize)
696      return malformedError("lazy_bind_off field of " + Twine(CmdName) +
697                            " command " + Twine(LoadCommandIndex) + " extends "
698                            "past the end of the file");
699    BigSize = DyldInfo.lazy_bind_off;
700    BigSize += DyldInfo.lazy_bind_size;
701    if (BigSize > FileSize)
702      return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
703                            Twine(CmdName) + " command " +
704                            Twine(LoadCommandIndex) + " extends past the end of "
705                            "the file");
706    if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
707                                            DyldInfo.lazy_bind_size,
708                                            "dyld lazy bind info"))
709      return Err;
710    if (DyldInfo.export_off > FileSize)
711      return malformedError("export_off field of " + Twine(CmdName) +
712                            " command " + Twine(LoadCommandIndex) + " extends "
713                            "past the end of the file");
714    BigSize = DyldInfo.export_off;
715    BigSize += DyldInfo.export_size;
716    if (BigSize > FileSize)
717      return malformedError("export_off field plus export_size field of " +
718                            Twine(CmdName) + " command " +
719                            Twine(LoadCommandIndex) + " extends past the end of "
720                            "the file");
721    if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
722                                            DyldInfo.export_size,
723                                            "dyld export info"))
724      return Err;
725    *LoadCmd = Load.Ptr;
726    return Error::success();
727  }
728  
checkDylibCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)729  static Error checkDylibCommand(const MachOObjectFile &Obj,
730                                 const MachOObjectFile::LoadCommandInfo &Load,
731                                 uint32_t LoadCommandIndex, const char *CmdName) {
732    if (Load.C.cmdsize < sizeof(MachO::dylib_command))
733      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
734                            CmdName + " cmdsize too small");
735    auto CommandOrErr = getStructOrErr<MachO::dylib_command>(Obj, Load.Ptr);
736    if (!CommandOrErr)
737      return CommandOrErr.takeError();
738    MachO::dylib_command D = CommandOrErr.get();
739    if (D.dylib.name < sizeof(MachO::dylib_command))
740      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
741                            CmdName + " name.offset field too small, not past "
742                            "the end of the dylib_command struct");
743    if (D.dylib.name >= D.cmdsize)
744      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
745                            CmdName + " name.offset field extends past the end "
746                            "of the load command");
747    // Make sure there is a null between the starting offset of the name and
748    // the end of the load command.
749    uint32_t i;
750    const char *P = (const char *)Load.Ptr;
751    for (i = D.dylib.name; i < D.cmdsize; i++)
752      if (P[i] == '\0')
753        break;
754    if (i >= D.cmdsize)
755      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
756                            CmdName + " library name extends past the end of the "
757                            "load command");
758    return Error::success();
759  }
760  
checkDylibIdCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd)761  static Error checkDylibIdCommand(const MachOObjectFile &Obj,
762                                   const MachOObjectFile::LoadCommandInfo &Load,
763                                   uint32_t LoadCommandIndex,
764                                   const char **LoadCmd) {
765    if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
766                                       "LC_ID_DYLIB"))
767      return Err;
768    if (*LoadCmd != nullptr)
769      return malformedError("more than one LC_ID_DYLIB command");
770    if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
771        Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
772      return malformedError("LC_ID_DYLIB load command in non-dynamic library "
773                            "file type");
774    *LoadCmd = Load.Ptr;
775    return Error::success();
776  }
777  
checkDyldCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)778  static Error checkDyldCommand(const MachOObjectFile &Obj,
779                                const MachOObjectFile::LoadCommandInfo &Load,
780                                uint32_t LoadCommandIndex, const char *CmdName) {
781    if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
782      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
783                            CmdName + " cmdsize too small");
784    auto CommandOrErr = getStructOrErr<MachO::dylinker_command>(Obj, Load.Ptr);
785    if (!CommandOrErr)
786      return CommandOrErr.takeError();
787    MachO::dylinker_command D = CommandOrErr.get();
788    if (D.name < sizeof(MachO::dylinker_command))
789      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
790                            CmdName + " name.offset field too small, not past "
791                            "the end of the dylinker_command struct");
792    if (D.name >= D.cmdsize)
793      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
794                            CmdName + " name.offset field extends past the end "
795                            "of the load command");
796    // Make sure there is a null between the starting offset of the name and
797    // the end of the load command.
798    uint32_t i;
799    const char *P = (const char *)Load.Ptr;
800    for (i = D.name; i < D.cmdsize; i++)
801      if (P[i] == '\0')
802        break;
803    if (i >= D.cmdsize)
804      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
805                            CmdName + " dyld name extends past the end of the "
806                            "load command");
807    return Error::success();
808  }
809  
checkVersCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName)810  static Error checkVersCommand(const MachOObjectFile &Obj,
811                                const MachOObjectFile::LoadCommandInfo &Load,
812                                uint32_t LoadCommandIndex,
813                                const char **LoadCmd, const char *CmdName) {
814    if (Load.C.cmdsize != sizeof(MachO::version_min_command))
815      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
816                            CmdName + " has incorrect cmdsize");
817    if (*LoadCmd != nullptr)
818      return malformedError("more than one LC_VERSION_MIN_MACOSX, "
819                            "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
820                            "LC_VERSION_MIN_WATCHOS command");
821    *LoadCmd = Load.Ptr;
822    return Error::success();
823  }
824  
checkNoteCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,std::list<MachOElement> & Elements)825  static Error checkNoteCommand(const MachOObjectFile &Obj,
826                                const MachOObjectFile::LoadCommandInfo &Load,
827                                uint32_t LoadCommandIndex,
828                                std::list<MachOElement> &Elements) {
829    if (Load.C.cmdsize != sizeof(MachO::note_command))
830      return malformedError("load command " + Twine(LoadCommandIndex) +
831                            " LC_NOTE has incorrect cmdsize");
832    auto NoteCmdOrErr = getStructOrErr<MachO::note_command>(Obj, Load.Ptr);
833    if (!NoteCmdOrErr)
834      return NoteCmdOrErr.takeError();
835    MachO::note_command Nt = NoteCmdOrErr.get();
836    uint64_t FileSize = Obj.getData().size();
837    if (Nt.offset > FileSize)
838      return malformedError("offset field of LC_NOTE command " +
839                            Twine(LoadCommandIndex) + " extends "
840                            "past the end of the file");
841    uint64_t BigSize = Nt.offset;
842    BigSize += Nt.size;
843    if (BigSize > FileSize)
844      return malformedError("size field plus offset field of LC_NOTE command " +
845                            Twine(LoadCommandIndex) + " extends past the end of "
846                            "the file");
847    if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
848                                            "LC_NOTE data"))
849      return Err;
850    return Error::success();
851  }
852  
853  static Error
parseBuildVersionCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & BuildTools,uint32_t LoadCommandIndex)854  parseBuildVersionCommand(const MachOObjectFile &Obj,
855                           const MachOObjectFile::LoadCommandInfo &Load,
856                           SmallVectorImpl<const char*> &BuildTools,
857                           uint32_t LoadCommandIndex) {
858    auto BVCOrErr =
859      getStructOrErr<MachO::build_version_command>(Obj, Load.Ptr);
860    if (!BVCOrErr)
861      return BVCOrErr.takeError();
862    MachO::build_version_command BVC = BVCOrErr.get();
863    if (Load.C.cmdsize !=
864        sizeof(MachO::build_version_command) +
865            BVC.ntools * sizeof(MachO::build_tool_version))
866      return malformedError("load command " + Twine(LoadCommandIndex) +
867                            " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
868  
869    auto Start = Load.Ptr + sizeof(MachO::build_version_command);
870    BuildTools.resize(BVC.ntools);
871    for (unsigned i = 0; i < BVC.ntools; ++i)
872      BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
873  
874    return Error::success();
875  }
876  
checkRpathCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)877  static Error checkRpathCommand(const MachOObjectFile &Obj,
878                                 const MachOObjectFile::LoadCommandInfo &Load,
879                                 uint32_t LoadCommandIndex) {
880    if (Load.C.cmdsize < sizeof(MachO::rpath_command))
881      return malformedError("load command " + Twine(LoadCommandIndex) +
882                            " LC_RPATH cmdsize too small");
883    auto ROrErr = getStructOrErr<MachO::rpath_command>(Obj, Load.Ptr);
884    if (!ROrErr)
885      return ROrErr.takeError();
886    MachO::rpath_command R = ROrErr.get();
887    if (R.path < sizeof(MachO::rpath_command))
888      return malformedError("load command " + Twine(LoadCommandIndex) +
889                            " LC_RPATH path.offset field too small, not past "
890                            "the end of the rpath_command struct");
891    if (R.path >= R.cmdsize)
892      return malformedError("load command " + Twine(LoadCommandIndex) +
893                            " LC_RPATH path.offset field extends past the end "
894                            "of the load command");
895    // Make sure there is a null between the starting offset of the path and
896    // the end of the load command.
897    uint32_t i;
898    const char *P = (const char *)Load.Ptr;
899    for (i = R.path; i < R.cmdsize; i++)
900      if (P[i] == '\0')
901        break;
902    if (i >= R.cmdsize)
903      return malformedError("load command " + Twine(LoadCommandIndex) +
904                            " LC_RPATH library name extends past the end of the "
905                            "load command");
906    return Error::success();
907  }
908  
checkEncryptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,uint64_t cryptoff,uint64_t cryptsize,const char ** LoadCmd,const char * CmdName)909  static Error checkEncryptCommand(const MachOObjectFile &Obj,
910                                   const MachOObjectFile::LoadCommandInfo &Load,
911                                   uint32_t LoadCommandIndex,
912                                   uint64_t cryptoff, uint64_t cryptsize,
913                                   const char **LoadCmd, const char *CmdName) {
914    if (*LoadCmd != nullptr)
915      return malformedError("more than one LC_ENCRYPTION_INFO and or "
916                            "LC_ENCRYPTION_INFO_64 command");
917    uint64_t FileSize = Obj.getData().size();
918    if (cryptoff > FileSize)
919      return malformedError("cryptoff field of " + Twine(CmdName) +
920                            " command " + Twine(LoadCommandIndex) + " extends "
921                            "past the end of the file");
922    uint64_t BigSize = cryptoff;
923    BigSize += cryptsize;
924    if (BigSize > FileSize)
925      return malformedError("cryptoff field plus cryptsize field of " +
926                            Twine(CmdName) + " command " +
927                            Twine(LoadCommandIndex) + " extends past the end of "
928                            "the file");
929    *LoadCmd = Load.Ptr;
930    return Error::success();
931  }
932  
checkLinkerOptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)933  static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
934                                     const MachOObjectFile::LoadCommandInfo &Load,
935                                     uint32_t LoadCommandIndex) {
936    if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
937      return malformedError("load command " + Twine(LoadCommandIndex) +
938                            " LC_LINKER_OPTION cmdsize too small");
939    auto LinkOptionOrErr =
940      getStructOrErr<MachO::linker_option_command>(Obj, Load.Ptr);
941    if (!LinkOptionOrErr)
942      return LinkOptionOrErr.takeError();
943    MachO::linker_option_command L = LinkOptionOrErr.get();
944    // Make sure the count of strings is correct.
945    const char *string = (const char *)Load.Ptr +
946                         sizeof(struct MachO::linker_option_command);
947    uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
948    uint32_t i = 0;
949    while (left > 0) {
950      while (*string == '\0' && left > 0) {
951        string++;
952        left--;
953      }
954      if (left > 0) {
955        i++;
956        uint32_t NullPos = StringRef(string, left).find('\0');
957        if (0xffffffff == NullPos)
958          return malformedError("load command " + Twine(LoadCommandIndex) +
959                                " LC_LINKER_OPTION string #" + Twine(i) +
960                                " is not NULL terminated");
961        uint32_t len = std::min(NullPos, left) + 1;
962        string += len;
963        left -= len;
964      }
965    }
966    if (L.count != i)
967      return malformedError("load command " + Twine(LoadCommandIndex) +
968                            " LC_LINKER_OPTION string count " + Twine(L.count) +
969                            " does not match number of strings");
970    return Error::success();
971  }
972  
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)973  static Error checkSubCommand(const MachOObjectFile &Obj,
974                               const MachOObjectFile::LoadCommandInfo &Load,
975                               uint32_t LoadCommandIndex, const char *CmdName,
976                               size_t SizeOfCmd, const char *CmdStructName,
977                               uint32_t PathOffset, const char *PathFieldName) {
978    if (PathOffset < SizeOfCmd)
979      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
980                            CmdName + " " + PathFieldName + ".offset field too "
981                            "small, not past the end of the " + CmdStructName);
982    if (PathOffset >= Load.C.cmdsize)
983      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
984                            CmdName + " " + PathFieldName + ".offset field "
985                            "extends past the end of the load command");
986    // Make sure there is a null between the starting offset of the path and
987    // the end of the load command.
988    uint32_t i;
989    const char *P = (const char *)Load.Ptr;
990    for (i = PathOffset; i < Load.C.cmdsize; i++)
991      if (P[i] == '\0')
992        break;
993    if (i >= Load.C.cmdsize)
994      return malformedError("load command " + Twine(LoadCommandIndex) + " " +
995                            CmdName + " " + PathFieldName + " name extends past "
996                            "the end of the load command");
997    return Error::success();
998  }
999  
checkThreadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)1000  static Error checkThreadCommand(const MachOObjectFile &Obj,
1001                                  const MachOObjectFile::LoadCommandInfo &Load,
1002                                  uint32_t LoadCommandIndex,
1003                                  const char *CmdName) {
1004    if (Load.C.cmdsize < sizeof(MachO::thread_command))
1005      return malformedError("load command " + Twine(LoadCommandIndex) +
1006                            CmdName + " cmdsize too small");
1007    auto ThreadCommandOrErr =
1008      getStructOrErr<MachO::thread_command>(Obj, Load.Ptr);
1009    if (!ThreadCommandOrErr)
1010      return ThreadCommandOrErr.takeError();
1011    MachO::thread_command T = ThreadCommandOrErr.get();
1012    const char *state = Load.Ptr + sizeof(MachO::thread_command);
1013    const char *end = Load.Ptr + T.cmdsize;
1014    uint32_t nflavor = 0;
1015    uint32_t cputype = getCPUType(Obj);
1016    while (state < end) {
1017      if(state + sizeof(uint32_t) > end)
1018        return malformedError("load command " + Twine(LoadCommandIndex) +
1019                              "flavor in " + CmdName + " extends past end of "
1020                              "command");
1021      uint32_t flavor;
1022      memcpy(&flavor, state, sizeof(uint32_t));
1023      if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
1024        sys::swapByteOrder(flavor);
1025      state += sizeof(uint32_t);
1026  
1027      if(state + sizeof(uint32_t) > end)
1028        return malformedError("load command " + Twine(LoadCommandIndex) +
1029                              " count in " + CmdName + " extends past end of "
1030                              "command");
1031      uint32_t count;
1032      memcpy(&count, state, sizeof(uint32_t));
1033      if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
1034        sys::swapByteOrder(count);
1035      state += sizeof(uint32_t);
1036  
1037      if (cputype == MachO::CPU_TYPE_I386) {
1038        if (flavor == MachO::x86_THREAD_STATE32) {
1039          if (count != MachO::x86_THREAD_STATE32_COUNT)
1040            return malformedError("load command " + Twine(LoadCommandIndex) +
1041                                  " count not x86_THREAD_STATE32_COUNT for "
1042                                  "flavor number " + Twine(nflavor) + " which is "
1043                                  "a x86_THREAD_STATE32 flavor in " + CmdName +
1044                                  " command");
1045          if (state + sizeof(MachO::x86_thread_state32_t) > end)
1046            return malformedError("load command " + Twine(LoadCommandIndex) +
1047                                  " x86_THREAD_STATE32 extends past end of "
1048                                  "command in " + CmdName + " command");
1049          state += sizeof(MachO::x86_thread_state32_t);
1050        } else {
1051          return malformedError("load command " + Twine(LoadCommandIndex) +
1052                                " unknown flavor (" + Twine(flavor) + ") for "
1053                                "flavor number " + Twine(nflavor) + " in " +
1054                                CmdName + " command");
1055        }
1056      } else if (cputype == MachO::CPU_TYPE_X86_64) {
1057        if (flavor == MachO::x86_THREAD_STATE) {
1058          if (count != MachO::x86_THREAD_STATE_COUNT)
1059            return malformedError("load command " + Twine(LoadCommandIndex) +
1060                                  " count not x86_THREAD_STATE_COUNT for "
1061                                  "flavor number " + Twine(nflavor) + " which is "
1062                                  "a x86_THREAD_STATE flavor in " + CmdName +
1063                                  " command");
1064          if (state + sizeof(MachO::x86_thread_state_t) > end)
1065            return malformedError("load command " + Twine(LoadCommandIndex) +
1066                                  " x86_THREAD_STATE extends past end of "
1067                                  "command in " + CmdName + " command");
1068          state += sizeof(MachO::x86_thread_state_t);
1069        } else if (flavor == MachO::x86_FLOAT_STATE) {
1070          if (count != MachO::x86_FLOAT_STATE_COUNT)
1071            return malformedError("load command " + Twine(LoadCommandIndex) +
1072                                  " count not x86_FLOAT_STATE_COUNT for "
1073                                  "flavor number " + Twine(nflavor) + " which is "
1074                                  "a x86_FLOAT_STATE flavor in " + CmdName +
1075                                  " command");
1076          if (state + sizeof(MachO::x86_float_state_t) > end)
1077            return malformedError("load command " + Twine(LoadCommandIndex) +
1078                                  " x86_FLOAT_STATE extends past end of "
1079                                  "command in " + CmdName + " command");
1080          state += sizeof(MachO::x86_float_state_t);
1081        } else if (flavor == MachO::x86_EXCEPTION_STATE) {
1082          if (count != MachO::x86_EXCEPTION_STATE_COUNT)
1083            return malformedError("load command " + Twine(LoadCommandIndex) +
1084                                  " count not x86_EXCEPTION_STATE_COUNT for "
1085                                  "flavor number " + Twine(nflavor) + " which is "
1086                                  "a x86_EXCEPTION_STATE flavor in " + CmdName +
1087                                  " command");
1088          if (state + sizeof(MachO::x86_exception_state_t) > end)
1089            return malformedError("load command " + Twine(LoadCommandIndex) +
1090                                  " x86_EXCEPTION_STATE extends past end of "
1091                                  "command in " + CmdName + " command");
1092          state += sizeof(MachO::x86_exception_state_t);
1093        } else if (flavor == MachO::x86_THREAD_STATE64) {
1094          if (count != MachO::x86_THREAD_STATE64_COUNT)
1095            return malformedError("load command " + Twine(LoadCommandIndex) +
1096                                  " count not x86_THREAD_STATE64_COUNT for "
1097                                  "flavor number " + Twine(nflavor) + " which is "
1098                                  "a x86_THREAD_STATE64 flavor in " + CmdName +
1099                                  " command");
1100          if (state + sizeof(MachO::x86_thread_state64_t) > end)
1101            return malformedError("load command " + Twine(LoadCommandIndex) +
1102                                  " x86_THREAD_STATE64 extends past end of "
1103                                  "command in " + CmdName + " command");
1104          state += sizeof(MachO::x86_thread_state64_t);
1105        } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
1106          if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
1107            return malformedError("load command " + Twine(LoadCommandIndex) +
1108                                  " count not x86_EXCEPTION_STATE64_COUNT for "
1109                                  "flavor number " + Twine(nflavor) + " which is "
1110                                  "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
1111                                  " command");
1112          if (state + sizeof(MachO::x86_exception_state64_t) > end)
1113            return malformedError("load command " + Twine(LoadCommandIndex) +
1114                                  " x86_EXCEPTION_STATE64 extends past end of "
1115                                  "command in " + CmdName + " command");
1116          state += sizeof(MachO::x86_exception_state64_t);
1117        } else {
1118          return malformedError("load command " + Twine(LoadCommandIndex) +
1119                                " unknown flavor (" + Twine(flavor) + ") for "
1120                                "flavor number " + Twine(nflavor) + " in " +
1121                                CmdName + " command");
1122        }
1123      } else if (cputype == MachO::CPU_TYPE_ARM) {
1124        if (flavor == MachO::ARM_THREAD_STATE) {
1125          if (count != MachO::ARM_THREAD_STATE_COUNT)
1126            return malformedError("load command " + Twine(LoadCommandIndex) +
1127                                  " count not ARM_THREAD_STATE_COUNT for "
1128                                  "flavor number " + Twine(nflavor) + " which is "
1129                                  "a ARM_THREAD_STATE flavor in " + CmdName +
1130                                  " command");
1131          if (state + sizeof(MachO::arm_thread_state32_t) > end)
1132            return malformedError("load command " + Twine(LoadCommandIndex) +
1133                                  " ARM_THREAD_STATE extends past end of "
1134                                  "command in " + CmdName + " command");
1135          state += sizeof(MachO::arm_thread_state32_t);
1136        } else {
1137          return malformedError("load command " + Twine(LoadCommandIndex) +
1138                                " unknown flavor (" + Twine(flavor) + ") for "
1139                                "flavor number " + Twine(nflavor) + " in " +
1140                                CmdName + " command");
1141        }
1142      } else if (cputype == MachO::CPU_TYPE_ARM64 ||
1143                 cputype == MachO::CPU_TYPE_ARM64_32) {
1144        if (flavor == MachO::ARM_THREAD_STATE64) {
1145          if (count != MachO::ARM_THREAD_STATE64_COUNT)
1146            return malformedError("load command " + Twine(LoadCommandIndex) +
1147                                  " count not ARM_THREAD_STATE64_COUNT for "
1148                                  "flavor number " + Twine(nflavor) + " which is "
1149                                  "a ARM_THREAD_STATE64 flavor in " + CmdName +
1150                                  " command");
1151          if (state + sizeof(MachO::arm_thread_state64_t) > end)
1152            return malformedError("load command " + Twine(LoadCommandIndex) +
1153                                  " ARM_THREAD_STATE64 extends past end of "
1154                                  "command in " + CmdName + " command");
1155          state += sizeof(MachO::arm_thread_state64_t);
1156        } else {
1157          return malformedError("load command " + Twine(LoadCommandIndex) +
1158                                " unknown flavor (" + Twine(flavor) + ") for "
1159                                "flavor number " + Twine(nflavor) + " in " +
1160                                CmdName + " command");
1161        }
1162      } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1163        if (flavor == MachO::PPC_THREAD_STATE) {
1164          if (count != MachO::PPC_THREAD_STATE_COUNT)
1165            return malformedError("load command " + Twine(LoadCommandIndex) +
1166                                  " count not PPC_THREAD_STATE_COUNT for "
1167                                  "flavor number " + Twine(nflavor) + " which is "
1168                                  "a PPC_THREAD_STATE flavor in " + CmdName +
1169                                  " command");
1170          if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1171            return malformedError("load command " + Twine(LoadCommandIndex) +
1172                                  " PPC_THREAD_STATE extends past end of "
1173                                  "command in " + CmdName + " command");
1174          state += sizeof(MachO::ppc_thread_state32_t);
1175        } else {
1176          return malformedError("load command " + Twine(LoadCommandIndex) +
1177                                " unknown flavor (" + Twine(flavor) + ") for "
1178                                "flavor number " + Twine(nflavor) + " in " +
1179                                CmdName + " command");
1180        }
1181      } else {
1182        return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1183                              "command " + Twine(LoadCommandIndex) + " for " +
1184                              CmdName + " command can't be checked");
1185      }
1186      nflavor++;
1187    }
1188    return Error::success();
1189  }
1190  
checkTwoLevelHintsCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,std::list<MachOElement> & Elements)1191  static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1192                                         const MachOObjectFile::LoadCommandInfo
1193                                           &Load,
1194                                         uint32_t LoadCommandIndex,
1195                                         const char **LoadCmd,
1196                                         std::list<MachOElement> &Elements) {
1197    if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1198      return malformedError("load command " + Twine(LoadCommandIndex) +
1199                            " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1200    if (*LoadCmd != nullptr)
1201      return malformedError("more than one LC_TWOLEVEL_HINTS command");
1202    auto HintsOrErr = getStructOrErr<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1203    if(!HintsOrErr)
1204      return HintsOrErr.takeError();
1205    MachO::twolevel_hints_command Hints = HintsOrErr.get();
1206    uint64_t FileSize = Obj.getData().size();
1207    if (Hints.offset > FileSize)
1208      return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1209                            Twine(LoadCommandIndex) + " extends past the end of "
1210                            "the file");
1211    uint64_t BigSize = Hints.nhints;
1212    BigSize *= sizeof(MachO::twolevel_hint);
1213    BigSize += Hints.offset;
1214    if (BigSize > FileSize)
1215      return malformedError("offset field plus nhints times sizeof(struct "
1216                            "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1217                            Twine(LoadCommandIndex) + " extends past the end of "
1218                            "the file");
1219    if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1220                                            sizeof(MachO::twolevel_hint),
1221                                            "two level hints"))
1222      return Err;
1223    *LoadCmd = Load.Ptr;
1224    return Error::success();
1225  }
1226  
1227  // Returns true if the libObject code does not support the load command and its
1228  // contents.  The cmd value it is treated as an unknown load command but with
1229  // an error message that says the cmd value is obsolete.
isLoadCommandObsolete(uint32_t cmd)1230  static bool isLoadCommandObsolete(uint32_t cmd) {
1231    if (cmd == MachO::LC_SYMSEG ||
1232        cmd == MachO::LC_LOADFVMLIB ||
1233        cmd == MachO::LC_IDFVMLIB ||
1234        cmd == MachO::LC_IDENT ||
1235        cmd == MachO::LC_FVMFILE ||
1236        cmd == MachO::LC_PREPAGE ||
1237        cmd == MachO::LC_PREBOUND_DYLIB ||
1238        cmd == MachO::LC_TWOLEVEL_HINTS ||
1239        cmd == MachO::LC_PREBIND_CKSUM)
1240      return true;
1241    return false;
1242  }
1243  
1244  Expected<std::unique_ptr<MachOObjectFile>>
create(MemoryBufferRef Object,bool IsLittleEndian,bool Is64Bits,uint32_t UniversalCputype,uint32_t UniversalIndex)1245  MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1246                          bool Is64Bits, uint32_t UniversalCputype,
1247                          uint32_t UniversalIndex) {
1248    Error Err = Error::success();
1249    std::unique_ptr<MachOObjectFile> Obj(
1250        new MachOObjectFile(std::move(Object), IsLittleEndian,
1251                            Is64Bits, Err, UniversalCputype,
1252                            UniversalIndex));
1253    if (Err)
1254      return std::move(Err);
1255    return std::move(Obj);
1256  }
1257  
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,Error & Err,uint32_t UniversalCputype,uint32_t UniversalIndex)1258  MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1259                                   bool Is64bits, Error &Err,
1260                                   uint32_t UniversalCputype,
1261                                   uint32_t UniversalIndex)
1262      : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
1263    ErrorAsOutParameter ErrAsOutParam(&Err);
1264    uint64_t SizeOfHeaders;
1265    uint32_t cputype;
1266    if (is64Bit()) {
1267      parseHeader(*this, Header64, Err);
1268      SizeOfHeaders = sizeof(MachO::mach_header_64);
1269      cputype = Header64.cputype;
1270    } else {
1271      parseHeader(*this, Header, Err);
1272      SizeOfHeaders = sizeof(MachO::mach_header);
1273      cputype = Header.cputype;
1274    }
1275    if (Err)
1276      return;
1277    SizeOfHeaders += getHeader().sizeofcmds;
1278    if (getData().data() + SizeOfHeaders > getData().end()) {
1279      Err = malformedError("load commands extend past the end of the file");
1280      return;
1281    }
1282    if (UniversalCputype != 0 && cputype != UniversalCputype) {
1283      Err = malformedError("universal header architecture: " +
1284                           Twine(UniversalIndex) + "'s cputype does not match "
1285                           "object file's mach header");
1286      return;
1287    }
1288    std::list<MachOElement> Elements;
1289    Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
1290  
1291    uint32_t LoadCommandCount = getHeader().ncmds;
1292    LoadCommandInfo Load;
1293    if (LoadCommandCount != 0) {
1294      if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
1295        Load = *LoadOrErr;
1296      else {
1297        Err = LoadOrErr.takeError();
1298        return;
1299      }
1300    }
1301  
1302    const char *DyldIdLoadCmd = nullptr;
1303    const char *FuncStartsLoadCmd = nullptr;
1304    const char *SplitInfoLoadCmd = nullptr;
1305    const char *CodeSignDrsLoadCmd = nullptr;
1306    const char *CodeSignLoadCmd = nullptr;
1307    const char *VersLoadCmd = nullptr;
1308    const char *SourceLoadCmd = nullptr;
1309    const char *EntryPointLoadCmd = nullptr;
1310    const char *EncryptLoadCmd = nullptr;
1311    const char *RoutinesLoadCmd = nullptr;
1312    const char *UnixThreadLoadCmd = nullptr;
1313    const char *TwoLevelHintsLoadCmd = nullptr;
1314    for (unsigned I = 0; I < LoadCommandCount; ++I) {
1315      if (is64Bit()) {
1316        if (Load.C.cmdsize % 8 != 0) {
1317          // We have a hack here to allow 64-bit Mach-O core files to have
1318          // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1319          // allowed since the macOS kernel produces them.
1320          if (getHeader().filetype != MachO::MH_CORE ||
1321              Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1322            Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1323                                 "multiple of 8");
1324            return;
1325          }
1326        }
1327      } else {
1328        if (Load.C.cmdsize % 4 != 0) {
1329          Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1330                               "multiple of 4");
1331          return;
1332        }
1333      }
1334      LoadCommands.push_back(Load);
1335      if (Load.C.cmd == MachO::LC_SYMTAB) {
1336        if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
1337          return;
1338      } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1339        if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1340                                        Elements)))
1341          return;
1342      } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1343        if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1344                                            "LC_DATA_IN_CODE", Elements,
1345                                            "data in code info")))
1346          return;
1347      } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1348        if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1349                                            "LC_LINKER_OPTIMIZATION_HINT",
1350                                            Elements, "linker optimization "
1351                                            "hints")))
1352          return;
1353      } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1354        if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1355                                            "LC_FUNCTION_STARTS", Elements,
1356                                            "function starts data")))
1357          return;
1358      } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1359        if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1360                                            "LC_SEGMENT_SPLIT_INFO", Elements,
1361                                            "split info data")))
1362          return;
1363      } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1364        if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1365                                            "LC_DYLIB_CODE_SIGN_DRS", Elements,
1366                                            "code signing RDs data")))
1367          return;
1368      } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1369        if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1370                                            "LC_CODE_SIGNATURE", Elements,
1371                                            "code signature data")))
1372          return;
1373      } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1374        if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1375                                        "LC_DYLD_INFO", Elements)))
1376          return;
1377      } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1378        if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1379                                        "LC_DYLD_INFO_ONLY", Elements)))
1380          return;
1381      } else if (Load.C.cmd == MachO::LC_UUID) {
1382        if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1383          Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1384                               "cmdsize");
1385          return;
1386        }
1387        if (UuidLoadCmd) {
1388          Err = malformedError("more than one LC_UUID command");
1389          return;
1390        }
1391        UuidLoadCmd = Load.Ptr;
1392      } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1393        if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1394                                           MachO::section_64>(
1395                     *this, Load, Sections, HasPageZeroSegment, I,
1396                     "LC_SEGMENT_64", SizeOfHeaders, Elements)))
1397          return;
1398      } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1399        if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1400                                           MachO::section>(
1401                     *this, Load, Sections, HasPageZeroSegment, I,
1402                     "LC_SEGMENT", SizeOfHeaders, Elements)))
1403          return;
1404      } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1405        if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1406          return;
1407      } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1408        if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1409          return;
1410        Libraries.push_back(Load.Ptr);
1411      } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1412        if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1413          return;
1414        Libraries.push_back(Load.Ptr);
1415      } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1416        if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1417          return;
1418        Libraries.push_back(Load.Ptr);
1419      } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1420        if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1421          return;
1422        Libraries.push_back(Load.Ptr);
1423      } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1424        if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1425          return;
1426        Libraries.push_back(Load.Ptr);
1427      } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1428        if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1429          return;
1430      } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1431        if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1432          return;
1433      } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1434        if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1435          return;
1436      } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1437        if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1438                                    "LC_VERSION_MIN_MACOSX")))
1439          return;
1440      } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1441        if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1442                                    "LC_VERSION_MIN_IPHONEOS")))
1443          return;
1444      } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1445        if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1446                                    "LC_VERSION_MIN_TVOS")))
1447          return;
1448      } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1449        if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1450                                    "LC_VERSION_MIN_WATCHOS")))
1451          return;
1452      } else if (Load.C.cmd == MachO::LC_NOTE) {
1453        if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1454          return;
1455      } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1456        if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1457          return;
1458      } else if (Load.C.cmd == MachO::LC_RPATH) {
1459        if ((Err = checkRpathCommand(*this, Load, I)))
1460          return;
1461      } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1462        if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1463          Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1464                               " has incorrect cmdsize");
1465          return;
1466        }
1467        if (SourceLoadCmd) {
1468          Err = malformedError("more than one LC_SOURCE_VERSION command");
1469          return;
1470        }
1471        SourceLoadCmd = Load.Ptr;
1472      } else if (Load.C.cmd == MachO::LC_MAIN) {
1473        if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1474          Err = malformedError("LC_MAIN command " + Twine(I) +
1475                               " has incorrect cmdsize");
1476          return;
1477        }
1478        if (EntryPointLoadCmd) {
1479          Err = malformedError("more than one LC_MAIN command");
1480          return;
1481        }
1482        EntryPointLoadCmd = Load.Ptr;
1483      } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1484        if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1485          Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1486                               " has incorrect cmdsize");
1487          return;
1488        }
1489        MachO::encryption_info_command E =
1490          getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1491        if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1492                                       &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1493          return;
1494      } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1495        if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1496          Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1497                               " has incorrect cmdsize");
1498          return;
1499        }
1500        MachO::encryption_info_command_64 E =
1501          getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1502        if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1503                                       &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1504          return;
1505      } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1506        if ((Err = checkLinkerOptCommand(*this, Load, I)))
1507          return;
1508      } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1509        if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1510          Err =  malformedError("load command " + Twine(I) +
1511                                " LC_SUB_FRAMEWORK cmdsize too small");
1512          return;
1513        }
1514        MachO::sub_framework_command S =
1515          getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1516        if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1517                                   sizeof(MachO::sub_framework_command),
1518                                   "sub_framework_command", S.umbrella,
1519                                   "umbrella")))
1520          return;
1521      } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1522        if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1523          Err =  malformedError("load command " + Twine(I) +
1524                                " LC_SUB_UMBRELLA cmdsize too small");
1525          return;
1526        }
1527        MachO::sub_umbrella_command S =
1528          getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1529        if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1530                                   sizeof(MachO::sub_umbrella_command),
1531                                   "sub_umbrella_command", S.sub_umbrella,
1532                                   "sub_umbrella")))
1533          return;
1534      } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1535        if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1536          Err =  malformedError("load command " + Twine(I) +
1537                                " LC_SUB_LIBRARY cmdsize too small");
1538          return;
1539        }
1540        MachO::sub_library_command S =
1541          getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1542        if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1543                                   sizeof(MachO::sub_library_command),
1544                                   "sub_library_command", S.sub_library,
1545                                   "sub_library")))
1546          return;
1547      } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1548        if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1549          Err =  malformedError("load command " + Twine(I) +
1550                                " LC_SUB_CLIENT cmdsize too small");
1551          return;
1552        }
1553        MachO::sub_client_command S =
1554          getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1555        if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1556                                   sizeof(MachO::sub_client_command),
1557                                   "sub_client_command", S.client, "client")))
1558          return;
1559      } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1560        if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1561          Err = malformedError("LC_ROUTINES command " + Twine(I) +
1562                               " has incorrect cmdsize");
1563          return;
1564        }
1565        if (RoutinesLoadCmd) {
1566          Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1567                               "command");
1568          return;
1569        }
1570        RoutinesLoadCmd = Load.Ptr;
1571      } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1572        if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1573          Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1574                               " has incorrect cmdsize");
1575          return;
1576        }
1577        if (RoutinesLoadCmd) {
1578          Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1579                               "command");
1580          return;
1581        }
1582        RoutinesLoadCmd = Load.Ptr;
1583      } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1584        if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1585          return;
1586        if (UnixThreadLoadCmd) {
1587          Err = malformedError("more than one LC_UNIXTHREAD command");
1588          return;
1589        }
1590        UnixThreadLoadCmd = Load.Ptr;
1591      } else if (Load.C.cmd == MachO::LC_THREAD) {
1592        if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1593          return;
1594      // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1595      } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1596         if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1597                                              &TwoLevelHintsLoadCmd, Elements)))
1598           return;
1599      } else if (isLoadCommandObsolete(Load.C.cmd)) {
1600        Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1601                             Twine(Load.C.cmd) + " is obsolete and not "
1602                             "supported");
1603        return;
1604      }
1605      // TODO: generate a error for unknown load commands by default.  But still
1606      // need work out an approach to allow or not allow unknown values like this
1607      // as an option for some uses like lldb.
1608      if (I < LoadCommandCount - 1) {
1609        if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
1610          Load = *LoadOrErr;
1611        else {
1612          Err = LoadOrErr.takeError();
1613          return;
1614        }
1615      }
1616    }
1617    if (!SymtabLoadCmd) {
1618      if (DysymtabLoadCmd) {
1619        Err = malformedError("contains LC_DYSYMTAB load command without a "
1620                             "LC_SYMTAB load command");
1621        return;
1622      }
1623    } else if (DysymtabLoadCmd) {
1624      MachO::symtab_command Symtab =
1625        getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
1626      MachO::dysymtab_command Dysymtab =
1627        getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
1628      if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1629        Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
1630                             "extends past the end of the symbol table");
1631        return;
1632      }
1633      uint64_t BigSize = Dysymtab.ilocalsym;
1634      BigSize += Dysymtab.nlocalsym;
1635      if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
1636        Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1637                             "command extends past the end of the symbol table");
1638        return;
1639      }
1640      if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
1641        Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
1642                             "extends past the end of the symbol table");
1643        return;
1644      }
1645      BigSize = Dysymtab.iextdefsym;
1646      BigSize += Dysymtab.nextdefsym;
1647      if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
1648        Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1649                             "load command extends past the end of the symbol "
1650                             "table");
1651        return;
1652      }
1653      if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
1654        Err = malformedError("iundefsym in LC_DYSYMTAB load command "
1655                             "extends past the end of the symbol table");
1656        return;
1657      }
1658      BigSize = Dysymtab.iundefsym;
1659      BigSize += Dysymtab.nundefsym;
1660      if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
1661        Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1662                             " command extends past the end of the symbol table");
1663        return;
1664      }
1665    }
1666    if ((getHeader().filetype == MachO::MH_DYLIB ||
1667         getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1668         DyldIdLoadCmd == nullptr) {
1669      Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1670                           "filetype");
1671      return;
1672    }
1673    assert(LoadCommands.size() == LoadCommandCount);
1674  
1675    Err = Error::success();
1676  }
1677  
checkSymbolTable() const1678  Error MachOObjectFile::checkSymbolTable() const {
1679    uint32_t Flags = 0;
1680    if (is64Bit()) {
1681      MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1682      Flags = H_64.flags;
1683    } else {
1684      MachO::mach_header H = MachOObjectFile::getHeader();
1685      Flags = H.flags;
1686    }
1687    uint8_t NType = 0;
1688    uint8_t NSect = 0;
1689    uint16_t NDesc = 0;
1690    uint32_t NStrx = 0;
1691    uint64_t NValue = 0;
1692    uint32_t SymbolIndex = 0;
1693    MachO::symtab_command S = getSymtabLoadCommand();
1694    for (const SymbolRef &Symbol : symbols()) {
1695      DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1696      if (is64Bit()) {
1697        MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1698        NType = STE_64.n_type;
1699        NSect = STE_64.n_sect;
1700        NDesc = STE_64.n_desc;
1701        NStrx = STE_64.n_strx;
1702        NValue = STE_64.n_value;
1703      } else {
1704        MachO::nlist STE = getSymbolTableEntry(SymDRI);
1705        NType = STE.n_type;
1706        NSect = STE.n_sect;
1707        NDesc = STE.n_desc;
1708        NStrx = STE.n_strx;
1709        NValue = STE.n_value;
1710      }
1711      if ((NType & MachO::N_STAB) == 0) {
1712        if ((NType & MachO::N_TYPE) == MachO::N_SECT) {
1713          if (NSect == 0 || NSect > Sections.size())
1714            return malformedError("bad section index: " + Twine((int)NSect) +
1715                                  " for symbol at index " + Twine(SymbolIndex));
1716        }
1717        if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
1718          if (NValue >= S.strsize)
1719            return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1720                                  "the end of string table, for N_INDR symbol at "
1721                                  "index " + Twine(SymbolIndex));
1722        }
1723        if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1724            (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1725             (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1726              uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1727              if (LibraryOrdinal != 0 &&
1728                  LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1729                  LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1730                  LibraryOrdinal - 1 >= Libraries.size() ) {
1731                return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1732                                      " for symbol at index " + Twine(SymbolIndex));
1733              }
1734            }
1735      }
1736      if (NStrx >= S.strsize)
1737        return malformedError("bad string table index: " + Twine((int)NStrx) +
1738                              " past the end of string table, for symbol at "
1739                              "index " + Twine(SymbolIndex));
1740      SymbolIndex++;
1741    }
1742    return Error::success();
1743  }
1744  
moveSymbolNext(DataRefImpl & Symb) const1745  void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1746    unsigned SymbolTableEntrySize = is64Bit() ?
1747      sizeof(MachO::nlist_64) :
1748      sizeof(MachO::nlist);
1749    Symb.p += SymbolTableEntrySize;
1750  }
1751  
getSymbolName(DataRefImpl Symb) const1752  Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1753    StringRef StringTable = getStringTableData();
1754    MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1755    if (Entry.n_strx == 0)
1756      // A n_strx value of 0 indicates that no name is associated with a
1757      // particular symbol table entry.
1758      return StringRef();
1759    const char *Start = &StringTable.data()[Entry.n_strx];
1760    if (Start < getData().begin() || Start >= getData().end()) {
1761      return malformedError("bad string index: " + Twine(Entry.n_strx) +
1762                            " for symbol at index " + Twine(getSymbolIndex(Symb)));
1763    }
1764    return StringRef(Start);
1765  }
1766  
getSectionType(SectionRef Sec) const1767  unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1768    DataRefImpl DRI = Sec.getRawDataRefImpl();
1769    uint32_t Flags = getSectionFlags(*this, DRI);
1770    return Flags & MachO::SECTION_TYPE;
1771  }
1772  
getNValue(DataRefImpl Sym) const1773  uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1774    if (is64Bit()) {
1775      MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1776      return Entry.n_value;
1777    }
1778    MachO::nlist Entry = getSymbolTableEntry(Sym);
1779    return Entry.n_value;
1780  }
1781  
1782  // getIndirectName() returns the name of the alias'ed symbol who's string table
1783  // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const1784  std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1785                                                   StringRef &Res) const {
1786    StringRef StringTable = getStringTableData();
1787    MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1788    if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1789      return object_error::parse_failed;
1790    uint64_t NValue = getNValue(Symb);
1791    if (NValue >= StringTable.size())
1792      return object_error::parse_failed;
1793    const char *Start = &StringTable.data()[NValue];
1794    Res = StringRef(Start);
1795    return std::error_code();
1796  }
1797  
getSymbolValueImpl(DataRefImpl Sym) const1798  uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1799    return getNValue(Sym);
1800  }
1801  
getSymbolAddress(DataRefImpl Sym) const1802  Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1803    return getSymbolValue(Sym);
1804  }
1805  
getSymbolAlignment(DataRefImpl DRI) const1806  uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
1807    uint32_t flags = getSymbolFlags(DRI);
1808    if (flags & SymbolRef::SF_Common) {
1809      MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1810      return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
1811    }
1812    return 0;
1813  }
1814  
getCommonSymbolSizeImpl(DataRefImpl DRI) const1815  uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1816    return getNValue(DRI);
1817  }
1818  
1819  Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const1820  MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1821    MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1822    uint8_t n_type = Entry.n_type;
1823  
1824    // If this is a STAB debugging symbol, we can do nothing more.
1825    if (n_type & MachO::N_STAB)
1826      return SymbolRef::ST_Debug;
1827  
1828    switch (n_type & MachO::N_TYPE) {
1829      case MachO::N_UNDF :
1830        return SymbolRef::ST_Unknown;
1831      case MachO::N_SECT :
1832        Expected<section_iterator> SecOrError = getSymbolSection(Symb);
1833        if (!SecOrError)
1834          return SecOrError.takeError();
1835        section_iterator Sec = *SecOrError;
1836        if (Sec->isData() || Sec->isBSS())
1837          return SymbolRef::ST_Data;
1838        return SymbolRef::ST_Function;
1839    }
1840    return SymbolRef::ST_Other;
1841  }
1842  
getSymbolFlags(DataRefImpl DRI) const1843  uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1844    MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1845  
1846    uint8_t MachOType = Entry.n_type;
1847    uint16_t MachOFlags = Entry.n_desc;
1848  
1849    uint32_t Result = SymbolRef::SF_None;
1850  
1851    if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1852      Result |= SymbolRef::SF_Indirect;
1853  
1854    if (MachOType & MachO::N_STAB)
1855      Result |= SymbolRef::SF_FormatSpecific;
1856  
1857    if (MachOType & MachO::N_EXT) {
1858      Result |= SymbolRef::SF_Global;
1859      if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1860        if (getNValue(DRI))
1861          Result |= SymbolRef::SF_Common;
1862        else
1863          Result |= SymbolRef::SF_Undefined;
1864      }
1865  
1866      if (!(MachOType & MachO::N_PEXT))
1867        Result |= SymbolRef::SF_Exported;
1868    }
1869  
1870    if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1871      Result |= SymbolRef::SF_Weak;
1872  
1873    if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1874      Result |= SymbolRef::SF_Thumb;
1875  
1876    if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1877      Result |= SymbolRef::SF_Absolute;
1878  
1879    return Result;
1880  }
1881  
1882  Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const1883  MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1884    MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1885    uint8_t index = Entry.n_sect;
1886  
1887    if (index == 0)
1888      return section_end();
1889    DataRefImpl DRI;
1890    DRI.d.a = index - 1;
1891    if (DRI.d.a >= Sections.size()){
1892      return malformedError("bad section index: " + Twine((int)index) +
1893                            " for symbol at index " + Twine(getSymbolIndex(Symb)));
1894    }
1895    return section_iterator(SectionRef(DRI, this));
1896  }
1897  
getSymbolSectionID(SymbolRef Sym) const1898  unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1899    MachO::nlist_base Entry =
1900        getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
1901    return Entry.n_sect - 1;
1902  }
1903  
moveSectionNext(DataRefImpl & Sec) const1904  void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1905    Sec.d.a++;
1906  }
1907  
getSectionName(DataRefImpl Sec) const1908  Expected<StringRef> MachOObjectFile::getSectionName(DataRefImpl Sec) const {
1909    ArrayRef<char> Raw = getSectionRawName(Sec);
1910    return parseSegmentOrSectionName(Raw.data());
1911  }
1912  
getSectionAddress(DataRefImpl Sec) const1913  uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1914    if (is64Bit())
1915      return getSection64(Sec).addr;
1916    return getSection(Sec).addr;
1917  }
1918  
getSectionIndex(DataRefImpl Sec) const1919  uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1920    return Sec.d.a;
1921  }
1922  
getSectionSize(DataRefImpl Sec) const1923  uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
1924    // In the case if a malformed Mach-O file where the section offset is past
1925    // the end of the file or some part of the section size is past the end of
1926    // the file return a size of zero or a size that covers the rest of the file
1927    // but does not extend past the end of the file.
1928    uint32_t SectOffset, SectType;
1929    uint64_t SectSize;
1930  
1931    if (is64Bit()) {
1932      MachO::section_64 Sect = getSection64(Sec);
1933      SectOffset = Sect.offset;
1934      SectSize = Sect.size;
1935      SectType = Sect.flags & MachO::SECTION_TYPE;
1936    } else {
1937      MachO::section Sect = getSection(Sec);
1938      SectOffset = Sect.offset;
1939      SectSize = Sect.size;
1940      SectType = Sect.flags & MachO::SECTION_TYPE;
1941    }
1942    if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1943      return SectSize;
1944    uint64_t FileSize = getData().size();
1945    if (SectOffset > FileSize)
1946      return 0;
1947    if (FileSize - SectOffset < SectSize)
1948      return FileSize - SectOffset;
1949    return SectSize;
1950  }
1951  
getSectionContents(uint32_t Offset,uint64_t Size) const1952  ArrayRef<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset,
1953                                                        uint64_t Size) const {
1954    return arrayRefFromStringRef(getData().substr(Offset, Size));
1955  }
1956  
1957  Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const1958  MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
1959    uint32_t Offset;
1960    uint64_t Size;
1961  
1962    if (is64Bit()) {
1963      MachO::section_64 Sect = getSection64(Sec);
1964      Offset = Sect.offset;
1965      Size = Sect.size;
1966    } else {
1967      MachO::section Sect = getSection(Sec);
1968      Offset = Sect.offset;
1969      Size = Sect.size;
1970    }
1971  
1972    return getSectionContents(Offset, Size);
1973  }
1974  
getSectionAlignment(DataRefImpl Sec) const1975  uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1976    uint32_t Align;
1977    if (is64Bit()) {
1978      MachO::section_64 Sect = getSection64(Sec);
1979      Align = Sect.align;
1980    } else {
1981      MachO::section Sect = getSection(Sec);
1982      Align = Sect.align;
1983    }
1984  
1985    return uint64_t(1) << Align;
1986  }
1987  
getSection(unsigned SectionIndex) const1988  Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
1989    if (SectionIndex < 1 || SectionIndex > Sections.size())
1990      return malformedError("bad section index: " + Twine((int)SectionIndex));
1991  
1992    DataRefImpl DRI;
1993    DRI.d.a = SectionIndex - 1;
1994    return SectionRef(DRI, this);
1995  }
1996  
getSection(StringRef SectionName) const1997  Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
1998    for (const SectionRef &Section : sections()) {
1999      auto NameOrErr = Section.getName();
2000      if (!NameOrErr)
2001        return NameOrErr.takeError();
2002      if (*NameOrErr == SectionName)
2003        return Section;
2004    }
2005    return errorCodeToError(object_error::parse_failed);
2006  }
2007  
isSectionCompressed(DataRefImpl Sec) const2008  bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
2009    return false;
2010  }
2011  
isSectionText(DataRefImpl Sec) const2012  bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
2013    uint32_t Flags = getSectionFlags(*this, Sec);
2014    return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
2015  }
2016  
isSectionData(DataRefImpl Sec) const2017  bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
2018    uint32_t Flags = getSectionFlags(*this, Sec);
2019    unsigned SectionType = Flags & MachO::SECTION_TYPE;
2020    return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
2021           !(SectionType == MachO::S_ZEROFILL ||
2022             SectionType == MachO::S_GB_ZEROFILL);
2023  }
2024  
isSectionBSS(DataRefImpl Sec) const2025  bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
2026    uint32_t Flags = getSectionFlags(*this, Sec);
2027    unsigned SectionType = Flags & MachO::SECTION_TYPE;
2028    return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
2029           (SectionType == MachO::S_ZEROFILL ||
2030            SectionType == MachO::S_GB_ZEROFILL);
2031  }
2032  
getSectionID(SectionRef Sec) const2033  unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
2034    return Sec.getRawDataRefImpl().d.a;
2035  }
2036  
isSectionVirtual(DataRefImpl Sec) const2037  bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
2038    uint32_t Flags = getSectionFlags(*this, Sec);
2039    unsigned SectionType = Flags & MachO::SECTION_TYPE;
2040    return SectionType == MachO::S_ZEROFILL ||
2041           SectionType == MachO::S_GB_ZEROFILL;
2042  }
2043  
isSectionBitcode(DataRefImpl Sec) const2044  bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
2045    StringRef SegmentName = getSectionFinalSegmentName(Sec);
2046    if (Expected<StringRef> NameOrErr = getSectionName(Sec))
2047      return (SegmentName == "__LLVM" && *NameOrErr == "__bitcode");
2048    return false;
2049  }
2050  
isSectionStripped(DataRefImpl Sec) const2051  bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
2052    if (is64Bit())
2053      return getSection64(Sec).offset == 0;
2054    return getSection(Sec).offset == 0;
2055  }
2056  
section_rel_begin(DataRefImpl Sec) const2057  relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
2058    DataRefImpl Ret;
2059    Ret.d.a = Sec.d.a;
2060    Ret.d.b = 0;
2061    return relocation_iterator(RelocationRef(Ret, this));
2062  }
2063  
2064  relocation_iterator
section_rel_end(DataRefImpl Sec) const2065  MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
2066    uint32_t Num;
2067    if (is64Bit()) {
2068      MachO::section_64 Sect = getSection64(Sec);
2069      Num = Sect.nreloc;
2070    } else {
2071      MachO::section Sect = getSection(Sec);
2072      Num = Sect.nreloc;
2073    }
2074  
2075    DataRefImpl Ret;
2076    Ret.d.a = Sec.d.a;
2077    Ret.d.b = Num;
2078    return relocation_iterator(RelocationRef(Ret, this));
2079  }
2080  
extrel_begin() const2081  relocation_iterator MachOObjectFile::extrel_begin() const {
2082    DataRefImpl Ret;
2083    // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2084    Ret.d.a = 0; // Would normally be a section index.
2085    Ret.d.b = 0; // Index into the external relocations
2086    return relocation_iterator(RelocationRef(Ret, this));
2087  }
2088  
extrel_end() const2089  relocation_iterator MachOObjectFile::extrel_end() const {
2090    MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2091    DataRefImpl Ret;
2092    // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2093    Ret.d.a = 0; // Would normally be a section index.
2094    Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2095    return relocation_iterator(RelocationRef(Ret, this));
2096  }
2097  
locrel_begin() const2098  relocation_iterator MachOObjectFile::locrel_begin() const {
2099    DataRefImpl Ret;
2100    // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2101    Ret.d.a = 1; // Would normally be a section index.
2102    Ret.d.b = 0; // Index into the local relocations
2103    return relocation_iterator(RelocationRef(Ret, this));
2104  }
2105  
locrel_end() const2106  relocation_iterator MachOObjectFile::locrel_end() const {
2107    MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2108    DataRefImpl Ret;
2109    // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2110    Ret.d.a = 1; // Would normally be a section index.
2111    Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
2112    return relocation_iterator(RelocationRef(Ret, this));
2113  }
2114  
moveRelocationNext(DataRefImpl & Rel) const2115  void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
2116    ++Rel.d.b;
2117  }
2118  
getRelocationOffset(DataRefImpl Rel) const2119  uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
2120    assert((getHeader().filetype == MachO::MH_OBJECT ||
2121            getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2122           "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2123    MachO::any_relocation_info RE = getRelocation(Rel);
2124    return getAnyRelocationAddress(RE);
2125  }
2126  
2127  symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const2128  MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
2129    MachO::any_relocation_info RE = getRelocation(Rel);
2130    if (isRelocationScattered(RE))
2131      return symbol_end();
2132  
2133    uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2134    bool isExtern = getPlainRelocationExternal(RE);
2135    if (!isExtern)
2136      return symbol_end();
2137  
2138    MachO::symtab_command S = getSymtabLoadCommand();
2139    unsigned SymbolTableEntrySize = is64Bit() ?
2140      sizeof(MachO::nlist_64) :
2141      sizeof(MachO::nlist);
2142    uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
2143    DataRefImpl Sym;
2144    Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2145    return symbol_iterator(SymbolRef(Sym, this));
2146  }
2147  
2148  section_iterator
getRelocationSection(DataRefImpl Rel) const2149  MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2150    return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2151  }
2152  
getRelocationType(DataRefImpl Rel) const2153  uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
2154    MachO::any_relocation_info RE = getRelocation(Rel);
2155    return getAnyRelocationType(RE);
2156  }
2157  
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const2158  void MachOObjectFile::getRelocationTypeName(
2159      DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
2160    StringRef res;
2161    uint64_t RType = getRelocationType(Rel);
2162  
2163    unsigned Arch = this->getArch();
2164  
2165    switch (Arch) {
2166      case Triple::x86: {
2167        static const char *const Table[] =  {
2168          "GENERIC_RELOC_VANILLA",
2169          "GENERIC_RELOC_PAIR",
2170          "GENERIC_RELOC_SECTDIFF",
2171          "GENERIC_RELOC_PB_LA_PTR",
2172          "GENERIC_RELOC_LOCAL_SECTDIFF",
2173          "GENERIC_RELOC_TLV" };
2174  
2175        if (RType > 5)
2176          res = "Unknown";
2177        else
2178          res = Table[RType];
2179        break;
2180      }
2181      case Triple::x86_64: {
2182        static const char *const Table[] =  {
2183          "X86_64_RELOC_UNSIGNED",
2184          "X86_64_RELOC_SIGNED",
2185          "X86_64_RELOC_BRANCH",
2186          "X86_64_RELOC_GOT_LOAD",
2187          "X86_64_RELOC_GOT",
2188          "X86_64_RELOC_SUBTRACTOR",
2189          "X86_64_RELOC_SIGNED_1",
2190          "X86_64_RELOC_SIGNED_2",
2191          "X86_64_RELOC_SIGNED_4",
2192          "X86_64_RELOC_TLV" };
2193  
2194        if (RType > 9)
2195          res = "Unknown";
2196        else
2197          res = Table[RType];
2198        break;
2199      }
2200      case Triple::arm: {
2201        static const char *const Table[] =  {
2202          "ARM_RELOC_VANILLA",
2203          "ARM_RELOC_PAIR",
2204          "ARM_RELOC_SECTDIFF",
2205          "ARM_RELOC_LOCAL_SECTDIFF",
2206          "ARM_RELOC_PB_LA_PTR",
2207          "ARM_RELOC_BR24",
2208          "ARM_THUMB_RELOC_BR22",
2209          "ARM_THUMB_32BIT_BRANCH",
2210          "ARM_RELOC_HALF",
2211          "ARM_RELOC_HALF_SECTDIFF" };
2212  
2213        if (RType > 9)
2214          res = "Unknown";
2215        else
2216          res = Table[RType];
2217        break;
2218      }
2219      case Triple::aarch64:
2220      case Triple::aarch64_32: {
2221        static const char *const Table[] = {
2222          "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
2223          "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
2224          "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
2225          "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2226          "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2227          "ARM64_RELOC_ADDEND"
2228        };
2229  
2230        if (RType >= array_lengthof(Table))
2231          res = "Unknown";
2232        else
2233          res = Table[RType];
2234        break;
2235      }
2236      case Triple::ppc: {
2237        static const char *const Table[] =  {
2238          "PPC_RELOC_VANILLA",
2239          "PPC_RELOC_PAIR",
2240          "PPC_RELOC_BR14",
2241          "PPC_RELOC_BR24",
2242          "PPC_RELOC_HI16",
2243          "PPC_RELOC_LO16",
2244          "PPC_RELOC_HA16",
2245          "PPC_RELOC_LO14",
2246          "PPC_RELOC_SECTDIFF",
2247          "PPC_RELOC_PB_LA_PTR",
2248          "PPC_RELOC_HI16_SECTDIFF",
2249          "PPC_RELOC_LO16_SECTDIFF",
2250          "PPC_RELOC_HA16_SECTDIFF",
2251          "PPC_RELOC_JBSR",
2252          "PPC_RELOC_LO14_SECTDIFF",
2253          "PPC_RELOC_LOCAL_SECTDIFF" };
2254  
2255        if (RType > 15)
2256          res = "Unknown";
2257        else
2258          res = Table[RType];
2259        break;
2260      }
2261      case Triple::UnknownArch:
2262        res = "Unknown";
2263        break;
2264    }
2265    Result.append(res.begin(), res.end());
2266  }
2267  
getRelocationLength(DataRefImpl Rel) const2268  uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2269    MachO::any_relocation_info RE = getRelocation(Rel);
2270    return getAnyRelocationLength(RE);
2271  }
2272  
2273  //
2274  // guessLibraryShortName() is passed a name of a dynamic library and returns a
2275  // guess on what the short name is.  Then name is returned as a substring of the
2276  // StringRef Name passed in.  The name of the dynamic library is recognized as
2277  // a framework if it has one of the two following forms:
2278  //      Foo.framework/Versions/A/Foo
2279  //      Foo.framework/Foo
2280  // Where A and Foo can be any string.  And may contain a trailing suffix
2281  // starting with an underbar.  If the Name is recognized as a framework then
2282  // isFramework is set to true else it is set to false.  If the Name has a
2283  // suffix then Suffix is set to the substring in Name that contains the suffix
2284  // else it is set to a NULL StringRef.
2285  //
2286  // The Name of the dynamic library is recognized as a library name if it has
2287  // one of the two following forms:
2288  //      libFoo.A.dylib
2289  //      libFoo.dylib
2290  //
2291  // The library may have a suffix trailing the name Foo of the form:
2292  //      libFoo_profile.A.dylib
2293  //      libFoo_profile.dylib
2294  // These dyld image suffixes are separated from the short name by a '_'
2295  // character. Because the '_' character is commonly used to separate words in
2296  // filenames guessLibraryShortName() cannot reliably separate a dylib's short
2297  // name from an arbitrary image suffix; imagine if both the short name and the
2298  // suffix contains an '_' character! To better deal with this ambiguity,
2299  // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2300  // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2301  // guessing incorrectly.
2302  //
2303  // The Name of the dynamic library is also recognized as a library name if it
2304  // has the following form:
2305  //      Foo.qtx
2306  //
2307  // If the Name of the dynamic library is none of the forms above then a NULL
2308  // StringRef is returned.
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)2309  StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2310                                                   bool &isFramework,
2311                                                   StringRef &Suffix) {
2312    StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2313    size_t a, b, c, d, Idx;
2314  
2315    isFramework = false;
2316    Suffix = StringRef();
2317  
2318    // Pull off the last component and make Foo point to it
2319    a = Name.rfind('/');
2320    if (a == Name.npos || a == 0)
2321      goto guess_library;
2322    Foo = Name.slice(a+1, Name.npos);
2323  
2324    // Look for a suffix starting with a '_'
2325    Idx = Foo.rfind('_');
2326    if (Idx != Foo.npos && Foo.size() >= 2) {
2327      Suffix = Foo.slice(Idx, Foo.npos);
2328      if (Suffix != "_debug" && Suffix != "_profile")
2329        Suffix = StringRef();
2330      else
2331        Foo = Foo.slice(0, Idx);
2332    }
2333  
2334    // First look for the form Foo.framework/Foo
2335    b = Name.rfind('/', a);
2336    if (b == Name.npos)
2337      Idx = 0;
2338    else
2339      Idx = b+1;
2340    F = Name.slice(Idx, Idx + Foo.size());
2341    DotFramework = Name.slice(Idx + Foo.size(),
2342                              Idx + Foo.size() + sizeof(".framework/")-1);
2343    if (F == Foo && DotFramework == ".framework/") {
2344      isFramework = true;
2345      return Foo;
2346    }
2347  
2348    // Next look for the form Foo.framework/Versions/A/Foo
2349    if (b == Name.npos)
2350      goto guess_library;
2351    c =  Name.rfind('/', b);
2352    if (c == Name.npos || c == 0)
2353      goto guess_library;
2354    V = Name.slice(c+1, Name.npos);
2355    if (!V.startswith("Versions/"))
2356      goto guess_library;
2357    d =  Name.rfind('/', c);
2358    if (d == Name.npos)
2359      Idx = 0;
2360    else
2361      Idx = d+1;
2362    F = Name.slice(Idx, Idx + Foo.size());
2363    DotFramework = Name.slice(Idx + Foo.size(),
2364                              Idx + Foo.size() + sizeof(".framework/")-1);
2365    if (F == Foo && DotFramework == ".framework/") {
2366      isFramework = true;
2367      return Foo;
2368    }
2369  
2370  guess_library:
2371    // pull off the suffix after the "." and make a point to it
2372    a = Name.rfind('.');
2373    if (a == Name.npos || a == 0)
2374      return StringRef();
2375    Dylib = Name.slice(a, Name.npos);
2376    if (Dylib != ".dylib")
2377      goto guess_qtx;
2378  
2379    // First pull off the version letter for the form Foo.A.dylib if any.
2380    if (a >= 3) {
2381      Dot = Name.slice(a-2, a-1);
2382      if (Dot == ".")
2383        a = a - 2;
2384    }
2385  
2386    b = Name.rfind('/', a);
2387    if (b == Name.npos)
2388      b = 0;
2389    else
2390      b = b+1;
2391    // ignore any suffix after an underbar like Foo_profile.A.dylib
2392    Idx = Name.rfind('_');
2393    if (Idx != Name.npos && Idx != b) {
2394      Lib = Name.slice(b, Idx);
2395      Suffix = Name.slice(Idx, a);
2396      if (Suffix != "_debug" && Suffix != "_profile") {
2397        Suffix = StringRef();
2398        Lib = Name.slice(b, a);
2399      }
2400    }
2401    else
2402      Lib = Name.slice(b, a);
2403    // There are incorrect library names of the form:
2404    // libATS.A_profile.dylib so check for these.
2405    if (Lib.size() >= 3) {
2406      Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2407      if (Dot == ".")
2408        Lib = Lib.slice(0, Lib.size()-2);
2409    }
2410    return Lib;
2411  
2412  guess_qtx:
2413    Qtx = Name.slice(a, Name.npos);
2414    if (Qtx != ".qtx")
2415      return StringRef();
2416    b = Name.rfind('/', a);
2417    if (b == Name.npos)
2418      Lib = Name.slice(0, a);
2419    else
2420      Lib = Name.slice(b+1, a);
2421    // There are library names of the form: QT.A.qtx so check for these.
2422    if (Lib.size() >= 3) {
2423      Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2424      if (Dot == ".")
2425        Lib = Lib.slice(0, Lib.size()-2);
2426    }
2427    return Lib;
2428  }
2429  
2430  // getLibraryShortNameByIndex() is used to get the short name of the library
2431  // for an undefined symbol in a linked Mach-O binary that was linked with the
2432  // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2433  // It is passed the index (0 - based) of the library as translated from
2434  // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const2435  std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
2436                                                           StringRef &Res) const {
2437    if (Index >= Libraries.size())
2438      return object_error::parse_failed;
2439  
2440    // If the cache of LibrariesShortNames is not built up do that first for
2441    // all the Libraries.
2442    if (LibrariesShortNames.size() == 0) {
2443      for (unsigned i = 0; i < Libraries.size(); i++) {
2444        auto CommandOrErr =
2445          getStructOrErr<MachO::dylib_command>(*this, Libraries[i]);
2446        if (!CommandOrErr)
2447          return object_error::parse_failed;
2448        MachO::dylib_command D = CommandOrErr.get();
2449        if (D.dylib.name >= D.cmdsize)
2450          return object_error::parse_failed;
2451        const char *P = (const char *)(Libraries[i]) + D.dylib.name;
2452        StringRef Name = StringRef(P);
2453        if (D.dylib.name+Name.size() >= D.cmdsize)
2454          return object_error::parse_failed;
2455        StringRef Suffix;
2456        bool isFramework;
2457        StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
2458        if (shortName.empty())
2459          LibrariesShortNames.push_back(Name);
2460        else
2461          LibrariesShortNames.push_back(shortName);
2462      }
2463    }
2464  
2465    Res = LibrariesShortNames[Index];
2466    return std::error_code();
2467  }
2468  
getLibraryCount() const2469  uint32_t MachOObjectFile::getLibraryCount() const {
2470    return Libraries.size();
2471  }
2472  
2473  section_iterator
getRelocationRelocatedSection(relocation_iterator Rel) const2474  MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2475    DataRefImpl Sec;
2476    Sec.d.a = Rel->getRawDataRefImpl().d.a;
2477    return section_iterator(SectionRef(Sec, this));
2478  }
2479  
symbol_begin() const2480  basic_symbol_iterator MachOObjectFile::symbol_begin() const {
2481    DataRefImpl DRI;
2482    MachO::symtab_command Symtab = getSymtabLoadCommand();
2483    if (!SymtabLoadCmd || Symtab.nsyms == 0)
2484      return basic_symbol_iterator(SymbolRef(DRI, this));
2485  
2486    return getSymbolByIndex(0);
2487  }
2488  
symbol_end() const2489  basic_symbol_iterator MachOObjectFile::symbol_end() const {
2490    DataRefImpl DRI;
2491    MachO::symtab_command Symtab = getSymtabLoadCommand();
2492    if (!SymtabLoadCmd || Symtab.nsyms == 0)
2493      return basic_symbol_iterator(SymbolRef(DRI, this));
2494  
2495    unsigned SymbolTableEntrySize = is64Bit() ?
2496      sizeof(MachO::nlist_64) :
2497      sizeof(MachO::nlist);
2498    unsigned Offset = Symtab.symoff +
2499      Symtab.nsyms * SymbolTableEntrySize;
2500    DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2501    return basic_symbol_iterator(SymbolRef(DRI, this));
2502  }
2503  
getSymbolByIndex(unsigned Index) const2504  symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
2505    MachO::symtab_command Symtab = getSymtabLoadCommand();
2506    if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2507      report_fatal_error("Requested symbol index is out of range.");
2508    unsigned SymbolTableEntrySize =
2509      is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2510    DataRefImpl DRI;
2511    DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2512    DRI.p += Index * SymbolTableEntrySize;
2513    return basic_symbol_iterator(SymbolRef(DRI, this));
2514  }
2515  
getSymbolIndex(DataRefImpl Symb) const2516  uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2517    MachO::symtab_command Symtab = getSymtabLoadCommand();
2518    if (!SymtabLoadCmd)
2519      report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2520    unsigned SymbolTableEntrySize =
2521      is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2522    DataRefImpl DRIstart;
2523    DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2524    uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2525    return Index;
2526  }
2527  
section_begin() const2528  section_iterator MachOObjectFile::section_begin() const {
2529    DataRefImpl DRI;
2530    return section_iterator(SectionRef(DRI, this));
2531  }
2532  
section_end() const2533  section_iterator MachOObjectFile::section_end() const {
2534    DataRefImpl DRI;
2535    DRI.d.a = Sections.size();
2536    return section_iterator(SectionRef(DRI, this));
2537  }
2538  
getBytesInAddress() const2539  uint8_t MachOObjectFile::getBytesInAddress() const {
2540    return is64Bit() ? 8 : 4;
2541  }
2542  
getFileFormatName() const2543  StringRef MachOObjectFile::getFileFormatName() const {
2544    unsigned CPUType = getCPUType(*this);
2545    if (!is64Bit()) {
2546      switch (CPUType) {
2547      case MachO::CPU_TYPE_I386:
2548        return "Mach-O 32-bit i386";
2549      case MachO::CPU_TYPE_ARM:
2550        return "Mach-O arm";
2551      case MachO::CPU_TYPE_ARM64_32:
2552        return "Mach-O arm64 (ILP32)";
2553      case MachO::CPU_TYPE_POWERPC:
2554        return "Mach-O 32-bit ppc";
2555      default:
2556        return "Mach-O 32-bit unknown";
2557      }
2558    }
2559  
2560    switch (CPUType) {
2561    case MachO::CPU_TYPE_X86_64:
2562      return "Mach-O 64-bit x86-64";
2563    case MachO::CPU_TYPE_ARM64:
2564      return "Mach-O arm64";
2565    case MachO::CPU_TYPE_POWERPC64:
2566      return "Mach-O 64-bit ppc64";
2567    default:
2568      return "Mach-O 64-bit unknown";
2569    }
2570  }
2571  
getArch(uint32_t CPUType,uint32_t CPUSubType)2572  Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
2573    switch (CPUType) {
2574    case MachO::CPU_TYPE_I386:
2575      return Triple::x86;
2576    case MachO::CPU_TYPE_X86_64:
2577      return Triple::x86_64;
2578    case MachO::CPU_TYPE_ARM:
2579      return Triple::arm;
2580    case MachO::CPU_TYPE_ARM64:
2581      return Triple::aarch64;
2582    case MachO::CPU_TYPE_ARM64_32:
2583      return Triple::aarch64_32;
2584    case MachO::CPU_TYPE_POWERPC:
2585      return Triple::ppc;
2586    case MachO::CPU_TYPE_POWERPC64:
2587      return Triple::ppc64;
2588    default:
2589      return Triple::UnknownArch;
2590    }
2591  }
2592  
getArchTriple(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,const char ** ArchFlag)2593  Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2594                                        const char **McpuDefault,
2595                                        const char **ArchFlag) {
2596    if (McpuDefault)
2597      *McpuDefault = nullptr;
2598    if (ArchFlag)
2599      *ArchFlag = nullptr;
2600  
2601    switch (CPUType) {
2602    case MachO::CPU_TYPE_I386:
2603      switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2604      case MachO::CPU_SUBTYPE_I386_ALL:
2605        if (ArchFlag)
2606          *ArchFlag = "i386";
2607        return Triple("i386-apple-darwin");
2608      default:
2609        return Triple();
2610      }
2611    case MachO::CPU_TYPE_X86_64:
2612      switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2613      case MachO::CPU_SUBTYPE_X86_64_ALL:
2614        if (ArchFlag)
2615          *ArchFlag = "x86_64";
2616        return Triple("x86_64-apple-darwin");
2617      case MachO::CPU_SUBTYPE_X86_64_H:
2618        if (ArchFlag)
2619          *ArchFlag = "x86_64h";
2620        return Triple("x86_64h-apple-darwin");
2621      default:
2622        return Triple();
2623      }
2624    case MachO::CPU_TYPE_ARM:
2625      switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2626      case MachO::CPU_SUBTYPE_ARM_V4T:
2627        if (ArchFlag)
2628          *ArchFlag = "armv4t";
2629        return Triple("armv4t-apple-darwin");
2630      case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2631        if (ArchFlag)
2632          *ArchFlag = "armv5e";
2633        return Triple("armv5e-apple-darwin");
2634      case MachO::CPU_SUBTYPE_ARM_XSCALE:
2635        if (ArchFlag)
2636          *ArchFlag = "xscale";
2637        return Triple("xscale-apple-darwin");
2638      case MachO::CPU_SUBTYPE_ARM_V6:
2639        if (ArchFlag)
2640          *ArchFlag = "armv6";
2641        return Triple("armv6-apple-darwin");
2642      case MachO::CPU_SUBTYPE_ARM_V6M:
2643        if (McpuDefault)
2644          *McpuDefault = "cortex-m0";
2645        if (ArchFlag)
2646          *ArchFlag = "armv6m";
2647        return Triple("armv6m-apple-darwin");
2648      case MachO::CPU_SUBTYPE_ARM_V7:
2649        if (ArchFlag)
2650          *ArchFlag = "armv7";
2651        return Triple("armv7-apple-darwin");
2652      case MachO::CPU_SUBTYPE_ARM_V7EM:
2653        if (McpuDefault)
2654          *McpuDefault = "cortex-m4";
2655        if (ArchFlag)
2656          *ArchFlag = "armv7em";
2657        return Triple("thumbv7em-apple-darwin");
2658      case MachO::CPU_SUBTYPE_ARM_V7K:
2659        if (McpuDefault)
2660          *McpuDefault = "cortex-a7";
2661        if (ArchFlag)
2662          *ArchFlag = "armv7k";
2663        return Triple("armv7k-apple-darwin");
2664      case MachO::CPU_SUBTYPE_ARM_V7M:
2665        if (McpuDefault)
2666          *McpuDefault = "cortex-m3";
2667        if (ArchFlag)
2668          *ArchFlag = "armv7m";
2669        return Triple("thumbv7m-apple-darwin");
2670      case MachO::CPU_SUBTYPE_ARM_V7S:
2671        if (McpuDefault)
2672          *McpuDefault = "cortex-a7";
2673        if (ArchFlag)
2674          *ArchFlag = "armv7s";
2675        return Triple("armv7s-apple-darwin");
2676      default:
2677        return Triple();
2678      }
2679    case MachO::CPU_TYPE_ARM64:
2680      switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2681      case MachO::CPU_SUBTYPE_ARM64_ALL:
2682        if (McpuDefault)
2683          *McpuDefault = "cyclone";
2684        if (ArchFlag)
2685          *ArchFlag = "arm64";
2686        return Triple("arm64-apple-darwin");
2687      default:
2688        return Triple();
2689      }
2690    case MachO::CPU_TYPE_ARM64_32:
2691      switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2692      case MachO::CPU_SUBTYPE_ARM64_32_V8:
2693        if (McpuDefault)
2694          *McpuDefault = "cyclone";
2695        if (ArchFlag)
2696          *ArchFlag = "arm64_32";
2697        return Triple("arm64_32-apple-darwin");
2698      default:
2699        return Triple();
2700      }
2701    case MachO::CPU_TYPE_POWERPC:
2702      switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2703      case MachO::CPU_SUBTYPE_POWERPC_ALL:
2704        if (ArchFlag)
2705          *ArchFlag = "ppc";
2706        return Triple("ppc-apple-darwin");
2707      default:
2708        return Triple();
2709      }
2710    case MachO::CPU_TYPE_POWERPC64:
2711      switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2712      case MachO::CPU_SUBTYPE_POWERPC_ALL:
2713        if (ArchFlag)
2714          *ArchFlag = "ppc64";
2715        return Triple("ppc64-apple-darwin");
2716      default:
2717        return Triple();
2718      }
2719    default:
2720      return Triple();
2721    }
2722  }
2723  
getHostArch()2724  Triple MachOObjectFile::getHostArch() {
2725    return Triple(sys::getDefaultTargetTriple());
2726  }
2727  
isValidArch(StringRef ArchFlag)2728  bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2729    auto validArchs = getValidArchs();
2730    return llvm::find(validArchs, ArchFlag) != validArchs.end();
2731  }
2732  
getValidArchs()2733  ArrayRef<StringRef> MachOObjectFile::getValidArchs() {
2734    static const std::array<StringRef, 17> validArchs = {{
2735        "i386",   "x86_64", "x86_64h",  "armv4t",  "arm",    "armv5e",
2736        "armv6",  "armv6m", "armv7",    "armv7em", "armv7k", "armv7m",
2737        "armv7s", "arm64",  "arm64_32", "ppc",     "ppc64",
2738    }};
2739  
2740    return validArchs;
2741  }
2742  
getArch() const2743  Triple::ArchType MachOObjectFile::getArch() const {
2744    return getArch(getCPUType(*this), getCPUSubType(*this));
2745  }
2746  
getArchTriple(const char ** McpuDefault) const2747  Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2748    return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2749  }
2750  
section_rel_begin(unsigned Index) const2751  relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2752    DataRefImpl DRI;
2753    DRI.d.a = Index;
2754    return section_rel_begin(DRI);
2755  }
2756  
section_rel_end(unsigned Index) const2757  relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2758    DataRefImpl DRI;
2759    DRI.d.a = Index;
2760    return section_rel_end(DRI);
2761  }
2762  
begin_dices() const2763  dice_iterator MachOObjectFile::begin_dices() const {
2764    DataRefImpl DRI;
2765    if (!DataInCodeLoadCmd)
2766      return dice_iterator(DiceRef(DRI, this));
2767  
2768    MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2769    DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2770    return dice_iterator(DiceRef(DRI, this));
2771  }
2772  
end_dices() const2773  dice_iterator MachOObjectFile::end_dices() const {
2774    DataRefImpl DRI;
2775    if (!DataInCodeLoadCmd)
2776      return dice_iterator(DiceRef(DRI, this));
2777  
2778    MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2779    unsigned Offset = DicLC.dataoff + DicLC.datasize;
2780    DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2781    return dice_iterator(DiceRef(DRI, this));
2782  }
2783  
ExportEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> T)2784  ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2785                           ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
2786  
moveToFirst()2787  void ExportEntry::moveToFirst() {
2788    ErrorAsOutParameter ErrAsOutParam(E);
2789    pushNode(0);
2790    if (*E)
2791      return;
2792    pushDownUntilBottom();
2793  }
2794  
moveToEnd()2795  void ExportEntry::moveToEnd() {
2796    Stack.clear();
2797    Done = true;
2798  }
2799  
operator ==(const ExportEntry & Other) const2800  bool ExportEntry::operator==(const ExportEntry &Other) const {
2801    // Common case, one at end, other iterating from begin.
2802    if (Done || Other.Done)
2803      return (Done == Other.Done);
2804    // Not equal if different stack sizes.
2805    if (Stack.size() != Other.Stack.size())
2806      return false;
2807    // Not equal if different cumulative strings.
2808    if (!CumulativeString.equals(Other.CumulativeString))
2809      return false;
2810    // Equal if all nodes in both stacks match.
2811    for (unsigned i=0; i < Stack.size(); ++i) {
2812      if (Stack[i].Start != Other.Stack[i].Start)
2813        return false;
2814    }
2815    return true;
2816  }
2817  
readULEB128(const uint8_t * & Ptr,const char ** error)2818  uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
2819    unsigned Count;
2820    uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
2821    Ptr += Count;
2822    if (Ptr > Trie.end())
2823      Ptr = Trie.end();
2824    return Result;
2825  }
2826  
name() const2827  StringRef ExportEntry::name() const {
2828    return CumulativeString;
2829  }
2830  
flags() const2831  uint64_t ExportEntry::flags() const {
2832    return Stack.back().Flags;
2833  }
2834  
address() const2835  uint64_t ExportEntry::address() const {
2836    return Stack.back().Address;
2837  }
2838  
other() const2839  uint64_t ExportEntry::other() const {
2840    return Stack.back().Other;
2841  }
2842  
otherName() const2843  StringRef ExportEntry::otherName() const {
2844    const char* ImportName = Stack.back().ImportName;
2845    if (ImportName)
2846      return StringRef(ImportName);
2847    return StringRef();
2848  }
2849  
nodeOffset() const2850  uint32_t ExportEntry::nodeOffset() const {
2851    return Stack.back().Start - Trie.begin();
2852  }
2853  
NodeState(const uint8_t * Ptr)2854  ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2855      : Start(Ptr), Current(Ptr) {}
2856  
pushNode(uint64_t offset)2857  void ExportEntry::pushNode(uint64_t offset) {
2858    ErrorAsOutParameter ErrAsOutParam(E);
2859    const uint8_t *Ptr = Trie.begin() + offset;
2860    NodeState State(Ptr);
2861    const char *error;
2862    uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2863    if (error) {
2864      *E = malformedError("export info size " + Twine(error) +
2865                          " in export trie data at node: 0x" +
2866                          Twine::utohexstr(offset));
2867      moveToEnd();
2868      return;
2869    }
2870    State.IsExportNode = (ExportInfoSize != 0);
2871    const uint8_t* Children = State.Current + ExportInfoSize;
2872    if (Children > Trie.end()) {
2873      *E = malformedError(
2874          "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
2875          " in export trie data at node: 0x" + Twine::utohexstr(offset) +
2876          " too big and extends past end of trie data");
2877      moveToEnd();
2878      return;
2879    }
2880    if (State.IsExportNode) {
2881      const uint8_t *ExportStart = State.Current;
2882      State.Flags = readULEB128(State.Current, &error);
2883      if (error) {
2884        *E = malformedError("flags " + Twine(error) +
2885                            " in export trie data at node: 0x" +
2886                            Twine::utohexstr(offset));
2887        moveToEnd();
2888        return;
2889      }
2890      uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2891      if (State.Flags != 0 &&
2892          (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
2893           Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
2894           Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
2895        *E = malformedError(
2896            "unsupported exported symbol kind: " + Twine((int)Kind) +
2897            " in flags: 0x" + Twine::utohexstr(State.Flags) +
2898            " in export trie data at node: 0x" + Twine::utohexstr(offset));
2899        moveToEnd();
2900        return;
2901      }
2902      if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2903        State.Address = 0;
2904        State.Other = readULEB128(State.Current, &error); // dylib ordinal
2905        if (error) {
2906          *E = malformedError("dylib ordinal of re-export " + Twine(error) +
2907                              " in export trie data at node: 0x" +
2908                              Twine::utohexstr(offset));
2909          moveToEnd();
2910          return;
2911        }
2912        if (O != nullptr) {
2913          if (State.Other > O->getLibraryCount()) {
2914            *E = malformedError(
2915                "bad library ordinal: " + Twine((int)State.Other) + " (max " +
2916                Twine((int)O->getLibraryCount()) +
2917                ") in export trie data at node: 0x" + Twine::utohexstr(offset));
2918            moveToEnd();
2919            return;
2920          }
2921        }
2922        State.ImportName = reinterpret_cast<const char*>(State.Current);
2923        if (*State.ImportName == '\0') {
2924          State.Current++;
2925        } else {
2926          const uint8_t *End = State.Current + 1;
2927          if (End >= Trie.end()) {
2928            *E = malformedError("import name of re-export in export trie data at "
2929                                "node: 0x" +
2930                                Twine::utohexstr(offset) +
2931                                " starts past end of trie data");
2932            moveToEnd();
2933            return;
2934          }
2935          while(*End != '\0' && End < Trie.end())
2936            End++;
2937          if (*End != '\0') {
2938            *E = malformedError("import name of re-export in export trie data at "
2939                                "node: 0x" +
2940                                Twine::utohexstr(offset) +
2941                                " extends past end of trie data");
2942            moveToEnd();
2943            return;
2944          }
2945          State.Current = End + 1;
2946        }
2947      } else {
2948        State.Address = readULEB128(State.Current, &error);
2949        if (error) {
2950          *E = malformedError("address " + Twine(error) +
2951                              " in export trie data at node: 0x" +
2952                              Twine::utohexstr(offset));
2953          moveToEnd();
2954          return;
2955        }
2956        if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2957          State.Other = readULEB128(State.Current, &error);
2958          if (error) {
2959            *E = malformedError("resolver of stub and resolver " + Twine(error) +
2960                                " in export trie data at node: 0x" +
2961                                Twine::utohexstr(offset));
2962            moveToEnd();
2963            return;
2964          }
2965        }
2966      }
2967      if(ExportStart + ExportInfoSize != State.Current) {
2968        *E = malformedError(
2969            "inconsistant export info size: 0x" +
2970            Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2971            Twine::utohexstr(State.Current - ExportStart) +
2972            " in export trie data at node: 0x" + Twine::utohexstr(offset));
2973        moveToEnd();
2974        return;
2975      }
2976    }
2977    State.ChildCount = *Children;
2978    if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
2979      *E = malformedError("byte for count of childern in export trie data at "
2980                          "node: 0x" +
2981                          Twine::utohexstr(offset) +
2982                          " extends past end of trie data");
2983      moveToEnd();
2984      return;
2985    }
2986    State.Current = Children + 1;
2987    State.NextChildIndex = 0;
2988    State.ParentStringLength = CumulativeString.size();
2989    Stack.push_back(State);
2990  }
2991  
pushDownUntilBottom()2992  void ExportEntry::pushDownUntilBottom() {
2993    ErrorAsOutParameter ErrAsOutParam(E);
2994    const char *error;
2995    while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2996      NodeState &Top = Stack.back();
2997      CumulativeString.resize(Top.ParentStringLength);
2998      for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
2999        char C = *Top.Current;
3000        CumulativeString.push_back(C);
3001      }
3002      if (Top.Current >= Trie.end()) {
3003        *E = malformedError("edge sub-string in export trie data at node: 0x" +
3004                            Twine::utohexstr(Top.Start - Trie.begin()) +
3005                            " for child #" + Twine((int)Top.NextChildIndex) +
3006                            " extends past end of trie data");
3007        moveToEnd();
3008        return;
3009      }
3010      Top.Current += 1;
3011      uint64_t childNodeIndex = readULEB128(Top.Current, &error);
3012      if (error) {
3013        *E = malformedError("child node offset " + Twine(error) +
3014                            " in export trie data at node: 0x" +
3015                            Twine::utohexstr(Top.Start - Trie.begin()));
3016        moveToEnd();
3017        return;
3018      }
3019      for (const NodeState &node : nodes()) {
3020        if (node.Start == Trie.begin() + childNodeIndex){
3021          *E = malformedError("loop in childern in export trie data at node: 0x" +
3022                              Twine::utohexstr(Top.Start - Trie.begin()) +
3023                              " back to node: 0x" +
3024                              Twine::utohexstr(childNodeIndex));
3025          moveToEnd();
3026          return;
3027        }
3028      }
3029      Top.NextChildIndex += 1;
3030      pushNode(childNodeIndex);
3031      if (*E)
3032        return;
3033    }
3034    if (!Stack.back().IsExportNode) {
3035      *E = malformedError("node is not an export node in export trie data at "
3036                          "node: 0x" +
3037                          Twine::utohexstr(Stack.back().Start - Trie.begin()));
3038      moveToEnd();
3039      return;
3040    }
3041  }
3042  
3043  // We have a trie data structure and need a way to walk it that is compatible
3044  // with the C++ iterator model. The solution is a non-recursive depth first
3045  // traversal where the iterator contains a stack of parent nodes along with a
3046  // string that is the accumulation of all edge strings along the parent chain
3047  // to this point.
3048  //
3049  // There is one "export" node for each exported symbol.  But because some
3050  // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
3051  // node may have child nodes too.
3052  //
3053  // The algorithm for moveNext() is to keep moving down the leftmost unvisited
3054  // child until hitting a node with no children (which is an export node or
3055  // else the trie is malformed). On the way down, each node is pushed on the
3056  // stack ivar.  If there is no more ways down, it pops up one and tries to go
3057  // down a sibling path until a childless node is reached.
moveNext()3058  void ExportEntry::moveNext() {
3059    assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
3060    if (!Stack.back().IsExportNode) {
3061      *E = malformedError("node is not an export node in export trie data at "
3062                          "node: 0x" +
3063                          Twine::utohexstr(Stack.back().Start - Trie.begin()));
3064      moveToEnd();
3065      return;
3066    }
3067  
3068    Stack.pop_back();
3069    while (!Stack.empty()) {
3070      NodeState &Top = Stack.back();
3071      if (Top.NextChildIndex < Top.ChildCount) {
3072        pushDownUntilBottom();
3073        // Now at the next export node.
3074        return;
3075      } else {
3076        if (Top.IsExportNode) {
3077          // This node has no children but is itself an export node.
3078          CumulativeString.resize(Top.ParentStringLength);
3079          return;
3080        }
3081        Stack.pop_back();
3082      }
3083    }
3084    Done = true;
3085  }
3086  
3087  iterator_range<export_iterator>
exports(Error & E,ArrayRef<uint8_t> Trie,const MachOObjectFile * O)3088  MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
3089                           const MachOObjectFile *O) {
3090    ExportEntry Start(&E, O, Trie);
3091    if (Trie.empty())
3092      Start.moveToEnd();
3093    else
3094      Start.moveToFirst();
3095  
3096    ExportEntry Finish(&E, O, Trie);
3097    Finish.moveToEnd();
3098  
3099    return make_range(export_iterator(Start), export_iterator(Finish));
3100  }
3101  
exports(Error & Err) const3102  iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3103    return exports(Err, getDyldInfoExportsTrie(), this);
3104  }
3105  
MachORebaseEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit)3106  MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
3107                                     ArrayRef<uint8_t> Bytes, bool is64Bit)
3108      : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3109        PointerSize(is64Bit ? 8 : 4) {}
3110  
moveToFirst()3111  void MachORebaseEntry::moveToFirst() {
3112    Ptr = Opcodes.begin();
3113    moveNext();
3114  }
3115  
moveToEnd()3116  void MachORebaseEntry::moveToEnd() {
3117    Ptr = Opcodes.end();
3118    RemainingLoopCount = 0;
3119    Done = true;
3120  }
3121  
moveNext()3122  void MachORebaseEntry::moveNext() {
3123    ErrorAsOutParameter ErrAsOutParam(E);
3124    // If in the middle of some loop, move to next rebasing in loop.
3125    SegmentOffset += AdvanceAmount;
3126    if (RemainingLoopCount) {
3127      --RemainingLoopCount;
3128      return;
3129    }
3130    // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3131    // pointer size. Therefore it is possible to reach the end without ever having
3132    // seen REBASE_OPCODE_DONE.
3133    if (Ptr == Opcodes.end()) {
3134      Done = true;
3135      return;
3136    }
3137    bool More = true;
3138    while (More) {
3139      // Parse next opcode and set up next loop.
3140      const uint8_t *OpcodeStart = Ptr;
3141      uint8_t Byte = *Ptr++;
3142      uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
3143      uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
3144      uint32_t Count, Skip;
3145      const char *error = nullptr;
3146      switch (Opcode) {
3147      case MachO::REBASE_OPCODE_DONE:
3148        More = false;
3149        Done = true;
3150        moveToEnd();
3151        DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3152        break;
3153      case MachO::REBASE_OPCODE_SET_TYPE_IMM:
3154        RebaseType = ImmValue;
3155        if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
3156          *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3157                              Twine((int)RebaseType) + " for opcode at: 0x" +
3158                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3159          moveToEnd();
3160          return;
3161        }
3162        DEBUG_WITH_TYPE(
3163            "mach-o-rebase",
3164            dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3165                   << "RebaseType=" << (int) RebaseType << "\n");
3166        break;
3167      case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3168        SegmentIndex = ImmValue;
3169        SegmentOffset = readULEB128(&error);
3170        if (error) {
3171          *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3172                              Twine(error) + " for opcode at: 0x" +
3173                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3174          moveToEnd();
3175          return;
3176        }
3177        error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3178                                                 PointerSize);
3179        if (error) {
3180          *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3181                              Twine(error) + " for opcode at: 0x" +
3182                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3183          moveToEnd();
3184          return;
3185        }
3186        DEBUG_WITH_TYPE(
3187            "mach-o-rebase",
3188            dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3189                   << "SegmentIndex=" << SegmentIndex << ", "
3190                   << format("SegmentOffset=0x%06X", SegmentOffset)
3191                   << "\n");
3192        break;
3193      case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
3194        SegmentOffset += readULEB128(&error);
3195        if (error) {
3196          *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3197                              " for opcode at: 0x" +
3198                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3199          moveToEnd();
3200          return;
3201        }
3202        error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3203                                                 PointerSize);
3204        if (error) {
3205          *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3206                              " for opcode at: 0x" +
3207                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3208          moveToEnd();
3209          return;
3210        }
3211        DEBUG_WITH_TYPE("mach-o-rebase",
3212                        dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3213                               << format("SegmentOffset=0x%06X",
3214                                         SegmentOffset) << "\n");
3215        break;
3216      case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
3217        error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3218                                                 PointerSize);
3219        if (error) {
3220          *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3221                              Twine(error) + " for opcode at: 0x" +
3222                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3223          moveToEnd();
3224          return;
3225        }
3226        SegmentOffset += ImmValue * PointerSize;
3227        error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3228                                                 PointerSize);
3229        if (error) {
3230          *E =
3231              malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3232                             " (after adding immediate times the pointer size) " +
3233                             Twine(error) + " for opcode at: 0x" +
3234                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3235          moveToEnd();
3236          return;
3237        }
3238        DEBUG_WITH_TYPE("mach-o-rebase",
3239                        dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3240                               << format("SegmentOffset=0x%06X",
3241                                         SegmentOffset) << "\n");
3242        break;
3243      case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
3244        AdvanceAmount = PointerSize;
3245        Skip = 0;
3246        Count = ImmValue;
3247        if (ImmValue != 0)
3248          RemainingLoopCount = ImmValue - 1;
3249        else
3250          RemainingLoopCount = 0;
3251        error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3252                                                 PointerSize, Count, Skip);
3253        if (error) {
3254          *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3255                              Twine(error) + " for opcode at: 0x" +
3256                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3257          moveToEnd();
3258          return;
3259        }
3260        DEBUG_WITH_TYPE(
3261            "mach-o-rebase",
3262            dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3263                   << format("SegmentOffset=0x%06X", SegmentOffset)
3264                   << ", AdvanceAmount=" << AdvanceAmount
3265                   << ", RemainingLoopCount=" << RemainingLoopCount
3266                   << "\n");
3267        return;
3268      case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
3269        AdvanceAmount = PointerSize;
3270        Skip = 0;
3271        Count = readULEB128(&error);
3272        if (error) {
3273          *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3274                              Twine(error) + " for opcode at: 0x" +
3275                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3276          moveToEnd();
3277          return;
3278        }
3279        if (Count != 0)
3280          RemainingLoopCount = Count - 1;
3281        else
3282          RemainingLoopCount = 0;
3283        error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3284                                                 PointerSize, Count, Skip);
3285        if (error) {
3286          *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3287                              Twine(error) + " for opcode at: 0x" +
3288                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3289          moveToEnd();
3290          return;
3291        }
3292        DEBUG_WITH_TYPE(
3293            "mach-o-rebase",
3294            dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3295                   << format("SegmentOffset=0x%06X", SegmentOffset)
3296                   << ", AdvanceAmount=" << AdvanceAmount
3297                   << ", RemainingLoopCount=" << RemainingLoopCount
3298                   << "\n");
3299        return;
3300      case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
3301        Skip = readULEB128(&error);
3302        if (error) {
3303          *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3304                              Twine(error) + " for opcode at: 0x" +
3305                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3306          moveToEnd();
3307          return;
3308        }
3309        AdvanceAmount = Skip + PointerSize;
3310        Count = 1;
3311        RemainingLoopCount = 0;
3312        error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3313                                                 PointerSize, Count, Skip);
3314        if (error) {
3315          *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3316                              Twine(error) + " for opcode at: 0x" +
3317                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3318          moveToEnd();
3319          return;
3320        }
3321        DEBUG_WITH_TYPE(
3322            "mach-o-rebase",
3323            dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3324                   << format("SegmentOffset=0x%06X", SegmentOffset)
3325                   << ", AdvanceAmount=" << AdvanceAmount
3326                   << ", RemainingLoopCount=" << RemainingLoopCount
3327                   << "\n");
3328        return;
3329      case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
3330        Count = readULEB128(&error);
3331        if (error) {
3332          *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3333                              "ULEB " +
3334                              Twine(error) + " for opcode at: 0x" +
3335                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3336          moveToEnd();
3337          return;
3338        }
3339        if (Count != 0)
3340          RemainingLoopCount = Count - 1;
3341        else
3342          RemainingLoopCount = 0;
3343        Skip = readULEB128(&error);
3344        if (error) {
3345          *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3346                              "ULEB " +
3347                              Twine(error) + " for opcode at: 0x" +
3348                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3349          moveToEnd();
3350          return;
3351        }
3352        AdvanceAmount = Skip + PointerSize;
3353  
3354        error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3355                                                 PointerSize, Count, Skip);
3356        if (error) {
3357          *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3358                              "ULEB " +
3359                              Twine(error) + " for opcode at: 0x" +
3360                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3361          moveToEnd();
3362          return;
3363        }
3364        DEBUG_WITH_TYPE(
3365            "mach-o-rebase",
3366            dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3367                   << format("SegmentOffset=0x%06X", SegmentOffset)
3368                   << ", AdvanceAmount=" << AdvanceAmount
3369                   << ", RemainingLoopCount=" << RemainingLoopCount
3370                   << "\n");
3371        return;
3372      default:
3373        *E = malformedError("bad rebase info (bad opcode value 0x" +
3374                            Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3375                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3376        moveToEnd();
3377        return;
3378      }
3379    }
3380  }
3381  
readULEB128(const char ** error)3382  uint64_t MachORebaseEntry::readULEB128(const char **error) {
3383    unsigned Count;
3384    uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3385    Ptr += Count;
3386    if (Ptr > Opcodes.end())
3387      Ptr = Opcodes.end();
3388    return Result;
3389  }
3390  
segmentIndex() const3391  int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
3392  
segmentOffset() const3393  uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3394  
typeName() const3395  StringRef MachORebaseEntry::typeName() const {
3396    switch (RebaseType) {
3397    case MachO::REBASE_TYPE_POINTER:
3398      return "pointer";
3399    case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3400      return "text abs32";
3401    case MachO::REBASE_TYPE_TEXT_PCREL32:
3402      return "text rel32";
3403    }
3404    return "unknown";
3405  }
3406  
3407  // For use with the SegIndex of a checked Mach-O Rebase entry
3408  // to get the segment name.
segmentName() const3409  StringRef MachORebaseEntry::segmentName() const {
3410    return O->BindRebaseSegmentName(SegmentIndex);
3411  }
3412  
3413  // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3414  // to get the section name.
sectionName() const3415  StringRef MachORebaseEntry::sectionName() const {
3416    return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3417  }
3418  
3419  // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3420  // to get the address.
address() const3421  uint64_t MachORebaseEntry::address() const {
3422    return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3423  }
3424  
operator ==(const MachORebaseEntry & Other) const3425  bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
3426  #ifdef EXPENSIVE_CHECKS
3427    assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3428  #else
3429    assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3430  #endif
3431    return (Ptr == Other.Ptr) &&
3432           (RemainingLoopCount == Other.RemainingLoopCount) &&
3433           (Done == Other.Done);
3434  }
3435  
3436  iterator_range<rebase_iterator>
rebaseTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64)3437  MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3438                               ArrayRef<uint8_t> Opcodes, bool is64) {
3439    if (O->BindRebaseSectionTable == nullptr)
3440      O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
3441    MachORebaseEntry Start(&Err, O, Opcodes, is64);
3442    Start.moveToFirst();
3443  
3444    MachORebaseEntry Finish(&Err, O, Opcodes, is64);
3445    Finish.moveToEnd();
3446  
3447    return make_range(rebase_iterator(Start), rebase_iterator(Finish));
3448  }
3449  
rebaseTable(Error & Err)3450  iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3451    return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
3452  }
3453  
MachOBindEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)3454  MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3455                                 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
3456      : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3457        PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
3458  
moveToFirst()3459  void MachOBindEntry::moveToFirst() {
3460    Ptr = Opcodes.begin();
3461    moveNext();
3462  }
3463  
moveToEnd()3464  void MachOBindEntry::moveToEnd() {
3465    Ptr = Opcodes.end();
3466    RemainingLoopCount = 0;
3467    Done = true;
3468  }
3469  
moveNext()3470  void MachOBindEntry::moveNext() {
3471    ErrorAsOutParameter ErrAsOutParam(E);
3472    // If in the middle of some loop, move to next binding in loop.
3473    SegmentOffset += AdvanceAmount;
3474    if (RemainingLoopCount) {
3475      --RemainingLoopCount;
3476      return;
3477    }
3478    // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3479    // pointer size. Therefore it is possible to reach the end without ever having
3480    // seen BIND_OPCODE_DONE.
3481    if (Ptr == Opcodes.end()) {
3482      Done = true;
3483      return;
3484    }
3485    bool More = true;
3486    while (More) {
3487      // Parse next opcode and set up next loop.
3488      const uint8_t *OpcodeStart = Ptr;
3489      uint8_t Byte = *Ptr++;
3490      uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3491      uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3492      int8_t SignExtended;
3493      const uint8_t *SymStart;
3494      uint32_t Count, Skip;
3495      const char *error = nullptr;
3496      switch (Opcode) {
3497      case MachO::BIND_OPCODE_DONE:
3498        if (TableKind == Kind::Lazy) {
3499          // Lazying bindings have a DONE opcode between entries.  Need to ignore
3500          // it to advance to next entry.  But need not if this is last entry.
3501          bool NotLastEntry = false;
3502          for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3503            if (*P) {
3504              NotLastEntry = true;
3505            }
3506          }
3507          if (NotLastEntry)
3508            break;
3509        }
3510        More = false;
3511        moveToEnd();
3512        DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3513        break;
3514      case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
3515        if (TableKind == Kind::Weak) {
3516          *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3517                              "weak bind table for opcode at: 0x" +
3518                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3519          moveToEnd();
3520          return;
3521        }
3522        Ordinal = ImmValue;
3523        LibraryOrdinalSet = true;
3524        if (ImmValue > O->getLibraryCount()) {
3525          *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3526                              "library ordinal: " +
3527                              Twine((int)ImmValue) + " (max " +
3528                              Twine((int)O->getLibraryCount()) +
3529                              ") for opcode at: 0x" +
3530                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3531          moveToEnd();
3532          return;
3533        }
3534        DEBUG_WITH_TYPE(
3535            "mach-o-bind",
3536            dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3537                   << "Ordinal=" << Ordinal << "\n");
3538        break;
3539      case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
3540        if (TableKind == Kind::Weak) {
3541          *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3542                              "weak bind table for opcode at: 0x" +
3543                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3544          moveToEnd();
3545          return;
3546        }
3547        Ordinal = readULEB128(&error);
3548        LibraryOrdinalSet = true;
3549        if (error) {
3550          *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3551                              Twine(error) + " for opcode at: 0x" +
3552                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3553          moveToEnd();
3554          return;
3555        }
3556        if (Ordinal > (int)O->getLibraryCount()) {
3557          *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3558                              "library ordinal: " +
3559                              Twine((int)Ordinal) + " (max " +
3560                              Twine((int)O->getLibraryCount()) +
3561                              ") for opcode at: 0x" +
3562                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3563          moveToEnd();
3564          return;
3565        }
3566        DEBUG_WITH_TYPE(
3567            "mach-o-bind",
3568            dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3569                   << "Ordinal=" << Ordinal << "\n");
3570        break;
3571      case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
3572        if (TableKind == Kind::Weak) {
3573          *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3574                              "weak bind table for opcode at: 0x" +
3575                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3576          moveToEnd();
3577          return;
3578        }
3579        if (ImmValue) {
3580          SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3581          Ordinal = SignExtended;
3582          if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3583            *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3584                                "special ordinal: " +
3585                                Twine((int)Ordinal) + " for opcode at: 0x" +
3586                                Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3587            moveToEnd();
3588            return;
3589          }
3590        } else
3591          Ordinal = 0;
3592        LibraryOrdinalSet = true;
3593        DEBUG_WITH_TYPE(
3594            "mach-o-bind",
3595            dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3596                   << "Ordinal=" << Ordinal << "\n");
3597        break;
3598      case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3599        Flags = ImmValue;
3600        SymStart = Ptr;
3601        while (*Ptr && (Ptr < Opcodes.end())) {
3602          ++Ptr;
3603        }
3604        if (Ptr == Opcodes.end()) {
3605          *E = malformedError(
3606              "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3607              "symbol name extends past opcodes for opcode at: 0x" +
3608              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3609          moveToEnd();
3610          return;
3611        }
3612        SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3613                               Ptr-SymStart);
3614        ++Ptr;
3615        DEBUG_WITH_TYPE(
3616            "mach-o-bind",
3617            dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3618                   << "SymbolName=" << SymbolName << "\n");
3619        if (TableKind == Kind::Weak) {
3620          if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3621            return;
3622        }
3623        break;
3624      case MachO::BIND_OPCODE_SET_TYPE_IMM:
3625        BindType = ImmValue;
3626        if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
3627          *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3628                              Twine((int)ImmValue) + " for opcode at: 0x" +
3629                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3630          moveToEnd();
3631          return;
3632        }
3633        DEBUG_WITH_TYPE(
3634            "mach-o-bind",
3635            dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3636                   << "BindType=" << (int)BindType << "\n");
3637        break;
3638      case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
3639        Addend = readSLEB128(&error);
3640        if (error) {
3641          *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
3642                              " for opcode at: 0x" +
3643                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3644          moveToEnd();
3645          return;
3646        }
3647        DEBUG_WITH_TYPE(
3648            "mach-o-bind",
3649            dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3650                   << "Addend=" << Addend << "\n");
3651        break;
3652      case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3653        SegmentIndex = ImmValue;
3654        SegmentOffset = readULEB128(&error);
3655        if (error) {
3656          *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3657                              Twine(error) + " for opcode at: 0x" +
3658                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3659          moveToEnd();
3660          return;
3661        }
3662        error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3663                                               PointerSize);
3664        if (error) {
3665          *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3666                              Twine(error) + " for opcode at: 0x" +
3667                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3668          moveToEnd();
3669          return;
3670        }
3671        DEBUG_WITH_TYPE(
3672            "mach-o-bind",
3673            dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3674                   << "SegmentIndex=" << SegmentIndex << ", "
3675                   << format("SegmentOffset=0x%06X", SegmentOffset)
3676                   << "\n");
3677        break;
3678      case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
3679        SegmentOffset += readULEB128(&error);
3680        if (error) {
3681          *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3682                              " for opcode at: 0x" +
3683                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3684          moveToEnd();
3685          return;
3686        }
3687        error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3688                                               PointerSize);
3689        if (error) {
3690          *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3691                              " for opcode at: 0x" +
3692                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3693          moveToEnd();
3694          return;
3695        }
3696        DEBUG_WITH_TYPE("mach-o-bind",
3697                        dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3698                               << format("SegmentOffset=0x%06X",
3699                                         SegmentOffset) << "\n");
3700        break;
3701      case MachO::BIND_OPCODE_DO_BIND:
3702        AdvanceAmount = PointerSize;
3703        RemainingLoopCount = 0;
3704        error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3705                                               PointerSize);
3706        if (error) {
3707          *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
3708                              " for opcode at: 0x" +
3709                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3710          moveToEnd();
3711          return;
3712        }
3713        if (SymbolName == StringRef()) {
3714          *E = malformedError(
3715              "for BIND_OPCODE_DO_BIND missing preceding "
3716              "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3717              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3718          moveToEnd();
3719          return;
3720        }
3721        if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3722          *E =
3723              malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3724                             "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3725                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3726          moveToEnd();
3727          return;
3728        }
3729        DEBUG_WITH_TYPE("mach-o-bind",
3730                        dbgs() << "BIND_OPCODE_DO_BIND: "
3731                               << format("SegmentOffset=0x%06X",
3732                                         SegmentOffset) << "\n");
3733        return;
3734       case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
3735        if (TableKind == Kind::Lazy) {
3736          *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3737                              "lazy bind table for opcode at: 0x" +
3738                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3739          moveToEnd();
3740          return;
3741        }
3742        error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3743                                               PointerSize);
3744        if (error) {
3745          *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3746                              Twine(error) + " for opcode at: 0x" +
3747                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3748          moveToEnd();
3749          return;
3750        }
3751        if (SymbolName == StringRef()) {
3752          *E = malformedError(
3753              "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3754              "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3755              "at: 0x" +
3756              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3757          moveToEnd();
3758          return;
3759        }
3760        if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3761          *E = malformedError(
3762              "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3763              "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3764              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3765          moveToEnd();
3766          return;
3767        }
3768        AdvanceAmount = readULEB128(&error) + PointerSize;
3769        if (error) {
3770          *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3771                              Twine(error) + " for opcode at: 0x" +
3772                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3773          moveToEnd();
3774          return;
3775        }
3776        // Note, this is not really an error until the next bind but make no sense
3777        // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3778        // bind operation.
3779        error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
3780                                              AdvanceAmount, PointerSize);
3781        if (error) {
3782          *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3783                              "ULEB) " +
3784                              Twine(error) + " for opcode at: 0x" +
3785                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3786          moveToEnd();
3787          return;
3788        }
3789        RemainingLoopCount = 0;
3790        DEBUG_WITH_TYPE(
3791            "mach-o-bind",
3792            dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3793                   << format("SegmentOffset=0x%06X", SegmentOffset)
3794                   << ", AdvanceAmount=" << AdvanceAmount
3795                   << ", RemainingLoopCount=" << RemainingLoopCount
3796                   << "\n");
3797        return;
3798      case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
3799        if (TableKind == Kind::Lazy) {
3800          *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3801                              "allowed in lazy bind table for opcode at: 0x" +
3802                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3803          moveToEnd();
3804          return;
3805        }
3806        error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3807                                               PointerSize);
3808        if (error) {
3809          *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3810                              Twine(error) + " for opcode at: 0x" +
3811                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3812          moveToEnd();
3813          return;
3814        }
3815        if (SymbolName == StringRef()) {
3816          *E = malformedError(
3817              "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3818              "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3819              "opcode at: 0x" +
3820              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3821          moveToEnd();
3822          return;
3823        }
3824        if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3825          *E = malformedError(
3826              "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3827              "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3828              "at: 0x" +
3829              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3830          moveToEnd();
3831          return;
3832        }
3833        AdvanceAmount = ImmValue * PointerSize + PointerSize;
3834        RemainingLoopCount = 0;
3835        error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
3836                                               AdvanceAmount, PointerSize);
3837        if (error) {
3838          *E =
3839              malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3840                             " (after adding immediate times the pointer size) " +
3841                             Twine(error) + " for opcode at: 0x" +
3842                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3843          moveToEnd();
3844          return;
3845        }
3846        DEBUG_WITH_TYPE("mach-o-bind",
3847                        dbgs()
3848                        << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3849                        << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
3850        return;
3851      case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3852        if (TableKind == Kind::Lazy) {
3853          *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3854                              "allowed in lazy bind table for opcode at: 0x" +
3855                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3856          moveToEnd();
3857          return;
3858        }
3859        Count = readULEB128(&error);
3860        if (Count != 0)
3861          RemainingLoopCount = Count - 1;
3862        else
3863          RemainingLoopCount = 0;
3864        if (error) {
3865          *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3866                              " (count value) " +
3867                              Twine(error) + " for opcode at: 0x" +
3868                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3869          moveToEnd();
3870          return;
3871        }
3872        Skip = readULEB128(&error);
3873        AdvanceAmount = Skip + PointerSize;
3874        if (error) {
3875          *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3876                              " (skip value) " +
3877                              Twine(error) + " for opcode at: 0x" +
3878                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3879          moveToEnd();
3880          return;
3881        }
3882        if (SymbolName == StringRef()) {
3883          *E = malformedError(
3884              "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3885              "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3886              "opcode at: 0x" +
3887              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3888          moveToEnd();
3889          return;
3890        }
3891        if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3892          *E = malformedError(
3893              "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3894              "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3895              "at: 0x" +
3896              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3897          moveToEnd();
3898          return;
3899        }
3900        error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3901                                               PointerSize, Count, Skip);
3902        if (error) {
3903          *E =
3904              malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3905                             Twine(error) + " for opcode at: 0x" +
3906                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3907          moveToEnd();
3908          return;
3909        }
3910        DEBUG_WITH_TYPE(
3911            "mach-o-bind",
3912            dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3913                   << format("SegmentOffset=0x%06X", SegmentOffset)
3914                   << ", AdvanceAmount=" << AdvanceAmount
3915                   << ", RemainingLoopCount=" << RemainingLoopCount
3916                   << "\n");
3917        return;
3918      default:
3919        *E = malformedError("bad bind info (bad opcode value 0x" +
3920                            Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3921                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3922        moveToEnd();
3923        return;
3924      }
3925    }
3926  }
3927  
readULEB128(const char ** error)3928  uint64_t MachOBindEntry::readULEB128(const char **error) {
3929    unsigned Count;
3930    uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3931    Ptr += Count;
3932    if (Ptr > Opcodes.end())
3933      Ptr = Opcodes.end();
3934    return Result;
3935  }
3936  
readSLEB128(const char ** error)3937  int64_t MachOBindEntry::readSLEB128(const char **error) {
3938    unsigned Count;
3939    int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
3940    Ptr += Count;
3941    if (Ptr > Opcodes.end())
3942      Ptr = Opcodes.end();
3943    return Result;
3944  }
3945  
segmentIndex() const3946  int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3947  
segmentOffset() const3948  uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3949  
typeName() const3950  StringRef MachOBindEntry::typeName() const {
3951    switch (BindType) {
3952    case MachO::BIND_TYPE_POINTER:
3953      return "pointer";
3954    case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3955      return "text abs32";
3956    case MachO::BIND_TYPE_TEXT_PCREL32:
3957      return "text rel32";
3958    }
3959    return "unknown";
3960  }
3961  
symbolName() const3962  StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3963  
addend() const3964  int64_t MachOBindEntry::addend() const { return Addend; }
3965  
flags() const3966  uint32_t MachOBindEntry::flags() const { return Flags; }
3967  
ordinal() const3968  int MachOBindEntry::ordinal() const { return Ordinal; }
3969  
3970  // For use with the SegIndex of a checked Mach-O Bind entry
3971  // to get the segment name.
segmentName() const3972  StringRef MachOBindEntry::segmentName() const {
3973    return O->BindRebaseSegmentName(SegmentIndex);
3974  }
3975  
3976  // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3977  // to get the section name.
sectionName() const3978  StringRef MachOBindEntry::sectionName() const {
3979    return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3980  }
3981  
3982  // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3983  // to get the address.
address() const3984  uint64_t MachOBindEntry::address() const {
3985    return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3986  }
3987  
operator ==(const MachOBindEntry & Other) const3988  bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3989  #ifdef EXPENSIVE_CHECKS
3990    assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3991  #else
3992    assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3993  #endif
3994    return (Ptr == Other.Ptr) &&
3995           (RemainingLoopCount == Other.RemainingLoopCount) &&
3996           (Done == Other.Done);
3997  }
3998  
3999  // Build table of sections so SegIndex/SegOffset pairs can be translated.
BindRebaseSegInfo(const object::MachOObjectFile * Obj)4000  BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
4001    uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
4002    StringRef CurSegName;
4003    uint64_t CurSegAddress;
4004    for (const SectionRef &Section : Obj->sections()) {
4005      SectionInfo Info;
4006      Expected<StringRef> NameOrErr = Section.getName();
4007      if (!NameOrErr)
4008        consumeError(NameOrErr.takeError());
4009      else
4010        Info.SectionName = *NameOrErr;
4011      Info.Address = Section.getAddress();
4012      Info.Size = Section.getSize();
4013      Info.SegmentName =
4014          Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
4015      if (!Info.SegmentName.equals(CurSegName)) {
4016        ++CurSegIndex;
4017        CurSegName = Info.SegmentName;
4018        CurSegAddress = Info.Address;
4019      }
4020      Info.SegmentIndex = CurSegIndex - 1;
4021      Info.OffsetInSegment = Info.Address - CurSegAddress;
4022      Info.SegmentStartAddress = CurSegAddress;
4023      Sections.push_back(Info);
4024    }
4025    MaxSegIndex = CurSegIndex;
4026  }
4027  
4028  // For use with a SegIndex, SegOffset, and PointerSize triple in
4029  // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
4030  //
4031  // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4032  // that fully contains a pointer at that location. Multiple fixups in a bind
4033  // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4034  // be tested via the Count and Skip parameters.
checkSegAndOffsets(int32_t SegIndex,uint64_t SegOffset,uint8_t PointerSize,uint32_t Count,uint32_t Skip)4035  const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
4036                                                     uint64_t SegOffset,
4037                                                     uint8_t PointerSize,
4038                                                     uint32_t Count,
4039                                                     uint32_t Skip) {
4040    if (SegIndex == -1)
4041      return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4042    if (SegIndex >= MaxSegIndex)
4043      return "bad segIndex (too large)";
4044    for (uint32_t i = 0; i < Count; ++i) {
4045      uint32_t Start = SegOffset + i * (PointerSize + Skip);
4046      uint32_t End = Start + PointerSize;
4047      bool Found = false;
4048      for (const SectionInfo &SI : Sections) {
4049        if (SI.SegmentIndex != SegIndex)
4050          continue;
4051        if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
4052          if (End <= SI.OffsetInSegment + SI.Size) {
4053            Found = true;
4054            break;
4055          }
4056          else
4057            return "bad offset, extends beyond section boundary";
4058        }
4059      }
4060      if (!Found)
4061        return "bad offset, not in section";
4062    }
4063    return nullptr;
4064  }
4065  
4066  // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4067  // to get the segment name.
segmentName(int32_t SegIndex)4068  StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
4069    for (const SectionInfo &SI : Sections) {
4070      if (SI.SegmentIndex == SegIndex)
4071        return SI.SegmentName;
4072    }
4073    llvm_unreachable("invalid SegIndex");
4074  }
4075  
4076  // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4077  // to get the SectionInfo.
findSection(int32_t SegIndex,uint64_t SegOffset)4078  const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
4079                                       int32_t SegIndex, uint64_t SegOffset) {
4080    for (const SectionInfo &SI : Sections) {
4081      if (SI.SegmentIndex != SegIndex)
4082        continue;
4083      if (SI.OffsetInSegment > SegOffset)
4084        continue;
4085      if (SegOffset >= (SI.OffsetInSegment + SI.Size))
4086        continue;
4087      return SI;
4088    }
4089    llvm_unreachable("SegIndex and SegOffset not in any section");
4090  }
4091  
4092  // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4093  // entry to get the section name.
sectionName(int32_t SegIndex,uint64_t SegOffset)4094  StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
4095                                           uint64_t SegOffset) {
4096    return findSection(SegIndex, SegOffset).SectionName;
4097  }
4098  
4099  // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4100  // entry to get the address.
address(uint32_t SegIndex,uint64_t OffsetInSeg)4101  uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
4102    const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4103    return SI.SegmentStartAddress + OffsetInSeg;
4104  }
4105  
4106  iterator_range<bind_iterator>
bindTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)4107  MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
4108                             ArrayRef<uint8_t> Opcodes, bool is64,
4109                             MachOBindEntry::Kind BKind) {
4110    if (O->BindRebaseSectionTable == nullptr)
4111      O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
4112    MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
4113    Start.moveToFirst();
4114  
4115    MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
4116    Finish.moveToEnd();
4117  
4118    return make_range(bind_iterator(Start), bind_iterator(Finish));
4119  }
4120  
bindTable(Error & Err)4121  iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
4122    return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
4123                     MachOBindEntry::Kind::Regular);
4124  }
4125  
lazyBindTable(Error & Err)4126  iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
4127    return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4128                     MachOBindEntry::Kind::Lazy);
4129  }
4130  
weakBindTable(Error & Err)4131  iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
4132    return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4133                     MachOBindEntry::Kind::Weak);
4134  }
4135  
4136  MachOObjectFile::load_command_iterator
begin_load_commands() const4137  MachOObjectFile::begin_load_commands() const {
4138    return LoadCommands.begin();
4139  }
4140  
4141  MachOObjectFile::load_command_iterator
end_load_commands() const4142  MachOObjectFile::end_load_commands() const {
4143    return LoadCommands.end();
4144  }
4145  
4146  iterator_range<MachOObjectFile::load_command_iterator>
load_commands() const4147  MachOObjectFile::load_commands() const {
4148    return make_range(begin_load_commands(), end_load_commands());
4149  }
4150  
4151  StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const4152  MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4153    ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4154    return parseSegmentOrSectionName(Raw.data());
4155  }
4156  
4157  ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const4158  MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
4159    assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4160    const section_base *Base =
4161      reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4162    return makeArrayRef(Base->sectname);
4163  }
4164  
4165  ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const4166  MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
4167    assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4168    const section_base *Base =
4169      reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4170    return makeArrayRef(Base->segname);
4171  }
4172  
4173  bool
isRelocationScattered(const MachO::any_relocation_info & RE) const4174  MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
4175    const {
4176    if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
4177      return false;
4178    return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
4179  }
4180  
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const4181  unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4182      const MachO::any_relocation_info &RE) const {
4183    if (isLittleEndian())
4184      return RE.r_word1 & 0xffffff;
4185    return RE.r_word1 >> 8;
4186  }
4187  
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const4188  bool MachOObjectFile::getPlainRelocationExternal(
4189      const MachO::any_relocation_info &RE) const {
4190    if (isLittleEndian())
4191      return (RE.r_word1 >> 27) & 1;
4192    return (RE.r_word1 >> 4) & 1;
4193  }
4194  
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const4195  bool MachOObjectFile::getScatteredRelocationScattered(
4196      const MachO::any_relocation_info &RE) const {
4197    return RE.r_word0 >> 31;
4198  }
4199  
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const4200  uint32_t MachOObjectFile::getScatteredRelocationValue(
4201      const MachO::any_relocation_info &RE) const {
4202    return RE.r_word1;
4203  }
4204  
getScatteredRelocationType(const MachO::any_relocation_info & RE) const4205  uint32_t MachOObjectFile::getScatteredRelocationType(
4206      const MachO::any_relocation_info &RE) const {
4207    return (RE.r_word0 >> 24) & 0xf;
4208  }
4209  
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const4210  unsigned MachOObjectFile::getAnyRelocationAddress(
4211      const MachO::any_relocation_info &RE) const {
4212    if (isRelocationScattered(RE))
4213      return getScatteredRelocationAddress(RE);
4214    return getPlainRelocationAddress(RE);
4215  }
4216  
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const4217  unsigned MachOObjectFile::getAnyRelocationPCRel(
4218      const MachO::any_relocation_info &RE) const {
4219    if (isRelocationScattered(RE))
4220      return getScatteredRelocationPCRel(RE);
4221    return getPlainRelocationPCRel(*this, RE);
4222  }
4223  
getAnyRelocationLength(const MachO::any_relocation_info & RE) const4224  unsigned MachOObjectFile::getAnyRelocationLength(
4225      const MachO::any_relocation_info &RE) const {
4226    if (isRelocationScattered(RE))
4227      return getScatteredRelocationLength(RE);
4228    return getPlainRelocationLength(*this, RE);
4229  }
4230  
4231  unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const4232  MachOObjectFile::getAnyRelocationType(
4233                                     const MachO::any_relocation_info &RE) const {
4234    if (isRelocationScattered(RE))
4235      return getScatteredRelocationType(RE);
4236    return getPlainRelocationType(*this, RE);
4237  }
4238  
4239  SectionRef
getAnyRelocationSection(const MachO::any_relocation_info & RE) const4240  MachOObjectFile::getAnyRelocationSection(
4241                                     const MachO::any_relocation_info &RE) const {
4242    if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
4243      return *section_end();
4244    unsigned SecNum = getPlainRelocationSymbolNum(RE);
4245    if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4246      return *section_end();
4247    DataRefImpl DRI;
4248    DRI.d.a = SecNum - 1;
4249    return SectionRef(DRI, this);
4250  }
4251  
getSection(DataRefImpl DRI) const4252  MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
4253    assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4254    return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
4255  }
4256  
getSection64(DataRefImpl DRI) const4257  MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
4258    assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4259    return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
4260  }
4261  
getSection(const LoadCommandInfo & L,unsigned Index) const4262  MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
4263                                             unsigned Index) const {
4264    const char *Sec = getSectionPtr(*this, L, Index);
4265    return getStruct<MachO::section>(*this, Sec);
4266  }
4267  
getSection64(const LoadCommandInfo & L,unsigned Index) const4268  MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4269                                                  unsigned Index) const {
4270    const char *Sec = getSectionPtr(*this, L, Index);
4271    return getStruct<MachO::section_64>(*this, Sec);
4272  }
4273  
4274  MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const4275  MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
4276    const char *P = reinterpret_cast<const char *>(DRI.p);
4277    return getStruct<MachO::nlist>(*this, P);
4278  }
4279  
4280  MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const4281  MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
4282    const char *P = reinterpret_cast<const char *>(DRI.p);
4283    return getStruct<MachO::nlist_64>(*this, P);
4284  }
4285  
4286  MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const4287  MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
4288    return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
4289  }
4290  
4291  MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const4292  MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
4293    return getStruct<MachO::segment_command>(*this, L.Ptr);
4294  }
4295  
4296  MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const4297  MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
4298    return getStruct<MachO::segment_command_64>(*this, L.Ptr);
4299  }
4300  
4301  MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const4302  MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
4303    return getStruct<MachO::linker_option_command>(*this, L.Ptr);
4304  }
4305  
4306  MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const4307  MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
4308    return getStruct<MachO::version_min_command>(*this, L.Ptr);
4309  }
4310  
4311  MachO::note_command
getNoteLoadCommand(const LoadCommandInfo & L) const4312  MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4313    return getStruct<MachO::note_command>(*this, L.Ptr);
4314  }
4315  
4316  MachO::build_version_command
getBuildVersionLoadCommand(const LoadCommandInfo & L) const4317  MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4318    return getStruct<MachO::build_version_command>(*this, L.Ptr);
4319  }
4320  
4321  MachO::build_tool_version
getBuildToolVersion(unsigned index) const4322  MachOObjectFile::getBuildToolVersion(unsigned index) const {
4323    return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4324  }
4325  
4326  MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const4327  MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
4328    return getStruct<MachO::dylib_command>(*this, L.Ptr);
4329  }
4330  
4331  MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const4332  MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
4333    return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
4334  }
4335  
4336  MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const4337  MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
4338    return getStruct<MachO::dylinker_command>(*this, L.Ptr);
4339  }
4340  
4341  MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const4342  MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
4343    return getStruct<MachO::uuid_command>(*this, L.Ptr);
4344  }
4345  
4346  MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const4347  MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
4348    return getStruct<MachO::rpath_command>(*this, L.Ptr);
4349  }
4350  
4351  MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const4352  MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
4353    return getStruct<MachO::source_version_command>(*this, L.Ptr);
4354  }
4355  
4356  MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const4357  MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
4358    return getStruct<MachO::entry_point_command>(*this, L.Ptr);
4359  }
4360  
4361  MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const4362  MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
4363    return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
4364  }
4365  
4366  MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const4367  MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
4368    return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
4369  }
4370  
4371  MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const4372  MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
4373    return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
4374  }
4375  
4376  MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const4377  MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
4378    return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
4379  }
4380  
4381  MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const4382  MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
4383    return getStruct<MachO::sub_library_command>(*this, L.Ptr);
4384  }
4385  
4386  MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const4387  MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
4388    return getStruct<MachO::sub_client_command>(*this, L.Ptr);
4389  }
4390  
4391  MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const4392  MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
4393    return getStruct<MachO::routines_command>(*this, L.Ptr);
4394  }
4395  
4396  MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const4397  MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
4398    return getStruct<MachO::routines_command_64>(*this, L.Ptr);
4399  }
4400  
4401  MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const4402  MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
4403    return getStruct<MachO::thread_command>(*this, L.Ptr);
4404  }
4405  
4406  MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const4407  MachOObjectFile::getRelocation(DataRefImpl Rel) const {
4408    uint32_t Offset;
4409    if (getHeader().filetype == MachO::MH_OBJECT) {
4410      DataRefImpl Sec;
4411      Sec.d.a = Rel.d.a;
4412      if (is64Bit()) {
4413        MachO::section_64 Sect = getSection64(Sec);
4414        Offset = Sect.reloff;
4415      } else {
4416        MachO::section Sect = getSection(Sec);
4417        Offset = Sect.reloff;
4418      }
4419    } else {
4420      MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
4421      if (Rel.d.a == 0)
4422        Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4423      else
4424        Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
4425    }
4426  
4427    auto P = reinterpret_cast<const MachO::any_relocation_info *>(
4428        getPtr(*this, Offset)) + Rel.d.b;
4429    return getStruct<MachO::any_relocation_info>(
4430        *this, reinterpret_cast<const char *>(P));
4431  }
4432  
4433  MachO::data_in_code_entry
getDice(DataRefImpl Rel) const4434  MachOObjectFile::getDice(DataRefImpl Rel) const {
4435    const char *P = reinterpret_cast<const char *>(Rel.p);
4436    return getStruct<MachO::data_in_code_entry>(*this, P);
4437  }
4438  
getHeader() const4439  const MachO::mach_header &MachOObjectFile::getHeader() const {
4440    return Header;
4441  }
4442  
getHeader64() const4443  const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4444    assert(is64Bit());
4445    return Header64;
4446  }
4447  
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const4448  uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4449                                               const MachO::dysymtab_command &DLC,
4450                                               unsigned Index) const {
4451    uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
4452    return getStruct<uint32_t>(*this, getPtr(*this, Offset));
4453  }
4454  
4455  MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const4456  MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4457                                           unsigned Index) const {
4458    uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
4459    return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
4460  }
4461  
getSymtabLoadCommand() const4462  MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
4463    if (SymtabLoadCmd)
4464      return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
4465  
4466    // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4467    MachO::symtab_command Cmd;
4468    Cmd.cmd = MachO::LC_SYMTAB;
4469    Cmd.cmdsize = sizeof(MachO::symtab_command);
4470    Cmd.symoff = 0;
4471    Cmd.nsyms = 0;
4472    Cmd.stroff = 0;
4473    Cmd.strsize = 0;
4474    return Cmd;
4475  }
4476  
getDysymtabLoadCommand() const4477  MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
4478    if (DysymtabLoadCmd)
4479      return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
4480  
4481    // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4482    MachO::dysymtab_command Cmd;
4483    Cmd.cmd = MachO::LC_DYSYMTAB;
4484    Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4485    Cmd.ilocalsym = 0;
4486    Cmd.nlocalsym = 0;
4487    Cmd.iextdefsym = 0;
4488    Cmd.nextdefsym = 0;
4489    Cmd.iundefsym = 0;
4490    Cmd.nundefsym = 0;
4491    Cmd.tocoff = 0;
4492    Cmd.ntoc = 0;
4493    Cmd.modtaboff = 0;
4494    Cmd.nmodtab = 0;
4495    Cmd.extrefsymoff = 0;
4496    Cmd.nextrefsyms = 0;
4497    Cmd.indirectsymoff = 0;
4498    Cmd.nindirectsyms = 0;
4499    Cmd.extreloff = 0;
4500    Cmd.nextrel = 0;
4501    Cmd.locreloff = 0;
4502    Cmd.nlocrel = 0;
4503    return Cmd;
4504  }
4505  
4506  MachO::linkedit_data_command
getDataInCodeLoadCommand() const4507  MachOObjectFile::getDataInCodeLoadCommand() const {
4508    if (DataInCodeLoadCmd)
4509      return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
4510  
4511    // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4512    MachO::linkedit_data_command Cmd;
4513    Cmd.cmd = MachO::LC_DATA_IN_CODE;
4514    Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4515    Cmd.dataoff = 0;
4516    Cmd.datasize = 0;
4517    return Cmd;
4518  }
4519  
4520  MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const4521  MachOObjectFile::getLinkOptHintsLoadCommand() const {
4522    if (LinkOptHintsLoadCmd)
4523      return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
4524  
4525    // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4526    // fields.
4527    MachO::linkedit_data_command Cmd;
4528    Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4529    Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4530    Cmd.dataoff = 0;
4531    Cmd.datasize = 0;
4532    return Cmd;
4533  }
4534  
getDyldInfoRebaseOpcodes() const4535  ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4536    if (!DyldInfoLoadCmd)
4537      return None;
4538  
4539    auto DyldInfoOrErr =
4540      getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4541    if (!DyldInfoOrErr)
4542      return None;
4543    MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4544    const uint8_t *Ptr =
4545        reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
4546    return makeArrayRef(Ptr, DyldInfo.rebase_size);
4547  }
4548  
getDyldInfoBindOpcodes() const4549  ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4550    if (!DyldInfoLoadCmd)
4551      return None;
4552  
4553    auto DyldInfoOrErr =
4554      getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4555    if (!DyldInfoOrErr)
4556      return None;
4557    MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4558    const uint8_t *Ptr =
4559        reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
4560    return makeArrayRef(Ptr, DyldInfo.bind_size);
4561  }
4562  
getDyldInfoWeakBindOpcodes() const4563  ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4564    if (!DyldInfoLoadCmd)
4565      return None;
4566  
4567    auto DyldInfoOrErr =
4568      getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4569    if (!DyldInfoOrErr)
4570      return None;
4571    MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4572    const uint8_t *Ptr =
4573        reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
4574    return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
4575  }
4576  
getDyldInfoLazyBindOpcodes() const4577  ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4578    if (!DyldInfoLoadCmd)
4579      return None;
4580  
4581    auto DyldInfoOrErr =
4582      getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4583    if (!DyldInfoOrErr)
4584      return None;
4585    MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4586    const uint8_t *Ptr =
4587        reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
4588    return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
4589  }
4590  
getDyldInfoExportsTrie() const4591  ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4592    if (!DyldInfoLoadCmd)
4593      return None;
4594  
4595    auto DyldInfoOrErr =
4596      getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4597    if (!DyldInfoOrErr)
4598      return None;
4599    MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4600    const uint8_t *Ptr =
4601        reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
4602    return makeArrayRef(Ptr, DyldInfo.export_size);
4603  }
4604  
getUuid() const4605  ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4606    if (!UuidLoadCmd)
4607      return None;
4608    // Returning a pointer is fine as uuid doesn't need endian swapping.
4609    const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
4610    return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
4611  }
4612  
getStringTableData() const4613  StringRef MachOObjectFile::getStringTableData() const {
4614    MachO::symtab_command S = getSymtabLoadCommand();
4615    return getData().substr(S.stroff, S.strsize);
4616  }
4617  
is64Bit() const4618  bool MachOObjectFile::is64Bit() const {
4619    return getType() == getMachOType(false, true) ||
4620      getType() == getMachOType(true, true);
4621  }
4622  
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const4623  void MachOObjectFile::ReadULEB128s(uint64_t Index,
4624                                     SmallVectorImpl<uint64_t> &Out) const {
4625    DataExtractor extractor(ObjectFile::getData(), true, 0);
4626  
4627    uint64_t offset = Index;
4628    uint64_t data = 0;
4629    while (uint64_t delta = extractor.getULEB128(&offset)) {
4630      data += delta;
4631      Out.push_back(data);
4632    }
4633  }
4634  
isRelocatableObject() const4635  bool MachOObjectFile::isRelocatableObject() const {
4636    return getHeader().filetype == MachO::MH_OBJECT;
4637  }
4638  
4639  Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer,uint32_t UniversalCputype,uint32_t UniversalIndex)4640  ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4641                                    uint32_t UniversalCputype,
4642                                    uint32_t UniversalIndex) {
4643    StringRef Magic = Buffer.getBuffer().slice(0, 4);
4644    if (Magic == "\xFE\xED\xFA\xCE")
4645      return MachOObjectFile::create(Buffer, false, false,
4646                                     UniversalCputype, UniversalIndex);
4647    if (Magic == "\xCE\xFA\xED\xFE")
4648      return MachOObjectFile::create(Buffer, true, false,
4649                                     UniversalCputype, UniversalIndex);
4650    if (Magic == "\xFE\xED\xFA\xCF")
4651      return MachOObjectFile::create(Buffer, false, true,
4652                                     UniversalCputype, UniversalIndex);
4653    if (Magic == "\xCF\xFA\xED\xFE")
4654      return MachOObjectFile::create(Buffer, true, true,
4655                                     UniversalCputype, UniversalIndex);
4656    return make_error<GenericBinaryError>("Unrecognized MachO magic number",
4657                                          object_error::invalid_file_type);
4658  }
4659  
mapDebugSectionName(StringRef Name) const4660  StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4661    return StringSwitch<StringRef>(Name)
4662        .Case("debug_str_offs", "debug_str_offsets")
4663        .Default(Name);
4664  }
4665