LCOV - code coverage report
Current view: top level - lib/Object - MachOObjectFile.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 2231 2608 85.5 %
Date: 2018-06-17 00:07:59 Functions: 248 261 95.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13