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

Generated by: LCOV version 1.13