10b57cec5SDimitry Andric //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the MachOObjectFile class, which binds the MachOObject
100b57cec5SDimitry Andric // class to the generic ObjectFile wrapper.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
150b57cec5SDimitry Andric #include "llvm/ADT/None.h"
160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
200b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
210b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
220b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
230b57cec5SDimitry Andric #include "llvm/Object/Error.h"
240b57cec5SDimitry Andric #include "llvm/Object/MachO.h"
250b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
260b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h"
270b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h"
280b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
290b57cec5SDimitry Andric #include "llvm/Support/Error.h"
300b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
310b57cec5SDimitry Andric #include "llvm/Support/Format.h"
320b57cec5SDimitry Andric #include "llvm/Support/Host.h"
330b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
340b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
350b57cec5SDimitry Andric #include "llvm/Support/SwapByteOrder.h"
360b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
370b57cec5SDimitry Andric #include <algorithm>
380b57cec5SDimitry Andric #include <cassert>
390b57cec5SDimitry Andric #include <cstddef>
400b57cec5SDimitry Andric #include <cstdint>
410b57cec5SDimitry Andric #include <cstring>
420b57cec5SDimitry Andric #include <limits>
430b57cec5SDimitry Andric #include <list>
440b57cec5SDimitry Andric #include <memory>
450b57cec5SDimitry Andric #include <system_error>
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric using namespace llvm;
480b57cec5SDimitry Andric using namespace object;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric namespace {
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   struct section_base {
530b57cec5SDimitry Andric     char sectname[16];
540b57cec5SDimitry Andric     char segname[16];
550b57cec5SDimitry Andric   };
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric } // end anonymous namespace
580b57cec5SDimitry Andric 
malformedError(const Twine & Msg)590b57cec5SDimitry Andric static Error malformedError(const Twine &Msg) {
600b57cec5SDimitry Andric   return make_error<GenericBinaryError>("truncated or malformed object (" +
610b57cec5SDimitry Andric                                             Msg + ")",
620b57cec5SDimitry Andric                                         object_error::parse_failed);
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric // FIXME: Replace all uses of this function with getStructOrErr.
660b57cec5SDimitry Andric template <typename T>
getStruct(const MachOObjectFile & O,const char * P)670b57cec5SDimitry Andric static T getStruct(const MachOObjectFile &O, const char *P) {
680b57cec5SDimitry Andric   // Don't read before the beginning or past the end of the file
690b57cec5SDimitry Andric   if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
700b57cec5SDimitry Andric     report_fatal_error("Malformed MachO file.");
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   T Cmd;
730b57cec5SDimitry Andric   memcpy(&Cmd, P, sizeof(T));
740b57cec5SDimitry Andric   if (O.isLittleEndian() != sys::IsLittleEndianHost)
750b57cec5SDimitry Andric     MachO::swapStruct(Cmd);
760b57cec5SDimitry Andric   return Cmd;
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric template <typename T>
getStructOrErr(const MachOObjectFile & O,const char * P)800b57cec5SDimitry Andric static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
810b57cec5SDimitry Andric   // Don't read before the beginning or past the end of the file
820b57cec5SDimitry Andric   if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
830b57cec5SDimitry Andric     return malformedError("Structure read out-of-range");
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   T Cmd;
860b57cec5SDimitry Andric   memcpy(&Cmd, P, sizeof(T));
870b57cec5SDimitry Andric   if (O.isLittleEndian() != sys::IsLittleEndianHost)
880b57cec5SDimitry Andric     MachO::swapStruct(Cmd);
890b57cec5SDimitry Andric   return Cmd;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric static const char *
getSectionPtr(const MachOObjectFile & O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)930b57cec5SDimitry Andric getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
940b57cec5SDimitry Andric               unsigned Sec) {
950b57cec5SDimitry Andric   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   bool Is64 = O.is64Bit();
980b57cec5SDimitry Andric   unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
990b57cec5SDimitry Andric                                     sizeof(MachO::segment_command);
1000b57cec5SDimitry Andric   unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
1010b57cec5SDimitry Andric                                 sizeof(MachO::section);
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
1040b57cec5SDimitry Andric   return reinterpret_cast<const char*>(SectionAddr);
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
getPtr(const MachOObjectFile & O,size_t Offset)1070b57cec5SDimitry Andric static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
1080b57cec5SDimitry Andric   assert(Offset <= O.getData().size());
1090b57cec5SDimitry Andric   return O.getData().data() + Offset;
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile & O,DataRefImpl DRI)1130b57cec5SDimitry Andric getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
1140b57cec5SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
1150b57cec5SDimitry Andric   return getStruct<MachO::nlist_base>(O, P);
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
parseSegmentOrSectionName(const char * P)1180b57cec5SDimitry Andric static StringRef parseSegmentOrSectionName(const char *P) {
1190b57cec5SDimitry Andric   if (P[15] == 0)
1200b57cec5SDimitry Andric     // Null terminated.
1210b57cec5SDimitry Andric     return P;
1220b57cec5SDimitry Andric   // Not null terminated, so this is a 16 char string.
1230b57cec5SDimitry Andric   return StringRef(P, 16);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
getCPUType(const MachOObjectFile & O)1260b57cec5SDimitry Andric static unsigned getCPUType(const MachOObjectFile &O) {
1270b57cec5SDimitry Andric   return O.getHeader().cputype;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
getCPUSubType(const MachOObjectFile & O)130480093f4SDimitry Andric static unsigned getCPUSubType(const MachOObjectFile &O) {
131480093f4SDimitry Andric   return O.getHeader().cpusubtype;
132480093f4SDimitry Andric }
133480093f4SDimitry Andric 
1340b57cec5SDimitry Andric static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)1350b57cec5SDimitry Andric getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
1360b57cec5SDimitry Andric   return RE.r_word0;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)1400b57cec5SDimitry Andric getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
1410b57cec5SDimitry Andric   return RE.r_word0 & 0xffffff;
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
getPlainRelocationPCRel(const MachOObjectFile & O,const MachO::any_relocation_info & RE)1440b57cec5SDimitry Andric static bool getPlainRelocationPCRel(const MachOObjectFile &O,
1450b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) {
1460b57cec5SDimitry Andric   if (O.isLittleEndian())
1470b57cec5SDimitry Andric     return (RE.r_word1 >> 24) & 1;
1480b57cec5SDimitry Andric   return (RE.r_word1 >> 7) & 1;
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric static bool
getScatteredRelocationPCRel(const MachO::any_relocation_info & RE)1520b57cec5SDimitry Andric getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
1530b57cec5SDimitry Andric   return (RE.r_word0 >> 30) & 1;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric 
getPlainRelocationLength(const MachOObjectFile & O,const MachO::any_relocation_info & RE)1560b57cec5SDimitry Andric static unsigned getPlainRelocationLength(const MachOObjectFile &O,
1570b57cec5SDimitry Andric                                          const MachO::any_relocation_info &RE) {
1580b57cec5SDimitry Andric   if (O.isLittleEndian())
1590b57cec5SDimitry Andric     return (RE.r_word1 >> 25) & 3;
1600b57cec5SDimitry Andric   return (RE.r_word1 >> 5) & 3;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)1640b57cec5SDimitry Andric getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
1650b57cec5SDimitry Andric   return (RE.r_word0 >> 28) & 3;
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric 
getPlainRelocationType(const MachOObjectFile & O,const MachO::any_relocation_info & RE)1680b57cec5SDimitry Andric static unsigned getPlainRelocationType(const MachOObjectFile &O,
1690b57cec5SDimitry Andric                                        const MachO::any_relocation_info &RE) {
1700b57cec5SDimitry Andric   if (O.isLittleEndian())
1710b57cec5SDimitry Andric     return RE.r_word1 >> 28;
1720b57cec5SDimitry Andric   return RE.r_word1 & 0xf;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
getSectionFlags(const MachOObjectFile & O,DataRefImpl Sec)1750b57cec5SDimitry Andric static uint32_t getSectionFlags(const MachOObjectFile &O,
1760b57cec5SDimitry Andric                                 DataRefImpl Sec) {
1770b57cec5SDimitry Andric   if (O.is64Bit()) {
1780b57cec5SDimitry Andric     MachO::section_64 Sect = O.getSection64(Sec);
1790b57cec5SDimitry Andric     return Sect.flags;
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric   MachO::section Sect = O.getSection(Sec);
1820b57cec5SDimitry Andric   return Sect.flags;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile & Obj,const char * Ptr,uint32_t LoadCommandIndex)1860b57cec5SDimitry Andric getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
1870b57cec5SDimitry Andric                    uint32_t LoadCommandIndex) {
1880b57cec5SDimitry Andric   if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
1890b57cec5SDimitry Andric     if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
1900b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
1910b57cec5SDimitry Andric                             " extends past end of file");
1920b57cec5SDimitry Andric     if (CmdOrErr->cmdsize < 8)
1930b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
1940b57cec5SDimitry Andric                             " with size less than 8 bytes");
1950b57cec5SDimitry Andric     return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
1960b57cec5SDimitry Andric   } else
1970b57cec5SDimitry Andric     return CmdOrErr.takeError();
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getFirstLoadCommandInfo(const MachOObjectFile & Obj)2010b57cec5SDimitry Andric getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
2020b57cec5SDimitry Andric   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
2030b57cec5SDimitry Andric                                       : sizeof(MachO::mach_header);
2040b57cec5SDimitry Andric   if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
2050b57cec5SDimitry Andric     return malformedError("load command 0 extends past the end all load "
2060b57cec5SDimitry Andric                           "commands in the file");
2070b57cec5SDimitry Andric   return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getNextLoadCommandInfo(const MachOObjectFile & Obj,uint32_t LoadCommandIndex,const MachOObjectFile::LoadCommandInfo & L)2110b57cec5SDimitry Andric getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
2120b57cec5SDimitry Andric                        const MachOObjectFile::LoadCommandInfo &L) {
2130b57cec5SDimitry Andric   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
2140b57cec5SDimitry Andric                                       : sizeof(MachO::mach_header);
2150b57cec5SDimitry Andric   if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
2160b57cec5SDimitry Andric       Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
2170b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex + 1) +
2180b57cec5SDimitry Andric                           " extends past the end all load commands in the file");
2190b57cec5SDimitry Andric   return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric template <typename T>
parseHeader(const MachOObjectFile & Obj,T & Header,Error & Err)2230b57cec5SDimitry Andric static void parseHeader(const MachOObjectFile &Obj, T &Header,
2240b57cec5SDimitry Andric                         Error &Err) {
2250b57cec5SDimitry Andric   if (sizeof(T) > Obj.getData().size()) {
2260b57cec5SDimitry Andric     Err = malformedError("the mach header extends past the end of the "
2270b57cec5SDimitry Andric                          "file");
2280b57cec5SDimitry Andric     return;
2290b57cec5SDimitry Andric   }
2300b57cec5SDimitry Andric   if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
2310b57cec5SDimitry Andric     Header = *HeaderOrErr;
2320b57cec5SDimitry Andric   else
2330b57cec5SDimitry Andric     Err = HeaderOrErr.takeError();
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric // This is used to check for overlapping of Mach-O elements.
2370b57cec5SDimitry Andric struct MachOElement {
2380b57cec5SDimitry Andric   uint64_t Offset;
2390b57cec5SDimitry Andric   uint64_t Size;
2400b57cec5SDimitry Andric   const char *Name;
2410b57cec5SDimitry Andric };
2420b57cec5SDimitry Andric 
checkOverlappingElement(std::list<MachOElement> & Elements,uint64_t Offset,uint64_t Size,const char * Name)2430b57cec5SDimitry Andric static Error checkOverlappingElement(std::list<MachOElement> &Elements,
2440b57cec5SDimitry Andric                                      uint64_t Offset, uint64_t Size,
2450b57cec5SDimitry Andric                                      const char *Name) {
2460b57cec5SDimitry Andric   if (Size == 0)
2470b57cec5SDimitry Andric     return Error::success();
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
2500b57cec5SDimitry Andric     auto E = *it;
2510b57cec5SDimitry Andric     if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
2520b57cec5SDimitry Andric         (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
2530b57cec5SDimitry Andric         (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
2540b57cec5SDimitry Andric       return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
2550b57cec5SDimitry Andric                             " with a size of " + Twine(Size) + ", overlaps " +
2560b57cec5SDimitry Andric                             E.Name + " at offset " + Twine(E.Offset) + " with "
2570b57cec5SDimitry Andric                             "a size of " + Twine(E.Size));
2580b57cec5SDimitry Andric     auto nt = it;
2590b57cec5SDimitry Andric     nt++;
2600b57cec5SDimitry Andric     if (nt != Elements.end()) {
2610b57cec5SDimitry Andric       auto N = *nt;
2620b57cec5SDimitry Andric       if (Offset + Size <= N.Offset) {
2630b57cec5SDimitry Andric         Elements.insert(nt, {Offset, Size, Name});
2640b57cec5SDimitry Andric         return Error::success();
2650b57cec5SDimitry Andric       }
2660b57cec5SDimitry Andric     }
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric   Elements.push_back({Offset, Size, Name});
2690b57cec5SDimitry Andric   return Error::success();
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
2730b57cec5SDimitry Andric // sections to \param Sections, and optionally sets
2740b57cec5SDimitry Andric // \param IsPageZeroSegment to true.
2750b57cec5SDimitry Andric template <typename Segment, typename Section>
parseSegmentLoadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & Sections,bool & IsPageZeroSegment,uint32_t LoadCommandIndex,const char * CmdName,uint64_t SizeOfHeaders,std::list<MachOElement> & Elements)2760b57cec5SDimitry Andric static Error parseSegmentLoadCommand(
2770b57cec5SDimitry Andric     const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
2780b57cec5SDimitry Andric     SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
2790b57cec5SDimitry Andric     uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
2800b57cec5SDimitry Andric     std::list<MachOElement> &Elements) {
2810b57cec5SDimitry Andric   const unsigned SegmentLoadSize = sizeof(Segment);
2820b57cec5SDimitry Andric   if (Load.C.cmdsize < SegmentLoadSize)
2830b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
2840b57cec5SDimitry Andric                           " " + CmdName + " cmdsize too small");
2850b57cec5SDimitry Andric   if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
2860b57cec5SDimitry Andric     Segment S = SegOrErr.get();
2870b57cec5SDimitry Andric     const unsigned SectionSize = sizeof(Section);
2880b57cec5SDimitry Andric     uint64_t FileSize = Obj.getData().size();
2890b57cec5SDimitry Andric     if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
2900b57cec5SDimitry Andric         S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
2910b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
2920b57cec5SDimitry Andric                             " inconsistent cmdsize in " + CmdName +
2930b57cec5SDimitry Andric                             " for the number of sections");
2940b57cec5SDimitry Andric     for (unsigned J = 0; J < S.nsects; ++J) {
2950b57cec5SDimitry Andric       const char *Sec = getSectionPtr(Obj, Load, J);
2960b57cec5SDimitry Andric       Sections.push_back(Sec);
2970b57cec5SDimitry Andric       auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
2980b57cec5SDimitry Andric       if (!SectionOrErr)
2990b57cec5SDimitry Andric         return SectionOrErr.takeError();
3000b57cec5SDimitry Andric       Section s = SectionOrErr.get();
3010b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3020b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3030b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3040b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
3050b57cec5SDimitry Andric           s.offset > FileSize)
3060b57cec5SDimitry Andric         return malformedError("offset field of section " + Twine(J) + " in " +
3070b57cec5SDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
3080b57cec5SDimitry Andric                               " extends past the end of the file");
3090b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3100b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3110b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3120b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
3130b57cec5SDimitry Andric           s.offset < SizeOfHeaders && s.size != 0)
3140b57cec5SDimitry Andric         return malformedError("offset field of section " + Twine(J) + " in " +
3150b57cec5SDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
3160b57cec5SDimitry Andric                               " not past the headers of the file");
3170b57cec5SDimitry Andric       uint64_t BigSize = s.offset;
3180b57cec5SDimitry Andric       BigSize += s.size;
3190b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3200b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3210b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3220b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
3230b57cec5SDimitry Andric           BigSize > FileSize)
3240b57cec5SDimitry Andric         return malformedError("offset field plus size field of section " +
3250b57cec5SDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
3260b57cec5SDimitry Andric                               Twine(LoadCommandIndex) +
3270b57cec5SDimitry Andric                               " extends past the end of the file");
3280b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3290b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3300b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3310b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
3320b57cec5SDimitry Andric           s.size > S.filesize)
3330b57cec5SDimitry Andric         return malformedError("size field of section " +
3340b57cec5SDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
3350b57cec5SDimitry Andric                               Twine(LoadCommandIndex) +
3360b57cec5SDimitry Andric                               " greater than the segment");
3370b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3380b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
3390b57cec5SDimitry Andric           s.addr < S.vmaddr)
3400b57cec5SDimitry Andric         return malformedError("addr field of section " + Twine(J) + " in " +
3410b57cec5SDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
3420b57cec5SDimitry Andric                               " less than the segment's vmaddr");
3430b57cec5SDimitry Andric       BigSize = s.addr;
3440b57cec5SDimitry Andric       BigSize += s.size;
3450b57cec5SDimitry Andric       uint64_t BigEnd = S.vmaddr;
3460b57cec5SDimitry Andric       BigEnd += S.vmsize;
3470b57cec5SDimitry Andric       if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
3480b57cec5SDimitry Andric         return malformedError("addr field plus size of section " + Twine(J) +
3490b57cec5SDimitry Andric                               " in " + CmdName + " command " +
3500b57cec5SDimitry Andric                               Twine(LoadCommandIndex) +
3510b57cec5SDimitry Andric                               " greater than than "
3520b57cec5SDimitry Andric                               "the segment's vmaddr plus vmsize");
3530b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3540b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3550b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3560b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
3570b57cec5SDimitry Andric         if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
3580b57cec5SDimitry Andric                                                 "section contents"))
3590b57cec5SDimitry Andric           return Err;
3600b57cec5SDimitry Andric       if (s.reloff > FileSize)
3610b57cec5SDimitry Andric         return malformedError("reloff field of section " + Twine(J) + " in " +
3620b57cec5SDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
3630b57cec5SDimitry Andric                               " extends past the end of the file");
3640b57cec5SDimitry Andric       BigSize = s.nreloc;
3650b57cec5SDimitry Andric       BigSize *= sizeof(struct MachO::relocation_info);
3660b57cec5SDimitry Andric       BigSize += s.reloff;
3670b57cec5SDimitry Andric       if (BigSize > FileSize)
3680b57cec5SDimitry Andric         return malformedError("reloff field plus nreloc field times sizeof("
3690b57cec5SDimitry Andric                               "struct relocation_info) of section " +
3700b57cec5SDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
3710b57cec5SDimitry Andric                               Twine(LoadCommandIndex) +
3720b57cec5SDimitry Andric                               " extends past the end of the file");
3730b57cec5SDimitry Andric       if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
3740b57cec5SDimitry Andric                                               sizeof(struct
3750b57cec5SDimitry Andric                                               MachO::relocation_info),
3760b57cec5SDimitry Andric                                               "section relocation entries"))
3770b57cec5SDimitry Andric         return Err;
3780b57cec5SDimitry Andric     }
3790b57cec5SDimitry Andric     if (S.fileoff > FileSize)
3800b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
3810b57cec5SDimitry Andric                             " fileoff field in " + CmdName +
3820b57cec5SDimitry Andric                             " extends past the end of the file");
3830b57cec5SDimitry Andric     uint64_t BigSize = S.fileoff;
3840b57cec5SDimitry Andric     BigSize += S.filesize;
3850b57cec5SDimitry Andric     if (BigSize > FileSize)
3860b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
3870b57cec5SDimitry Andric                             " fileoff field plus filesize field in " +
3880b57cec5SDimitry Andric                             CmdName + " extends past the end of the file");
3890b57cec5SDimitry Andric     if (S.vmsize != 0 && S.filesize > S.vmsize)
3900b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
3910b57cec5SDimitry Andric                             " filesize field in " + CmdName +
3920b57cec5SDimitry Andric                             " greater than vmsize field");
3930b57cec5SDimitry Andric     IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
3940b57cec5SDimitry Andric   } else
3950b57cec5SDimitry Andric     return SegOrErr.takeError();
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   return Error::success();
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric 
checkSymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** SymtabLoadCmd,std::list<MachOElement> & Elements)4000b57cec5SDimitry Andric static Error checkSymtabCommand(const MachOObjectFile &Obj,
4010b57cec5SDimitry Andric                                 const MachOObjectFile::LoadCommandInfo &Load,
4020b57cec5SDimitry Andric                                 uint32_t LoadCommandIndex,
4030b57cec5SDimitry Andric                                 const char **SymtabLoadCmd,
4040b57cec5SDimitry Andric                                 std::list<MachOElement> &Elements) {
4050b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::symtab_command))
4060b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
4070b57cec5SDimitry Andric                           " LC_SYMTAB cmdsize too small");
4080b57cec5SDimitry Andric   if (*SymtabLoadCmd != nullptr)
4090b57cec5SDimitry Andric     return malformedError("more than one LC_SYMTAB command");
4100b57cec5SDimitry Andric   auto SymtabOrErr = getStructOrErr<MachO::symtab_command>(Obj, Load.Ptr);
4110b57cec5SDimitry Andric   if (!SymtabOrErr)
4120b57cec5SDimitry Andric     return SymtabOrErr.takeError();
4130b57cec5SDimitry Andric   MachO::symtab_command Symtab = SymtabOrErr.get();
4140b57cec5SDimitry Andric   if (Symtab.cmdsize != sizeof(MachO::symtab_command))
4150b57cec5SDimitry Andric     return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
4160b57cec5SDimitry Andric                           " has incorrect cmdsize");
4170b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
4180b57cec5SDimitry Andric   if (Symtab.symoff > FileSize)
4190b57cec5SDimitry Andric     return malformedError("symoff field of LC_SYMTAB command " +
4200b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
4210b57cec5SDimitry Andric                           "of the file");
4220b57cec5SDimitry Andric   uint64_t SymtabSize = Symtab.nsyms;
4230b57cec5SDimitry Andric   const char *struct_nlist_name;
4240b57cec5SDimitry Andric   if (Obj.is64Bit()) {
4250b57cec5SDimitry Andric     SymtabSize *= sizeof(MachO::nlist_64);
4260b57cec5SDimitry Andric     struct_nlist_name = "struct nlist_64";
4270b57cec5SDimitry Andric   } else {
4280b57cec5SDimitry Andric     SymtabSize *= sizeof(MachO::nlist);
4290b57cec5SDimitry Andric     struct_nlist_name = "struct nlist";
4300b57cec5SDimitry Andric   }
4310b57cec5SDimitry Andric   uint64_t BigSize = SymtabSize;
4320b57cec5SDimitry Andric   BigSize += Symtab.symoff;
4330b57cec5SDimitry Andric   if (BigSize > FileSize)
4340b57cec5SDimitry Andric     return malformedError("symoff field plus nsyms field times sizeof(" +
4350b57cec5SDimitry Andric                           Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
4360b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
4370b57cec5SDimitry Andric                           "of the file");
4380b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
4390b57cec5SDimitry Andric                                           "symbol table"))
4400b57cec5SDimitry Andric     return Err;
4410b57cec5SDimitry Andric   if (Symtab.stroff > FileSize)
4420b57cec5SDimitry Andric     return malformedError("stroff field of LC_SYMTAB command " +
4430b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
4440b57cec5SDimitry Andric                           "of the file");
4450b57cec5SDimitry Andric   BigSize = Symtab.stroff;
4460b57cec5SDimitry Andric   BigSize += Symtab.strsize;
4470b57cec5SDimitry Andric   if (BigSize > FileSize)
4480b57cec5SDimitry Andric     return malformedError("stroff field plus strsize field of LC_SYMTAB "
4490b57cec5SDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
4500b57cec5SDimitry Andric                           "past the end of the file");
4510b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
4520b57cec5SDimitry Andric                                           Symtab.strsize, "string table"))
4530b57cec5SDimitry Andric     return Err;
4540b57cec5SDimitry Andric   *SymtabLoadCmd = Load.Ptr;
4550b57cec5SDimitry Andric   return Error::success();
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric 
checkDysymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** DysymtabLoadCmd,std::list<MachOElement> & Elements)4580b57cec5SDimitry Andric static Error checkDysymtabCommand(const MachOObjectFile &Obj,
4590b57cec5SDimitry Andric                                   const MachOObjectFile::LoadCommandInfo &Load,
4600b57cec5SDimitry Andric                                   uint32_t LoadCommandIndex,
4610b57cec5SDimitry Andric                                   const char **DysymtabLoadCmd,
4620b57cec5SDimitry Andric                                   std::list<MachOElement> &Elements) {
4630b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
4640b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
4650b57cec5SDimitry Andric                           " LC_DYSYMTAB cmdsize too small");
4660b57cec5SDimitry Andric   if (*DysymtabLoadCmd != nullptr)
4670b57cec5SDimitry Andric     return malformedError("more than one LC_DYSYMTAB command");
4680b57cec5SDimitry Andric   auto DysymtabOrErr =
4690b57cec5SDimitry Andric     getStructOrErr<MachO::dysymtab_command>(Obj, Load.Ptr);
4700b57cec5SDimitry Andric   if (!DysymtabOrErr)
4710b57cec5SDimitry Andric     return DysymtabOrErr.takeError();
4720b57cec5SDimitry Andric   MachO::dysymtab_command Dysymtab = DysymtabOrErr.get();
4730b57cec5SDimitry Andric   if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
4740b57cec5SDimitry Andric     return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
4750b57cec5SDimitry Andric                           " has incorrect cmdsize");
4760b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
4770b57cec5SDimitry Andric   if (Dysymtab.tocoff > FileSize)
4780b57cec5SDimitry Andric     return malformedError("tocoff field of LC_DYSYMTAB command " +
4790b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
4800b57cec5SDimitry Andric                           "the file");
4810b57cec5SDimitry Andric   uint64_t BigSize = Dysymtab.ntoc;
4820b57cec5SDimitry Andric   BigSize *= sizeof(MachO::dylib_table_of_contents);
4830b57cec5SDimitry Andric   BigSize += Dysymtab.tocoff;
4840b57cec5SDimitry Andric   if (BigSize > FileSize)
4850b57cec5SDimitry Andric     return malformedError("tocoff field plus ntoc field times sizeof(struct "
4860b57cec5SDimitry Andric                           "dylib_table_of_contents) of LC_DYSYMTAB command " +
4870b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
4880b57cec5SDimitry Andric                           "the file");
4890b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
4900b57cec5SDimitry Andric                                           Dysymtab.ntoc * sizeof(struct
4910b57cec5SDimitry Andric                                           MachO::dylib_table_of_contents),
4920b57cec5SDimitry Andric                                           "table of contents"))
4930b57cec5SDimitry Andric     return Err;
4940b57cec5SDimitry Andric   if (Dysymtab.modtaboff > FileSize)
4950b57cec5SDimitry Andric     return malformedError("modtaboff field of LC_DYSYMTAB command " +
4960b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
4970b57cec5SDimitry Andric                           "the file");
4980b57cec5SDimitry Andric   BigSize = Dysymtab.nmodtab;
4990b57cec5SDimitry Andric   const char *struct_dylib_module_name;
5000b57cec5SDimitry Andric   uint64_t sizeof_modtab;
5010b57cec5SDimitry Andric   if (Obj.is64Bit()) {
5020b57cec5SDimitry Andric     sizeof_modtab = sizeof(MachO::dylib_module_64);
5030b57cec5SDimitry Andric     struct_dylib_module_name = "struct dylib_module_64";
5040b57cec5SDimitry Andric   } else {
5050b57cec5SDimitry Andric     sizeof_modtab = sizeof(MachO::dylib_module);
5060b57cec5SDimitry Andric     struct_dylib_module_name = "struct dylib_module";
5070b57cec5SDimitry Andric   }
5080b57cec5SDimitry Andric   BigSize *= sizeof_modtab;
5090b57cec5SDimitry Andric   BigSize += Dysymtab.modtaboff;
5100b57cec5SDimitry Andric   if (BigSize > FileSize)
5110b57cec5SDimitry Andric     return malformedError("modtaboff field plus nmodtab field times sizeof(" +
5120b57cec5SDimitry Andric                           Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
5130b57cec5SDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
5140b57cec5SDimitry Andric                           "past the end of the file");
5150b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
5160b57cec5SDimitry Andric                                           Dysymtab.nmodtab * sizeof_modtab,
5170b57cec5SDimitry Andric                                           "module table"))
5180b57cec5SDimitry Andric     return Err;
5190b57cec5SDimitry Andric   if (Dysymtab.extrefsymoff > FileSize)
5200b57cec5SDimitry Andric     return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
5210b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5220b57cec5SDimitry Andric                           "the file");
5230b57cec5SDimitry Andric   BigSize = Dysymtab.nextrefsyms;
5240b57cec5SDimitry Andric   BigSize *= sizeof(MachO::dylib_reference);
5250b57cec5SDimitry Andric   BigSize += Dysymtab.extrefsymoff;
5260b57cec5SDimitry Andric   if (BigSize > FileSize)
5270b57cec5SDimitry Andric     return malformedError("extrefsymoff field plus nextrefsyms field times "
5280b57cec5SDimitry Andric                           "sizeof(struct dylib_reference) of LC_DYSYMTAB "
5290b57cec5SDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
5300b57cec5SDimitry Andric                           "past the end of the file");
5310b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
5320b57cec5SDimitry Andric                                           Dysymtab.nextrefsyms *
5330b57cec5SDimitry Andric                                               sizeof(MachO::dylib_reference),
5340b57cec5SDimitry Andric                                           "reference table"))
5350b57cec5SDimitry Andric     return Err;
5360b57cec5SDimitry Andric   if (Dysymtab.indirectsymoff > FileSize)
5370b57cec5SDimitry Andric     return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
5380b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5390b57cec5SDimitry Andric                           "the file");
5400b57cec5SDimitry Andric   BigSize = Dysymtab.nindirectsyms;
5410b57cec5SDimitry Andric   BigSize *= sizeof(uint32_t);
5420b57cec5SDimitry Andric   BigSize += Dysymtab.indirectsymoff;
5430b57cec5SDimitry Andric   if (BigSize > FileSize)
5440b57cec5SDimitry Andric     return malformedError("indirectsymoff field plus nindirectsyms field times "
5450b57cec5SDimitry Andric                           "sizeof(uint32_t) of LC_DYSYMTAB command " +
5460b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5470b57cec5SDimitry Andric                           "the file");
5480b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
5490b57cec5SDimitry Andric                                           Dysymtab.nindirectsyms *
5500b57cec5SDimitry Andric                                           sizeof(uint32_t),
5510b57cec5SDimitry Andric                                           "indirect table"))
5520b57cec5SDimitry Andric     return Err;
5530b57cec5SDimitry Andric   if (Dysymtab.extreloff > FileSize)
5540b57cec5SDimitry Andric     return malformedError("extreloff field of LC_DYSYMTAB command " +
5550b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5560b57cec5SDimitry Andric                           "the file");
5570b57cec5SDimitry Andric   BigSize = Dysymtab.nextrel;
5580b57cec5SDimitry Andric   BigSize *= sizeof(MachO::relocation_info);
5590b57cec5SDimitry Andric   BigSize += Dysymtab.extreloff;
5600b57cec5SDimitry Andric   if (BigSize > FileSize)
5610b57cec5SDimitry Andric     return malformedError("extreloff field plus nextrel field times sizeof"
5620b57cec5SDimitry Andric                           "(struct relocation_info) of LC_DYSYMTAB command " +
5630b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5640b57cec5SDimitry Andric                           "the file");
5650b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
5660b57cec5SDimitry Andric                                           Dysymtab.nextrel *
5670b57cec5SDimitry Andric                                               sizeof(MachO::relocation_info),
5680b57cec5SDimitry Andric                                           "external relocation table"))
5690b57cec5SDimitry Andric     return Err;
5700b57cec5SDimitry Andric   if (Dysymtab.locreloff > FileSize)
5710b57cec5SDimitry Andric     return malformedError("locreloff field of LC_DYSYMTAB command " +
5720b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5730b57cec5SDimitry Andric                           "the file");
5740b57cec5SDimitry Andric   BigSize = Dysymtab.nlocrel;
5750b57cec5SDimitry Andric   BigSize *= sizeof(MachO::relocation_info);
5760b57cec5SDimitry Andric   BigSize += Dysymtab.locreloff;
5770b57cec5SDimitry Andric   if (BigSize > FileSize)
5780b57cec5SDimitry Andric     return malformedError("locreloff field plus nlocrel field times sizeof"
5790b57cec5SDimitry Andric                           "(struct relocation_info) of LC_DYSYMTAB command " +
5800b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5810b57cec5SDimitry Andric                           "the file");
5820b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
5830b57cec5SDimitry Andric                                           Dysymtab.nlocrel *
5840b57cec5SDimitry Andric                                               sizeof(MachO::relocation_info),
5850b57cec5SDimitry Andric                                           "local relocation table"))
5860b57cec5SDimitry Andric     return Err;
5870b57cec5SDimitry Andric   *DysymtabLoadCmd = Load.Ptr;
5880b57cec5SDimitry Andric   return Error::success();
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
checkLinkeditDataCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements,const char * ElementName)5910b57cec5SDimitry Andric static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
5920b57cec5SDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
5930b57cec5SDimitry Andric                                  uint32_t LoadCommandIndex,
5940b57cec5SDimitry Andric                                  const char **LoadCmd, const char *CmdName,
5950b57cec5SDimitry Andric                                  std::list<MachOElement> &Elements,
5960b57cec5SDimitry Andric                                  const char *ElementName) {
5970b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
5980b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
5990b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
6000b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
6010b57cec5SDimitry Andric     return malformedError("more than one " + Twine(CmdName) + " command");
6020b57cec5SDimitry Andric   auto LinkDataOrError =
6030b57cec5SDimitry Andric     getStructOrErr<MachO::linkedit_data_command>(Obj, Load.Ptr);
6040b57cec5SDimitry Andric   if (!LinkDataOrError)
6050b57cec5SDimitry Andric     return LinkDataOrError.takeError();
6060b57cec5SDimitry Andric   MachO::linkedit_data_command LinkData = LinkDataOrError.get();
6070b57cec5SDimitry Andric   if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
6080b57cec5SDimitry Andric     return malformedError(Twine(CmdName) + " command " +
6090b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " has incorrect cmdsize");
6100b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
6110b57cec5SDimitry Andric   if (LinkData.dataoff > FileSize)
6120b57cec5SDimitry Andric     return malformedError("dataoff field of " + Twine(CmdName) + " command " +
6130b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6140b57cec5SDimitry Andric                           "the file");
6150b57cec5SDimitry Andric   uint64_t BigSize = LinkData.dataoff;
6160b57cec5SDimitry Andric   BigSize += LinkData.datasize;
6170b57cec5SDimitry Andric   if (BigSize > FileSize)
6180b57cec5SDimitry Andric     return malformedError("dataoff field plus datasize field of " +
6190b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
6200b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6210b57cec5SDimitry Andric                           "the file");
6220b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
6230b57cec5SDimitry Andric                                           LinkData.datasize, ElementName))
6240b57cec5SDimitry Andric     return Err;
6250b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
6260b57cec5SDimitry Andric   return Error::success();
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric 
checkDyldInfoCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements)6290b57cec5SDimitry Andric static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
6300b57cec5SDimitry Andric                                   const MachOObjectFile::LoadCommandInfo &Load,
6310b57cec5SDimitry Andric                                   uint32_t LoadCommandIndex,
6320b57cec5SDimitry Andric                                   const char **LoadCmd, const char *CmdName,
6330b57cec5SDimitry Andric                                   std::list<MachOElement> &Elements) {
6340b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
6350b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
6360b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
6370b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
6380b57cec5SDimitry Andric     return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
6390b57cec5SDimitry Andric                           "command");
6400b57cec5SDimitry Andric   auto DyldInfoOrErr =
6410b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(Obj, Load.Ptr);
6420b57cec5SDimitry Andric   if (!DyldInfoOrErr)
6430b57cec5SDimitry Andric     return DyldInfoOrErr.takeError();
6440b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
6450b57cec5SDimitry Andric   if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
6460b57cec5SDimitry Andric     return malformedError(Twine(CmdName) + " command " +
6470b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " has incorrect cmdsize");
6480b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
6490b57cec5SDimitry Andric   if (DyldInfo.rebase_off > FileSize)
6500b57cec5SDimitry Andric     return malformedError("rebase_off field of " + Twine(CmdName) +
6510b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
6520b57cec5SDimitry Andric                           "past the end of the file");
6530b57cec5SDimitry Andric   uint64_t BigSize = DyldInfo.rebase_off;
6540b57cec5SDimitry Andric   BigSize += DyldInfo.rebase_size;
6550b57cec5SDimitry Andric   if (BigSize > FileSize)
6560b57cec5SDimitry Andric     return malformedError("rebase_off field plus rebase_size field of " +
6570b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
6580b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6590b57cec5SDimitry Andric                           "the file");
6600b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
6610b57cec5SDimitry Andric                                           DyldInfo.rebase_size,
6620b57cec5SDimitry Andric                                           "dyld rebase info"))
6630b57cec5SDimitry Andric     return Err;
6640b57cec5SDimitry Andric   if (DyldInfo.bind_off > FileSize)
6650b57cec5SDimitry Andric     return malformedError("bind_off field of " + Twine(CmdName) +
6660b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
6670b57cec5SDimitry Andric                           "past the end of the file");
6680b57cec5SDimitry Andric   BigSize = DyldInfo.bind_off;
6690b57cec5SDimitry Andric   BigSize += DyldInfo.bind_size;
6700b57cec5SDimitry Andric   if (BigSize > FileSize)
6710b57cec5SDimitry Andric     return malformedError("bind_off field plus bind_size field of " +
6720b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
6730b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6740b57cec5SDimitry Andric                           "the file");
6750b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
6760b57cec5SDimitry Andric                                           DyldInfo.bind_size,
6770b57cec5SDimitry Andric                                           "dyld bind info"))
6780b57cec5SDimitry Andric     return Err;
6790b57cec5SDimitry Andric   if (DyldInfo.weak_bind_off > FileSize)
6800b57cec5SDimitry Andric     return malformedError("weak_bind_off field of " + Twine(CmdName) +
6810b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
6820b57cec5SDimitry Andric                           "past the end of the file");
6830b57cec5SDimitry Andric   BigSize = DyldInfo.weak_bind_off;
6840b57cec5SDimitry Andric   BigSize += DyldInfo.weak_bind_size;
6850b57cec5SDimitry Andric   if (BigSize > FileSize)
6860b57cec5SDimitry Andric     return malformedError("weak_bind_off field plus weak_bind_size field of " +
6870b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
6880b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6890b57cec5SDimitry Andric                           "the file");
6900b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
6910b57cec5SDimitry Andric                                           DyldInfo.weak_bind_size,
6920b57cec5SDimitry Andric                                           "dyld weak bind info"))
6930b57cec5SDimitry Andric     return Err;
6940b57cec5SDimitry Andric   if (DyldInfo.lazy_bind_off > FileSize)
6950b57cec5SDimitry Andric     return malformedError("lazy_bind_off field of " + Twine(CmdName) +
6960b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
6970b57cec5SDimitry Andric                           "past the end of the file");
6980b57cec5SDimitry Andric   BigSize = DyldInfo.lazy_bind_off;
6990b57cec5SDimitry Andric   BigSize += DyldInfo.lazy_bind_size;
7000b57cec5SDimitry Andric   if (BigSize > FileSize)
7010b57cec5SDimitry Andric     return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
7020b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
7030b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
7040b57cec5SDimitry Andric                           "the file");
7050b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
7060b57cec5SDimitry Andric                                           DyldInfo.lazy_bind_size,
7070b57cec5SDimitry Andric                                           "dyld lazy bind info"))
7080b57cec5SDimitry Andric     return Err;
7090b57cec5SDimitry Andric   if (DyldInfo.export_off > FileSize)
7100b57cec5SDimitry Andric     return malformedError("export_off field of " + Twine(CmdName) +
7110b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
7120b57cec5SDimitry Andric                           "past the end of the file");
7130b57cec5SDimitry Andric   BigSize = DyldInfo.export_off;
7140b57cec5SDimitry Andric   BigSize += DyldInfo.export_size;
7150b57cec5SDimitry Andric   if (BigSize > FileSize)
7160b57cec5SDimitry Andric     return malformedError("export_off field plus export_size field of " +
7170b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
7180b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
7190b57cec5SDimitry Andric                           "the file");
7200b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
7210b57cec5SDimitry Andric                                           DyldInfo.export_size,
7220b57cec5SDimitry Andric                                           "dyld export info"))
7230b57cec5SDimitry Andric     return Err;
7240b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
7250b57cec5SDimitry Andric   return Error::success();
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric 
checkDylibCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)7280b57cec5SDimitry Andric static Error checkDylibCommand(const MachOObjectFile &Obj,
7290b57cec5SDimitry Andric                                const MachOObjectFile::LoadCommandInfo &Load,
7300b57cec5SDimitry Andric                                uint32_t LoadCommandIndex, const char *CmdName) {
7310b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dylib_command))
7320b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7330b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
7340b57cec5SDimitry Andric   auto CommandOrErr = getStructOrErr<MachO::dylib_command>(Obj, Load.Ptr);
7350b57cec5SDimitry Andric   if (!CommandOrErr)
7360b57cec5SDimitry Andric     return CommandOrErr.takeError();
7370b57cec5SDimitry Andric   MachO::dylib_command D = CommandOrErr.get();
7380b57cec5SDimitry Andric   if (D.dylib.name < sizeof(MachO::dylib_command))
7390b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7400b57cec5SDimitry Andric                           CmdName + " name.offset field too small, not past "
7410b57cec5SDimitry Andric                           "the end of the dylib_command struct");
7420b57cec5SDimitry Andric   if (D.dylib.name >= D.cmdsize)
7430b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7440b57cec5SDimitry Andric                           CmdName + " name.offset field extends past the end "
7450b57cec5SDimitry Andric                           "of the load command");
7460b57cec5SDimitry Andric   // Make sure there is a null between the starting offset of the name and
7470b57cec5SDimitry Andric   // the end of the load command.
7480b57cec5SDimitry Andric   uint32_t i;
7490b57cec5SDimitry Andric   const char *P = (const char *)Load.Ptr;
7500b57cec5SDimitry Andric   for (i = D.dylib.name; i < D.cmdsize; i++)
7510b57cec5SDimitry Andric     if (P[i] == '\0')
7520b57cec5SDimitry Andric       break;
7530b57cec5SDimitry Andric   if (i >= D.cmdsize)
7540b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7550b57cec5SDimitry Andric                           CmdName + " library name extends past the end of the "
7560b57cec5SDimitry Andric                           "load command");
7570b57cec5SDimitry Andric   return Error::success();
7580b57cec5SDimitry Andric }
7590b57cec5SDimitry Andric 
checkDylibIdCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd)7600b57cec5SDimitry Andric static Error checkDylibIdCommand(const MachOObjectFile &Obj,
7610b57cec5SDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
7620b57cec5SDimitry Andric                                  uint32_t LoadCommandIndex,
7630b57cec5SDimitry Andric                                  const char **LoadCmd) {
7640b57cec5SDimitry Andric   if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
7650b57cec5SDimitry Andric                                      "LC_ID_DYLIB"))
7660b57cec5SDimitry Andric     return Err;
7670b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
7680b57cec5SDimitry Andric     return malformedError("more than one LC_ID_DYLIB command");
7690b57cec5SDimitry Andric   if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
7700b57cec5SDimitry Andric       Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
7710b57cec5SDimitry Andric     return malformedError("LC_ID_DYLIB load command in non-dynamic library "
7720b57cec5SDimitry Andric                           "file type");
7730b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
7740b57cec5SDimitry Andric   return Error::success();
7750b57cec5SDimitry Andric }
7760b57cec5SDimitry Andric 
checkDyldCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)7770b57cec5SDimitry Andric static Error checkDyldCommand(const MachOObjectFile &Obj,
7780b57cec5SDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
7790b57cec5SDimitry Andric                               uint32_t LoadCommandIndex, const char *CmdName) {
7800b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
7810b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7820b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
7830b57cec5SDimitry Andric   auto CommandOrErr = getStructOrErr<MachO::dylinker_command>(Obj, Load.Ptr);
7840b57cec5SDimitry Andric   if (!CommandOrErr)
7850b57cec5SDimitry Andric     return CommandOrErr.takeError();
7860b57cec5SDimitry Andric   MachO::dylinker_command D = CommandOrErr.get();
7870b57cec5SDimitry Andric   if (D.name < sizeof(MachO::dylinker_command))
7880b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7890b57cec5SDimitry Andric                           CmdName + " name.offset field too small, not past "
7900b57cec5SDimitry Andric                           "the end of the dylinker_command struct");
7910b57cec5SDimitry Andric   if (D.name >= D.cmdsize)
7920b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7930b57cec5SDimitry Andric                           CmdName + " name.offset field extends past the end "
7940b57cec5SDimitry Andric                           "of the load command");
7950b57cec5SDimitry Andric   // Make sure there is a null between the starting offset of the name and
7960b57cec5SDimitry Andric   // the end of the load command.
7970b57cec5SDimitry Andric   uint32_t i;
7980b57cec5SDimitry Andric   const char *P = (const char *)Load.Ptr;
7990b57cec5SDimitry Andric   for (i = D.name; i < D.cmdsize; i++)
8000b57cec5SDimitry Andric     if (P[i] == '\0')
8010b57cec5SDimitry Andric       break;
8020b57cec5SDimitry Andric   if (i >= D.cmdsize)
8030b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
8040b57cec5SDimitry Andric                           CmdName + " dyld name extends past the end of the "
8050b57cec5SDimitry Andric                           "load command");
8060b57cec5SDimitry Andric   return Error::success();
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric 
checkVersCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName)8090b57cec5SDimitry Andric static Error checkVersCommand(const MachOObjectFile &Obj,
8100b57cec5SDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
8110b57cec5SDimitry Andric                               uint32_t LoadCommandIndex,
8120b57cec5SDimitry Andric                               const char **LoadCmd, const char *CmdName) {
8130b57cec5SDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::version_min_command))
8140b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
8150b57cec5SDimitry Andric                           CmdName + " has incorrect cmdsize");
8160b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
8170b57cec5SDimitry Andric     return malformedError("more than one LC_VERSION_MIN_MACOSX, "
8180b57cec5SDimitry Andric                           "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
8190b57cec5SDimitry Andric                           "LC_VERSION_MIN_WATCHOS command");
8200b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
8210b57cec5SDimitry Andric   return Error::success();
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric 
checkNoteCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,std::list<MachOElement> & Elements)8240b57cec5SDimitry Andric static Error checkNoteCommand(const MachOObjectFile &Obj,
8250b57cec5SDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
8260b57cec5SDimitry Andric                               uint32_t LoadCommandIndex,
8270b57cec5SDimitry Andric                               std::list<MachOElement> &Elements) {
8280b57cec5SDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::note_command))
8290b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8300b57cec5SDimitry Andric                           " LC_NOTE has incorrect cmdsize");
8310b57cec5SDimitry Andric   auto NoteCmdOrErr = getStructOrErr<MachO::note_command>(Obj, Load.Ptr);
8320b57cec5SDimitry Andric   if (!NoteCmdOrErr)
8330b57cec5SDimitry Andric     return NoteCmdOrErr.takeError();
8340b57cec5SDimitry Andric   MachO::note_command Nt = NoteCmdOrErr.get();
8350b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
8360b57cec5SDimitry Andric   if (Nt.offset > FileSize)
8370b57cec5SDimitry Andric     return malformedError("offset field of LC_NOTE command " +
8380b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends "
8390b57cec5SDimitry Andric                           "past the end of the file");
8400b57cec5SDimitry Andric   uint64_t BigSize = Nt.offset;
8410b57cec5SDimitry Andric   BigSize += Nt.size;
8420b57cec5SDimitry Andric   if (BigSize > FileSize)
8430b57cec5SDimitry Andric     return malformedError("size field plus offset field of LC_NOTE command " +
8440b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
8450b57cec5SDimitry Andric                           "the file");
8460b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
8470b57cec5SDimitry Andric                                           "LC_NOTE data"))
8480b57cec5SDimitry Andric     return Err;
8490b57cec5SDimitry Andric   return Error::success();
8500b57cec5SDimitry Andric }
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric static Error
parseBuildVersionCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & BuildTools,uint32_t LoadCommandIndex)8530b57cec5SDimitry Andric parseBuildVersionCommand(const MachOObjectFile &Obj,
8540b57cec5SDimitry Andric                          const MachOObjectFile::LoadCommandInfo &Load,
8550b57cec5SDimitry Andric                          SmallVectorImpl<const char*> &BuildTools,
8560b57cec5SDimitry Andric                          uint32_t LoadCommandIndex) {
8570b57cec5SDimitry Andric   auto BVCOrErr =
8580b57cec5SDimitry Andric     getStructOrErr<MachO::build_version_command>(Obj, Load.Ptr);
8590b57cec5SDimitry Andric   if (!BVCOrErr)
8600b57cec5SDimitry Andric     return BVCOrErr.takeError();
8610b57cec5SDimitry Andric   MachO::build_version_command BVC = BVCOrErr.get();
8620b57cec5SDimitry Andric   if (Load.C.cmdsize !=
8630b57cec5SDimitry Andric       sizeof(MachO::build_version_command) +
8640b57cec5SDimitry Andric           BVC.ntools * sizeof(MachO::build_tool_version))
8650b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8660b57cec5SDimitry Andric                           " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric   auto Start = Load.Ptr + sizeof(MachO::build_version_command);
8690b57cec5SDimitry Andric   BuildTools.resize(BVC.ntools);
8700b57cec5SDimitry Andric   for (unsigned i = 0; i < BVC.ntools; ++i)
8710b57cec5SDimitry Andric     BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   return Error::success();
8740b57cec5SDimitry Andric }
8750b57cec5SDimitry Andric 
checkRpathCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)8760b57cec5SDimitry Andric static Error checkRpathCommand(const MachOObjectFile &Obj,
8770b57cec5SDimitry Andric                                const MachOObjectFile::LoadCommandInfo &Load,
8780b57cec5SDimitry Andric                                uint32_t LoadCommandIndex) {
8790b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::rpath_command))
8800b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8810b57cec5SDimitry Andric                           " LC_RPATH cmdsize too small");
8820b57cec5SDimitry Andric   auto ROrErr = getStructOrErr<MachO::rpath_command>(Obj, Load.Ptr);
8830b57cec5SDimitry Andric   if (!ROrErr)
8840b57cec5SDimitry Andric     return ROrErr.takeError();
8850b57cec5SDimitry Andric   MachO::rpath_command R = ROrErr.get();
8860b57cec5SDimitry Andric   if (R.path < sizeof(MachO::rpath_command))
8870b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8880b57cec5SDimitry Andric                           " LC_RPATH path.offset field too small, not past "
8890b57cec5SDimitry Andric                           "the end of the rpath_command struct");
8900b57cec5SDimitry Andric   if (R.path >= R.cmdsize)
8910b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8920b57cec5SDimitry Andric                           " LC_RPATH path.offset field extends past the end "
8930b57cec5SDimitry Andric                           "of the load command");
8940b57cec5SDimitry Andric   // Make sure there is a null between the starting offset of the path and
8950b57cec5SDimitry Andric   // the end of the load command.
8960b57cec5SDimitry Andric   uint32_t i;
8970b57cec5SDimitry Andric   const char *P = (const char *)Load.Ptr;
8980b57cec5SDimitry Andric   for (i = R.path; i < R.cmdsize; i++)
8990b57cec5SDimitry Andric     if (P[i] == '\0')
9000b57cec5SDimitry Andric       break;
9010b57cec5SDimitry Andric   if (i >= R.cmdsize)
9020b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
9030b57cec5SDimitry Andric                           " LC_RPATH library name extends past the end of the "
9040b57cec5SDimitry Andric                           "load command");
9050b57cec5SDimitry Andric   return Error::success();
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
checkEncryptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,uint64_t cryptoff,uint64_t cryptsize,const char ** LoadCmd,const char * CmdName)9080b57cec5SDimitry Andric static Error checkEncryptCommand(const MachOObjectFile &Obj,
9090b57cec5SDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
9100b57cec5SDimitry Andric                                  uint32_t LoadCommandIndex,
9110b57cec5SDimitry Andric                                  uint64_t cryptoff, uint64_t cryptsize,
9120b57cec5SDimitry Andric                                  const char **LoadCmd, const char *CmdName) {
9130b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
9140b57cec5SDimitry Andric     return malformedError("more than one LC_ENCRYPTION_INFO and or "
9150b57cec5SDimitry Andric                           "LC_ENCRYPTION_INFO_64 command");
9160b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
9170b57cec5SDimitry Andric   if (cryptoff > FileSize)
9180b57cec5SDimitry Andric     return malformedError("cryptoff field of " + Twine(CmdName) +
9190b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
9200b57cec5SDimitry Andric                           "past the end of the file");
9210b57cec5SDimitry Andric   uint64_t BigSize = cryptoff;
9220b57cec5SDimitry Andric   BigSize += cryptsize;
9230b57cec5SDimitry Andric   if (BigSize > FileSize)
9240b57cec5SDimitry Andric     return malformedError("cryptoff field plus cryptsize field of " +
9250b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
9260b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
9270b57cec5SDimitry Andric                           "the file");
9280b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
9290b57cec5SDimitry Andric   return Error::success();
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
checkLinkerOptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)9320b57cec5SDimitry Andric static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
9330b57cec5SDimitry Andric                                    const MachOObjectFile::LoadCommandInfo &Load,
9340b57cec5SDimitry Andric                                    uint32_t LoadCommandIndex) {
9350b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
9360b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
9370b57cec5SDimitry Andric                           " LC_LINKER_OPTION cmdsize too small");
9380b57cec5SDimitry Andric   auto LinkOptionOrErr =
9390b57cec5SDimitry Andric     getStructOrErr<MachO::linker_option_command>(Obj, Load.Ptr);
9400b57cec5SDimitry Andric   if (!LinkOptionOrErr)
9410b57cec5SDimitry Andric     return LinkOptionOrErr.takeError();
9420b57cec5SDimitry Andric   MachO::linker_option_command L = LinkOptionOrErr.get();
9430b57cec5SDimitry Andric   // Make sure the count of strings is correct.
9440b57cec5SDimitry Andric   const char *string = (const char *)Load.Ptr +
9450b57cec5SDimitry Andric                        sizeof(struct MachO::linker_option_command);
9460b57cec5SDimitry Andric   uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
9470b57cec5SDimitry Andric   uint32_t i = 0;
9480b57cec5SDimitry Andric   while (left > 0) {
9490b57cec5SDimitry Andric     while (*string == '\0' && left > 0) {
9500b57cec5SDimitry Andric       string++;
9510b57cec5SDimitry Andric       left--;
9520b57cec5SDimitry Andric     }
9530b57cec5SDimitry Andric     if (left > 0) {
9540b57cec5SDimitry Andric       i++;
9550b57cec5SDimitry Andric       uint32_t NullPos = StringRef(string, left).find('\0');
9560b57cec5SDimitry Andric       if (0xffffffff == NullPos)
9570b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
9580b57cec5SDimitry Andric                               " LC_LINKER_OPTION string #" + Twine(i) +
9590b57cec5SDimitry Andric                               " is not NULL terminated");
9600b57cec5SDimitry Andric       uint32_t len = std::min(NullPos, left) + 1;
9610b57cec5SDimitry Andric       string += len;
9620b57cec5SDimitry Andric       left -= len;
9630b57cec5SDimitry Andric     }
9640b57cec5SDimitry Andric   }
9650b57cec5SDimitry Andric   if (L.count != i)
9660b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
9670b57cec5SDimitry Andric                           " LC_LINKER_OPTION string count " + Twine(L.count) +
9680b57cec5SDimitry Andric                           " does not match number of strings");
9690b57cec5SDimitry Andric   return Error::success();
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
checkSubCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName,size_t SizeOfCmd,const char * CmdStructName,uint32_t PathOffset,const char * PathFieldName)9720b57cec5SDimitry Andric static Error checkSubCommand(const MachOObjectFile &Obj,
9730b57cec5SDimitry Andric                              const MachOObjectFile::LoadCommandInfo &Load,
9740b57cec5SDimitry Andric                              uint32_t LoadCommandIndex, const char *CmdName,
9750b57cec5SDimitry Andric                              size_t SizeOfCmd, const char *CmdStructName,
9760b57cec5SDimitry Andric                              uint32_t PathOffset, const char *PathFieldName) {
9770b57cec5SDimitry Andric   if (PathOffset < SizeOfCmd)
9780b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
9790b57cec5SDimitry Andric                           CmdName + " " + PathFieldName + ".offset field too "
9800b57cec5SDimitry Andric                           "small, not past the end of the " + CmdStructName);
9810b57cec5SDimitry Andric   if (PathOffset >= Load.C.cmdsize)
9820b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
9830b57cec5SDimitry Andric                           CmdName + " " + PathFieldName + ".offset field "
9840b57cec5SDimitry Andric                           "extends past the end of the load command");
9850b57cec5SDimitry Andric   // Make sure there is a null between the starting offset of the path and
9860b57cec5SDimitry Andric   // the end of the load command.
9870b57cec5SDimitry Andric   uint32_t i;
9880b57cec5SDimitry Andric   const char *P = (const char *)Load.Ptr;
9890b57cec5SDimitry Andric   for (i = PathOffset; i < Load.C.cmdsize; i++)
9900b57cec5SDimitry Andric     if (P[i] == '\0')
9910b57cec5SDimitry Andric       break;
9920b57cec5SDimitry Andric   if (i >= Load.C.cmdsize)
9930b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
9940b57cec5SDimitry Andric                           CmdName + " " + PathFieldName + " name extends past "
9950b57cec5SDimitry Andric                           "the end of the load command");
9960b57cec5SDimitry Andric   return Error::success();
9970b57cec5SDimitry Andric }
9980b57cec5SDimitry Andric 
checkThreadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)9990b57cec5SDimitry Andric static Error checkThreadCommand(const MachOObjectFile &Obj,
10000b57cec5SDimitry Andric                                 const MachOObjectFile::LoadCommandInfo &Load,
10010b57cec5SDimitry Andric                                 uint32_t LoadCommandIndex,
10020b57cec5SDimitry Andric                                 const char *CmdName) {
10030b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::thread_command))
10040b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
10050b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
10060b57cec5SDimitry Andric   auto ThreadCommandOrErr =
10070b57cec5SDimitry Andric     getStructOrErr<MachO::thread_command>(Obj, Load.Ptr);
10080b57cec5SDimitry Andric   if (!ThreadCommandOrErr)
10090b57cec5SDimitry Andric     return ThreadCommandOrErr.takeError();
10100b57cec5SDimitry Andric   MachO::thread_command T = ThreadCommandOrErr.get();
10110b57cec5SDimitry Andric   const char *state = Load.Ptr + sizeof(MachO::thread_command);
10120b57cec5SDimitry Andric   const char *end = Load.Ptr + T.cmdsize;
10130b57cec5SDimitry Andric   uint32_t nflavor = 0;
10140b57cec5SDimitry Andric   uint32_t cputype = getCPUType(Obj);
10150b57cec5SDimitry Andric   while (state < end) {
10160b57cec5SDimitry Andric     if(state + sizeof(uint32_t) > end)
10170b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
10180b57cec5SDimitry Andric                             "flavor in " + CmdName + " extends past end of "
10190b57cec5SDimitry Andric                             "command");
10200b57cec5SDimitry Andric     uint32_t flavor;
10210b57cec5SDimitry Andric     memcpy(&flavor, state, sizeof(uint32_t));
10220b57cec5SDimitry Andric     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
10230b57cec5SDimitry Andric       sys::swapByteOrder(flavor);
10240b57cec5SDimitry Andric     state += sizeof(uint32_t);
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric     if(state + sizeof(uint32_t) > end)
10270b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
10280b57cec5SDimitry Andric                             " count in " + CmdName + " extends past end of "
10290b57cec5SDimitry Andric                             "command");
10300b57cec5SDimitry Andric     uint32_t count;
10310b57cec5SDimitry Andric     memcpy(&count, state, sizeof(uint32_t));
10320b57cec5SDimitry Andric     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
10330b57cec5SDimitry Andric       sys::swapByteOrder(count);
10340b57cec5SDimitry Andric     state += sizeof(uint32_t);
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric     if (cputype == MachO::CPU_TYPE_I386) {
10370b57cec5SDimitry Andric       if (flavor == MachO::x86_THREAD_STATE32) {
10380b57cec5SDimitry Andric         if (count != MachO::x86_THREAD_STATE32_COUNT)
10390b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10400b57cec5SDimitry Andric                                 " count not x86_THREAD_STATE32_COUNT for "
10410b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10420b57cec5SDimitry Andric                                 "a x86_THREAD_STATE32 flavor in " + CmdName +
10430b57cec5SDimitry Andric                                 " command");
10440b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_thread_state32_t) > end)
10450b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10460b57cec5SDimitry Andric                                 " x86_THREAD_STATE32 extends past end of "
10470b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
10480b57cec5SDimitry Andric         state += sizeof(MachO::x86_thread_state32_t);
10490b57cec5SDimitry Andric       } else {
10500b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
10510b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
10520b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
10530b57cec5SDimitry Andric                               CmdName + " command");
10540b57cec5SDimitry Andric       }
10550b57cec5SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_X86_64) {
10560b57cec5SDimitry Andric       if (flavor == MachO::x86_THREAD_STATE) {
10570b57cec5SDimitry Andric         if (count != MachO::x86_THREAD_STATE_COUNT)
10580b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10590b57cec5SDimitry Andric                                 " count not x86_THREAD_STATE_COUNT for "
10600b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10610b57cec5SDimitry Andric                                 "a x86_THREAD_STATE flavor in " + CmdName +
10620b57cec5SDimitry Andric                                 " command");
10630b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_thread_state_t) > end)
10640b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10650b57cec5SDimitry Andric                                 " x86_THREAD_STATE extends past end of "
10660b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
10670b57cec5SDimitry Andric         state += sizeof(MachO::x86_thread_state_t);
10680b57cec5SDimitry Andric       } else if (flavor == MachO::x86_FLOAT_STATE) {
10690b57cec5SDimitry Andric         if (count != MachO::x86_FLOAT_STATE_COUNT)
10700b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10710b57cec5SDimitry Andric                                 " count not x86_FLOAT_STATE_COUNT for "
10720b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10730b57cec5SDimitry Andric                                 "a x86_FLOAT_STATE flavor in " + CmdName +
10740b57cec5SDimitry Andric                                 " command");
10750b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_float_state_t) > end)
10760b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10770b57cec5SDimitry Andric                                 " x86_FLOAT_STATE extends past end of "
10780b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
10790b57cec5SDimitry Andric         state += sizeof(MachO::x86_float_state_t);
10800b57cec5SDimitry Andric       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
10810b57cec5SDimitry Andric         if (count != MachO::x86_EXCEPTION_STATE_COUNT)
10820b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10830b57cec5SDimitry Andric                                 " count not x86_EXCEPTION_STATE_COUNT for "
10840b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10850b57cec5SDimitry Andric                                 "a x86_EXCEPTION_STATE flavor in " + CmdName +
10860b57cec5SDimitry Andric                                 " command");
10870b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_exception_state_t) > end)
10880b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10890b57cec5SDimitry Andric                                 " x86_EXCEPTION_STATE extends past end of "
10900b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
10910b57cec5SDimitry Andric         state += sizeof(MachO::x86_exception_state_t);
10920b57cec5SDimitry Andric       } else if (flavor == MachO::x86_THREAD_STATE64) {
10930b57cec5SDimitry Andric         if (count != MachO::x86_THREAD_STATE64_COUNT)
10940b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10950b57cec5SDimitry Andric                                 " count not x86_THREAD_STATE64_COUNT for "
10960b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10970b57cec5SDimitry Andric                                 "a x86_THREAD_STATE64 flavor in " + CmdName +
10980b57cec5SDimitry Andric                                 " command");
10990b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_thread_state64_t) > end)
11000b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11010b57cec5SDimitry Andric                                 " x86_THREAD_STATE64 extends past end of "
11020b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11030b57cec5SDimitry Andric         state += sizeof(MachO::x86_thread_state64_t);
11040b57cec5SDimitry Andric       } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
11050b57cec5SDimitry Andric         if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
11060b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11070b57cec5SDimitry Andric                                 " count not x86_EXCEPTION_STATE64_COUNT for "
11080b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11090b57cec5SDimitry Andric                                 "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
11100b57cec5SDimitry Andric                                 " command");
11110b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_exception_state64_t) > end)
11120b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11130b57cec5SDimitry Andric                                 " x86_EXCEPTION_STATE64 extends past end of "
11140b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11150b57cec5SDimitry Andric         state += sizeof(MachO::x86_exception_state64_t);
11160b57cec5SDimitry Andric       } else {
11170b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
11180b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
11190b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
11200b57cec5SDimitry Andric                               CmdName + " command");
11210b57cec5SDimitry Andric       }
11220b57cec5SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_ARM) {
11230b57cec5SDimitry Andric       if (flavor == MachO::ARM_THREAD_STATE) {
11240b57cec5SDimitry Andric         if (count != MachO::ARM_THREAD_STATE_COUNT)
11250b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11260b57cec5SDimitry Andric                                 " count not ARM_THREAD_STATE_COUNT for "
11270b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11280b57cec5SDimitry Andric                                 "a ARM_THREAD_STATE flavor in " + CmdName +
11290b57cec5SDimitry Andric                                 " command");
11300b57cec5SDimitry Andric         if (state + sizeof(MachO::arm_thread_state32_t) > end)
11310b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11320b57cec5SDimitry Andric                                 " ARM_THREAD_STATE extends past end of "
11330b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11340b57cec5SDimitry Andric         state += sizeof(MachO::arm_thread_state32_t);
11350b57cec5SDimitry Andric       } else {
11360b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
11370b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
11380b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
11390b57cec5SDimitry Andric                               CmdName + " command");
11400b57cec5SDimitry Andric       }
11410b57cec5SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_ARM64 ||
11420b57cec5SDimitry Andric                cputype == MachO::CPU_TYPE_ARM64_32) {
11430b57cec5SDimitry Andric       if (flavor == MachO::ARM_THREAD_STATE64) {
11440b57cec5SDimitry Andric         if (count != MachO::ARM_THREAD_STATE64_COUNT)
11450b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11460b57cec5SDimitry Andric                                 " count not ARM_THREAD_STATE64_COUNT for "
11470b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11480b57cec5SDimitry Andric                                 "a ARM_THREAD_STATE64 flavor in " + CmdName +
11490b57cec5SDimitry Andric                                 " command");
11500b57cec5SDimitry Andric         if (state + sizeof(MachO::arm_thread_state64_t) > end)
11510b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11520b57cec5SDimitry Andric                                 " ARM_THREAD_STATE64 extends past end of "
11530b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11540b57cec5SDimitry Andric         state += sizeof(MachO::arm_thread_state64_t);
11550b57cec5SDimitry Andric       } else {
11560b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
11570b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
11580b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
11590b57cec5SDimitry Andric                               CmdName + " command");
11600b57cec5SDimitry Andric       }
11610b57cec5SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_POWERPC) {
11620b57cec5SDimitry Andric       if (flavor == MachO::PPC_THREAD_STATE) {
11630b57cec5SDimitry Andric         if (count != MachO::PPC_THREAD_STATE_COUNT)
11640b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11650b57cec5SDimitry Andric                                 " count not PPC_THREAD_STATE_COUNT for "
11660b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11670b57cec5SDimitry Andric                                 "a PPC_THREAD_STATE flavor in " + CmdName +
11680b57cec5SDimitry Andric                                 " command");
11690b57cec5SDimitry Andric         if (state + sizeof(MachO::ppc_thread_state32_t) > end)
11700b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11710b57cec5SDimitry Andric                                 " PPC_THREAD_STATE extends past end of "
11720b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11730b57cec5SDimitry Andric         state += sizeof(MachO::ppc_thread_state32_t);
11740b57cec5SDimitry Andric       } else {
11750b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
11760b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
11770b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
11780b57cec5SDimitry Andric                               CmdName + " command");
11790b57cec5SDimitry Andric       }
11800b57cec5SDimitry Andric     } else {
11810b57cec5SDimitry Andric       return malformedError("unknown cputype (" + Twine(cputype) + ") load "
11820b57cec5SDimitry Andric                             "command " + Twine(LoadCommandIndex) + " for " +
11830b57cec5SDimitry Andric                             CmdName + " command can't be checked");
11840b57cec5SDimitry Andric     }
11850b57cec5SDimitry Andric     nflavor++;
11860b57cec5SDimitry Andric   }
11870b57cec5SDimitry Andric   return Error::success();
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric 
checkTwoLevelHintsCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,std::list<MachOElement> & Elements)11900b57cec5SDimitry Andric static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
11910b57cec5SDimitry Andric                                        const MachOObjectFile::LoadCommandInfo
11920b57cec5SDimitry Andric                                          &Load,
11930b57cec5SDimitry Andric                                        uint32_t LoadCommandIndex,
11940b57cec5SDimitry Andric                                        const char **LoadCmd,
11950b57cec5SDimitry Andric                                        std::list<MachOElement> &Elements) {
11960b57cec5SDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
11970b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
11980b57cec5SDimitry Andric                           " LC_TWOLEVEL_HINTS has incorrect cmdsize");
11990b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
12000b57cec5SDimitry Andric     return malformedError("more than one LC_TWOLEVEL_HINTS command");
12010b57cec5SDimitry Andric   auto HintsOrErr = getStructOrErr<MachO::twolevel_hints_command>(Obj, Load.Ptr);
12020b57cec5SDimitry Andric   if(!HintsOrErr)
12030b57cec5SDimitry Andric     return HintsOrErr.takeError();
12040b57cec5SDimitry Andric   MachO::twolevel_hints_command Hints = HintsOrErr.get();
12050b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
12060b57cec5SDimitry Andric   if (Hints.offset > FileSize)
12070b57cec5SDimitry Andric     return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
12080b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
12090b57cec5SDimitry Andric                           "the file");
12100b57cec5SDimitry Andric   uint64_t BigSize = Hints.nhints;
12110b57cec5SDimitry Andric   BigSize *= sizeof(MachO::twolevel_hint);
12120b57cec5SDimitry Andric   BigSize += Hints.offset;
12130b57cec5SDimitry Andric   if (BigSize > FileSize)
12140b57cec5SDimitry Andric     return malformedError("offset field plus nhints times sizeof(struct "
12150b57cec5SDimitry Andric                           "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
12160b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
12170b57cec5SDimitry Andric                           "the file");
12180b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
12190b57cec5SDimitry Andric                                           sizeof(MachO::twolevel_hint),
12200b57cec5SDimitry Andric                                           "two level hints"))
12210b57cec5SDimitry Andric     return Err;
12220b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
12230b57cec5SDimitry Andric   return Error::success();
12240b57cec5SDimitry Andric }
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric // Returns true if the libObject code does not support the load command and its
12270b57cec5SDimitry Andric // contents.  The cmd value it is treated as an unknown load command but with
12280b57cec5SDimitry Andric // an error message that says the cmd value is obsolete.
isLoadCommandObsolete(uint32_t cmd)12290b57cec5SDimitry Andric static bool isLoadCommandObsolete(uint32_t cmd) {
12300b57cec5SDimitry Andric   if (cmd == MachO::LC_SYMSEG ||
12310b57cec5SDimitry Andric       cmd == MachO::LC_LOADFVMLIB ||
12320b57cec5SDimitry Andric       cmd == MachO::LC_IDFVMLIB ||
12330b57cec5SDimitry Andric       cmd == MachO::LC_IDENT ||
12340b57cec5SDimitry Andric       cmd == MachO::LC_FVMFILE ||
12350b57cec5SDimitry Andric       cmd == MachO::LC_PREPAGE ||
12360b57cec5SDimitry Andric       cmd == MachO::LC_PREBOUND_DYLIB ||
12370b57cec5SDimitry Andric       cmd == MachO::LC_TWOLEVEL_HINTS ||
12380b57cec5SDimitry Andric       cmd == MachO::LC_PREBIND_CKSUM)
12390b57cec5SDimitry Andric     return true;
12400b57cec5SDimitry Andric   return false;
12410b57cec5SDimitry Andric }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric Expected<std::unique_ptr<MachOObjectFile>>
create(MemoryBufferRef Object,bool IsLittleEndian,bool Is64Bits,uint32_t UniversalCputype,uint32_t UniversalIndex)12440b57cec5SDimitry Andric MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
12450b57cec5SDimitry Andric                         bool Is64Bits, uint32_t UniversalCputype,
12460b57cec5SDimitry Andric                         uint32_t UniversalIndex) {
12470b57cec5SDimitry Andric   Error Err = Error::success();
12480b57cec5SDimitry Andric   std::unique_ptr<MachOObjectFile> Obj(
12490b57cec5SDimitry Andric       new MachOObjectFile(std::move(Object), IsLittleEndian,
12500b57cec5SDimitry Andric                           Is64Bits, Err, UniversalCputype,
12510b57cec5SDimitry Andric                           UniversalIndex));
12520b57cec5SDimitry Andric   if (Err)
12530b57cec5SDimitry Andric     return std::move(Err);
12540b57cec5SDimitry Andric   return std::move(Obj);
12550b57cec5SDimitry Andric }
12560b57cec5SDimitry Andric 
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,Error & Err,uint32_t UniversalCputype,uint32_t UniversalIndex)12570b57cec5SDimitry Andric MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
12580b57cec5SDimitry Andric                                  bool Is64bits, Error &Err,
12590b57cec5SDimitry Andric                                  uint32_t UniversalCputype,
12600b57cec5SDimitry Andric                                  uint32_t UniversalIndex)
12610b57cec5SDimitry Andric     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
12620b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
12630b57cec5SDimitry Andric   uint64_t SizeOfHeaders;
12640b57cec5SDimitry Andric   uint32_t cputype;
12650b57cec5SDimitry Andric   if (is64Bit()) {
12660b57cec5SDimitry Andric     parseHeader(*this, Header64, Err);
12670b57cec5SDimitry Andric     SizeOfHeaders = sizeof(MachO::mach_header_64);
12680b57cec5SDimitry Andric     cputype = Header64.cputype;
12690b57cec5SDimitry Andric   } else {
12700b57cec5SDimitry Andric     parseHeader(*this, Header, Err);
12710b57cec5SDimitry Andric     SizeOfHeaders = sizeof(MachO::mach_header);
12720b57cec5SDimitry Andric     cputype = Header.cputype;
12730b57cec5SDimitry Andric   }
12740b57cec5SDimitry Andric   if (Err)
12750b57cec5SDimitry Andric     return;
12760b57cec5SDimitry Andric   SizeOfHeaders += getHeader().sizeofcmds;
12770b57cec5SDimitry Andric   if (getData().data() + SizeOfHeaders > getData().end()) {
12780b57cec5SDimitry Andric     Err = malformedError("load commands extend past the end of the file");
12790b57cec5SDimitry Andric     return;
12800b57cec5SDimitry Andric   }
12810b57cec5SDimitry Andric   if (UniversalCputype != 0 && cputype != UniversalCputype) {
12820b57cec5SDimitry Andric     Err = malformedError("universal header architecture: " +
12830b57cec5SDimitry Andric                          Twine(UniversalIndex) + "'s cputype does not match "
12840b57cec5SDimitry Andric                          "object file's mach header");
12850b57cec5SDimitry Andric     return;
12860b57cec5SDimitry Andric   }
12870b57cec5SDimitry Andric   std::list<MachOElement> Elements;
12880b57cec5SDimitry Andric   Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric   uint32_t LoadCommandCount = getHeader().ncmds;
12910b57cec5SDimitry Andric   LoadCommandInfo Load;
12920b57cec5SDimitry Andric   if (LoadCommandCount != 0) {
12930b57cec5SDimitry Andric     if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
12940b57cec5SDimitry Andric       Load = *LoadOrErr;
12950b57cec5SDimitry Andric     else {
12960b57cec5SDimitry Andric       Err = LoadOrErr.takeError();
12970b57cec5SDimitry Andric       return;
12980b57cec5SDimitry Andric     }
12990b57cec5SDimitry Andric   }
13000b57cec5SDimitry Andric 
13010b57cec5SDimitry Andric   const char *DyldIdLoadCmd = nullptr;
13020b57cec5SDimitry Andric   const char *FuncStartsLoadCmd = nullptr;
13030b57cec5SDimitry Andric   const char *SplitInfoLoadCmd = nullptr;
13040b57cec5SDimitry Andric   const char *CodeSignDrsLoadCmd = nullptr;
13050b57cec5SDimitry Andric   const char *CodeSignLoadCmd = nullptr;
13060b57cec5SDimitry Andric   const char *VersLoadCmd = nullptr;
13070b57cec5SDimitry Andric   const char *SourceLoadCmd = nullptr;
13080b57cec5SDimitry Andric   const char *EntryPointLoadCmd = nullptr;
13090b57cec5SDimitry Andric   const char *EncryptLoadCmd = nullptr;
13100b57cec5SDimitry Andric   const char *RoutinesLoadCmd = nullptr;
13110b57cec5SDimitry Andric   const char *UnixThreadLoadCmd = nullptr;
13120b57cec5SDimitry Andric   const char *TwoLevelHintsLoadCmd = nullptr;
13130b57cec5SDimitry Andric   for (unsigned I = 0; I < LoadCommandCount; ++I) {
13140b57cec5SDimitry Andric     if (is64Bit()) {
13150b57cec5SDimitry Andric       if (Load.C.cmdsize % 8 != 0) {
13160b57cec5SDimitry Andric         // We have a hack here to allow 64-bit Mach-O core files to have
13170b57cec5SDimitry Andric         // LC_THREAD commands that are only a multiple of 4 and not 8 to be
13180b57cec5SDimitry Andric         // allowed since the macOS kernel produces them.
13190b57cec5SDimitry Andric         if (getHeader().filetype != MachO::MH_CORE ||
13200b57cec5SDimitry Andric             Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
13210b57cec5SDimitry Andric           Err = malformedError("load command " + Twine(I) + " cmdsize not a "
13220b57cec5SDimitry Andric                                "multiple of 8");
13230b57cec5SDimitry Andric           return;
13240b57cec5SDimitry Andric         }
13250b57cec5SDimitry Andric       }
13260b57cec5SDimitry Andric     } else {
13270b57cec5SDimitry Andric       if (Load.C.cmdsize % 4 != 0) {
13280b57cec5SDimitry Andric         Err = malformedError("load command " + Twine(I) + " cmdsize not a "
13290b57cec5SDimitry Andric                              "multiple of 4");
13300b57cec5SDimitry Andric         return;
13310b57cec5SDimitry Andric       }
13320b57cec5SDimitry Andric     }
13330b57cec5SDimitry Andric     LoadCommands.push_back(Load);
13340b57cec5SDimitry Andric     if (Load.C.cmd == MachO::LC_SYMTAB) {
13350b57cec5SDimitry Andric       if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
13360b57cec5SDimitry Andric         return;
13370b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
13380b57cec5SDimitry Andric       if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
13390b57cec5SDimitry Andric                                       Elements)))
13400b57cec5SDimitry Andric         return;
13410b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
13420b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
13430b57cec5SDimitry Andric                                           "LC_DATA_IN_CODE", Elements,
13440b57cec5SDimitry Andric                                           "data in code info")))
13450b57cec5SDimitry Andric         return;
13460b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
13470b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
13480b57cec5SDimitry Andric                                           "LC_LINKER_OPTIMIZATION_HINT",
13490b57cec5SDimitry Andric                                           Elements, "linker optimization "
13500b57cec5SDimitry Andric                                           "hints")))
13510b57cec5SDimitry Andric         return;
13520b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
13530b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
13540b57cec5SDimitry Andric                                           "LC_FUNCTION_STARTS", Elements,
13550b57cec5SDimitry Andric                                           "function starts data")))
13560b57cec5SDimitry Andric         return;
13570b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
13580b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
13590b57cec5SDimitry Andric                                           "LC_SEGMENT_SPLIT_INFO", Elements,
13600b57cec5SDimitry Andric                                           "split info data")))
13610b57cec5SDimitry Andric         return;
13620b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
13630b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
13640b57cec5SDimitry Andric                                           "LC_DYLIB_CODE_SIGN_DRS", Elements,
13650b57cec5SDimitry Andric                                           "code signing RDs data")))
13660b57cec5SDimitry Andric         return;
13670b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
13680b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
13690b57cec5SDimitry Andric                                           "LC_CODE_SIGNATURE", Elements,
13700b57cec5SDimitry Andric                                           "code signature data")))
13710b57cec5SDimitry Andric         return;
13720b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
13730b57cec5SDimitry Andric       if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
13740b57cec5SDimitry Andric                                       "LC_DYLD_INFO", Elements)))
13750b57cec5SDimitry Andric         return;
13760b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
13770b57cec5SDimitry Andric       if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
13780b57cec5SDimitry Andric                                       "LC_DYLD_INFO_ONLY", Elements)))
13790b57cec5SDimitry Andric         return;
13800b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_UUID) {
13810b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
13820b57cec5SDimitry Andric         Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
13830b57cec5SDimitry Andric                              "cmdsize");
13840b57cec5SDimitry Andric         return;
13850b57cec5SDimitry Andric       }
13860b57cec5SDimitry Andric       if (UuidLoadCmd) {
13870b57cec5SDimitry Andric         Err = malformedError("more than one LC_UUID command");
13880b57cec5SDimitry Andric         return;
13890b57cec5SDimitry Andric       }
13900b57cec5SDimitry Andric       UuidLoadCmd = Load.Ptr;
13910b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
13920b57cec5SDimitry Andric       if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
13930b57cec5SDimitry Andric                                          MachO::section_64>(
13940b57cec5SDimitry Andric                    *this, Load, Sections, HasPageZeroSegment, I,
13950b57cec5SDimitry Andric                    "LC_SEGMENT_64", SizeOfHeaders, Elements)))
13960b57cec5SDimitry Andric         return;
13970b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
13980b57cec5SDimitry Andric       if ((Err = parseSegmentLoadCommand<MachO::segment_command,
13990b57cec5SDimitry Andric                                          MachO::section>(
14000b57cec5SDimitry Andric                    *this, Load, Sections, HasPageZeroSegment, I,
14010b57cec5SDimitry Andric                    "LC_SEGMENT", SizeOfHeaders, Elements)))
14020b57cec5SDimitry Andric         return;
14030b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
14040b57cec5SDimitry Andric       if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
14050b57cec5SDimitry Andric         return;
14060b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
14070b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
14080b57cec5SDimitry Andric         return;
14090b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14100b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
14110b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
14120b57cec5SDimitry Andric         return;
14130b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14140b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
14150b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
14160b57cec5SDimitry Andric         return;
14170b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14180b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
14190b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
14200b57cec5SDimitry Andric         return;
14210b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14220b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
14230b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
14240b57cec5SDimitry Andric         return;
14250b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14260b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
14270b57cec5SDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
14280b57cec5SDimitry Andric         return;
14290b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
14300b57cec5SDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
14310b57cec5SDimitry Andric         return;
14320b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
14330b57cec5SDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
14340b57cec5SDimitry Andric         return;
14350b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
14360b57cec5SDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
14370b57cec5SDimitry Andric                                   "LC_VERSION_MIN_MACOSX")))
14380b57cec5SDimitry Andric         return;
14390b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
14400b57cec5SDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
14410b57cec5SDimitry Andric                                   "LC_VERSION_MIN_IPHONEOS")))
14420b57cec5SDimitry Andric         return;
14430b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
14440b57cec5SDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
14450b57cec5SDimitry Andric                                   "LC_VERSION_MIN_TVOS")))
14460b57cec5SDimitry Andric         return;
14470b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
14480b57cec5SDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
14490b57cec5SDimitry Andric                                   "LC_VERSION_MIN_WATCHOS")))
14500b57cec5SDimitry Andric         return;
14510b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_NOTE) {
14520b57cec5SDimitry Andric       if ((Err = checkNoteCommand(*this, Load, I, Elements)))
14530b57cec5SDimitry Andric         return;
14540b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
14550b57cec5SDimitry Andric       if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
14560b57cec5SDimitry Andric         return;
14570b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_RPATH) {
14580b57cec5SDimitry Andric       if ((Err = checkRpathCommand(*this, Load, I)))
14590b57cec5SDimitry Andric         return;
14600b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
14610b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
14620b57cec5SDimitry Andric         Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
14630b57cec5SDimitry Andric                              " has incorrect cmdsize");
14640b57cec5SDimitry Andric         return;
14650b57cec5SDimitry Andric       }
14660b57cec5SDimitry Andric       if (SourceLoadCmd) {
14670b57cec5SDimitry Andric         Err = malformedError("more than one LC_SOURCE_VERSION command");
14680b57cec5SDimitry Andric         return;
14690b57cec5SDimitry Andric       }
14700b57cec5SDimitry Andric       SourceLoadCmd = Load.Ptr;
14710b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_MAIN) {
14720b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
14730b57cec5SDimitry Andric         Err = malformedError("LC_MAIN command " + Twine(I) +
14740b57cec5SDimitry Andric                              " has incorrect cmdsize");
14750b57cec5SDimitry Andric         return;
14760b57cec5SDimitry Andric       }
14770b57cec5SDimitry Andric       if (EntryPointLoadCmd) {
14780b57cec5SDimitry Andric         Err = malformedError("more than one LC_MAIN command");
14790b57cec5SDimitry Andric         return;
14800b57cec5SDimitry Andric       }
14810b57cec5SDimitry Andric       EntryPointLoadCmd = Load.Ptr;
14820b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
14830b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
14840b57cec5SDimitry Andric         Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
14850b57cec5SDimitry Andric                              " has incorrect cmdsize");
14860b57cec5SDimitry Andric         return;
14870b57cec5SDimitry Andric       }
14880b57cec5SDimitry Andric       MachO::encryption_info_command E =
14890b57cec5SDimitry Andric         getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
14900b57cec5SDimitry Andric       if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
14910b57cec5SDimitry Andric                                      &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
14920b57cec5SDimitry Andric         return;
14930b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
14940b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
14950b57cec5SDimitry Andric         Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
14960b57cec5SDimitry Andric                              " has incorrect cmdsize");
14970b57cec5SDimitry Andric         return;
14980b57cec5SDimitry Andric       }
14990b57cec5SDimitry Andric       MachO::encryption_info_command_64 E =
15000b57cec5SDimitry Andric         getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
15010b57cec5SDimitry Andric       if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
15020b57cec5SDimitry Andric                                      &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
15030b57cec5SDimitry Andric         return;
15040b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
15050b57cec5SDimitry Andric       if ((Err = checkLinkerOptCommand(*this, Load, I)))
15060b57cec5SDimitry Andric         return;
15070b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
15080b57cec5SDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
15090b57cec5SDimitry Andric         Err =  malformedError("load command " + Twine(I) +
15100b57cec5SDimitry Andric                               " LC_SUB_FRAMEWORK cmdsize too small");
15110b57cec5SDimitry Andric         return;
15120b57cec5SDimitry Andric       }
15130b57cec5SDimitry Andric       MachO::sub_framework_command S =
15140b57cec5SDimitry Andric         getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
15150b57cec5SDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
15160b57cec5SDimitry Andric                                  sizeof(MachO::sub_framework_command),
15170b57cec5SDimitry Andric                                  "sub_framework_command", S.umbrella,
15180b57cec5SDimitry Andric                                  "umbrella")))
15190b57cec5SDimitry Andric         return;
15200b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
15210b57cec5SDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
15220b57cec5SDimitry Andric         Err =  malformedError("load command " + Twine(I) +
15230b57cec5SDimitry Andric                               " LC_SUB_UMBRELLA cmdsize too small");
15240b57cec5SDimitry Andric         return;
15250b57cec5SDimitry Andric       }
15260b57cec5SDimitry Andric       MachO::sub_umbrella_command S =
15270b57cec5SDimitry Andric         getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
15280b57cec5SDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
15290b57cec5SDimitry Andric                                  sizeof(MachO::sub_umbrella_command),
15300b57cec5SDimitry Andric                                  "sub_umbrella_command", S.sub_umbrella,
15310b57cec5SDimitry Andric                                  "sub_umbrella")))
15320b57cec5SDimitry Andric         return;
15330b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
15340b57cec5SDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
15350b57cec5SDimitry Andric         Err =  malformedError("load command " + Twine(I) +
15360b57cec5SDimitry Andric                               " LC_SUB_LIBRARY cmdsize too small");
15370b57cec5SDimitry Andric         return;
15380b57cec5SDimitry Andric       }
15390b57cec5SDimitry Andric       MachO::sub_library_command S =
15400b57cec5SDimitry Andric         getStruct<MachO::sub_library_command>(*this, Load.Ptr);
15410b57cec5SDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
15420b57cec5SDimitry Andric                                  sizeof(MachO::sub_library_command),
15430b57cec5SDimitry Andric                                  "sub_library_command", S.sub_library,
15440b57cec5SDimitry Andric                                  "sub_library")))
15450b57cec5SDimitry Andric         return;
15460b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
15470b57cec5SDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
15480b57cec5SDimitry Andric         Err =  malformedError("load command " + Twine(I) +
15490b57cec5SDimitry Andric                               " LC_SUB_CLIENT cmdsize too small");
15500b57cec5SDimitry Andric         return;
15510b57cec5SDimitry Andric       }
15520b57cec5SDimitry Andric       MachO::sub_client_command S =
15530b57cec5SDimitry Andric         getStruct<MachO::sub_client_command>(*this, Load.Ptr);
15540b57cec5SDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
15550b57cec5SDimitry Andric                                  sizeof(MachO::sub_client_command),
15560b57cec5SDimitry Andric                                  "sub_client_command", S.client, "client")))
15570b57cec5SDimitry Andric         return;
15580b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ROUTINES) {
15590b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
15600b57cec5SDimitry Andric         Err = malformedError("LC_ROUTINES command " + Twine(I) +
15610b57cec5SDimitry Andric                              " has incorrect cmdsize");
15620b57cec5SDimitry Andric         return;
15630b57cec5SDimitry Andric       }
15640b57cec5SDimitry Andric       if (RoutinesLoadCmd) {
15650b57cec5SDimitry Andric         Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
15660b57cec5SDimitry Andric                              "command");
15670b57cec5SDimitry Andric         return;
15680b57cec5SDimitry Andric       }
15690b57cec5SDimitry Andric       RoutinesLoadCmd = Load.Ptr;
15700b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
15710b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
15720b57cec5SDimitry Andric         Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
15730b57cec5SDimitry Andric                              " has incorrect cmdsize");
15740b57cec5SDimitry Andric         return;
15750b57cec5SDimitry Andric       }
15760b57cec5SDimitry Andric       if (RoutinesLoadCmd) {
15770b57cec5SDimitry Andric         Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
15780b57cec5SDimitry Andric                              "command");
15790b57cec5SDimitry Andric         return;
15800b57cec5SDimitry Andric       }
15810b57cec5SDimitry Andric       RoutinesLoadCmd = Load.Ptr;
15820b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
15830b57cec5SDimitry Andric       if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
15840b57cec5SDimitry Andric         return;
15850b57cec5SDimitry Andric       if (UnixThreadLoadCmd) {
15860b57cec5SDimitry Andric         Err = malformedError("more than one LC_UNIXTHREAD command");
15870b57cec5SDimitry Andric         return;
15880b57cec5SDimitry Andric       }
15890b57cec5SDimitry Andric       UnixThreadLoadCmd = Load.Ptr;
15900b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_THREAD) {
15910b57cec5SDimitry Andric       if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
15920b57cec5SDimitry Andric         return;
15930b57cec5SDimitry Andric     // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
15940b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
15950b57cec5SDimitry Andric        if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
15960b57cec5SDimitry Andric                                             &TwoLevelHintsLoadCmd, Elements)))
15970b57cec5SDimitry Andric          return;
1598af732203SDimitry Andric     } else if (Load.C.cmd == MachO::LC_IDENT) {
1599af732203SDimitry Andric       // Note: LC_IDENT is ignored.
1600af732203SDimitry Andric       continue;
16010b57cec5SDimitry Andric     } else if (isLoadCommandObsolete(Load.C.cmd)) {
16020b57cec5SDimitry Andric       Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
16030b57cec5SDimitry Andric                            Twine(Load.C.cmd) + " is obsolete and not "
16040b57cec5SDimitry Andric                            "supported");
16050b57cec5SDimitry Andric       return;
16060b57cec5SDimitry Andric     }
16070b57cec5SDimitry Andric     // TODO: generate a error for unknown load commands by default.  But still
16080b57cec5SDimitry Andric     // need work out an approach to allow or not allow unknown values like this
16090b57cec5SDimitry Andric     // as an option for some uses like lldb.
16100b57cec5SDimitry Andric     if (I < LoadCommandCount - 1) {
16110b57cec5SDimitry Andric       if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
16120b57cec5SDimitry Andric         Load = *LoadOrErr;
16130b57cec5SDimitry Andric       else {
16140b57cec5SDimitry Andric         Err = LoadOrErr.takeError();
16150b57cec5SDimitry Andric         return;
16160b57cec5SDimitry Andric       }
16170b57cec5SDimitry Andric     }
16180b57cec5SDimitry Andric   }
16190b57cec5SDimitry Andric   if (!SymtabLoadCmd) {
16200b57cec5SDimitry Andric     if (DysymtabLoadCmd) {
16210b57cec5SDimitry Andric       Err = malformedError("contains LC_DYSYMTAB load command without a "
16220b57cec5SDimitry Andric                            "LC_SYMTAB load command");
16230b57cec5SDimitry Andric       return;
16240b57cec5SDimitry Andric     }
16250b57cec5SDimitry Andric   } else if (DysymtabLoadCmd) {
16260b57cec5SDimitry Andric     MachO::symtab_command Symtab =
16270b57cec5SDimitry Andric       getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
16280b57cec5SDimitry Andric     MachO::dysymtab_command Dysymtab =
16290b57cec5SDimitry Andric       getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
16300b57cec5SDimitry Andric     if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
16310b57cec5SDimitry Andric       Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
16320b57cec5SDimitry Andric                            "extends past the end of the symbol table");
16330b57cec5SDimitry Andric       return;
16340b57cec5SDimitry Andric     }
16350b57cec5SDimitry Andric     uint64_t BigSize = Dysymtab.ilocalsym;
16360b57cec5SDimitry Andric     BigSize += Dysymtab.nlocalsym;
16370b57cec5SDimitry Andric     if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
16380b57cec5SDimitry Andric       Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
16390b57cec5SDimitry Andric                            "command extends past the end of the symbol table");
16400b57cec5SDimitry Andric       return;
16410b57cec5SDimitry Andric     }
16420b57cec5SDimitry Andric     if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
16430b57cec5SDimitry Andric       Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
16440b57cec5SDimitry Andric                            "extends past the end of the symbol table");
16450b57cec5SDimitry Andric       return;
16460b57cec5SDimitry Andric     }
16470b57cec5SDimitry Andric     BigSize = Dysymtab.iextdefsym;
16480b57cec5SDimitry Andric     BigSize += Dysymtab.nextdefsym;
16490b57cec5SDimitry Andric     if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
16500b57cec5SDimitry Andric       Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
16510b57cec5SDimitry Andric                            "load command extends past the end of the symbol "
16520b57cec5SDimitry Andric                            "table");
16530b57cec5SDimitry Andric       return;
16540b57cec5SDimitry Andric     }
16550b57cec5SDimitry Andric     if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
16560b57cec5SDimitry Andric       Err = malformedError("iundefsym in LC_DYSYMTAB load command "
16570b57cec5SDimitry Andric                            "extends past the end of the symbol table");
16580b57cec5SDimitry Andric       return;
16590b57cec5SDimitry Andric     }
16600b57cec5SDimitry Andric     BigSize = Dysymtab.iundefsym;
16610b57cec5SDimitry Andric     BigSize += Dysymtab.nundefsym;
16620b57cec5SDimitry Andric     if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
16630b57cec5SDimitry Andric       Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
16640b57cec5SDimitry Andric                            " command extends past the end of the symbol table");
16650b57cec5SDimitry Andric       return;
16660b57cec5SDimitry Andric     }
16670b57cec5SDimitry Andric   }
16680b57cec5SDimitry Andric   if ((getHeader().filetype == MachO::MH_DYLIB ||
16690b57cec5SDimitry Andric        getHeader().filetype == MachO::MH_DYLIB_STUB) &&
16700b57cec5SDimitry Andric        DyldIdLoadCmd == nullptr) {
16710b57cec5SDimitry Andric     Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
16720b57cec5SDimitry Andric                          "filetype");
16730b57cec5SDimitry Andric     return;
16740b57cec5SDimitry Andric   }
16750b57cec5SDimitry Andric   assert(LoadCommands.size() == LoadCommandCount);
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric   Err = Error::success();
16780b57cec5SDimitry Andric }
16790b57cec5SDimitry Andric 
checkSymbolTable() const16800b57cec5SDimitry Andric Error MachOObjectFile::checkSymbolTable() const {
16810b57cec5SDimitry Andric   uint32_t Flags = 0;
16820b57cec5SDimitry Andric   if (is64Bit()) {
16830b57cec5SDimitry Andric     MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
16840b57cec5SDimitry Andric     Flags = H_64.flags;
16850b57cec5SDimitry Andric   } else {
16860b57cec5SDimitry Andric     MachO::mach_header H = MachOObjectFile::getHeader();
16870b57cec5SDimitry Andric     Flags = H.flags;
16880b57cec5SDimitry Andric   }
16890b57cec5SDimitry Andric   uint8_t NType = 0;
16900b57cec5SDimitry Andric   uint8_t NSect = 0;
16910b57cec5SDimitry Andric   uint16_t NDesc = 0;
16920b57cec5SDimitry Andric   uint32_t NStrx = 0;
16930b57cec5SDimitry Andric   uint64_t NValue = 0;
16940b57cec5SDimitry Andric   uint32_t SymbolIndex = 0;
16950b57cec5SDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
16960b57cec5SDimitry Andric   for (const SymbolRef &Symbol : symbols()) {
16970b57cec5SDimitry Andric     DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
16980b57cec5SDimitry Andric     if (is64Bit()) {
16990b57cec5SDimitry Andric       MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
17000b57cec5SDimitry Andric       NType = STE_64.n_type;
17010b57cec5SDimitry Andric       NSect = STE_64.n_sect;
17020b57cec5SDimitry Andric       NDesc = STE_64.n_desc;
17030b57cec5SDimitry Andric       NStrx = STE_64.n_strx;
17040b57cec5SDimitry Andric       NValue = STE_64.n_value;
17050b57cec5SDimitry Andric     } else {
17060b57cec5SDimitry Andric       MachO::nlist STE = getSymbolTableEntry(SymDRI);
17070b57cec5SDimitry Andric       NType = STE.n_type;
17080b57cec5SDimitry Andric       NSect = STE.n_sect;
17090b57cec5SDimitry Andric       NDesc = STE.n_desc;
17100b57cec5SDimitry Andric       NStrx = STE.n_strx;
17110b57cec5SDimitry Andric       NValue = STE.n_value;
17120b57cec5SDimitry Andric     }
17130b57cec5SDimitry Andric     if ((NType & MachO::N_STAB) == 0) {
17140b57cec5SDimitry Andric       if ((NType & MachO::N_TYPE) == MachO::N_SECT) {
17150b57cec5SDimitry Andric         if (NSect == 0 || NSect > Sections.size())
17160b57cec5SDimitry Andric           return malformedError("bad section index: " + Twine((int)NSect) +
17170b57cec5SDimitry Andric                                 " for symbol at index " + Twine(SymbolIndex));
17180b57cec5SDimitry Andric       }
17190b57cec5SDimitry Andric       if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
17200b57cec5SDimitry Andric         if (NValue >= S.strsize)
17210b57cec5SDimitry Andric           return malformedError("bad n_value: " + Twine((int)NValue) + " past "
17220b57cec5SDimitry Andric                                 "the end of string table, for N_INDR symbol at "
17230b57cec5SDimitry Andric                                 "index " + Twine(SymbolIndex));
17240b57cec5SDimitry Andric       }
17250b57cec5SDimitry Andric       if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
17260b57cec5SDimitry Andric           (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
17270b57cec5SDimitry Andric            (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
17280b57cec5SDimitry Andric             uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
17290b57cec5SDimitry Andric             if (LibraryOrdinal != 0 &&
17300b57cec5SDimitry Andric                 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
17310b57cec5SDimitry Andric                 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
17320b57cec5SDimitry Andric                 LibraryOrdinal - 1 >= Libraries.size() ) {
17330b57cec5SDimitry Andric               return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
17340b57cec5SDimitry Andric                                     " for symbol at index " + Twine(SymbolIndex));
17350b57cec5SDimitry Andric             }
17360b57cec5SDimitry Andric           }
17370b57cec5SDimitry Andric     }
17380b57cec5SDimitry Andric     if (NStrx >= S.strsize)
17390b57cec5SDimitry Andric       return malformedError("bad string table index: " + Twine((int)NStrx) +
17400b57cec5SDimitry Andric                             " past the end of string table, for symbol at "
17410b57cec5SDimitry Andric                             "index " + Twine(SymbolIndex));
17420b57cec5SDimitry Andric     SymbolIndex++;
17430b57cec5SDimitry Andric   }
17440b57cec5SDimitry Andric   return Error::success();
17450b57cec5SDimitry Andric }
17460b57cec5SDimitry Andric 
moveSymbolNext(DataRefImpl & Symb) const17470b57cec5SDimitry Andric void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
17480b57cec5SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
17490b57cec5SDimitry Andric     sizeof(MachO::nlist_64) :
17500b57cec5SDimitry Andric     sizeof(MachO::nlist);
17510b57cec5SDimitry Andric   Symb.p += SymbolTableEntrySize;
17520b57cec5SDimitry Andric }
17530b57cec5SDimitry Andric 
getSymbolName(DataRefImpl Symb) const17540b57cec5SDimitry Andric Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
17550b57cec5SDimitry Andric   StringRef StringTable = getStringTableData();
17560b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
17570b57cec5SDimitry Andric   if (Entry.n_strx == 0)
17580b57cec5SDimitry Andric     // A n_strx value of 0 indicates that no name is associated with a
17590b57cec5SDimitry Andric     // particular symbol table entry.
17600b57cec5SDimitry Andric     return StringRef();
17610b57cec5SDimitry Andric   const char *Start = &StringTable.data()[Entry.n_strx];
17620b57cec5SDimitry Andric   if (Start < getData().begin() || Start >= getData().end()) {
17630b57cec5SDimitry Andric     return malformedError("bad string index: " + Twine(Entry.n_strx) +
17640b57cec5SDimitry Andric                           " for symbol at index " + Twine(getSymbolIndex(Symb)));
17650b57cec5SDimitry Andric   }
17660b57cec5SDimitry Andric   return StringRef(Start);
17670b57cec5SDimitry Andric }
17680b57cec5SDimitry Andric 
getSectionType(SectionRef Sec) const17690b57cec5SDimitry Andric unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
17700b57cec5SDimitry Andric   DataRefImpl DRI = Sec.getRawDataRefImpl();
17710b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, DRI);
17720b57cec5SDimitry Andric   return Flags & MachO::SECTION_TYPE;
17730b57cec5SDimitry Andric }
17740b57cec5SDimitry Andric 
getNValue(DataRefImpl Sym) const17750b57cec5SDimitry Andric uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
17760b57cec5SDimitry Andric   if (is64Bit()) {
17770b57cec5SDimitry Andric     MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
17780b57cec5SDimitry Andric     return Entry.n_value;
17790b57cec5SDimitry Andric   }
17800b57cec5SDimitry Andric   MachO::nlist Entry = getSymbolTableEntry(Sym);
17810b57cec5SDimitry Andric   return Entry.n_value;
17820b57cec5SDimitry Andric }
17830b57cec5SDimitry Andric 
17840b57cec5SDimitry Andric // getIndirectName() returns the name of the alias'ed symbol who's string table
17850b57cec5SDimitry Andric // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const17860b57cec5SDimitry Andric std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
17870b57cec5SDimitry Andric                                                  StringRef &Res) const {
17880b57cec5SDimitry Andric   StringRef StringTable = getStringTableData();
17890b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
17900b57cec5SDimitry Andric   if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
17910b57cec5SDimitry Andric     return object_error::parse_failed;
17920b57cec5SDimitry Andric   uint64_t NValue = getNValue(Symb);
17930b57cec5SDimitry Andric   if (NValue >= StringTable.size())
17940b57cec5SDimitry Andric     return object_error::parse_failed;
17950b57cec5SDimitry Andric   const char *Start = &StringTable.data()[NValue];
17960b57cec5SDimitry Andric   Res = StringRef(Start);
17970b57cec5SDimitry Andric   return std::error_code();
17980b57cec5SDimitry Andric }
17990b57cec5SDimitry Andric 
getSymbolValueImpl(DataRefImpl Sym) const18000b57cec5SDimitry Andric uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
18010b57cec5SDimitry Andric   return getNValue(Sym);
18020b57cec5SDimitry Andric }
18030b57cec5SDimitry Andric 
getSymbolAddress(DataRefImpl Sym) const18040b57cec5SDimitry Andric Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
18050b57cec5SDimitry Andric   return getSymbolValue(Sym);
18060b57cec5SDimitry Andric }
18070b57cec5SDimitry Andric 
getSymbolAlignment(DataRefImpl DRI) const18080b57cec5SDimitry Andric uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
18095ffd83dbSDimitry Andric   uint32_t Flags = cantFail(getSymbolFlags(DRI));
18105ffd83dbSDimitry Andric   if (Flags & SymbolRef::SF_Common) {
18110b57cec5SDimitry Andric     MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
18120b57cec5SDimitry Andric     return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
18130b57cec5SDimitry Andric   }
18140b57cec5SDimitry Andric   return 0;
18150b57cec5SDimitry Andric }
18160b57cec5SDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl DRI) const18170b57cec5SDimitry Andric uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
18180b57cec5SDimitry Andric   return getNValue(DRI);
18190b57cec5SDimitry Andric }
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const18220b57cec5SDimitry Andric MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
18230b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
18240b57cec5SDimitry Andric   uint8_t n_type = Entry.n_type;
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric   // If this is a STAB debugging symbol, we can do nothing more.
18270b57cec5SDimitry Andric   if (n_type & MachO::N_STAB)
18280b57cec5SDimitry Andric     return SymbolRef::ST_Debug;
18290b57cec5SDimitry Andric 
18300b57cec5SDimitry Andric   switch (n_type & MachO::N_TYPE) {
18310b57cec5SDimitry Andric     case MachO::N_UNDF :
18320b57cec5SDimitry Andric       return SymbolRef::ST_Unknown;
18330b57cec5SDimitry Andric     case MachO::N_SECT :
18340b57cec5SDimitry Andric       Expected<section_iterator> SecOrError = getSymbolSection(Symb);
18350b57cec5SDimitry Andric       if (!SecOrError)
18360b57cec5SDimitry Andric         return SecOrError.takeError();
18370b57cec5SDimitry Andric       section_iterator Sec = *SecOrError;
1838*5f7ddb14SDimitry Andric       if (Sec == section_end())
1839*5f7ddb14SDimitry Andric         return SymbolRef::ST_Other;
18400b57cec5SDimitry Andric       if (Sec->isData() || Sec->isBSS())
18410b57cec5SDimitry Andric         return SymbolRef::ST_Data;
18420b57cec5SDimitry Andric       return SymbolRef::ST_Function;
18430b57cec5SDimitry Andric   }
18440b57cec5SDimitry Andric   return SymbolRef::ST_Other;
18450b57cec5SDimitry Andric }
18460b57cec5SDimitry Andric 
getSymbolFlags(DataRefImpl DRI) const18475ffd83dbSDimitry Andric Expected<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
18480b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
18490b57cec5SDimitry Andric 
18500b57cec5SDimitry Andric   uint8_t MachOType = Entry.n_type;
18510b57cec5SDimitry Andric   uint16_t MachOFlags = Entry.n_desc;
18520b57cec5SDimitry Andric 
18530b57cec5SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
18540b57cec5SDimitry Andric 
18550b57cec5SDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
18560b57cec5SDimitry Andric     Result |= SymbolRef::SF_Indirect;
18570b57cec5SDimitry Andric 
18580b57cec5SDimitry Andric   if (MachOType & MachO::N_STAB)
18590b57cec5SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
18600b57cec5SDimitry Andric 
18610b57cec5SDimitry Andric   if (MachOType & MachO::N_EXT) {
18620b57cec5SDimitry Andric     Result |= SymbolRef::SF_Global;
18630b57cec5SDimitry Andric     if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
18640b57cec5SDimitry Andric       if (getNValue(DRI))
18650b57cec5SDimitry Andric         Result |= SymbolRef::SF_Common;
18660b57cec5SDimitry Andric       else
18670b57cec5SDimitry Andric         Result |= SymbolRef::SF_Undefined;
18680b57cec5SDimitry Andric     }
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric     if (!(MachOType & MachO::N_PEXT))
18710b57cec5SDimitry Andric       Result |= SymbolRef::SF_Exported;
18720b57cec5SDimitry Andric   }
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric   if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
18750b57cec5SDimitry Andric     Result |= SymbolRef::SF_Weak;
18760b57cec5SDimitry Andric 
18770b57cec5SDimitry Andric   if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
18780b57cec5SDimitry Andric     Result |= SymbolRef::SF_Thumb;
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
18810b57cec5SDimitry Andric     Result |= SymbolRef::SF_Absolute;
18820b57cec5SDimitry Andric 
18830b57cec5SDimitry Andric   return Result;
18840b57cec5SDimitry Andric }
18850b57cec5SDimitry Andric 
18860b57cec5SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const18870b57cec5SDimitry Andric MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
18880b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
18890b57cec5SDimitry Andric   uint8_t index = Entry.n_sect;
18900b57cec5SDimitry Andric 
18910b57cec5SDimitry Andric   if (index == 0)
18920b57cec5SDimitry Andric     return section_end();
18930b57cec5SDimitry Andric   DataRefImpl DRI;
18940b57cec5SDimitry Andric   DRI.d.a = index - 1;
18950b57cec5SDimitry Andric   if (DRI.d.a >= Sections.size()){
18960b57cec5SDimitry Andric     return malformedError("bad section index: " + Twine((int)index) +
18970b57cec5SDimitry Andric                           " for symbol at index " + Twine(getSymbolIndex(Symb)));
18980b57cec5SDimitry Andric   }
18990b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
19000b57cec5SDimitry Andric }
19010b57cec5SDimitry Andric 
getSymbolSectionID(SymbolRef Sym) const19020b57cec5SDimitry Andric unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
19030b57cec5SDimitry Andric   MachO::nlist_base Entry =
19040b57cec5SDimitry Andric       getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
19050b57cec5SDimitry Andric   return Entry.n_sect - 1;
19060b57cec5SDimitry Andric }
19070b57cec5SDimitry Andric 
moveSectionNext(DataRefImpl & Sec) const19080b57cec5SDimitry Andric void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
19090b57cec5SDimitry Andric   Sec.d.a++;
19100b57cec5SDimitry Andric }
19110b57cec5SDimitry Andric 
getSectionName(DataRefImpl Sec) const19120b57cec5SDimitry Andric Expected<StringRef> MachOObjectFile::getSectionName(DataRefImpl Sec) const {
19130b57cec5SDimitry Andric   ArrayRef<char> Raw = getSectionRawName(Sec);
19140b57cec5SDimitry Andric   return parseSegmentOrSectionName(Raw.data());
19150b57cec5SDimitry Andric }
19160b57cec5SDimitry Andric 
getSectionAddress(DataRefImpl Sec) const19170b57cec5SDimitry Andric uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
19180b57cec5SDimitry Andric   if (is64Bit())
19190b57cec5SDimitry Andric     return getSection64(Sec).addr;
19200b57cec5SDimitry Andric   return getSection(Sec).addr;
19210b57cec5SDimitry Andric }
19220b57cec5SDimitry Andric 
getSectionIndex(DataRefImpl Sec) const19230b57cec5SDimitry Andric uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
19240b57cec5SDimitry Andric   return Sec.d.a;
19250b57cec5SDimitry Andric }
19260b57cec5SDimitry Andric 
getSectionSize(DataRefImpl Sec) const19270b57cec5SDimitry Andric uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
19280b57cec5SDimitry Andric   // In the case if a malformed Mach-O file where the section offset is past
19290b57cec5SDimitry Andric   // the end of the file or some part of the section size is past the end of
19300b57cec5SDimitry Andric   // the file return a size of zero or a size that covers the rest of the file
19310b57cec5SDimitry Andric   // but does not extend past the end of the file.
19320b57cec5SDimitry Andric   uint32_t SectOffset, SectType;
19330b57cec5SDimitry Andric   uint64_t SectSize;
19340b57cec5SDimitry Andric 
19350b57cec5SDimitry Andric   if (is64Bit()) {
19360b57cec5SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
19370b57cec5SDimitry Andric     SectOffset = Sect.offset;
19380b57cec5SDimitry Andric     SectSize = Sect.size;
19390b57cec5SDimitry Andric     SectType = Sect.flags & MachO::SECTION_TYPE;
19400b57cec5SDimitry Andric   } else {
19410b57cec5SDimitry Andric     MachO::section Sect = getSection(Sec);
19420b57cec5SDimitry Andric     SectOffset = Sect.offset;
19430b57cec5SDimitry Andric     SectSize = Sect.size;
19440b57cec5SDimitry Andric     SectType = Sect.flags & MachO::SECTION_TYPE;
19450b57cec5SDimitry Andric   }
19460b57cec5SDimitry Andric   if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
19470b57cec5SDimitry Andric     return SectSize;
19480b57cec5SDimitry Andric   uint64_t FileSize = getData().size();
19490b57cec5SDimitry Andric   if (SectOffset > FileSize)
19500b57cec5SDimitry Andric     return 0;
19510b57cec5SDimitry Andric   if (FileSize - SectOffset < SectSize)
19520b57cec5SDimitry Andric     return FileSize - SectOffset;
19530b57cec5SDimitry Andric   return SectSize;
19540b57cec5SDimitry Andric }
19550b57cec5SDimitry Andric 
getSectionContents(uint32_t Offset,uint64_t Size) const19568bcb0991SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset,
19578bcb0991SDimitry Andric                                                       uint64_t Size) const {
19588bcb0991SDimitry Andric   return arrayRefFromStringRef(getData().substr(Offset, Size));
19598bcb0991SDimitry Andric }
19608bcb0991SDimitry Andric 
19610b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const19620b57cec5SDimitry Andric MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
19630b57cec5SDimitry Andric   uint32_t Offset;
19640b57cec5SDimitry Andric   uint64_t Size;
19650b57cec5SDimitry Andric 
19660b57cec5SDimitry Andric   if (is64Bit()) {
19670b57cec5SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
19680b57cec5SDimitry Andric     Offset = Sect.offset;
19690b57cec5SDimitry Andric     Size = Sect.size;
19700b57cec5SDimitry Andric   } else {
19710b57cec5SDimitry Andric     MachO::section Sect = getSection(Sec);
19720b57cec5SDimitry Andric     Offset = Sect.offset;
19730b57cec5SDimitry Andric     Size = Sect.size;
19740b57cec5SDimitry Andric   }
19750b57cec5SDimitry Andric 
19768bcb0991SDimitry Andric   return getSectionContents(Offset, Size);
19770b57cec5SDimitry Andric }
19780b57cec5SDimitry Andric 
getSectionAlignment(DataRefImpl Sec) const19790b57cec5SDimitry Andric uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
19800b57cec5SDimitry Andric   uint32_t Align;
19810b57cec5SDimitry Andric   if (is64Bit()) {
19820b57cec5SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
19830b57cec5SDimitry Andric     Align = Sect.align;
19840b57cec5SDimitry Andric   } else {
19850b57cec5SDimitry Andric     MachO::section Sect = getSection(Sec);
19860b57cec5SDimitry Andric     Align = Sect.align;
19870b57cec5SDimitry Andric   }
19880b57cec5SDimitry Andric 
19890b57cec5SDimitry Andric   return uint64_t(1) << Align;
19900b57cec5SDimitry Andric }
19910b57cec5SDimitry Andric 
getSection(unsigned SectionIndex) const19920b57cec5SDimitry Andric Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
19930b57cec5SDimitry Andric   if (SectionIndex < 1 || SectionIndex > Sections.size())
19940b57cec5SDimitry Andric     return malformedError("bad section index: " + Twine((int)SectionIndex));
19950b57cec5SDimitry Andric 
19960b57cec5SDimitry Andric   DataRefImpl DRI;
19970b57cec5SDimitry Andric   DRI.d.a = SectionIndex - 1;
19980b57cec5SDimitry Andric   return SectionRef(DRI, this);
19990b57cec5SDimitry Andric }
20000b57cec5SDimitry Andric 
getSection(StringRef SectionName) const20010b57cec5SDimitry Andric Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
20020b57cec5SDimitry Andric   for (const SectionRef &Section : sections()) {
20038bcb0991SDimitry Andric     auto NameOrErr = Section.getName();
20048bcb0991SDimitry Andric     if (!NameOrErr)
20058bcb0991SDimitry Andric       return NameOrErr.takeError();
20068bcb0991SDimitry Andric     if (*NameOrErr == SectionName)
20070b57cec5SDimitry Andric       return Section;
20080b57cec5SDimitry Andric   }
20090b57cec5SDimitry Andric   return errorCodeToError(object_error::parse_failed);
20100b57cec5SDimitry Andric }
20110b57cec5SDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const20120b57cec5SDimitry Andric bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
20130b57cec5SDimitry Andric   return false;
20140b57cec5SDimitry Andric }
20150b57cec5SDimitry Andric 
isSectionText(DataRefImpl Sec) const20160b57cec5SDimitry Andric bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
20170b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
20180b57cec5SDimitry Andric   return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
20190b57cec5SDimitry Andric }
20200b57cec5SDimitry Andric 
isSectionData(DataRefImpl Sec) const20210b57cec5SDimitry Andric bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
20220b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
20230b57cec5SDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
20240b57cec5SDimitry Andric   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
20250b57cec5SDimitry Andric          !(SectionType == MachO::S_ZEROFILL ||
20260b57cec5SDimitry Andric            SectionType == MachO::S_GB_ZEROFILL);
20270b57cec5SDimitry Andric }
20280b57cec5SDimitry Andric 
isSectionBSS(DataRefImpl Sec) const20290b57cec5SDimitry Andric bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
20300b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
20310b57cec5SDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
20320b57cec5SDimitry Andric   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
20330b57cec5SDimitry Andric          (SectionType == MachO::S_ZEROFILL ||
20340b57cec5SDimitry Andric           SectionType == MachO::S_GB_ZEROFILL);
20350b57cec5SDimitry Andric }
20360b57cec5SDimitry Andric 
isDebugSection(DataRefImpl Sec) const2037*5f7ddb14SDimitry Andric bool MachOObjectFile::isDebugSection(DataRefImpl Sec) const {
2038*5f7ddb14SDimitry Andric   Expected<StringRef> SectionNameOrErr = getSectionName(Sec);
2039*5f7ddb14SDimitry Andric   if (!SectionNameOrErr) {
2040*5f7ddb14SDimitry Andric     // TODO: Report the error message properly.
2041*5f7ddb14SDimitry Andric     consumeError(SectionNameOrErr.takeError());
2042*5f7ddb14SDimitry Andric     return false;
2043*5f7ddb14SDimitry Andric   }
2044*5f7ddb14SDimitry Andric   StringRef SectionName = SectionNameOrErr.get();
20455ffd83dbSDimitry Andric   return SectionName.startswith("__debug") ||
2046af732203SDimitry Andric          SectionName.startswith("__zdebug") ||
2047af732203SDimitry Andric          SectionName.startswith("__apple") || SectionName == "__gdb_index" ||
2048af732203SDimitry Andric          SectionName == "__swift_ast";
20495ffd83dbSDimitry Andric }
20505ffd83dbSDimitry Andric 
getSectionID(SectionRef Sec) const20510b57cec5SDimitry Andric unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
20520b57cec5SDimitry Andric   return Sec.getRawDataRefImpl().d.a;
20530b57cec5SDimitry Andric }
20540b57cec5SDimitry Andric 
isSectionVirtual(DataRefImpl Sec) const20550b57cec5SDimitry Andric bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
20560b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
20570b57cec5SDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
20580b57cec5SDimitry Andric   return SectionType == MachO::S_ZEROFILL ||
20590b57cec5SDimitry Andric          SectionType == MachO::S_GB_ZEROFILL;
20600b57cec5SDimitry Andric }
20610b57cec5SDimitry Andric 
isSectionBitcode(DataRefImpl Sec) const20620b57cec5SDimitry Andric bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
20630b57cec5SDimitry Andric   StringRef SegmentName = getSectionFinalSegmentName(Sec);
20640b57cec5SDimitry Andric   if (Expected<StringRef> NameOrErr = getSectionName(Sec))
20650b57cec5SDimitry Andric     return (SegmentName == "__LLVM" && *NameOrErr == "__bitcode");
20660b57cec5SDimitry Andric   return false;
20670b57cec5SDimitry Andric }
20680b57cec5SDimitry Andric 
isSectionStripped(DataRefImpl Sec) const20690b57cec5SDimitry Andric bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
20700b57cec5SDimitry Andric   if (is64Bit())
20710b57cec5SDimitry Andric     return getSection64(Sec).offset == 0;
20720b57cec5SDimitry Andric   return getSection(Sec).offset == 0;
20730b57cec5SDimitry Andric }
20740b57cec5SDimitry Andric 
section_rel_begin(DataRefImpl Sec) const20750b57cec5SDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
20760b57cec5SDimitry Andric   DataRefImpl Ret;
20770b57cec5SDimitry Andric   Ret.d.a = Sec.d.a;
20780b57cec5SDimitry Andric   Ret.d.b = 0;
20790b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
20800b57cec5SDimitry Andric }
20810b57cec5SDimitry Andric 
20820b57cec5SDimitry Andric relocation_iterator
section_rel_end(DataRefImpl Sec) const20830b57cec5SDimitry Andric MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
20840b57cec5SDimitry Andric   uint32_t Num;
20850b57cec5SDimitry Andric   if (is64Bit()) {
20860b57cec5SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
20870b57cec5SDimitry Andric     Num = Sect.nreloc;
20880b57cec5SDimitry Andric   } else {
20890b57cec5SDimitry Andric     MachO::section Sect = getSection(Sec);
20900b57cec5SDimitry Andric     Num = Sect.nreloc;
20910b57cec5SDimitry Andric   }
20920b57cec5SDimitry Andric 
20930b57cec5SDimitry Andric   DataRefImpl Ret;
20940b57cec5SDimitry Andric   Ret.d.a = Sec.d.a;
20950b57cec5SDimitry Andric   Ret.d.b = Num;
20960b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
20970b57cec5SDimitry Andric }
20980b57cec5SDimitry Andric 
extrel_begin() const20990b57cec5SDimitry Andric relocation_iterator MachOObjectFile::extrel_begin() const {
21000b57cec5SDimitry Andric   DataRefImpl Ret;
21010b57cec5SDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
21020b57cec5SDimitry Andric   Ret.d.a = 0; // Would normally be a section index.
21030b57cec5SDimitry Andric   Ret.d.b = 0; // Index into the external relocations
21040b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
21050b57cec5SDimitry Andric }
21060b57cec5SDimitry Andric 
extrel_end() const21070b57cec5SDimitry Andric relocation_iterator MachOObjectFile::extrel_end() const {
21080b57cec5SDimitry Andric   MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
21090b57cec5SDimitry Andric   DataRefImpl Ret;
21100b57cec5SDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
21110b57cec5SDimitry Andric   Ret.d.a = 0; // Would normally be a section index.
21120b57cec5SDimitry Andric   Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
21130b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
21140b57cec5SDimitry Andric }
21150b57cec5SDimitry Andric 
locrel_begin() const21160b57cec5SDimitry Andric relocation_iterator MachOObjectFile::locrel_begin() const {
21170b57cec5SDimitry Andric   DataRefImpl Ret;
21180b57cec5SDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
21190b57cec5SDimitry Andric   Ret.d.a = 1; // Would normally be a section index.
21200b57cec5SDimitry Andric   Ret.d.b = 0; // Index into the local relocations
21210b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
21220b57cec5SDimitry Andric }
21230b57cec5SDimitry Andric 
locrel_end() const21240b57cec5SDimitry Andric relocation_iterator MachOObjectFile::locrel_end() const {
21250b57cec5SDimitry Andric   MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
21260b57cec5SDimitry Andric   DataRefImpl Ret;
21270b57cec5SDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
21280b57cec5SDimitry Andric   Ret.d.a = 1; // Would normally be a section index.
21290b57cec5SDimitry Andric   Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
21300b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
21310b57cec5SDimitry Andric }
21320b57cec5SDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const21330b57cec5SDimitry Andric void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
21340b57cec5SDimitry Andric   ++Rel.d.b;
21350b57cec5SDimitry Andric }
21360b57cec5SDimitry Andric 
getRelocationOffset(DataRefImpl Rel) const21370b57cec5SDimitry Andric uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
21380b57cec5SDimitry Andric   assert((getHeader().filetype == MachO::MH_OBJECT ||
21390b57cec5SDimitry Andric           getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
21400b57cec5SDimitry Andric          "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
21410b57cec5SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
21420b57cec5SDimitry Andric   return getAnyRelocationAddress(RE);
21430b57cec5SDimitry Andric }
21440b57cec5SDimitry Andric 
21450b57cec5SDimitry Andric symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const21460b57cec5SDimitry Andric MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
21470b57cec5SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
21480b57cec5SDimitry Andric   if (isRelocationScattered(RE))
21490b57cec5SDimitry Andric     return symbol_end();
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
21520b57cec5SDimitry Andric   bool isExtern = getPlainRelocationExternal(RE);
21530b57cec5SDimitry Andric   if (!isExtern)
21540b57cec5SDimitry Andric     return symbol_end();
21550b57cec5SDimitry Andric 
21560b57cec5SDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
21570b57cec5SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
21580b57cec5SDimitry Andric     sizeof(MachO::nlist_64) :
21590b57cec5SDimitry Andric     sizeof(MachO::nlist);
21600b57cec5SDimitry Andric   uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
21610b57cec5SDimitry Andric   DataRefImpl Sym;
21620b57cec5SDimitry Andric   Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
21630b57cec5SDimitry Andric   return symbol_iterator(SymbolRef(Sym, this));
21640b57cec5SDimitry Andric }
21650b57cec5SDimitry Andric 
21660b57cec5SDimitry Andric section_iterator
getRelocationSection(DataRefImpl Rel) const21670b57cec5SDimitry Andric MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
21680b57cec5SDimitry Andric   return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
21690b57cec5SDimitry Andric }
21700b57cec5SDimitry Andric 
getRelocationType(DataRefImpl Rel) const21710b57cec5SDimitry Andric uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
21720b57cec5SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
21730b57cec5SDimitry Andric   return getAnyRelocationType(RE);
21740b57cec5SDimitry Andric }
21750b57cec5SDimitry Andric 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const21760b57cec5SDimitry Andric void MachOObjectFile::getRelocationTypeName(
21770b57cec5SDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
21780b57cec5SDimitry Andric   StringRef res;
21790b57cec5SDimitry Andric   uint64_t RType = getRelocationType(Rel);
21800b57cec5SDimitry Andric 
21810b57cec5SDimitry Andric   unsigned Arch = this->getArch();
21820b57cec5SDimitry Andric 
21830b57cec5SDimitry Andric   switch (Arch) {
21840b57cec5SDimitry Andric     case Triple::x86: {
21850b57cec5SDimitry Andric       static const char *const Table[] =  {
21860b57cec5SDimitry Andric         "GENERIC_RELOC_VANILLA",
21870b57cec5SDimitry Andric         "GENERIC_RELOC_PAIR",
21880b57cec5SDimitry Andric         "GENERIC_RELOC_SECTDIFF",
21890b57cec5SDimitry Andric         "GENERIC_RELOC_PB_LA_PTR",
21900b57cec5SDimitry Andric         "GENERIC_RELOC_LOCAL_SECTDIFF",
21910b57cec5SDimitry Andric         "GENERIC_RELOC_TLV" };
21920b57cec5SDimitry Andric 
21930b57cec5SDimitry Andric       if (RType > 5)
21940b57cec5SDimitry Andric         res = "Unknown";
21950b57cec5SDimitry Andric       else
21960b57cec5SDimitry Andric         res = Table[RType];
21970b57cec5SDimitry Andric       break;
21980b57cec5SDimitry Andric     }
21990b57cec5SDimitry Andric     case Triple::x86_64: {
22000b57cec5SDimitry Andric       static const char *const Table[] =  {
22010b57cec5SDimitry Andric         "X86_64_RELOC_UNSIGNED",
22020b57cec5SDimitry Andric         "X86_64_RELOC_SIGNED",
22030b57cec5SDimitry Andric         "X86_64_RELOC_BRANCH",
22040b57cec5SDimitry Andric         "X86_64_RELOC_GOT_LOAD",
22050b57cec5SDimitry Andric         "X86_64_RELOC_GOT",
22060b57cec5SDimitry Andric         "X86_64_RELOC_SUBTRACTOR",
22070b57cec5SDimitry Andric         "X86_64_RELOC_SIGNED_1",
22080b57cec5SDimitry Andric         "X86_64_RELOC_SIGNED_2",
22090b57cec5SDimitry Andric         "X86_64_RELOC_SIGNED_4",
22100b57cec5SDimitry Andric         "X86_64_RELOC_TLV" };
22110b57cec5SDimitry Andric 
22120b57cec5SDimitry Andric       if (RType > 9)
22130b57cec5SDimitry Andric         res = "Unknown";
22140b57cec5SDimitry Andric       else
22150b57cec5SDimitry Andric         res = Table[RType];
22160b57cec5SDimitry Andric       break;
22170b57cec5SDimitry Andric     }
22180b57cec5SDimitry Andric     case Triple::arm: {
22190b57cec5SDimitry Andric       static const char *const Table[] =  {
22200b57cec5SDimitry Andric         "ARM_RELOC_VANILLA",
22210b57cec5SDimitry Andric         "ARM_RELOC_PAIR",
22220b57cec5SDimitry Andric         "ARM_RELOC_SECTDIFF",
22230b57cec5SDimitry Andric         "ARM_RELOC_LOCAL_SECTDIFF",
22240b57cec5SDimitry Andric         "ARM_RELOC_PB_LA_PTR",
22250b57cec5SDimitry Andric         "ARM_RELOC_BR24",
22260b57cec5SDimitry Andric         "ARM_THUMB_RELOC_BR22",
22270b57cec5SDimitry Andric         "ARM_THUMB_32BIT_BRANCH",
22280b57cec5SDimitry Andric         "ARM_RELOC_HALF",
22290b57cec5SDimitry Andric         "ARM_RELOC_HALF_SECTDIFF" };
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric       if (RType > 9)
22320b57cec5SDimitry Andric         res = "Unknown";
22330b57cec5SDimitry Andric       else
22340b57cec5SDimitry Andric         res = Table[RType];
22350b57cec5SDimitry Andric       break;
22360b57cec5SDimitry Andric     }
22370b57cec5SDimitry Andric     case Triple::aarch64:
22380b57cec5SDimitry Andric     case Triple::aarch64_32: {
22390b57cec5SDimitry Andric       static const char *const Table[] = {
22400b57cec5SDimitry Andric         "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
22410b57cec5SDimitry Andric         "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
22420b57cec5SDimitry Andric         "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
22430b57cec5SDimitry Andric         "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
22440b57cec5SDimitry Andric         "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
22450b57cec5SDimitry Andric         "ARM64_RELOC_ADDEND"
22460b57cec5SDimitry Andric       };
22470b57cec5SDimitry Andric 
22480b57cec5SDimitry Andric       if (RType >= array_lengthof(Table))
22490b57cec5SDimitry Andric         res = "Unknown";
22500b57cec5SDimitry Andric       else
22510b57cec5SDimitry Andric         res = Table[RType];
22520b57cec5SDimitry Andric       break;
22530b57cec5SDimitry Andric     }
22540b57cec5SDimitry Andric     case Triple::ppc: {
22550b57cec5SDimitry Andric       static const char *const Table[] =  {
22560b57cec5SDimitry Andric         "PPC_RELOC_VANILLA",
22570b57cec5SDimitry Andric         "PPC_RELOC_PAIR",
22580b57cec5SDimitry Andric         "PPC_RELOC_BR14",
22590b57cec5SDimitry Andric         "PPC_RELOC_BR24",
22600b57cec5SDimitry Andric         "PPC_RELOC_HI16",
22610b57cec5SDimitry Andric         "PPC_RELOC_LO16",
22620b57cec5SDimitry Andric         "PPC_RELOC_HA16",
22630b57cec5SDimitry Andric         "PPC_RELOC_LO14",
22640b57cec5SDimitry Andric         "PPC_RELOC_SECTDIFF",
22650b57cec5SDimitry Andric         "PPC_RELOC_PB_LA_PTR",
22660b57cec5SDimitry Andric         "PPC_RELOC_HI16_SECTDIFF",
22670b57cec5SDimitry Andric         "PPC_RELOC_LO16_SECTDIFF",
22680b57cec5SDimitry Andric         "PPC_RELOC_HA16_SECTDIFF",
22690b57cec5SDimitry Andric         "PPC_RELOC_JBSR",
22700b57cec5SDimitry Andric         "PPC_RELOC_LO14_SECTDIFF",
22710b57cec5SDimitry Andric         "PPC_RELOC_LOCAL_SECTDIFF" };
22720b57cec5SDimitry Andric 
22730b57cec5SDimitry Andric       if (RType > 15)
22740b57cec5SDimitry Andric         res = "Unknown";
22750b57cec5SDimitry Andric       else
22760b57cec5SDimitry Andric         res = Table[RType];
22770b57cec5SDimitry Andric       break;
22780b57cec5SDimitry Andric     }
22790b57cec5SDimitry Andric     case Triple::UnknownArch:
22800b57cec5SDimitry Andric       res = "Unknown";
22810b57cec5SDimitry Andric       break;
22820b57cec5SDimitry Andric   }
22830b57cec5SDimitry Andric   Result.append(res.begin(), res.end());
22840b57cec5SDimitry Andric }
22850b57cec5SDimitry Andric 
getRelocationLength(DataRefImpl Rel) const22860b57cec5SDimitry Andric uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
22870b57cec5SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
22880b57cec5SDimitry Andric   return getAnyRelocationLength(RE);
22890b57cec5SDimitry Andric }
22900b57cec5SDimitry Andric 
22910b57cec5SDimitry Andric //
22920b57cec5SDimitry Andric // guessLibraryShortName() is passed a name of a dynamic library and returns a
22930b57cec5SDimitry Andric // guess on what the short name is.  Then name is returned as a substring of the
22940b57cec5SDimitry Andric // StringRef Name passed in.  The name of the dynamic library is recognized as
22950b57cec5SDimitry Andric // a framework if it has one of the two following forms:
22960b57cec5SDimitry Andric //      Foo.framework/Versions/A/Foo
22970b57cec5SDimitry Andric //      Foo.framework/Foo
22980b57cec5SDimitry Andric // Where A and Foo can be any string.  And may contain a trailing suffix
22990b57cec5SDimitry Andric // starting with an underbar.  If the Name is recognized as a framework then
23000b57cec5SDimitry Andric // isFramework is set to true else it is set to false.  If the Name has a
23010b57cec5SDimitry Andric // suffix then Suffix is set to the substring in Name that contains the suffix
23020b57cec5SDimitry Andric // else it is set to a NULL StringRef.
23030b57cec5SDimitry Andric //
23040b57cec5SDimitry Andric // The Name of the dynamic library is recognized as a library name if it has
23050b57cec5SDimitry Andric // one of the two following forms:
23060b57cec5SDimitry Andric //      libFoo.A.dylib
23070b57cec5SDimitry Andric //      libFoo.dylib
23080b57cec5SDimitry Andric //
23090b57cec5SDimitry Andric // The library may have a suffix trailing the name Foo of the form:
23100b57cec5SDimitry Andric //      libFoo_profile.A.dylib
23110b57cec5SDimitry Andric //      libFoo_profile.dylib
23120b57cec5SDimitry Andric // These dyld image suffixes are separated from the short name by a '_'
23130b57cec5SDimitry Andric // character. Because the '_' character is commonly used to separate words in
23140b57cec5SDimitry Andric // filenames guessLibraryShortName() cannot reliably separate a dylib's short
23150b57cec5SDimitry Andric // name from an arbitrary image suffix; imagine if both the short name and the
23160b57cec5SDimitry Andric // suffix contains an '_' character! To better deal with this ambiguity,
23170b57cec5SDimitry Andric // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
23180b57cec5SDimitry Andric // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
23190b57cec5SDimitry Andric // guessing incorrectly.
23200b57cec5SDimitry Andric //
23210b57cec5SDimitry Andric // The Name of the dynamic library is also recognized as a library name if it
23220b57cec5SDimitry Andric // has the following form:
23230b57cec5SDimitry Andric //      Foo.qtx
23240b57cec5SDimitry Andric //
23250b57cec5SDimitry Andric // If the Name of the dynamic library is none of the forms above then a NULL
23260b57cec5SDimitry Andric // StringRef is returned.
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)23270b57cec5SDimitry Andric StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
23280b57cec5SDimitry Andric                                                  bool &isFramework,
23290b57cec5SDimitry Andric                                                  StringRef &Suffix) {
23300b57cec5SDimitry Andric   StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
23310b57cec5SDimitry Andric   size_t a, b, c, d, Idx;
23320b57cec5SDimitry Andric 
23330b57cec5SDimitry Andric   isFramework = false;
23340b57cec5SDimitry Andric   Suffix = StringRef();
23350b57cec5SDimitry Andric 
23360b57cec5SDimitry Andric   // Pull off the last component and make Foo point to it
23370b57cec5SDimitry Andric   a = Name.rfind('/');
23380b57cec5SDimitry Andric   if (a == Name.npos || a == 0)
23390b57cec5SDimitry Andric     goto guess_library;
23400b57cec5SDimitry Andric   Foo = Name.slice(a+1, Name.npos);
23410b57cec5SDimitry Andric 
23420b57cec5SDimitry Andric   // Look for a suffix starting with a '_'
23430b57cec5SDimitry Andric   Idx = Foo.rfind('_');
23440b57cec5SDimitry Andric   if (Idx != Foo.npos && Foo.size() >= 2) {
23450b57cec5SDimitry Andric     Suffix = Foo.slice(Idx, Foo.npos);
23460b57cec5SDimitry Andric     if (Suffix != "_debug" && Suffix != "_profile")
23470b57cec5SDimitry Andric       Suffix = StringRef();
23480b57cec5SDimitry Andric     else
23490b57cec5SDimitry Andric       Foo = Foo.slice(0, Idx);
23500b57cec5SDimitry Andric   }
23510b57cec5SDimitry Andric 
23520b57cec5SDimitry Andric   // First look for the form Foo.framework/Foo
23530b57cec5SDimitry Andric   b = Name.rfind('/', a);
23540b57cec5SDimitry Andric   if (b == Name.npos)
23550b57cec5SDimitry Andric     Idx = 0;
23560b57cec5SDimitry Andric   else
23570b57cec5SDimitry Andric     Idx = b+1;
23580b57cec5SDimitry Andric   F = Name.slice(Idx, Idx + Foo.size());
23590b57cec5SDimitry Andric   DotFramework = Name.slice(Idx + Foo.size(),
23600b57cec5SDimitry Andric                             Idx + Foo.size() + sizeof(".framework/")-1);
23610b57cec5SDimitry Andric   if (F == Foo && DotFramework == ".framework/") {
23620b57cec5SDimitry Andric     isFramework = true;
23630b57cec5SDimitry Andric     return Foo;
23640b57cec5SDimitry Andric   }
23650b57cec5SDimitry Andric 
23660b57cec5SDimitry Andric   // Next look for the form Foo.framework/Versions/A/Foo
23670b57cec5SDimitry Andric   if (b == Name.npos)
23680b57cec5SDimitry Andric     goto guess_library;
23690b57cec5SDimitry Andric   c =  Name.rfind('/', b);
23700b57cec5SDimitry Andric   if (c == Name.npos || c == 0)
23710b57cec5SDimitry Andric     goto guess_library;
23720b57cec5SDimitry Andric   V = Name.slice(c+1, Name.npos);
23730b57cec5SDimitry Andric   if (!V.startswith("Versions/"))
23740b57cec5SDimitry Andric     goto guess_library;
23750b57cec5SDimitry Andric   d =  Name.rfind('/', c);
23760b57cec5SDimitry Andric   if (d == Name.npos)
23770b57cec5SDimitry Andric     Idx = 0;
23780b57cec5SDimitry Andric   else
23790b57cec5SDimitry Andric     Idx = d+1;
23800b57cec5SDimitry Andric   F = Name.slice(Idx, Idx + Foo.size());
23810b57cec5SDimitry Andric   DotFramework = Name.slice(Idx + Foo.size(),
23820b57cec5SDimitry Andric                             Idx + Foo.size() + sizeof(".framework/")-1);
23830b57cec5SDimitry Andric   if (F == Foo && DotFramework == ".framework/") {
23840b57cec5SDimitry Andric     isFramework = true;
23850b57cec5SDimitry Andric     return Foo;
23860b57cec5SDimitry Andric   }
23870b57cec5SDimitry Andric 
23880b57cec5SDimitry Andric guess_library:
23890b57cec5SDimitry Andric   // pull off the suffix after the "." and make a point to it
23900b57cec5SDimitry Andric   a = Name.rfind('.');
23910b57cec5SDimitry Andric   if (a == Name.npos || a == 0)
23920b57cec5SDimitry Andric     return StringRef();
23930b57cec5SDimitry Andric   Dylib = Name.slice(a, Name.npos);
23940b57cec5SDimitry Andric   if (Dylib != ".dylib")
23950b57cec5SDimitry Andric     goto guess_qtx;
23960b57cec5SDimitry Andric 
23970b57cec5SDimitry Andric   // First pull off the version letter for the form Foo.A.dylib if any.
23980b57cec5SDimitry Andric   if (a >= 3) {
23990b57cec5SDimitry Andric     Dot = Name.slice(a-2, a-1);
24000b57cec5SDimitry Andric     if (Dot == ".")
24010b57cec5SDimitry Andric       a = a - 2;
24020b57cec5SDimitry Andric   }
24030b57cec5SDimitry Andric 
24040b57cec5SDimitry Andric   b = Name.rfind('/', a);
24050b57cec5SDimitry Andric   if (b == Name.npos)
24060b57cec5SDimitry Andric     b = 0;
24070b57cec5SDimitry Andric   else
24080b57cec5SDimitry Andric     b = b+1;
24090b57cec5SDimitry Andric   // ignore any suffix after an underbar like Foo_profile.A.dylib
24100b57cec5SDimitry Andric   Idx = Name.rfind('_');
24110b57cec5SDimitry Andric   if (Idx != Name.npos && Idx != b) {
24120b57cec5SDimitry Andric     Lib = Name.slice(b, Idx);
24130b57cec5SDimitry Andric     Suffix = Name.slice(Idx, a);
24140b57cec5SDimitry Andric     if (Suffix != "_debug" && Suffix != "_profile") {
24150b57cec5SDimitry Andric       Suffix = StringRef();
24160b57cec5SDimitry Andric       Lib = Name.slice(b, a);
24170b57cec5SDimitry Andric     }
24180b57cec5SDimitry Andric   }
24190b57cec5SDimitry Andric   else
24200b57cec5SDimitry Andric     Lib = Name.slice(b, a);
24210b57cec5SDimitry Andric   // There are incorrect library names of the form:
24220b57cec5SDimitry Andric   // libATS.A_profile.dylib so check for these.
24230b57cec5SDimitry Andric   if (Lib.size() >= 3) {
24240b57cec5SDimitry Andric     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
24250b57cec5SDimitry Andric     if (Dot == ".")
24260b57cec5SDimitry Andric       Lib = Lib.slice(0, Lib.size()-2);
24270b57cec5SDimitry Andric   }
24280b57cec5SDimitry Andric   return Lib;
24290b57cec5SDimitry Andric 
24300b57cec5SDimitry Andric guess_qtx:
24310b57cec5SDimitry Andric   Qtx = Name.slice(a, Name.npos);
24320b57cec5SDimitry Andric   if (Qtx != ".qtx")
24330b57cec5SDimitry Andric     return StringRef();
24340b57cec5SDimitry Andric   b = Name.rfind('/', a);
24350b57cec5SDimitry Andric   if (b == Name.npos)
24360b57cec5SDimitry Andric     Lib = Name.slice(0, a);
24370b57cec5SDimitry Andric   else
24380b57cec5SDimitry Andric     Lib = Name.slice(b+1, a);
24390b57cec5SDimitry Andric   // There are library names of the form: QT.A.qtx so check for these.
24400b57cec5SDimitry Andric   if (Lib.size() >= 3) {
24410b57cec5SDimitry Andric     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
24420b57cec5SDimitry Andric     if (Dot == ".")
24430b57cec5SDimitry Andric       Lib = Lib.slice(0, Lib.size()-2);
24440b57cec5SDimitry Andric   }
24450b57cec5SDimitry Andric   return Lib;
24460b57cec5SDimitry Andric }
24470b57cec5SDimitry Andric 
24480b57cec5SDimitry Andric // getLibraryShortNameByIndex() is used to get the short name of the library
24490b57cec5SDimitry Andric // for an undefined symbol in a linked Mach-O binary that was linked with the
24500b57cec5SDimitry Andric // normal two-level namespace default (that is MH_TWOLEVEL in the header).
24510b57cec5SDimitry Andric // It is passed the index (0 - based) of the library as translated from
24520b57cec5SDimitry Andric // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const24530b57cec5SDimitry Andric std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
24540b57cec5SDimitry Andric                                                          StringRef &Res) const {
24550b57cec5SDimitry Andric   if (Index >= Libraries.size())
24560b57cec5SDimitry Andric     return object_error::parse_failed;
24570b57cec5SDimitry Andric 
24580b57cec5SDimitry Andric   // If the cache of LibrariesShortNames is not built up do that first for
24590b57cec5SDimitry Andric   // all the Libraries.
24600b57cec5SDimitry Andric   if (LibrariesShortNames.size() == 0) {
24610b57cec5SDimitry Andric     for (unsigned i = 0; i < Libraries.size(); i++) {
24620b57cec5SDimitry Andric       auto CommandOrErr =
24630b57cec5SDimitry Andric         getStructOrErr<MachO::dylib_command>(*this, Libraries[i]);
24640b57cec5SDimitry Andric       if (!CommandOrErr)
24650b57cec5SDimitry Andric         return object_error::parse_failed;
24660b57cec5SDimitry Andric       MachO::dylib_command D = CommandOrErr.get();
24670b57cec5SDimitry Andric       if (D.dylib.name >= D.cmdsize)
24680b57cec5SDimitry Andric         return object_error::parse_failed;
24690b57cec5SDimitry Andric       const char *P = (const char *)(Libraries[i]) + D.dylib.name;
24700b57cec5SDimitry Andric       StringRef Name = StringRef(P);
24710b57cec5SDimitry Andric       if (D.dylib.name+Name.size() >= D.cmdsize)
24720b57cec5SDimitry Andric         return object_error::parse_failed;
24730b57cec5SDimitry Andric       StringRef Suffix;
24740b57cec5SDimitry Andric       bool isFramework;
24750b57cec5SDimitry Andric       StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
24760b57cec5SDimitry Andric       if (shortName.empty())
24770b57cec5SDimitry Andric         LibrariesShortNames.push_back(Name);
24780b57cec5SDimitry Andric       else
24790b57cec5SDimitry Andric         LibrariesShortNames.push_back(shortName);
24800b57cec5SDimitry Andric     }
24810b57cec5SDimitry Andric   }
24820b57cec5SDimitry Andric 
24830b57cec5SDimitry Andric   Res = LibrariesShortNames[Index];
24840b57cec5SDimitry Andric   return std::error_code();
24850b57cec5SDimitry Andric }
24860b57cec5SDimitry Andric 
getLibraryCount() const24870b57cec5SDimitry Andric uint32_t MachOObjectFile::getLibraryCount() const {
24880b57cec5SDimitry Andric   return Libraries.size();
24890b57cec5SDimitry Andric }
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric section_iterator
getRelocationRelocatedSection(relocation_iterator Rel) const24920b57cec5SDimitry Andric MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
24930b57cec5SDimitry Andric   DataRefImpl Sec;
24940b57cec5SDimitry Andric   Sec.d.a = Rel->getRawDataRefImpl().d.a;
24950b57cec5SDimitry Andric   return section_iterator(SectionRef(Sec, this));
24960b57cec5SDimitry Andric }
24970b57cec5SDimitry Andric 
symbol_begin() const24980b57cec5SDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_begin() const {
24990b57cec5SDimitry Andric   DataRefImpl DRI;
25000b57cec5SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
25010b57cec5SDimitry Andric   if (!SymtabLoadCmd || Symtab.nsyms == 0)
25020b57cec5SDimitry Andric     return basic_symbol_iterator(SymbolRef(DRI, this));
25030b57cec5SDimitry Andric 
25040b57cec5SDimitry Andric   return getSymbolByIndex(0);
25050b57cec5SDimitry Andric }
25060b57cec5SDimitry Andric 
symbol_end() const25070b57cec5SDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_end() const {
25080b57cec5SDimitry Andric   DataRefImpl DRI;
25090b57cec5SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
25100b57cec5SDimitry Andric   if (!SymtabLoadCmd || Symtab.nsyms == 0)
25110b57cec5SDimitry Andric     return basic_symbol_iterator(SymbolRef(DRI, this));
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
25140b57cec5SDimitry Andric     sizeof(MachO::nlist_64) :
25150b57cec5SDimitry Andric     sizeof(MachO::nlist);
25160b57cec5SDimitry Andric   unsigned Offset = Symtab.symoff +
25170b57cec5SDimitry Andric     Symtab.nsyms * SymbolTableEntrySize;
25180b57cec5SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
25190b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(DRI, this));
25200b57cec5SDimitry Andric }
25210b57cec5SDimitry Andric 
getSymbolByIndex(unsigned Index) const25220b57cec5SDimitry Andric symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
25230b57cec5SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
25240b57cec5SDimitry Andric   if (!SymtabLoadCmd || Index >= Symtab.nsyms)
25250b57cec5SDimitry Andric     report_fatal_error("Requested symbol index is out of range.");
25260b57cec5SDimitry Andric   unsigned SymbolTableEntrySize =
25270b57cec5SDimitry Andric     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
25280b57cec5SDimitry Andric   DataRefImpl DRI;
25290b57cec5SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
25300b57cec5SDimitry Andric   DRI.p += Index * SymbolTableEntrySize;
25310b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(DRI, this));
25320b57cec5SDimitry Andric }
25330b57cec5SDimitry Andric 
getSymbolIndex(DataRefImpl Symb) const25340b57cec5SDimitry Andric uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
25350b57cec5SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
25360b57cec5SDimitry Andric   if (!SymtabLoadCmd)
25370b57cec5SDimitry Andric     report_fatal_error("getSymbolIndex() called with no symbol table symbol");
25380b57cec5SDimitry Andric   unsigned SymbolTableEntrySize =
25390b57cec5SDimitry Andric     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
25400b57cec5SDimitry Andric   DataRefImpl DRIstart;
25410b57cec5SDimitry Andric   DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
25420b57cec5SDimitry Andric   uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
25430b57cec5SDimitry Andric   return Index;
25440b57cec5SDimitry Andric }
25450b57cec5SDimitry Andric 
section_begin() const25460b57cec5SDimitry Andric section_iterator MachOObjectFile::section_begin() const {
25470b57cec5SDimitry Andric   DataRefImpl DRI;
25480b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
25490b57cec5SDimitry Andric }
25500b57cec5SDimitry Andric 
section_end() const25510b57cec5SDimitry Andric section_iterator MachOObjectFile::section_end() const {
25520b57cec5SDimitry Andric   DataRefImpl DRI;
25530b57cec5SDimitry Andric   DRI.d.a = Sections.size();
25540b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
25550b57cec5SDimitry Andric }
25560b57cec5SDimitry Andric 
getBytesInAddress() const25570b57cec5SDimitry Andric uint8_t MachOObjectFile::getBytesInAddress() const {
25580b57cec5SDimitry Andric   return is64Bit() ? 8 : 4;
25590b57cec5SDimitry Andric }
25600b57cec5SDimitry Andric 
getFileFormatName() const25610b57cec5SDimitry Andric StringRef MachOObjectFile::getFileFormatName() const {
25620b57cec5SDimitry Andric   unsigned CPUType = getCPUType(*this);
25630b57cec5SDimitry Andric   if (!is64Bit()) {
25640b57cec5SDimitry Andric     switch (CPUType) {
25650b57cec5SDimitry Andric     case MachO::CPU_TYPE_I386:
25660b57cec5SDimitry Andric       return "Mach-O 32-bit i386";
25670b57cec5SDimitry Andric     case MachO::CPU_TYPE_ARM:
25680b57cec5SDimitry Andric       return "Mach-O arm";
25690b57cec5SDimitry Andric     case MachO::CPU_TYPE_ARM64_32:
25700b57cec5SDimitry Andric       return "Mach-O arm64 (ILP32)";
25710b57cec5SDimitry Andric     case MachO::CPU_TYPE_POWERPC:
25720b57cec5SDimitry Andric       return "Mach-O 32-bit ppc";
25730b57cec5SDimitry Andric     default:
25740b57cec5SDimitry Andric       return "Mach-O 32-bit unknown";
25750b57cec5SDimitry Andric     }
25760b57cec5SDimitry Andric   }
25770b57cec5SDimitry Andric 
25780b57cec5SDimitry Andric   switch (CPUType) {
25790b57cec5SDimitry Andric   case MachO::CPU_TYPE_X86_64:
25800b57cec5SDimitry Andric     return "Mach-O 64-bit x86-64";
25810b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64:
25820b57cec5SDimitry Andric     return "Mach-O arm64";
25830b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
25840b57cec5SDimitry Andric     return "Mach-O 64-bit ppc64";
25850b57cec5SDimitry Andric   default:
25860b57cec5SDimitry Andric     return "Mach-O 64-bit unknown";
25870b57cec5SDimitry Andric   }
25880b57cec5SDimitry Andric }
25890b57cec5SDimitry Andric 
getArch(uint32_t CPUType,uint32_t CPUSubType)2590480093f4SDimitry Andric Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
25910b57cec5SDimitry Andric   switch (CPUType) {
25920b57cec5SDimitry Andric   case MachO::CPU_TYPE_I386:
25930b57cec5SDimitry Andric     return Triple::x86;
25940b57cec5SDimitry Andric   case MachO::CPU_TYPE_X86_64:
25950b57cec5SDimitry Andric     return Triple::x86_64;
25960b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM:
25970b57cec5SDimitry Andric     return Triple::arm;
25980b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64:
25990b57cec5SDimitry Andric     return Triple::aarch64;
26000b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64_32:
26010b57cec5SDimitry Andric     return Triple::aarch64_32;
26020b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC:
26030b57cec5SDimitry Andric     return Triple::ppc;
26040b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
26050b57cec5SDimitry Andric     return Triple::ppc64;
26060b57cec5SDimitry Andric   default:
26070b57cec5SDimitry Andric     return Triple::UnknownArch;
26080b57cec5SDimitry Andric   }
26090b57cec5SDimitry Andric }
26100b57cec5SDimitry Andric 
getArchTriple(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,const char ** ArchFlag)26110b57cec5SDimitry Andric Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
26120b57cec5SDimitry Andric                                       const char **McpuDefault,
26130b57cec5SDimitry Andric                                       const char **ArchFlag) {
26140b57cec5SDimitry Andric   if (McpuDefault)
26150b57cec5SDimitry Andric     *McpuDefault = nullptr;
26160b57cec5SDimitry Andric   if (ArchFlag)
26170b57cec5SDimitry Andric     *ArchFlag = nullptr;
26180b57cec5SDimitry Andric 
26190b57cec5SDimitry Andric   switch (CPUType) {
26200b57cec5SDimitry Andric   case MachO::CPU_TYPE_I386:
26210b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
26220b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_I386_ALL:
26230b57cec5SDimitry Andric       if (ArchFlag)
26240b57cec5SDimitry Andric         *ArchFlag = "i386";
26250b57cec5SDimitry Andric       return Triple("i386-apple-darwin");
26260b57cec5SDimitry Andric     default:
26270b57cec5SDimitry Andric       return Triple();
26280b57cec5SDimitry Andric     }
26290b57cec5SDimitry Andric   case MachO::CPU_TYPE_X86_64:
26300b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
26310b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_X86_64_ALL:
26320b57cec5SDimitry Andric       if (ArchFlag)
26330b57cec5SDimitry Andric         *ArchFlag = "x86_64";
26340b57cec5SDimitry Andric       return Triple("x86_64-apple-darwin");
26350b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_X86_64_H:
26360b57cec5SDimitry Andric       if (ArchFlag)
26370b57cec5SDimitry Andric         *ArchFlag = "x86_64h";
26380b57cec5SDimitry Andric       return Triple("x86_64h-apple-darwin");
26390b57cec5SDimitry Andric     default:
26400b57cec5SDimitry Andric       return Triple();
26410b57cec5SDimitry Andric     }
26420b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM:
26430b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
26440b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V4T:
26450b57cec5SDimitry Andric       if (ArchFlag)
26460b57cec5SDimitry Andric         *ArchFlag = "armv4t";
26470b57cec5SDimitry Andric       return Triple("armv4t-apple-darwin");
26480b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
26490b57cec5SDimitry Andric       if (ArchFlag)
26500b57cec5SDimitry Andric         *ArchFlag = "armv5e";
26510b57cec5SDimitry Andric       return Triple("armv5e-apple-darwin");
26520b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_XSCALE:
26530b57cec5SDimitry Andric       if (ArchFlag)
26540b57cec5SDimitry Andric         *ArchFlag = "xscale";
26550b57cec5SDimitry Andric       return Triple("xscale-apple-darwin");
26560b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V6:
26570b57cec5SDimitry Andric       if (ArchFlag)
26580b57cec5SDimitry Andric         *ArchFlag = "armv6";
26590b57cec5SDimitry Andric       return Triple("armv6-apple-darwin");
26600b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V6M:
26610b57cec5SDimitry Andric       if (McpuDefault)
26620b57cec5SDimitry Andric         *McpuDefault = "cortex-m0";
26630b57cec5SDimitry Andric       if (ArchFlag)
26640b57cec5SDimitry Andric         *ArchFlag = "armv6m";
26650b57cec5SDimitry Andric       return Triple("armv6m-apple-darwin");
26660b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7:
26670b57cec5SDimitry Andric       if (ArchFlag)
26680b57cec5SDimitry Andric         *ArchFlag = "armv7";
26690b57cec5SDimitry Andric       return Triple("armv7-apple-darwin");
26700b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7EM:
26710b57cec5SDimitry Andric       if (McpuDefault)
26720b57cec5SDimitry Andric         *McpuDefault = "cortex-m4";
26730b57cec5SDimitry Andric       if (ArchFlag)
26740b57cec5SDimitry Andric         *ArchFlag = "armv7em";
26750b57cec5SDimitry Andric       return Triple("thumbv7em-apple-darwin");
26760b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7K:
26770b57cec5SDimitry Andric       if (McpuDefault)
26780b57cec5SDimitry Andric         *McpuDefault = "cortex-a7";
26790b57cec5SDimitry Andric       if (ArchFlag)
26800b57cec5SDimitry Andric         *ArchFlag = "armv7k";
26810b57cec5SDimitry Andric       return Triple("armv7k-apple-darwin");
26820b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7M:
26830b57cec5SDimitry Andric       if (McpuDefault)
26840b57cec5SDimitry Andric         *McpuDefault = "cortex-m3";
26850b57cec5SDimitry Andric       if (ArchFlag)
26860b57cec5SDimitry Andric         *ArchFlag = "armv7m";
26870b57cec5SDimitry Andric       return Triple("thumbv7m-apple-darwin");
26880b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7S:
26890b57cec5SDimitry Andric       if (McpuDefault)
26900b57cec5SDimitry Andric         *McpuDefault = "cortex-a7";
26910b57cec5SDimitry Andric       if (ArchFlag)
26920b57cec5SDimitry Andric         *ArchFlag = "armv7s";
26930b57cec5SDimitry Andric       return Triple("armv7s-apple-darwin");
26940b57cec5SDimitry Andric     default:
26950b57cec5SDimitry Andric       return Triple();
26960b57cec5SDimitry Andric     }
26970b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64:
26980b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
26990b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM64_ALL:
27000b57cec5SDimitry Andric       if (McpuDefault)
27010b57cec5SDimitry Andric         *McpuDefault = "cyclone";
27020b57cec5SDimitry Andric       if (ArchFlag)
27030b57cec5SDimitry Andric         *ArchFlag = "arm64";
27040b57cec5SDimitry Andric       return Triple("arm64-apple-darwin");
2705af732203SDimitry Andric     case MachO::CPU_SUBTYPE_ARM64E:
2706af732203SDimitry Andric       if (McpuDefault)
2707af732203SDimitry Andric         *McpuDefault = "apple-a12";
2708af732203SDimitry Andric       if (ArchFlag)
2709af732203SDimitry Andric         *ArchFlag = "arm64e";
2710af732203SDimitry Andric       return Triple("arm64e-apple-darwin");
27110b57cec5SDimitry Andric     default:
27120b57cec5SDimitry Andric       return Triple();
27130b57cec5SDimitry Andric     }
27140b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64_32:
27150b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
27160b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM64_32_V8:
27170b57cec5SDimitry Andric       if (McpuDefault)
27180b57cec5SDimitry Andric         *McpuDefault = "cyclone";
27190b57cec5SDimitry Andric       if (ArchFlag)
27200b57cec5SDimitry Andric         *ArchFlag = "arm64_32";
27210b57cec5SDimitry Andric       return Triple("arm64_32-apple-darwin");
27220b57cec5SDimitry Andric     default:
27230b57cec5SDimitry Andric       return Triple();
27240b57cec5SDimitry Andric     }
27250b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC:
27260b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
27270b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_POWERPC_ALL:
27280b57cec5SDimitry Andric       if (ArchFlag)
27290b57cec5SDimitry Andric         *ArchFlag = "ppc";
27300b57cec5SDimitry Andric       return Triple("ppc-apple-darwin");
27310b57cec5SDimitry Andric     default:
27320b57cec5SDimitry Andric       return Triple();
27330b57cec5SDimitry Andric     }
27340b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
27350b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
27360b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_POWERPC_ALL:
27370b57cec5SDimitry Andric       if (ArchFlag)
27380b57cec5SDimitry Andric         *ArchFlag = "ppc64";
27390b57cec5SDimitry Andric       return Triple("ppc64-apple-darwin");
27400b57cec5SDimitry Andric     default:
27410b57cec5SDimitry Andric       return Triple();
27420b57cec5SDimitry Andric     }
27430b57cec5SDimitry Andric   default:
27440b57cec5SDimitry Andric     return Triple();
27450b57cec5SDimitry Andric   }
27460b57cec5SDimitry Andric }
27470b57cec5SDimitry Andric 
getHostArch()27480b57cec5SDimitry Andric Triple MachOObjectFile::getHostArch() {
27490b57cec5SDimitry Andric   return Triple(sys::getDefaultTargetTriple());
27500b57cec5SDimitry Andric }
27510b57cec5SDimitry Andric 
isValidArch(StringRef ArchFlag)27520b57cec5SDimitry Andric bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
27538bcb0991SDimitry Andric   auto validArchs = getValidArchs();
2754af732203SDimitry Andric   return llvm::is_contained(validArchs, ArchFlag);
27550b57cec5SDimitry Andric }
27560b57cec5SDimitry Andric 
getValidArchs()27578bcb0991SDimitry Andric ArrayRef<StringRef> MachOObjectFile::getValidArchs() {
2758af732203SDimitry Andric   static const std::array<StringRef, 18> ValidArchs = {{
2759af732203SDimitry Andric       "i386",
2760af732203SDimitry Andric       "x86_64",
2761af732203SDimitry Andric       "x86_64h",
2762af732203SDimitry Andric       "armv4t",
2763af732203SDimitry Andric       "arm",
2764af732203SDimitry Andric       "armv5e",
2765af732203SDimitry Andric       "armv6",
2766af732203SDimitry Andric       "armv6m",
2767af732203SDimitry Andric       "armv7",
2768af732203SDimitry Andric       "armv7em",
2769af732203SDimitry Andric       "armv7k",
2770af732203SDimitry Andric       "armv7m",
2771af732203SDimitry Andric       "armv7s",
2772af732203SDimitry Andric       "arm64",
2773af732203SDimitry Andric       "arm64e",
2774af732203SDimitry Andric       "arm64_32",
2775af732203SDimitry Andric       "ppc",
2776af732203SDimitry Andric       "ppc64",
27778bcb0991SDimitry Andric   }};
27788bcb0991SDimitry Andric 
2779af732203SDimitry Andric   return ValidArchs;
27808bcb0991SDimitry Andric }
27810b57cec5SDimitry Andric 
getArch() const27820b57cec5SDimitry Andric Triple::ArchType MachOObjectFile::getArch() const {
2783480093f4SDimitry Andric   return getArch(getCPUType(*this), getCPUSubType(*this));
27840b57cec5SDimitry Andric }
27850b57cec5SDimitry Andric 
getArchTriple(const char ** McpuDefault) const27860b57cec5SDimitry Andric Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
27870b57cec5SDimitry Andric   return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
27880b57cec5SDimitry Andric }
27890b57cec5SDimitry Andric 
section_rel_begin(unsigned Index) const27900b57cec5SDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
27910b57cec5SDimitry Andric   DataRefImpl DRI;
27920b57cec5SDimitry Andric   DRI.d.a = Index;
27930b57cec5SDimitry Andric   return section_rel_begin(DRI);
27940b57cec5SDimitry Andric }
27950b57cec5SDimitry Andric 
section_rel_end(unsigned Index) const27960b57cec5SDimitry Andric relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
27970b57cec5SDimitry Andric   DataRefImpl DRI;
27980b57cec5SDimitry Andric   DRI.d.a = Index;
27990b57cec5SDimitry Andric   return section_rel_end(DRI);
28000b57cec5SDimitry Andric }
28010b57cec5SDimitry Andric 
begin_dices() const28020b57cec5SDimitry Andric dice_iterator MachOObjectFile::begin_dices() const {
28030b57cec5SDimitry Andric   DataRefImpl DRI;
28040b57cec5SDimitry Andric   if (!DataInCodeLoadCmd)
28050b57cec5SDimitry Andric     return dice_iterator(DiceRef(DRI, this));
28060b57cec5SDimitry Andric 
28070b57cec5SDimitry Andric   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
28080b57cec5SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
28090b57cec5SDimitry Andric   return dice_iterator(DiceRef(DRI, this));
28100b57cec5SDimitry Andric }
28110b57cec5SDimitry Andric 
end_dices() const28120b57cec5SDimitry Andric dice_iterator MachOObjectFile::end_dices() const {
28130b57cec5SDimitry Andric   DataRefImpl DRI;
28140b57cec5SDimitry Andric   if (!DataInCodeLoadCmd)
28150b57cec5SDimitry Andric     return dice_iterator(DiceRef(DRI, this));
28160b57cec5SDimitry Andric 
28170b57cec5SDimitry Andric   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
28180b57cec5SDimitry Andric   unsigned Offset = DicLC.dataoff + DicLC.datasize;
28190b57cec5SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
28200b57cec5SDimitry Andric   return dice_iterator(DiceRef(DRI, this));
28210b57cec5SDimitry Andric }
28220b57cec5SDimitry Andric 
ExportEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> T)28230b57cec5SDimitry Andric ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
28240b57cec5SDimitry Andric                          ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
28250b57cec5SDimitry Andric 
moveToFirst()28260b57cec5SDimitry Andric void ExportEntry::moveToFirst() {
28270b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
28280b57cec5SDimitry Andric   pushNode(0);
28290b57cec5SDimitry Andric   if (*E)
28300b57cec5SDimitry Andric     return;
28310b57cec5SDimitry Andric   pushDownUntilBottom();
28320b57cec5SDimitry Andric }
28330b57cec5SDimitry Andric 
moveToEnd()28340b57cec5SDimitry Andric void ExportEntry::moveToEnd() {
28350b57cec5SDimitry Andric   Stack.clear();
28360b57cec5SDimitry Andric   Done = true;
28370b57cec5SDimitry Andric }
28380b57cec5SDimitry Andric 
operator ==(const ExportEntry & Other) const28390b57cec5SDimitry Andric bool ExportEntry::operator==(const ExportEntry &Other) const {
28400b57cec5SDimitry Andric   // Common case, one at end, other iterating from begin.
28410b57cec5SDimitry Andric   if (Done || Other.Done)
28420b57cec5SDimitry Andric     return (Done == Other.Done);
28430b57cec5SDimitry Andric   // Not equal if different stack sizes.
28440b57cec5SDimitry Andric   if (Stack.size() != Other.Stack.size())
28450b57cec5SDimitry Andric     return false;
28460b57cec5SDimitry Andric   // Not equal if different cumulative strings.
28470b57cec5SDimitry Andric   if (!CumulativeString.equals(Other.CumulativeString))
28480b57cec5SDimitry Andric     return false;
28490b57cec5SDimitry Andric   // Equal if all nodes in both stacks match.
28500b57cec5SDimitry Andric   for (unsigned i=0; i < Stack.size(); ++i) {
28510b57cec5SDimitry Andric     if (Stack[i].Start != Other.Stack[i].Start)
28520b57cec5SDimitry Andric       return false;
28530b57cec5SDimitry Andric   }
28540b57cec5SDimitry Andric   return true;
28550b57cec5SDimitry Andric }
28560b57cec5SDimitry Andric 
readULEB128(const uint8_t * & Ptr,const char ** error)28570b57cec5SDimitry Andric uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
28580b57cec5SDimitry Andric   unsigned Count;
28590b57cec5SDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
28600b57cec5SDimitry Andric   Ptr += Count;
28610b57cec5SDimitry Andric   if (Ptr > Trie.end())
28620b57cec5SDimitry Andric     Ptr = Trie.end();
28630b57cec5SDimitry Andric   return Result;
28640b57cec5SDimitry Andric }
28650b57cec5SDimitry Andric 
name() const28660b57cec5SDimitry Andric StringRef ExportEntry::name() const {
28670b57cec5SDimitry Andric   return CumulativeString;
28680b57cec5SDimitry Andric }
28690b57cec5SDimitry Andric 
flags() const28700b57cec5SDimitry Andric uint64_t ExportEntry::flags() const {
28710b57cec5SDimitry Andric   return Stack.back().Flags;
28720b57cec5SDimitry Andric }
28730b57cec5SDimitry Andric 
address() const28740b57cec5SDimitry Andric uint64_t ExportEntry::address() const {
28750b57cec5SDimitry Andric   return Stack.back().Address;
28760b57cec5SDimitry Andric }
28770b57cec5SDimitry Andric 
other() const28780b57cec5SDimitry Andric uint64_t ExportEntry::other() const {
28790b57cec5SDimitry Andric   return Stack.back().Other;
28800b57cec5SDimitry Andric }
28810b57cec5SDimitry Andric 
otherName() const28820b57cec5SDimitry Andric StringRef ExportEntry::otherName() const {
28830b57cec5SDimitry Andric   const char* ImportName = Stack.back().ImportName;
28840b57cec5SDimitry Andric   if (ImportName)
28850b57cec5SDimitry Andric     return StringRef(ImportName);
28860b57cec5SDimitry Andric   return StringRef();
28870b57cec5SDimitry Andric }
28880b57cec5SDimitry Andric 
nodeOffset() const28890b57cec5SDimitry Andric uint32_t ExportEntry::nodeOffset() const {
28900b57cec5SDimitry Andric   return Stack.back().Start - Trie.begin();
28910b57cec5SDimitry Andric }
28920b57cec5SDimitry Andric 
NodeState(const uint8_t * Ptr)28930b57cec5SDimitry Andric ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
28940b57cec5SDimitry Andric     : Start(Ptr), Current(Ptr) {}
28950b57cec5SDimitry Andric 
pushNode(uint64_t offset)28960b57cec5SDimitry Andric void ExportEntry::pushNode(uint64_t offset) {
28970b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
28980b57cec5SDimitry Andric   const uint8_t *Ptr = Trie.begin() + offset;
28990b57cec5SDimitry Andric   NodeState State(Ptr);
29000b57cec5SDimitry Andric   const char *error;
29010b57cec5SDimitry Andric   uint64_t ExportInfoSize = readULEB128(State.Current, &error);
29020b57cec5SDimitry Andric   if (error) {
29030b57cec5SDimitry Andric     *E = malformedError("export info size " + Twine(error) +
29040b57cec5SDimitry Andric                         " in export trie data at node: 0x" +
29050b57cec5SDimitry Andric                         Twine::utohexstr(offset));
29060b57cec5SDimitry Andric     moveToEnd();
29070b57cec5SDimitry Andric     return;
29080b57cec5SDimitry Andric   }
29090b57cec5SDimitry Andric   State.IsExportNode = (ExportInfoSize != 0);
29100b57cec5SDimitry Andric   const uint8_t* Children = State.Current + ExportInfoSize;
29110b57cec5SDimitry Andric   if (Children > Trie.end()) {
29120b57cec5SDimitry Andric     *E = malformedError(
29130b57cec5SDimitry Andric         "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
29140b57cec5SDimitry Andric         " in export trie data at node: 0x" + Twine::utohexstr(offset) +
29150b57cec5SDimitry Andric         " too big and extends past end of trie data");
29160b57cec5SDimitry Andric     moveToEnd();
29170b57cec5SDimitry Andric     return;
29180b57cec5SDimitry Andric   }
29190b57cec5SDimitry Andric   if (State.IsExportNode) {
29200b57cec5SDimitry Andric     const uint8_t *ExportStart = State.Current;
29210b57cec5SDimitry Andric     State.Flags = readULEB128(State.Current, &error);
29220b57cec5SDimitry Andric     if (error) {
29230b57cec5SDimitry Andric       *E = malformedError("flags " + Twine(error) +
29240b57cec5SDimitry Andric                           " in export trie data at node: 0x" +
29250b57cec5SDimitry Andric                           Twine::utohexstr(offset));
29260b57cec5SDimitry Andric       moveToEnd();
29270b57cec5SDimitry Andric       return;
29280b57cec5SDimitry Andric     }
29290b57cec5SDimitry Andric     uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
29300b57cec5SDimitry Andric     if (State.Flags != 0 &&
29310b57cec5SDimitry Andric         (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
29320b57cec5SDimitry Andric          Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
29330b57cec5SDimitry Andric          Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
29340b57cec5SDimitry Andric       *E = malformedError(
29350b57cec5SDimitry Andric           "unsupported exported symbol kind: " + Twine((int)Kind) +
29360b57cec5SDimitry Andric           " in flags: 0x" + Twine::utohexstr(State.Flags) +
29370b57cec5SDimitry Andric           " in export trie data at node: 0x" + Twine::utohexstr(offset));
29380b57cec5SDimitry Andric       moveToEnd();
29390b57cec5SDimitry Andric       return;
29400b57cec5SDimitry Andric     }
29410b57cec5SDimitry Andric     if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
29420b57cec5SDimitry Andric       State.Address = 0;
29430b57cec5SDimitry Andric       State.Other = readULEB128(State.Current, &error); // dylib ordinal
29440b57cec5SDimitry Andric       if (error) {
29450b57cec5SDimitry Andric         *E = malformedError("dylib ordinal of re-export " + Twine(error) +
29460b57cec5SDimitry Andric                             " in export trie data at node: 0x" +
29470b57cec5SDimitry Andric                             Twine::utohexstr(offset));
29480b57cec5SDimitry Andric         moveToEnd();
29490b57cec5SDimitry Andric         return;
29500b57cec5SDimitry Andric       }
29510b57cec5SDimitry Andric       if (O != nullptr) {
29520b57cec5SDimitry Andric         if (State.Other > O->getLibraryCount()) {
29530b57cec5SDimitry Andric           *E = malformedError(
29540b57cec5SDimitry Andric               "bad library ordinal: " + Twine((int)State.Other) + " (max " +
29550b57cec5SDimitry Andric               Twine((int)O->getLibraryCount()) +
29560b57cec5SDimitry Andric               ") in export trie data at node: 0x" + Twine::utohexstr(offset));
29570b57cec5SDimitry Andric           moveToEnd();
29580b57cec5SDimitry Andric           return;
29590b57cec5SDimitry Andric         }
29600b57cec5SDimitry Andric       }
29610b57cec5SDimitry Andric       State.ImportName = reinterpret_cast<const char*>(State.Current);
29620b57cec5SDimitry Andric       if (*State.ImportName == '\0') {
29630b57cec5SDimitry Andric         State.Current++;
29640b57cec5SDimitry Andric       } else {
29650b57cec5SDimitry Andric         const uint8_t *End = State.Current + 1;
29660b57cec5SDimitry Andric         if (End >= Trie.end()) {
29670b57cec5SDimitry Andric           *E = malformedError("import name of re-export in export trie data at "
29680b57cec5SDimitry Andric                               "node: 0x" +
29690b57cec5SDimitry Andric                               Twine::utohexstr(offset) +
29700b57cec5SDimitry Andric                               " starts past end of trie data");
29710b57cec5SDimitry Andric           moveToEnd();
29720b57cec5SDimitry Andric           return;
29730b57cec5SDimitry Andric         }
29740b57cec5SDimitry Andric         while(*End != '\0' && End < Trie.end())
29750b57cec5SDimitry Andric           End++;
29760b57cec5SDimitry Andric         if (*End != '\0') {
29770b57cec5SDimitry Andric           *E = malformedError("import name of re-export in export trie data at "
29780b57cec5SDimitry Andric                               "node: 0x" +
29790b57cec5SDimitry Andric                               Twine::utohexstr(offset) +
29800b57cec5SDimitry Andric                               " extends past end of trie data");
29810b57cec5SDimitry Andric           moveToEnd();
29820b57cec5SDimitry Andric           return;
29830b57cec5SDimitry Andric         }
29840b57cec5SDimitry Andric         State.Current = End + 1;
29850b57cec5SDimitry Andric       }
29860b57cec5SDimitry Andric     } else {
29870b57cec5SDimitry Andric       State.Address = readULEB128(State.Current, &error);
29880b57cec5SDimitry Andric       if (error) {
29890b57cec5SDimitry Andric         *E = malformedError("address " + Twine(error) +
29900b57cec5SDimitry Andric                             " in export trie data at node: 0x" +
29910b57cec5SDimitry Andric                             Twine::utohexstr(offset));
29920b57cec5SDimitry Andric         moveToEnd();
29930b57cec5SDimitry Andric         return;
29940b57cec5SDimitry Andric       }
29950b57cec5SDimitry Andric       if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
29960b57cec5SDimitry Andric         State.Other = readULEB128(State.Current, &error);
29970b57cec5SDimitry Andric         if (error) {
29980b57cec5SDimitry Andric           *E = malformedError("resolver of stub and resolver " + Twine(error) +
29990b57cec5SDimitry Andric                               " in export trie data at node: 0x" +
30000b57cec5SDimitry Andric                               Twine::utohexstr(offset));
30010b57cec5SDimitry Andric           moveToEnd();
30020b57cec5SDimitry Andric           return;
30030b57cec5SDimitry Andric         }
30040b57cec5SDimitry Andric       }
30050b57cec5SDimitry Andric     }
30060b57cec5SDimitry Andric     if(ExportStart + ExportInfoSize != State.Current) {
30070b57cec5SDimitry Andric       *E = malformedError(
30080b57cec5SDimitry Andric           "inconsistant export info size: 0x" +
30090b57cec5SDimitry Andric           Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
30100b57cec5SDimitry Andric           Twine::utohexstr(State.Current - ExportStart) +
30110b57cec5SDimitry Andric           " in export trie data at node: 0x" + Twine::utohexstr(offset));
30120b57cec5SDimitry Andric       moveToEnd();
30130b57cec5SDimitry Andric       return;
30140b57cec5SDimitry Andric     }
30150b57cec5SDimitry Andric   }
30160b57cec5SDimitry Andric   State.ChildCount = *Children;
30170b57cec5SDimitry Andric   if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
30180b57cec5SDimitry Andric     *E = malformedError("byte for count of childern in export trie data at "
30190b57cec5SDimitry Andric                         "node: 0x" +
30200b57cec5SDimitry Andric                         Twine::utohexstr(offset) +
30210b57cec5SDimitry Andric                         " extends past end of trie data");
30220b57cec5SDimitry Andric     moveToEnd();
30230b57cec5SDimitry Andric     return;
30240b57cec5SDimitry Andric   }
30250b57cec5SDimitry Andric   State.Current = Children + 1;
30260b57cec5SDimitry Andric   State.NextChildIndex = 0;
30270b57cec5SDimitry Andric   State.ParentStringLength = CumulativeString.size();
30280b57cec5SDimitry Andric   Stack.push_back(State);
30290b57cec5SDimitry Andric }
30300b57cec5SDimitry Andric 
pushDownUntilBottom()30310b57cec5SDimitry Andric void ExportEntry::pushDownUntilBottom() {
30320b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
30330b57cec5SDimitry Andric   const char *error;
30340b57cec5SDimitry Andric   while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
30350b57cec5SDimitry Andric     NodeState &Top = Stack.back();
30360b57cec5SDimitry Andric     CumulativeString.resize(Top.ParentStringLength);
30370b57cec5SDimitry Andric     for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
30380b57cec5SDimitry Andric       char C = *Top.Current;
30390b57cec5SDimitry Andric       CumulativeString.push_back(C);
30400b57cec5SDimitry Andric     }
30410b57cec5SDimitry Andric     if (Top.Current >= Trie.end()) {
30420b57cec5SDimitry Andric       *E = malformedError("edge sub-string in export trie data at node: 0x" +
30430b57cec5SDimitry Andric                           Twine::utohexstr(Top.Start - Trie.begin()) +
30440b57cec5SDimitry Andric                           " for child #" + Twine((int)Top.NextChildIndex) +
30450b57cec5SDimitry Andric                           " extends past end of trie data");
30460b57cec5SDimitry Andric       moveToEnd();
30470b57cec5SDimitry Andric       return;
30480b57cec5SDimitry Andric     }
30490b57cec5SDimitry Andric     Top.Current += 1;
30500b57cec5SDimitry Andric     uint64_t childNodeIndex = readULEB128(Top.Current, &error);
30510b57cec5SDimitry Andric     if (error) {
30520b57cec5SDimitry Andric       *E = malformedError("child node offset " + Twine(error) +
30530b57cec5SDimitry Andric                           " in export trie data at node: 0x" +
30540b57cec5SDimitry Andric                           Twine::utohexstr(Top.Start - Trie.begin()));
30550b57cec5SDimitry Andric       moveToEnd();
30560b57cec5SDimitry Andric       return;
30570b57cec5SDimitry Andric     }
30580b57cec5SDimitry Andric     for (const NodeState &node : nodes()) {
30590b57cec5SDimitry Andric       if (node.Start == Trie.begin() + childNodeIndex){
30600b57cec5SDimitry Andric         *E = malformedError("loop in childern in export trie data at node: 0x" +
30610b57cec5SDimitry Andric                             Twine::utohexstr(Top.Start - Trie.begin()) +
30620b57cec5SDimitry Andric                             " back to node: 0x" +
30630b57cec5SDimitry Andric                             Twine::utohexstr(childNodeIndex));
30640b57cec5SDimitry Andric         moveToEnd();
30650b57cec5SDimitry Andric         return;
30660b57cec5SDimitry Andric       }
30670b57cec5SDimitry Andric     }
30680b57cec5SDimitry Andric     Top.NextChildIndex += 1;
30690b57cec5SDimitry Andric     pushNode(childNodeIndex);
30700b57cec5SDimitry Andric     if (*E)
30710b57cec5SDimitry Andric       return;
30720b57cec5SDimitry Andric   }
30730b57cec5SDimitry Andric   if (!Stack.back().IsExportNode) {
30740b57cec5SDimitry Andric     *E = malformedError("node is not an export node in export trie data at "
30750b57cec5SDimitry Andric                         "node: 0x" +
30760b57cec5SDimitry Andric                         Twine::utohexstr(Stack.back().Start - Trie.begin()));
30770b57cec5SDimitry Andric     moveToEnd();
30780b57cec5SDimitry Andric     return;
30790b57cec5SDimitry Andric   }
30800b57cec5SDimitry Andric }
30810b57cec5SDimitry Andric 
30820b57cec5SDimitry Andric // We have a trie data structure and need a way to walk it that is compatible
30830b57cec5SDimitry Andric // with the C++ iterator model. The solution is a non-recursive depth first
30840b57cec5SDimitry Andric // traversal where the iterator contains a stack of parent nodes along with a
30850b57cec5SDimitry Andric // string that is the accumulation of all edge strings along the parent chain
30860b57cec5SDimitry Andric // to this point.
30870b57cec5SDimitry Andric //
30880b57cec5SDimitry Andric // There is one "export" node for each exported symbol.  But because some
30890b57cec5SDimitry Andric // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
30900b57cec5SDimitry Andric // node may have child nodes too.
30910b57cec5SDimitry Andric //
30920b57cec5SDimitry Andric // The algorithm for moveNext() is to keep moving down the leftmost unvisited
30930b57cec5SDimitry Andric // child until hitting a node with no children (which is an export node or
30940b57cec5SDimitry Andric // else the trie is malformed). On the way down, each node is pushed on the
30950b57cec5SDimitry Andric // stack ivar.  If there is no more ways down, it pops up one and tries to go
30960b57cec5SDimitry Andric // down a sibling path until a childless node is reached.
moveNext()30970b57cec5SDimitry Andric void ExportEntry::moveNext() {
30980b57cec5SDimitry Andric   assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
30990b57cec5SDimitry Andric   if (!Stack.back().IsExportNode) {
31000b57cec5SDimitry Andric     *E = malformedError("node is not an export node in export trie data at "
31010b57cec5SDimitry Andric                         "node: 0x" +
31020b57cec5SDimitry Andric                         Twine::utohexstr(Stack.back().Start - Trie.begin()));
31030b57cec5SDimitry Andric     moveToEnd();
31040b57cec5SDimitry Andric     return;
31050b57cec5SDimitry Andric   }
31060b57cec5SDimitry Andric 
31070b57cec5SDimitry Andric   Stack.pop_back();
31080b57cec5SDimitry Andric   while (!Stack.empty()) {
31090b57cec5SDimitry Andric     NodeState &Top = Stack.back();
31100b57cec5SDimitry Andric     if (Top.NextChildIndex < Top.ChildCount) {
31110b57cec5SDimitry Andric       pushDownUntilBottom();
31120b57cec5SDimitry Andric       // Now at the next export node.
31130b57cec5SDimitry Andric       return;
31140b57cec5SDimitry Andric     } else {
31150b57cec5SDimitry Andric       if (Top.IsExportNode) {
31160b57cec5SDimitry Andric         // This node has no children but is itself an export node.
31170b57cec5SDimitry Andric         CumulativeString.resize(Top.ParentStringLength);
31180b57cec5SDimitry Andric         return;
31190b57cec5SDimitry Andric       }
31200b57cec5SDimitry Andric       Stack.pop_back();
31210b57cec5SDimitry Andric     }
31220b57cec5SDimitry Andric   }
31230b57cec5SDimitry Andric   Done = true;
31240b57cec5SDimitry Andric }
31250b57cec5SDimitry Andric 
31260b57cec5SDimitry Andric iterator_range<export_iterator>
exports(Error & E,ArrayRef<uint8_t> Trie,const MachOObjectFile * O)31270b57cec5SDimitry Andric MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
31280b57cec5SDimitry Andric                          const MachOObjectFile *O) {
31290b57cec5SDimitry Andric   ExportEntry Start(&E, O, Trie);
31300b57cec5SDimitry Andric   if (Trie.empty())
31310b57cec5SDimitry Andric     Start.moveToEnd();
31320b57cec5SDimitry Andric   else
31330b57cec5SDimitry Andric     Start.moveToFirst();
31340b57cec5SDimitry Andric 
31350b57cec5SDimitry Andric   ExportEntry Finish(&E, O, Trie);
31360b57cec5SDimitry Andric   Finish.moveToEnd();
31370b57cec5SDimitry Andric 
31380b57cec5SDimitry Andric   return make_range(export_iterator(Start), export_iterator(Finish));
31390b57cec5SDimitry Andric }
31400b57cec5SDimitry Andric 
exports(Error & Err) const31410b57cec5SDimitry Andric iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
31420b57cec5SDimitry Andric   return exports(Err, getDyldInfoExportsTrie(), this);
31430b57cec5SDimitry Andric }
31440b57cec5SDimitry Andric 
MachORebaseEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit)31450b57cec5SDimitry Andric MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
31460b57cec5SDimitry Andric                                    ArrayRef<uint8_t> Bytes, bool is64Bit)
31470b57cec5SDimitry Andric     : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
31480b57cec5SDimitry Andric       PointerSize(is64Bit ? 8 : 4) {}
31490b57cec5SDimitry Andric 
moveToFirst()31500b57cec5SDimitry Andric void MachORebaseEntry::moveToFirst() {
31510b57cec5SDimitry Andric   Ptr = Opcodes.begin();
31520b57cec5SDimitry Andric   moveNext();
31530b57cec5SDimitry Andric }
31540b57cec5SDimitry Andric 
moveToEnd()31550b57cec5SDimitry Andric void MachORebaseEntry::moveToEnd() {
31560b57cec5SDimitry Andric   Ptr = Opcodes.end();
31570b57cec5SDimitry Andric   RemainingLoopCount = 0;
31580b57cec5SDimitry Andric   Done = true;
31590b57cec5SDimitry Andric }
31600b57cec5SDimitry Andric 
moveNext()31610b57cec5SDimitry Andric void MachORebaseEntry::moveNext() {
31620b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
31630b57cec5SDimitry Andric   // If in the middle of some loop, move to next rebasing in loop.
31640b57cec5SDimitry Andric   SegmentOffset += AdvanceAmount;
31650b57cec5SDimitry Andric   if (RemainingLoopCount) {
31660b57cec5SDimitry Andric     --RemainingLoopCount;
31670b57cec5SDimitry Andric     return;
31680b57cec5SDimitry Andric   }
31690b57cec5SDimitry Andric   // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
31700b57cec5SDimitry Andric   // pointer size. Therefore it is possible to reach the end without ever having
31710b57cec5SDimitry Andric   // seen REBASE_OPCODE_DONE.
31720b57cec5SDimitry Andric   if (Ptr == Opcodes.end()) {
31730b57cec5SDimitry Andric     Done = true;
31740b57cec5SDimitry Andric     return;
31750b57cec5SDimitry Andric   }
31760b57cec5SDimitry Andric   bool More = true;
31770b57cec5SDimitry Andric   while (More) {
31780b57cec5SDimitry Andric     // Parse next opcode and set up next loop.
31790b57cec5SDimitry Andric     const uint8_t *OpcodeStart = Ptr;
31800b57cec5SDimitry Andric     uint8_t Byte = *Ptr++;
31810b57cec5SDimitry Andric     uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
31820b57cec5SDimitry Andric     uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
31830b57cec5SDimitry Andric     uint32_t Count, Skip;
31840b57cec5SDimitry Andric     const char *error = nullptr;
31850b57cec5SDimitry Andric     switch (Opcode) {
31860b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DONE:
31870b57cec5SDimitry Andric       More = false;
31880b57cec5SDimitry Andric       Done = true;
31890b57cec5SDimitry Andric       moveToEnd();
31900b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
31910b57cec5SDimitry Andric       break;
31920b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_SET_TYPE_IMM:
31930b57cec5SDimitry Andric       RebaseType = ImmValue;
31940b57cec5SDimitry Andric       if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
31950b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
31960b57cec5SDimitry Andric                             Twine((int)RebaseType) + " for opcode at: 0x" +
31970b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31980b57cec5SDimitry Andric         moveToEnd();
31990b57cec5SDimitry Andric         return;
32000b57cec5SDimitry Andric       }
32010b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
32020b57cec5SDimitry Andric           "mach-o-rebase",
32030b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
32040b57cec5SDimitry Andric                  << "RebaseType=" << (int) RebaseType << "\n");
32050b57cec5SDimitry Andric       break;
32060b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
32070b57cec5SDimitry Andric       SegmentIndex = ImmValue;
32080b57cec5SDimitry Andric       SegmentOffset = readULEB128(&error);
32090b57cec5SDimitry Andric       if (error) {
32100b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
32110b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32120b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32130b57cec5SDimitry Andric         moveToEnd();
32140b57cec5SDimitry Andric         return;
32150b57cec5SDimitry Andric       }
32160b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
32170b57cec5SDimitry Andric                                                PointerSize);
32180b57cec5SDimitry Andric       if (error) {
32190b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
32200b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32210b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32220b57cec5SDimitry Andric         moveToEnd();
32230b57cec5SDimitry Andric         return;
32240b57cec5SDimitry Andric       }
32250b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
32260b57cec5SDimitry Andric           "mach-o-rebase",
32270b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
32280b57cec5SDimitry Andric                  << "SegmentIndex=" << SegmentIndex << ", "
32290b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
32300b57cec5SDimitry Andric                  << "\n");
32310b57cec5SDimitry Andric       break;
32320b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
32330b57cec5SDimitry Andric       SegmentOffset += readULEB128(&error);
32340b57cec5SDimitry Andric       if (error) {
32350b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
32360b57cec5SDimitry Andric                             " for opcode at: 0x" +
32370b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32380b57cec5SDimitry Andric         moveToEnd();
32390b57cec5SDimitry Andric         return;
32400b57cec5SDimitry Andric       }
32410b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
32420b57cec5SDimitry Andric                                                PointerSize);
32430b57cec5SDimitry Andric       if (error) {
32440b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
32450b57cec5SDimitry Andric                             " for opcode at: 0x" +
32460b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32470b57cec5SDimitry Andric         moveToEnd();
32480b57cec5SDimitry Andric         return;
32490b57cec5SDimitry Andric       }
32500b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase",
32510b57cec5SDimitry Andric                       dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
32520b57cec5SDimitry Andric                              << format("SegmentOffset=0x%06X",
32530b57cec5SDimitry Andric                                        SegmentOffset) << "\n");
32540b57cec5SDimitry Andric       break;
32550b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
32560b57cec5SDimitry Andric       SegmentOffset += ImmValue * PointerSize;
32570b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
32580b57cec5SDimitry Andric                                                PointerSize);
32590b57cec5SDimitry Andric       if (error) {
32605ffd83dbSDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
32610b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32620b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32630b57cec5SDimitry Andric         moveToEnd();
32640b57cec5SDimitry Andric         return;
32650b57cec5SDimitry Andric       }
32660b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase",
32670b57cec5SDimitry Andric                       dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
32680b57cec5SDimitry Andric                              << format("SegmentOffset=0x%06X",
32690b57cec5SDimitry Andric                                        SegmentOffset) << "\n");
32700b57cec5SDimitry Andric       break;
32710b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
32720b57cec5SDimitry Andric       AdvanceAmount = PointerSize;
32730b57cec5SDimitry Andric       Skip = 0;
32740b57cec5SDimitry Andric       Count = ImmValue;
32750b57cec5SDimitry Andric       if (ImmValue != 0)
32760b57cec5SDimitry Andric         RemainingLoopCount = ImmValue - 1;
32770b57cec5SDimitry Andric       else
32780b57cec5SDimitry Andric         RemainingLoopCount = 0;
32790b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
32800b57cec5SDimitry Andric                                                PointerSize, Count, Skip);
32810b57cec5SDimitry Andric       if (error) {
32820b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
32830b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
32840b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32850b57cec5SDimitry Andric         moveToEnd();
32860b57cec5SDimitry Andric         return;
32870b57cec5SDimitry Andric       }
32880b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
32890b57cec5SDimitry Andric           "mach-o-rebase",
32900b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
32910b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
32920b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
32930b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
32940b57cec5SDimitry Andric                  << "\n");
32950b57cec5SDimitry Andric       return;
32960b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
32970b57cec5SDimitry Andric       AdvanceAmount = PointerSize;
32980b57cec5SDimitry Andric       Skip = 0;
32990b57cec5SDimitry Andric       Count = readULEB128(&error);
33000b57cec5SDimitry Andric       if (error) {
33010b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
33020b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33030b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33040b57cec5SDimitry Andric         moveToEnd();
33050b57cec5SDimitry Andric         return;
33060b57cec5SDimitry Andric       }
33070b57cec5SDimitry Andric       if (Count != 0)
33080b57cec5SDimitry Andric         RemainingLoopCount = Count - 1;
33090b57cec5SDimitry Andric       else
33100b57cec5SDimitry Andric         RemainingLoopCount = 0;
33110b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
33120b57cec5SDimitry Andric                                                PointerSize, Count, Skip);
33130b57cec5SDimitry Andric       if (error) {
33140b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
33150b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33160b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33170b57cec5SDimitry Andric         moveToEnd();
33180b57cec5SDimitry Andric         return;
33190b57cec5SDimitry Andric       }
33200b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
33210b57cec5SDimitry Andric           "mach-o-rebase",
33220b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
33230b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
33240b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
33250b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
33260b57cec5SDimitry Andric                  << "\n");
33270b57cec5SDimitry Andric       return;
33280b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
33290b57cec5SDimitry Andric       Skip = readULEB128(&error);
33300b57cec5SDimitry Andric       if (error) {
33310b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
33320b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33330b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33340b57cec5SDimitry Andric         moveToEnd();
33350b57cec5SDimitry Andric         return;
33360b57cec5SDimitry Andric       }
33370b57cec5SDimitry Andric       AdvanceAmount = Skip + PointerSize;
33380b57cec5SDimitry Andric       Count = 1;
33390b57cec5SDimitry Andric       RemainingLoopCount = 0;
33400b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
33410b57cec5SDimitry Andric                                                PointerSize, Count, Skip);
33420b57cec5SDimitry Andric       if (error) {
33430b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
33440b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33450b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33460b57cec5SDimitry Andric         moveToEnd();
33470b57cec5SDimitry Andric         return;
33480b57cec5SDimitry Andric       }
33490b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
33500b57cec5SDimitry Andric           "mach-o-rebase",
33510b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
33520b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
33530b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
33540b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
33550b57cec5SDimitry Andric                  << "\n");
33560b57cec5SDimitry Andric       return;
33570b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
33580b57cec5SDimitry Andric       Count = readULEB128(&error);
33590b57cec5SDimitry Andric       if (error) {
33600b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
33610b57cec5SDimitry Andric                             "ULEB " +
33620b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33630b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33640b57cec5SDimitry Andric         moveToEnd();
33650b57cec5SDimitry Andric         return;
33660b57cec5SDimitry Andric       }
33670b57cec5SDimitry Andric       if (Count != 0)
33680b57cec5SDimitry Andric         RemainingLoopCount = Count - 1;
33690b57cec5SDimitry Andric       else
33700b57cec5SDimitry Andric         RemainingLoopCount = 0;
33710b57cec5SDimitry Andric       Skip = readULEB128(&error);
33720b57cec5SDimitry Andric       if (error) {
33730b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
33740b57cec5SDimitry Andric                             "ULEB " +
33750b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33760b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33770b57cec5SDimitry Andric         moveToEnd();
33780b57cec5SDimitry Andric         return;
33790b57cec5SDimitry Andric       }
33800b57cec5SDimitry Andric       AdvanceAmount = Skip + PointerSize;
33810b57cec5SDimitry Andric 
33820b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
33830b57cec5SDimitry Andric                                                PointerSize, Count, Skip);
33840b57cec5SDimitry Andric       if (error) {
33850b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
33860b57cec5SDimitry Andric                             "ULEB " +
33870b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
33880b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33890b57cec5SDimitry Andric         moveToEnd();
33900b57cec5SDimitry Andric         return;
33910b57cec5SDimitry Andric       }
33920b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
33930b57cec5SDimitry Andric           "mach-o-rebase",
33940b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
33950b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
33960b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
33970b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
33980b57cec5SDimitry Andric                  << "\n");
33990b57cec5SDimitry Andric       return;
34000b57cec5SDimitry Andric     default:
34010b57cec5SDimitry Andric       *E = malformedError("bad rebase info (bad opcode value 0x" +
34020b57cec5SDimitry Andric                           Twine::utohexstr(Opcode) + " for opcode at: 0x" +
34030b57cec5SDimitry Andric                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
34040b57cec5SDimitry Andric       moveToEnd();
34050b57cec5SDimitry Andric       return;
34060b57cec5SDimitry Andric     }
34070b57cec5SDimitry Andric   }
34080b57cec5SDimitry Andric }
34090b57cec5SDimitry Andric 
readULEB128(const char ** error)34100b57cec5SDimitry Andric uint64_t MachORebaseEntry::readULEB128(const char **error) {
34110b57cec5SDimitry Andric   unsigned Count;
34120b57cec5SDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
34130b57cec5SDimitry Andric   Ptr += Count;
34140b57cec5SDimitry Andric   if (Ptr > Opcodes.end())
34150b57cec5SDimitry Andric     Ptr = Opcodes.end();
34160b57cec5SDimitry Andric   return Result;
34170b57cec5SDimitry Andric }
34180b57cec5SDimitry Andric 
segmentIndex() const34190b57cec5SDimitry Andric int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
34200b57cec5SDimitry Andric 
segmentOffset() const34210b57cec5SDimitry Andric uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
34220b57cec5SDimitry Andric 
typeName() const34230b57cec5SDimitry Andric StringRef MachORebaseEntry::typeName() const {
34240b57cec5SDimitry Andric   switch (RebaseType) {
34250b57cec5SDimitry Andric   case MachO::REBASE_TYPE_POINTER:
34260b57cec5SDimitry Andric     return "pointer";
34270b57cec5SDimitry Andric   case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
34280b57cec5SDimitry Andric     return "text abs32";
34290b57cec5SDimitry Andric   case MachO::REBASE_TYPE_TEXT_PCREL32:
34300b57cec5SDimitry Andric     return "text rel32";
34310b57cec5SDimitry Andric   }
34320b57cec5SDimitry Andric   return "unknown";
34330b57cec5SDimitry Andric }
34340b57cec5SDimitry Andric 
34350b57cec5SDimitry Andric // For use with the SegIndex of a checked Mach-O Rebase entry
34360b57cec5SDimitry Andric // to get the segment name.
segmentName() const34370b57cec5SDimitry Andric StringRef MachORebaseEntry::segmentName() const {
34380b57cec5SDimitry Andric   return O->BindRebaseSegmentName(SegmentIndex);
34390b57cec5SDimitry Andric }
34400b57cec5SDimitry Andric 
34410b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
34420b57cec5SDimitry Andric // to get the section name.
sectionName() const34430b57cec5SDimitry Andric StringRef MachORebaseEntry::sectionName() const {
34440b57cec5SDimitry Andric   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
34450b57cec5SDimitry Andric }
34460b57cec5SDimitry Andric 
34470b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
34480b57cec5SDimitry Andric // to get the address.
address() const34490b57cec5SDimitry Andric uint64_t MachORebaseEntry::address() const {
34500b57cec5SDimitry Andric   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
34510b57cec5SDimitry Andric }
34520b57cec5SDimitry Andric 
operator ==(const MachORebaseEntry & Other) const34530b57cec5SDimitry Andric bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
34540b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
34550b57cec5SDimitry Andric   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
34560b57cec5SDimitry Andric #else
34570b57cec5SDimitry Andric   assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
34580b57cec5SDimitry Andric #endif
34590b57cec5SDimitry Andric   return (Ptr == Other.Ptr) &&
34600b57cec5SDimitry Andric          (RemainingLoopCount == Other.RemainingLoopCount) &&
34610b57cec5SDimitry Andric          (Done == Other.Done);
34620b57cec5SDimitry Andric }
34630b57cec5SDimitry Andric 
34640b57cec5SDimitry Andric iterator_range<rebase_iterator>
rebaseTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64)34650b57cec5SDimitry Andric MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
34660b57cec5SDimitry Andric                              ArrayRef<uint8_t> Opcodes, bool is64) {
34670b57cec5SDimitry Andric   if (O->BindRebaseSectionTable == nullptr)
34688bcb0991SDimitry Andric     O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
34690b57cec5SDimitry Andric   MachORebaseEntry Start(&Err, O, Opcodes, is64);
34700b57cec5SDimitry Andric   Start.moveToFirst();
34710b57cec5SDimitry Andric 
34720b57cec5SDimitry Andric   MachORebaseEntry Finish(&Err, O, Opcodes, is64);
34730b57cec5SDimitry Andric   Finish.moveToEnd();
34740b57cec5SDimitry Andric 
34750b57cec5SDimitry Andric   return make_range(rebase_iterator(Start), rebase_iterator(Finish));
34760b57cec5SDimitry Andric }
34770b57cec5SDimitry Andric 
rebaseTable(Error & Err)34780b57cec5SDimitry Andric iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
34790b57cec5SDimitry Andric   return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
34800b57cec5SDimitry Andric }
34810b57cec5SDimitry Andric 
MachOBindEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)34820b57cec5SDimitry Andric MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
34830b57cec5SDimitry Andric                                ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
34840b57cec5SDimitry Andric     : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
34850b57cec5SDimitry Andric       PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
34860b57cec5SDimitry Andric 
moveToFirst()34870b57cec5SDimitry Andric void MachOBindEntry::moveToFirst() {
34880b57cec5SDimitry Andric   Ptr = Opcodes.begin();
34890b57cec5SDimitry Andric   moveNext();
34900b57cec5SDimitry Andric }
34910b57cec5SDimitry Andric 
moveToEnd()34920b57cec5SDimitry Andric void MachOBindEntry::moveToEnd() {
34930b57cec5SDimitry Andric   Ptr = Opcodes.end();
34940b57cec5SDimitry Andric   RemainingLoopCount = 0;
34950b57cec5SDimitry Andric   Done = true;
34960b57cec5SDimitry Andric }
34970b57cec5SDimitry Andric 
moveNext()34980b57cec5SDimitry Andric void MachOBindEntry::moveNext() {
34990b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
35000b57cec5SDimitry Andric   // If in the middle of some loop, move to next binding in loop.
35010b57cec5SDimitry Andric   SegmentOffset += AdvanceAmount;
35020b57cec5SDimitry Andric   if (RemainingLoopCount) {
35030b57cec5SDimitry Andric     --RemainingLoopCount;
35040b57cec5SDimitry Andric     return;
35050b57cec5SDimitry Andric   }
35060b57cec5SDimitry Andric   // BIND_OPCODE_DONE is only used for padding if we are not aligned to
35070b57cec5SDimitry Andric   // pointer size. Therefore it is possible to reach the end without ever having
35080b57cec5SDimitry Andric   // seen BIND_OPCODE_DONE.
35090b57cec5SDimitry Andric   if (Ptr == Opcodes.end()) {
35100b57cec5SDimitry Andric     Done = true;
35110b57cec5SDimitry Andric     return;
35120b57cec5SDimitry Andric   }
35130b57cec5SDimitry Andric   bool More = true;
35140b57cec5SDimitry Andric   while (More) {
35150b57cec5SDimitry Andric     // Parse next opcode and set up next loop.
35160b57cec5SDimitry Andric     const uint8_t *OpcodeStart = Ptr;
35170b57cec5SDimitry Andric     uint8_t Byte = *Ptr++;
35180b57cec5SDimitry Andric     uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
35190b57cec5SDimitry Andric     uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
35200b57cec5SDimitry Andric     int8_t SignExtended;
35210b57cec5SDimitry Andric     const uint8_t *SymStart;
35220b57cec5SDimitry Andric     uint32_t Count, Skip;
35230b57cec5SDimitry Andric     const char *error = nullptr;
35240b57cec5SDimitry Andric     switch (Opcode) {
35250b57cec5SDimitry Andric     case MachO::BIND_OPCODE_DONE:
35260b57cec5SDimitry Andric       if (TableKind == Kind::Lazy) {
35270b57cec5SDimitry Andric         // Lazying bindings have a DONE opcode between entries.  Need to ignore
35280b57cec5SDimitry Andric         // it to advance to next entry.  But need not if this is last entry.
35290b57cec5SDimitry Andric         bool NotLastEntry = false;
35300b57cec5SDimitry Andric         for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
35310b57cec5SDimitry Andric           if (*P) {
35320b57cec5SDimitry Andric             NotLastEntry = true;
35330b57cec5SDimitry Andric           }
35340b57cec5SDimitry Andric         }
35350b57cec5SDimitry Andric         if (NotLastEntry)
35360b57cec5SDimitry Andric           break;
35370b57cec5SDimitry Andric       }
35380b57cec5SDimitry Andric       More = false;
35390b57cec5SDimitry Andric       moveToEnd();
35400b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
35410b57cec5SDimitry Andric       break;
35420b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
35430b57cec5SDimitry Andric       if (TableKind == Kind::Weak) {
35440b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
35450b57cec5SDimitry Andric                             "weak bind table for opcode at: 0x" +
35460b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35470b57cec5SDimitry Andric         moveToEnd();
35480b57cec5SDimitry Andric         return;
35490b57cec5SDimitry Andric       }
35500b57cec5SDimitry Andric       Ordinal = ImmValue;
35510b57cec5SDimitry Andric       LibraryOrdinalSet = true;
35520b57cec5SDimitry Andric       if (ImmValue > O->getLibraryCount()) {
35530b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
35540b57cec5SDimitry Andric                             "library ordinal: " +
35550b57cec5SDimitry Andric                             Twine((int)ImmValue) + " (max " +
35560b57cec5SDimitry Andric                             Twine((int)O->getLibraryCount()) +
35570b57cec5SDimitry Andric                             ") for opcode at: 0x" +
35580b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35590b57cec5SDimitry Andric         moveToEnd();
35600b57cec5SDimitry Andric         return;
35610b57cec5SDimitry Andric       }
35620b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
35630b57cec5SDimitry Andric           "mach-o-bind",
35640b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
35650b57cec5SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
35660b57cec5SDimitry Andric       break;
35670b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
35680b57cec5SDimitry Andric       if (TableKind == Kind::Weak) {
35690b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
35700b57cec5SDimitry Andric                             "weak bind table for opcode at: 0x" +
35710b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35720b57cec5SDimitry Andric         moveToEnd();
35730b57cec5SDimitry Andric         return;
35740b57cec5SDimitry Andric       }
35750b57cec5SDimitry Andric       Ordinal = readULEB128(&error);
35760b57cec5SDimitry Andric       LibraryOrdinalSet = true;
35770b57cec5SDimitry Andric       if (error) {
35780b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
35790b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
35800b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35810b57cec5SDimitry Andric         moveToEnd();
35820b57cec5SDimitry Andric         return;
35830b57cec5SDimitry Andric       }
35840b57cec5SDimitry Andric       if (Ordinal > (int)O->getLibraryCount()) {
35850b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
35860b57cec5SDimitry Andric                             "library ordinal: " +
35870b57cec5SDimitry Andric                             Twine((int)Ordinal) + " (max " +
35880b57cec5SDimitry Andric                             Twine((int)O->getLibraryCount()) +
35890b57cec5SDimitry Andric                             ") for opcode at: 0x" +
35900b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35910b57cec5SDimitry Andric         moveToEnd();
35920b57cec5SDimitry Andric         return;
35930b57cec5SDimitry Andric       }
35940b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
35950b57cec5SDimitry Andric           "mach-o-bind",
35960b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
35970b57cec5SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
35980b57cec5SDimitry Andric       break;
35990b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
36000b57cec5SDimitry Andric       if (TableKind == Kind::Weak) {
36010b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
36020b57cec5SDimitry Andric                             "weak bind table for opcode at: 0x" +
36030b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36040b57cec5SDimitry Andric         moveToEnd();
36050b57cec5SDimitry Andric         return;
36060b57cec5SDimitry Andric       }
36070b57cec5SDimitry Andric       if (ImmValue) {
36080b57cec5SDimitry Andric         SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
36090b57cec5SDimitry Andric         Ordinal = SignExtended;
36100b57cec5SDimitry Andric         if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
36110b57cec5SDimitry Andric           *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
36120b57cec5SDimitry Andric                               "special ordinal: " +
36130b57cec5SDimitry Andric                               Twine((int)Ordinal) + " for opcode at: 0x" +
36140b57cec5SDimitry Andric                               Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36150b57cec5SDimitry Andric           moveToEnd();
36160b57cec5SDimitry Andric           return;
36170b57cec5SDimitry Andric         }
36180b57cec5SDimitry Andric       } else
36190b57cec5SDimitry Andric         Ordinal = 0;
36200b57cec5SDimitry Andric       LibraryOrdinalSet = true;
36210b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
36220b57cec5SDimitry Andric           "mach-o-bind",
36230b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
36240b57cec5SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
36250b57cec5SDimitry Andric       break;
36260b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
36270b57cec5SDimitry Andric       Flags = ImmValue;
36280b57cec5SDimitry Andric       SymStart = Ptr;
36290b57cec5SDimitry Andric       while (*Ptr && (Ptr < Opcodes.end())) {
36300b57cec5SDimitry Andric         ++Ptr;
36310b57cec5SDimitry Andric       }
36320b57cec5SDimitry Andric       if (Ptr == Opcodes.end()) {
36330b57cec5SDimitry Andric         *E = malformedError(
36340b57cec5SDimitry Andric             "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
36350b57cec5SDimitry Andric             "symbol name extends past opcodes for opcode at: 0x" +
36360b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36370b57cec5SDimitry Andric         moveToEnd();
36380b57cec5SDimitry Andric         return;
36390b57cec5SDimitry Andric       }
36400b57cec5SDimitry Andric       SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
36410b57cec5SDimitry Andric                              Ptr-SymStart);
36420b57cec5SDimitry Andric       ++Ptr;
36430b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
36440b57cec5SDimitry Andric           "mach-o-bind",
36450b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
36460b57cec5SDimitry Andric                  << "SymbolName=" << SymbolName << "\n");
36470b57cec5SDimitry Andric       if (TableKind == Kind::Weak) {
36480b57cec5SDimitry Andric         if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
36490b57cec5SDimitry Andric           return;
36500b57cec5SDimitry Andric       }
36510b57cec5SDimitry Andric       break;
36520b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_TYPE_IMM:
36530b57cec5SDimitry Andric       BindType = ImmValue;
36540b57cec5SDimitry Andric       if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
36550b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
36560b57cec5SDimitry Andric                             Twine((int)ImmValue) + " for opcode at: 0x" +
36570b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36580b57cec5SDimitry Andric         moveToEnd();
36590b57cec5SDimitry Andric         return;
36600b57cec5SDimitry Andric       }
36610b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
36620b57cec5SDimitry Andric           "mach-o-bind",
36630b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
36640b57cec5SDimitry Andric                  << "BindType=" << (int)BindType << "\n");
36650b57cec5SDimitry Andric       break;
36660b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
36670b57cec5SDimitry Andric       Addend = readSLEB128(&error);
36680b57cec5SDimitry Andric       if (error) {
36690b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
36700b57cec5SDimitry Andric                             " for opcode at: 0x" +
36710b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36720b57cec5SDimitry Andric         moveToEnd();
36730b57cec5SDimitry Andric         return;
36740b57cec5SDimitry Andric       }
36750b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
36760b57cec5SDimitry Andric           "mach-o-bind",
36770b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
36780b57cec5SDimitry Andric                  << "Addend=" << Addend << "\n");
36790b57cec5SDimitry Andric       break;
36800b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
36810b57cec5SDimitry Andric       SegmentIndex = ImmValue;
36820b57cec5SDimitry Andric       SegmentOffset = readULEB128(&error);
36830b57cec5SDimitry Andric       if (error) {
36840b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
36850b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36860b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36870b57cec5SDimitry Andric         moveToEnd();
36880b57cec5SDimitry Andric         return;
36890b57cec5SDimitry Andric       }
36900b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
36910b57cec5SDimitry Andric                                              PointerSize);
36920b57cec5SDimitry Andric       if (error) {
36930b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
36940b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36950b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36960b57cec5SDimitry Andric         moveToEnd();
36970b57cec5SDimitry Andric         return;
36980b57cec5SDimitry Andric       }
36990b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
37000b57cec5SDimitry Andric           "mach-o-bind",
37010b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
37020b57cec5SDimitry Andric                  << "SegmentIndex=" << SegmentIndex << ", "
37030b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
37040b57cec5SDimitry Andric                  << "\n");
37050b57cec5SDimitry Andric       break;
37060b57cec5SDimitry Andric     case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
37070b57cec5SDimitry Andric       SegmentOffset += readULEB128(&error);
37080b57cec5SDimitry Andric       if (error) {
37090b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
37100b57cec5SDimitry Andric                             " for opcode at: 0x" +
37110b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37120b57cec5SDimitry Andric         moveToEnd();
37130b57cec5SDimitry Andric         return;
37140b57cec5SDimitry Andric       }
37150b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
37160b57cec5SDimitry Andric                                              PointerSize);
37170b57cec5SDimitry Andric       if (error) {
37180b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
37190b57cec5SDimitry Andric                             " for opcode at: 0x" +
37200b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37210b57cec5SDimitry Andric         moveToEnd();
37220b57cec5SDimitry Andric         return;
37230b57cec5SDimitry Andric       }
37240b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
37250b57cec5SDimitry Andric                       dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
37260b57cec5SDimitry Andric                              << format("SegmentOffset=0x%06X",
37270b57cec5SDimitry Andric                                        SegmentOffset) << "\n");
37280b57cec5SDimitry Andric       break;
37290b57cec5SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND:
37300b57cec5SDimitry Andric       AdvanceAmount = PointerSize;
37310b57cec5SDimitry Andric       RemainingLoopCount = 0;
37320b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
37330b57cec5SDimitry Andric                                              PointerSize);
37340b57cec5SDimitry Andric       if (error) {
37350b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
37360b57cec5SDimitry Andric                             " for opcode at: 0x" +
37370b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37380b57cec5SDimitry Andric         moveToEnd();
37390b57cec5SDimitry Andric         return;
37400b57cec5SDimitry Andric       }
37410b57cec5SDimitry Andric       if (SymbolName == StringRef()) {
37420b57cec5SDimitry Andric         *E = malformedError(
37430b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND missing preceding "
37440b57cec5SDimitry Andric             "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
37450b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37460b57cec5SDimitry Andric         moveToEnd();
37470b57cec5SDimitry Andric         return;
37480b57cec5SDimitry Andric       }
37490b57cec5SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
37500b57cec5SDimitry Andric         *E =
37510b57cec5SDimitry Andric             malformedError("for BIND_OPCODE_DO_BIND missing preceding "
37520b57cec5SDimitry Andric                            "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
37530b57cec5SDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37540b57cec5SDimitry Andric         moveToEnd();
37550b57cec5SDimitry Andric         return;
37560b57cec5SDimitry Andric       }
37570b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
37580b57cec5SDimitry Andric                       dbgs() << "BIND_OPCODE_DO_BIND: "
37590b57cec5SDimitry Andric                              << format("SegmentOffset=0x%06X",
37600b57cec5SDimitry Andric                                        SegmentOffset) << "\n");
37610b57cec5SDimitry Andric       return;
37620b57cec5SDimitry Andric      case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
37630b57cec5SDimitry Andric       if (TableKind == Kind::Lazy) {
37640b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
37650b57cec5SDimitry Andric                             "lazy bind table for opcode at: 0x" +
37660b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37670b57cec5SDimitry Andric         moveToEnd();
37680b57cec5SDimitry Andric         return;
37690b57cec5SDimitry Andric       }
37700b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
37710b57cec5SDimitry Andric                                              PointerSize);
37720b57cec5SDimitry Andric       if (error) {
37730b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
37740b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
37750b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37760b57cec5SDimitry Andric         moveToEnd();
37770b57cec5SDimitry Andric         return;
37780b57cec5SDimitry Andric       }
37790b57cec5SDimitry Andric       if (SymbolName == StringRef()) {
37800b57cec5SDimitry Andric         *E = malformedError(
37810b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
37820b57cec5SDimitry Andric             "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
37830b57cec5SDimitry Andric             "at: 0x" +
37840b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37850b57cec5SDimitry Andric         moveToEnd();
37860b57cec5SDimitry Andric         return;
37870b57cec5SDimitry Andric       }
37880b57cec5SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
37890b57cec5SDimitry Andric         *E = malformedError(
37900b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
37910b57cec5SDimitry Andric             "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
37920b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37930b57cec5SDimitry Andric         moveToEnd();
37940b57cec5SDimitry Andric         return;
37950b57cec5SDimitry Andric       }
37960b57cec5SDimitry Andric       AdvanceAmount = readULEB128(&error) + PointerSize;
37970b57cec5SDimitry Andric       if (error) {
37980b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
37990b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
38000b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38010b57cec5SDimitry Andric         moveToEnd();
38020b57cec5SDimitry Andric         return;
38030b57cec5SDimitry Andric       }
38040b57cec5SDimitry Andric       // Note, this is not really an error until the next bind but make no sense
38050b57cec5SDimitry Andric       // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
38060b57cec5SDimitry Andric       // bind operation.
38070b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
38080b57cec5SDimitry Andric                                             AdvanceAmount, PointerSize);
38090b57cec5SDimitry Andric       if (error) {
38100b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
38110b57cec5SDimitry Andric                             "ULEB) " +
38120b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
38130b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38140b57cec5SDimitry Andric         moveToEnd();
38150b57cec5SDimitry Andric         return;
38160b57cec5SDimitry Andric       }
38170b57cec5SDimitry Andric       RemainingLoopCount = 0;
38180b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
38190b57cec5SDimitry Andric           "mach-o-bind",
38200b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
38210b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
38220b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
38230b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
38240b57cec5SDimitry Andric                  << "\n");
38250b57cec5SDimitry Andric       return;
38260b57cec5SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
38270b57cec5SDimitry Andric       if (TableKind == Kind::Lazy) {
38280b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
38290b57cec5SDimitry Andric                             "allowed in lazy bind table for opcode at: 0x" +
38300b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38310b57cec5SDimitry Andric         moveToEnd();
38320b57cec5SDimitry Andric         return;
38330b57cec5SDimitry Andric       }
38340b57cec5SDimitry Andric       if (SymbolName == StringRef()) {
38350b57cec5SDimitry Andric         *E = malformedError(
38360b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
38370b57cec5SDimitry Andric             "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
38380b57cec5SDimitry Andric             "opcode at: 0x" +
38390b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38400b57cec5SDimitry Andric         moveToEnd();
38410b57cec5SDimitry Andric         return;
38420b57cec5SDimitry Andric       }
38430b57cec5SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
38440b57cec5SDimitry Andric         *E = malformedError(
38450b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
38460b57cec5SDimitry Andric             "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
38470b57cec5SDimitry Andric             "at: 0x" +
38480b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38490b57cec5SDimitry Andric         moveToEnd();
38500b57cec5SDimitry Andric         return;
38510b57cec5SDimitry Andric       }
38520b57cec5SDimitry Andric       AdvanceAmount = ImmValue * PointerSize + PointerSize;
38530b57cec5SDimitry Andric       RemainingLoopCount = 0;
38540b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
38550b57cec5SDimitry Andric                                              AdvanceAmount, PointerSize);
38560b57cec5SDimitry Andric       if (error) {
38575ffd83dbSDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
38580b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
38590b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38600b57cec5SDimitry Andric         moveToEnd();
38610b57cec5SDimitry Andric         return;
38620b57cec5SDimitry Andric       }
38630b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
38640b57cec5SDimitry Andric                       dbgs()
38650b57cec5SDimitry Andric                       << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
38660b57cec5SDimitry Andric                       << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
38670b57cec5SDimitry Andric       return;
38680b57cec5SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
38690b57cec5SDimitry Andric       if (TableKind == Kind::Lazy) {
38700b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
38710b57cec5SDimitry Andric                             "allowed in lazy bind table for opcode at: 0x" +
38720b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38730b57cec5SDimitry Andric         moveToEnd();
38740b57cec5SDimitry Andric         return;
38750b57cec5SDimitry Andric       }
38760b57cec5SDimitry Andric       Count = readULEB128(&error);
38770b57cec5SDimitry Andric       if (Count != 0)
38780b57cec5SDimitry Andric         RemainingLoopCount = Count - 1;
38790b57cec5SDimitry Andric       else
38800b57cec5SDimitry Andric         RemainingLoopCount = 0;
38810b57cec5SDimitry Andric       if (error) {
38820b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38830b57cec5SDimitry Andric                             " (count value) " +
38840b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
38850b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38860b57cec5SDimitry Andric         moveToEnd();
38870b57cec5SDimitry Andric         return;
38880b57cec5SDimitry Andric       }
38890b57cec5SDimitry Andric       Skip = readULEB128(&error);
38900b57cec5SDimitry Andric       AdvanceAmount = Skip + PointerSize;
38910b57cec5SDimitry Andric       if (error) {
38920b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38930b57cec5SDimitry Andric                             " (skip value) " +
38940b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
38950b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38960b57cec5SDimitry Andric         moveToEnd();
38970b57cec5SDimitry Andric         return;
38980b57cec5SDimitry Andric       }
38990b57cec5SDimitry Andric       if (SymbolName == StringRef()) {
39000b57cec5SDimitry Andric         *E = malformedError(
39010b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
39020b57cec5SDimitry Andric             "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
39030b57cec5SDimitry Andric             "opcode at: 0x" +
39040b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39050b57cec5SDimitry Andric         moveToEnd();
39060b57cec5SDimitry Andric         return;
39070b57cec5SDimitry Andric       }
39080b57cec5SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
39090b57cec5SDimitry Andric         *E = malformedError(
39100b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
39110b57cec5SDimitry Andric             "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
39120b57cec5SDimitry Andric             "at: 0x" +
39130b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39140b57cec5SDimitry Andric         moveToEnd();
39150b57cec5SDimitry Andric         return;
39160b57cec5SDimitry Andric       }
39170b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
39180b57cec5SDimitry Andric                                              PointerSize, Count, Skip);
39190b57cec5SDimitry Andric       if (error) {
39200b57cec5SDimitry Andric         *E =
39210b57cec5SDimitry Andric             malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
39220b57cec5SDimitry Andric                            Twine(error) + " for opcode at: 0x" +
39230b57cec5SDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39240b57cec5SDimitry Andric         moveToEnd();
39250b57cec5SDimitry Andric         return;
39260b57cec5SDimitry Andric       }
39270b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
39280b57cec5SDimitry Andric           "mach-o-bind",
39290b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
39300b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
39310b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
39320b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
39330b57cec5SDimitry Andric                  << "\n");
39340b57cec5SDimitry Andric       return;
39350b57cec5SDimitry Andric     default:
39360b57cec5SDimitry Andric       *E = malformedError("bad bind info (bad opcode value 0x" +
39370b57cec5SDimitry Andric                           Twine::utohexstr(Opcode) + " for opcode at: 0x" +
39380b57cec5SDimitry Andric                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39390b57cec5SDimitry Andric       moveToEnd();
39400b57cec5SDimitry Andric       return;
39410b57cec5SDimitry Andric     }
39420b57cec5SDimitry Andric   }
39430b57cec5SDimitry Andric }
39440b57cec5SDimitry Andric 
readULEB128(const char ** error)39450b57cec5SDimitry Andric uint64_t MachOBindEntry::readULEB128(const char **error) {
39460b57cec5SDimitry Andric   unsigned Count;
39470b57cec5SDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
39480b57cec5SDimitry Andric   Ptr += Count;
39490b57cec5SDimitry Andric   if (Ptr > Opcodes.end())
39500b57cec5SDimitry Andric     Ptr = Opcodes.end();
39510b57cec5SDimitry Andric   return Result;
39520b57cec5SDimitry Andric }
39530b57cec5SDimitry Andric 
readSLEB128(const char ** error)39540b57cec5SDimitry Andric int64_t MachOBindEntry::readSLEB128(const char **error) {
39550b57cec5SDimitry Andric   unsigned Count;
39560b57cec5SDimitry Andric   int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
39570b57cec5SDimitry Andric   Ptr += Count;
39580b57cec5SDimitry Andric   if (Ptr > Opcodes.end())
39590b57cec5SDimitry Andric     Ptr = Opcodes.end();
39600b57cec5SDimitry Andric   return Result;
39610b57cec5SDimitry Andric }
39620b57cec5SDimitry Andric 
segmentIndex() const39630b57cec5SDimitry Andric int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
39640b57cec5SDimitry Andric 
segmentOffset() const39650b57cec5SDimitry Andric uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
39660b57cec5SDimitry Andric 
typeName() const39670b57cec5SDimitry Andric StringRef MachOBindEntry::typeName() const {
39680b57cec5SDimitry Andric   switch (BindType) {
39690b57cec5SDimitry Andric   case MachO::BIND_TYPE_POINTER:
39700b57cec5SDimitry Andric     return "pointer";
39710b57cec5SDimitry Andric   case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
39720b57cec5SDimitry Andric     return "text abs32";
39730b57cec5SDimitry Andric   case MachO::BIND_TYPE_TEXT_PCREL32:
39740b57cec5SDimitry Andric     return "text rel32";
39750b57cec5SDimitry Andric   }
39760b57cec5SDimitry Andric   return "unknown";
39770b57cec5SDimitry Andric }
39780b57cec5SDimitry Andric 
symbolName() const39790b57cec5SDimitry Andric StringRef MachOBindEntry::symbolName() const { return SymbolName; }
39800b57cec5SDimitry Andric 
addend() const39810b57cec5SDimitry Andric int64_t MachOBindEntry::addend() const { return Addend; }
39820b57cec5SDimitry Andric 
flags() const39830b57cec5SDimitry Andric uint32_t MachOBindEntry::flags() const { return Flags; }
39840b57cec5SDimitry Andric 
ordinal() const39850b57cec5SDimitry Andric int MachOBindEntry::ordinal() const { return Ordinal; }
39860b57cec5SDimitry Andric 
39870b57cec5SDimitry Andric // For use with the SegIndex of a checked Mach-O Bind entry
39880b57cec5SDimitry Andric // to get the segment name.
segmentName() const39890b57cec5SDimitry Andric StringRef MachOBindEntry::segmentName() const {
39900b57cec5SDimitry Andric   return O->BindRebaseSegmentName(SegmentIndex);
39910b57cec5SDimitry Andric }
39920b57cec5SDimitry Andric 
39930b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
39940b57cec5SDimitry Andric // to get the section name.
sectionName() const39950b57cec5SDimitry Andric StringRef MachOBindEntry::sectionName() const {
39960b57cec5SDimitry Andric   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
39970b57cec5SDimitry Andric }
39980b57cec5SDimitry Andric 
39990b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
40000b57cec5SDimitry Andric // to get the address.
address() const40010b57cec5SDimitry Andric uint64_t MachOBindEntry::address() const {
40020b57cec5SDimitry Andric   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
40030b57cec5SDimitry Andric }
40040b57cec5SDimitry Andric 
operator ==(const MachOBindEntry & Other) const40050b57cec5SDimitry Andric bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
40060b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
40070b57cec5SDimitry Andric   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
40080b57cec5SDimitry Andric #else
40090b57cec5SDimitry Andric   assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
40100b57cec5SDimitry Andric #endif
40110b57cec5SDimitry Andric   return (Ptr == Other.Ptr) &&
40120b57cec5SDimitry Andric          (RemainingLoopCount == Other.RemainingLoopCount) &&
40130b57cec5SDimitry Andric          (Done == Other.Done);
40140b57cec5SDimitry Andric }
40150b57cec5SDimitry Andric 
40160b57cec5SDimitry Andric // Build table of sections so SegIndex/SegOffset pairs can be translated.
BindRebaseSegInfo(const object::MachOObjectFile * Obj)40170b57cec5SDimitry Andric BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
40180b57cec5SDimitry Andric   uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
40190b57cec5SDimitry Andric   StringRef CurSegName;
40200b57cec5SDimitry Andric   uint64_t CurSegAddress;
40210b57cec5SDimitry Andric   for (const SectionRef &Section : Obj->sections()) {
40220b57cec5SDimitry Andric     SectionInfo Info;
40238bcb0991SDimitry Andric     Expected<StringRef> NameOrErr = Section.getName();
40248bcb0991SDimitry Andric     if (!NameOrErr)
40258bcb0991SDimitry Andric       consumeError(NameOrErr.takeError());
40268bcb0991SDimitry Andric     else
40278bcb0991SDimitry Andric       Info.SectionName = *NameOrErr;
40280b57cec5SDimitry Andric     Info.Address = Section.getAddress();
40290b57cec5SDimitry Andric     Info.Size = Section.getSize();
40300b57cec5SDimitry Andric     Info.SegmentName =
40310b57cec5SDimitry Andric         Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
40320b57cec5SDimitry Andric     if (!Info.SegmentName.equals(CurSegName)) {
40330b57cec5SDimitry Andric       ++CurSegIndex;
40340b57cec5SDimitry Andric       CurSegName = Info.SegmentName;
40350b57cec5SDimitry Andric       CurSegAddress = Info.Address;
40360b57cec5SDimitry Andric     }
40370b57cec5SDimitry Andric     Info.SegmentIndex = CurSegIndex - 1;
40380b57cec5SDimitry Andric     Info.OffsetInSegment = Info.Address - CurSegAddress;
40390b57cec5SDimitry Andric     Info.SegmentStartAddress = CurSegAddress;
40400b57cec5SDimitry Andric     Sections.push_back(Info);
40410b57cec5SDimitry Andric   }
40420b57cec5SDimitry Andric   MaxSegIndex = CurSegIndex;
40430b57cec5SDimitry Andric }
40440b57cec5SDimitry Andric 
40450b57cec5SDimitry Andric // For use with a SegIndex, SegOffset, and PointerSize triple in
40460b57cec5SDimitry Andric // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
40470b57cec5SDimitry Andric //
40480b57cec5SDimitry Andric // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
40490b57cec5SDimitry Andric // that fully contains a pointer at that location. Multiple fixups in a bind
40500b57cec5SDimitry Andric // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
40510b57cec5SDimitry Andric // be tested via the Count and Skip parameters.
checkSegAndOffsets(int32_t SegIndex,uint64_t SegOffset,uint8_t PointerSize,uint32_t Count,uint32_t Skip)40520b57cec5SDimitry Andric const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
40530b57cec5SDimitry Andric                                                    uint64_t SegOffset,
40540b57cec5SDimitry Andric                                                    uint8_t PointerSize,
40550b57cec5SDimitry Andric                                                    uint32_t Count,
40560b57cec5SDimitry Andric                                                    uint32_t Skip) {
40570b57cec5SDimitry Andric   if (SegIndex == -1)
40580b57cec5SDimitry Andric     return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
40590b57cec5SDimitry Andric   if (SegIndex >= MaxSegIndex)
40600b57cec5SDimitry Andric     return "bad segIndex (too large)";
40610b57cec5SDimitry Andric   for (uint32_t i = 0; i < Count; ++i) {
40620b57cec5SDimitry Andric     uint32_t Start = SegOffset + i * (PointerSize + Skip);
40630b57cec5SDimitry Andric     uint32_t End = Start + PointerSize;
40640b57cec5SDimitry Andric     bool Found = false;
40650b57cec5SDimitry Andric     for (const SectionInfo &SI : Sections) {
40660b57cec5SDimitry Andric       if (SI.SegmentIndex != SegIndex)
40670b57cec5SDimitry Andric         continue;
40680b57cec5SDimitry Andric       if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
40690b57cec5SDimitry Andric         if (End <= SI.OffsetInSegment + SI.Size) {
40700b57cec5SDimitry Andric           Found = true;
40710b57cec5SDimitry Andric           break;
40720b57cec5SDimitry Andric         }
40730b57cec5SDimitry Andric         else
40740b57cec5SDimitry Andric           return "bad offset, extends beyond section boundary";
40750b57cec5SDimitry Andric       }
40760b57cec5SDimitry Andric     }
40770b57cec5SDimitry Andric     if (!Found)
40780b57cec5SDimitry Andric       return "bad offset, not in section";
40790b57cec5SDimitry Andric   }
40800b57cec5SDimitry Andric   return nullptr;
40810b57cec5SDimitry Andric }
40820b57cec5SDimitry Andric 
40830b57cec5SDimitry Andric // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
40840b57cec5SDimitry Andric // to get the segment name.
segmentName(int32_t SegIndex)40850b57cec5SDimitry Andric StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
40860b57cec5SDimitry Andric   for (const SectionInfo &SI : Sections) {
40870b57cec5SDimitry Andric     if (SI.SegmentIndex == SegIndex)
40880b57cec5SDimitry Andric       return SI.SegmentName;
40890b57cec5SDimitry Andric   }
40900b57cec5SDimitry Andric   llvm_unreachable("invalid SegIndex");
40910b57cec5SDimitry Andric }
40920b57cec5SDimitry Andric 
40930b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
40940b57cec5SDimitry Andric // to get the SectionInfo.
findSection(int32_t SegIndex,uint64_t SegOffset)40950b57cec5SDimitry Andric const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
40960b57cec5SDimitry Andric                                      int32_t SegIndex, uint64_t SegOffset) {
40970b57cec5SDimitry Andric   for (const SectionInfo &SI : Sections) {
40980b57cec5SDimitry Andric     if (SI.SegmentIndex != SegIndex)
40990b57cec5SDimitry Andric       continue;
41000b57cec5SDimitry Andric     if (SI.OffsetInSegment > SegOffset)
41010b57cec5SDimitry Andric       continue;
41020b57cec5SDimitry Andric     if (SegOffset >= (SI.OffsetInSegment + SI.Size))
41030b57cec5SDimitry Andric       continue;
41040b57cec5SDimitry Andric     return SI;
41050b57cec5SDimitry Andric   }
41060b57cec5SDimitry Andric   llvm_unreachable("SegIndex and SegOffset not in any section");
41070b57cec5SDimitry Andric }
41080b57cec5SDimitry Andric 
41090b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
41100b57cec5SDimitry Andric // entry to get the section name.
sectionName(int32_t SegIndex,uint64_t SegOffset)41110b57cec5SDimitry Andric StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
41120b57cec5SDimitry Andric                                          uint64_t SegOffset) {
41130b57cec5SDimitry Andric   return findSection(SegIndex, SegOffset).SectionName;
41140b57cec5SDimitry Andric }
41150b57cec5SDimitry Andric 
41160b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
41170b57cec5SDimitry Andric // entry to get the address.
address(uint32_t SegIndex,uint64_t OffsetInSeg)41180b57cec5SDimitry Andric uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
41190b57cec5SDimitry Andric   const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
41200b57cec5SDimitry Andric   return SI.SegmentStartAddress + OffsetInSeg;
41210b57cec5SDimitry Andric }
41220b57cec5SDimitry Andric 
41230b57cec5SDimitry Andric iterator_range<bind_iterator>
bindTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)41240b57cec5SDimitry Andric MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
41250b57cec5SDimitry Andric                            ArrayRef<uint8_t> Opcodes, bool is64,
41260b57cec5SDimitry Andric                            MachOBindEntry::Kind BKind) {
41270b57cec5SDimitry Andric   if (O->BindRebaseSectionTable == nullptr)
41288bcb0991SDimitry Andric     O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
41290b57cec5SDimitry Andric   MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
41300b57cec5SDimitry Andric   Start.moveToFirst();
41310b57cec5SDimitry Andric 
41320b57cec5SDimitry Andric   MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
41330b57cec5SDimitry Andric   Finish.moveToEnd();
41340b57cec5SDimitry Andric 
41350b57cec5SDimitry Andric   return make_range(bind_iterator(Start), bind_iterator(Finish));
41360b57cec5SDimitry Andric }
41370b57cec5SDimitry Andric 
bindTable(Error & Err)41380b57cec5SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
41390b57cec5SDimitry Andric   return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
41400b57cec5SDimitry Andric                    MachOBindEntry::Kind::Regular);
41410b57cec5SDimitry Andric }
41420b57cec5SDimitry Andric 
lazyBindTable(Error & Err)41430b57cec5SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
41440b57cec5SDimitry Andric   return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
41450b57cec5SDimitry Andric                    MachOBindEntry::Kind::Lazy);
41460b57cec5SDimitry Andric }
41470b57cec5SDimitry Andric 
weakBindTable(Error & Err)41480b57cec5SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
41490b57cec5SDimitry Andric   return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
41500b57cec5SDimitry Andric                    MachOBindEntry::Kind::Weak);
41510b57cec5SDimitry Andric }
41520b57cec5SDimitry Andric 
41530b57cec5SDimitry Andric MachOObjectFile::load_command_iterator
begin_load_commands() const41540b57cec5SDimitry Andric MachOObjectFile::begin_load_commands() const {
41550b57cec5SDimitry Andric   return LoadCommands.begin();
41560b57cec5SDimitry Andric }
41570b57cec5SDimitry Andric 
41580b57cec5SDimitry Andric MachOObjectFile::load_command_iterator
end_load_commands() const41590b57cec5SDimitry Andric MachOObjectFile::end_load_commands() const {
41600b57cec5SDimitry Andric   return LoadCommands.end();
41610b57cec5SDimitry Andric }
41620b57cec5SDimitry Andric 
41630b57cec5SDimitry Andric iterator_range<MachOObjectFile::load_command_iterator>
load_commands() const41640b57cec5SDimitry Andric MachOObjectFile::load_commands() const {
41650b57cec5SDimitry Andric   return make_range(begin_load_commands(), end_load_commands());
41660b57cec5SDimitry Andric }
41670b57cec5SDimitry Andric 
41680b57cec5SDimitry Andric StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const41690b57cec5SDimitry Andric MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
41700b57cec5SDimitry Andric   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
41710b57cec5SDimitry Andric   return parseSegmentOrSectionName(Raw.data());
41720b57cec5SDimitry Andric }
41730b57cec5SDimitry Andric 
41740b57cec5SDimitry Andric ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const41750b57cec5SDimitry Andric MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
41760b57cec5SDimitry Andric   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
41770b57cec5SDimitry Andric   const section_base *Base =
41780b57cec5SDimitry Andric     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
41790b57cec5SDimitry Andric   return makeArrayRef(Base->sectname);
41800b57cec5SDimitry Andric }
41810b57cec5SDimitry Andric 
41820b57cec5SDimitry Andric ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const41830b57cec5SDimitry Andric MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
41840b57cec5SDimitry Andric   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
41850b57cec5SDimitry Andric   const section_base *Base =
41860b57cec5SDimitry Andric     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
41870b57cec5SDimitry Andric   return makeArrayRef(Base->segname);
41880b57cec5SDimitry Andric }
41890b57cec5SDimitry Andric 
41900b57cec5SDimitry Andric bool
isRelocationScattered(const MachO::any_relocation_info & RE) const41910b57cec5SDimitry Andric MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
41920b57cec5SDimitry Andric   const {
41930b57cec5SDimitry Andric   if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
41940b57cec5SDimitry Andric     return false;
41950b57cec5SDimitry Andric   return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
41960b57cec5SDimitry Andric }
41970b57cec5SDimitry Andric 
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const41980b57cec5SDimitry Andric unsigned MachOObjectFile::getPlainRelocationSymbolNum(
41990b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
42000b57cec5SDimitry Andric   if (isLittleEndian())
42010b57cec5SDimitry Andric     return RE.r_word1 & 0xffffff;
42020b57cec5SDimitry Andric   return RE.r_word1 >> 8;
42030b57cec5SDimitry Andric }
42040b57cec5SDimitry Andric 
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const42050b57cec5SDimitry Andric bool MachOObjectFile::getPlainRelocationExternal(
42060b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
42070b57cec5SDimitry Andric   if (isLittleEndian())
42080b57cec5SDimitry Andric     return (RE.r_word1 >> 27) & 1;
42090b57cec5SDimitry Andric   return (RE.r_word1 >> 4) & 1;
42100b57cec5SDimitry Andric }
42110b57cec5SDimitry Andric 
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const42120b57cec5SDimitry Andric bool MachOObjectFile::getScatteredRelocationScattered(
42130b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
42140b57cec5SDimitry Andric   return RE.r_word0 >> 31;
42150b57cec5SDimitry Andric }
42160b57cec5SDimitry Andric 
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const42170b57cec5SDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationValue(
42180b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
42190b57cec5SDimitry Andric   return RE.r_word1;
42200b57cec5SDimitry Andric }
42210b57cec5SDimitry Andric 
getScatteredRelocationType(const MachO::any_relocation_info & RE) const42220b57cec5SDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationType(
42230b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
42240b57cec5SDimitry Andric   return (RE.r_word0 >> 24) & 0xf;
42250b57cec5SDimitry Andric }
42260b57cec5SDimitry Andric 
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const42270b57cec5SDimitry Andric unsigned MachOObjectFile::getAnyRelocationAddress(
42280b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
42290b57cec5SDimitry Andric   if (isRelocationScattered(RE))
42300b57cec5SDimitry Andric     return getScatteredRelocationAddress(RE);
42310b57cec5SDimitry Andric   return getPlainRelocationAddress(RE);
42320b57cec5SDimitry Andric }
42330b57cec5SDimitry Andric 
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const42340b57cec5SDimitry Andric unsigned MachOObjectFile::getAnyRelocationPCRel(
42350b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
42360b57cec5SDimitry Andric   if (isRelocationScattered(RE))
42370b57cec5SDimitry Andric     return getScatteredRelocationPCRel(RE);
42380b57cec5SDimitry Andric   return getPlainRelocationPCRel(*this, RE);
42390b57cec5SDimitry Andric }
42400b57cec5SDimitry Andric 
getAnyRelocationLength(const MachO::any_relocation_info & RE) const42410b57cec5SDimitry Andric unsigned MachOObjectFile::getAnyRelocationLength(
42420b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
42430b57cec5SDimitry Andric   if (isRelocationScattered(RE))
42440b57cec5SDimitry Andric     return getScatteredRelocationLength(RE);
42450b57cec5SDimitry Andric   return getPlainRelocationLength(*this, RE);
42460b57cec5SDimitry Andric }
42470b57cec5SDimitry Andric 
42480b57cec5SDimitry Andric unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const42490b57cec5SDimitry Andric MachOObjectFile::getAnyRelocationType(
42500b57cec5SDimitry Andric                                    const MachO::any_relocation_info &RE) const {
42510b57cec5SDimitry Andric   if (isRelocationScattered(RE))
42520b57cec5SDimitry Andric     return getScatteredRelocationType(RE);
42530b57cec5SDimitry Andric   return getPlainRelocationType(*this, RE);
42540b57cec5SDimitry Andric }
42550b57cec5SDimitry Andric 
42560b57cec5SDimitry Andric SectionRef
getAnyRelocationSection(const MachO::any_relocation_info & RE) const42570b57cec5SDimitry Andric MachOObjectFile::getAnyRelocationSection(
42580b57cec5SDimitry Andric                                    const MachO::any_relocation_info &RE) const {
42590b57cec5SDimitry Andric   if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
42600b57cec5SDimitry Andric     return *section_end();
42610b57cec5SDimitry Andric   unsigned SecNum = getPlainRelocationSymbolNum(RE);
42620b57cec5SDimitry Andric   if (SecNum == MachO::R_ABS || SecNum > Sections.size())
42630b57cec5SDimitry Andric     return *section_end();
42640b57cec5SDimitry Andric   DataRefImpl DRI;
42650b57cec5SDimitry Andric   DRI.d.a = SecNum - 1;
42660b57cec5SDimitry Andric   return SectionRef(DRI, this);
42670b57cec5SDimitry Andric }
42680b57cec5SDimitry Andric 
getSection(DataRefImpl DRI) const42690b57cec5SDimitry Andric MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
42700b57cec5SDimitry Andric   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
42710b57cec5SDimitry Andric   return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
42720b57cec5SDimitry Andric }
42730b57cec5SDimitry Andric 
getSection64(DataRefImpl DRI) const42740b57cec5SDimitry Andric MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
42750b57cec5SDimitry Andric   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
42760b57cec5SDimitry Andric   return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
42770b57cec5SDimitry Andric }
42780b57cec5SDimitry Andric 
getSection(const LoadCommandInfo & L,unsigned Index) const42790b57cec5SDimitry Andric MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
42800b57cec5SDimitry Andric                                            unsigned Index) const {
42810b57cec5SDimitry Andric   const char *Sec = getSectionPtr(*this, L, Index);
42820b57cec5SDimitry Andric   return getStruct<MachO::section>(*this, Sec);
42830b57cec5SDimitry Andric }
42840b57cec5SDimitry Andric 
getSection64(const LoadCommandInfo & L,unsigned Index) const42850b57cec5SDimitry Andric MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
42860b57cec5SDimitry Andric                                                 unsigned Index) const {
42870b57cec5SDimitry Andric   const char *Sec = getSectionPtr(*this, L, Index);
42880b57cec5SDimitry Andric   return getStruct<MachO::section_64>(*this, Sec);
42890b57cec5SDimitry Andric }
42900b57cec5SDimitry Andric 
42910b57cec5SDimitry Andric MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const42920b57cec5SDimitry Andric MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
42930b57cec5SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
42940b57cec5SDimitry Andric   return getStruct<MachO::nlist>(*this, P);
42950b57cec5SDimitry Andric }
42960b57cec5SDimitry Andric 
42970b57cec5SDimitry Andric MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const42980b57cec5SDimitry Andric MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
42990b57cec5SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
43000b57cec5SDimitry Andric   return getStruct<MachO::nlist_64>(*this, P);
43010b57cec5SDimitry Andric }
43020b57cec5SDimitry Andric 
43030b57cec5SDimitry Andric MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const43040b57cec5SDimitry Andric MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
43050b57cec5SDimitry Andric   return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
43060b57cec5SDimitry Andric }
43070b57cec5SDimitry Andric 
43080b57cec5SDimitry Andric MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const43090b57cec5SDimitry Andric MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
43100b57cec5SDimitry Andric   return getStruct<MachO::segment_command>(*this, L.Ptr);
43110b57cec5SDimitry Andric }
43120b57cec5SDimitry Andric 
43130b57cec5SDimitry Andric MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const43140b57cec5SDimitry Andric MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
43150b57cec5SDimitry Andric   return getStruct<MachO::segment_command_64>(*this, L.Ptr);
43160b57cec5SDimitry Andric }
43170b57cec5SDimitry Andric 
43180b57cec5SDimitry Andric MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const43190b57cec5SDimitry Andric MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
43200b57cec5SDimitry Andric   return getStruct<MachO::linker_option_command>(*this, L.Ptr);
43210b57cec5SDimitry Andric }
43220b57cec5SDimitry Andric 
43230b57cec5SDimitry Andric MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const43240b57cec5SDimitry Andric MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
43250b57cec5SDimitry Andric   return getStruct<MachO::version_min_command>(*this, L.Ptr);
43260b57cec5SDimitry Andric }
43270b57cec5SDimitry Andric 
43280b57cec5SDimitry Andric MachO::note_command
getNoteLoadCommand(const LoadCommandInfo & L) const43290b57cec5SDimitry Andric MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
43300b57cec5SDimitry Andric   return getStruct<MachO::note_command>(*this, L.Ptr);
43310b57cec5SDimitry Andric }
43320b57cec5SDimitry Andric 
43330b57cec5SDimitry Andric MachO::build_version_command
getBuildVersionLoadCommand(const LoadCommandInfo & L) const43340b57cec5SDimitry Andric MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
43350b57cec5SDimitry Andric   return getStruct<MachO::build_version_command>(*this, L.Ptr);
43360b57cec5SDimitry Andric }
43370b57cec5SDimitry Andric 
43380b57cec5SDimitry Andric MachO::build_tool_version
getBuildToolVersion(unsigned index) const43390b57cec5SDimitry Andric MachOObjectFile::getBuildToolVersion(unsigned index) const {
43400b57cec5SDimitry Andric   return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
43410b57cec5SDimitry Andric }
43420b57cec5SDimitry Andric 
43430b57cec5SDimitry Andric MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const43440b57cec5SDimitry Andric MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
43450b57cec5SDimitry Andric   return getStruct<MachO::dylib_command>(*this, L.Ptr);
43460b57cec5SDimitry Andric }
43470b57cec5SDimitry Andric 
43480b57cec5SDimitry Andric MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const43490b57cec5SDimitry Andric MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
43500b57cec5SDimitry Andric   return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
43510b57cec5SDimitry Andric }
43520b57cec5SDimitry Andric 
43530b57cec5SDimitry Andric MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const43540b57cec5SDimitry Andric MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
43550b57cec5SDimitry Andric   return getStruct<MachO::dylinker_command>(*this, L.Ptr);
43560b57cec5SDimitry Andric }
43570b57cec5SDimitry Andric 
43580b57cec5SDimitry Andric MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const43590b57cec5SDimitry Andric MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
43600b57cec5SDimitry Andric   return getStruct<MachO::uuid_command>(*this, L.Ptr);
43610b57cec5SDimitry Andric }
43620b57cec5SDimitry Andric 
43630b57cec5SDimitry Andric MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const43640b57cec5SDimitry Andric MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
43650b57cec5SDimitry Andric   return getStruct<MachO::rpath_command>(*this, L.Ptr);
43660b57cec5SDimitry Andric }
43670b57cec5SDimitry Andric 
43680b57cec5SDimitry Andric MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const43690b57cec5SDimitry Andric MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
43700b57cec5SDimitry Andric   return getStruct<MachO::source_version_command>(*this, L.Ptr);
43710b57cec5SDimitry Andric }
43720b57cec5SDimitry Andric 
43730b57cec5SDimitry Andric MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const43740b57cec5SDimitry Andric MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
43750b57cec5SDimitry Andric   return getStruct<MachO::entry_point_command>(*this, L.Ptr);
43760b57cec5SDimitry Andric }
43770b57cec5SDimitry Andric 
43780b57cec5SDimitry Andric MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const43790b57cec5SDimitry Andric MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
43800b57cec5SDimitry Andric   return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
43810b57cec5SDimitry Andric }
43820b57cec5SDimitry Andric 
43830b57cec5SDimitry Andric MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const43840b57cec5SDimitry Andric MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
43850b57cec5SDimitry Andric   return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
43860b57cec5SDimitry Andric }
43870b57cec5SDimitry Andric 
43880b57cec5SDimitry Andric MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const43890b57cec5SDimitry Andric MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
43900b57cec5SDimitry Andric   return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
43910b57cec5SDimitry Andric }
43920b57cec5SDimitry Andric 
43930b57cec5SDimitry Andric MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const43940b57cec5SDimitry Andric MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
43950b57cec5SDimitry Andric   return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
43960b57cec5SDimitry Andric }
43970b57cec5SDimitry Andric 
43980b57cec5SDimitry Andric MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const43990b57cec5SDimitry Andric MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
44000b57cec5SDimitry Andric   return getStruct<MachO::sub_library_command>(*this, L.Ptr);
44010b57cec5SDimitry Andric }
44020b57cec5SDimitry Andric 
44030b57cec5SDimitry Andric MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const44040b57cec5SDimitry Andric MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
44050b57cec5SDimitry Andric   return getStruct<MachO::sub_client_command>(*this, L.Ptr);
44060b57cec5SDimitry Andric }
44070b57cec5SDimitry Andric 
44080b57cec5SDimitry Andric MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const44090b57cec5SDimitry Andric MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
44100b57cec5SDimitry Andric   return getStruct<MachO::routines_command>(*this, L.Ptr);
44110b57cec5SDimitry Andric }
44120b57cec5SDimitry Andric 
44130b57cec5SDimitry Andric MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const44140b57cec5SDimitry Andric MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
44150b57cec5SDimitry Andric   return getStruct<MachO::routines_command_64>(*this, L.Ptr);
44160b57cec5SDimitry Andric }
44170b57cec5SDimitry Andric 
44180b57cec5SDimitry Andric MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const44190b57cec5SDimitry Andric MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
44200b57cec5SDimitry Andric   return getStruct<MachO::thread_command>(*this, L.Ptr);
44210b57cec5SDimitry Andric }
44220b57cec5SDimitry Andric 
44230b57cec5SDimitry Andric MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const44240b57cec5SDimitry Andric MachOObjectFile::getRelocation(DataRefImpl Rel) const {
44250b57cec5SDimitry Andric   uint32_t Offset;
44260b57cec5SDimitry Andric   if (getHeader().filetype == MachO::MH_OBJECT) {
44270b57cec5SDimitry Andric     DataRefImpl Sec;
44280b57cec5SDimitry Andric     Sec.d.a = Rel.d.a;
44290b57cec5SDimitry Andric     if (is64Bit()) {
44300b57cec5SDimitry Andric       MachO::section_64 Sect = getSection64(Sec);
44310b57cec5SDimitry Andric       Offset = Sect.reloff;
44320b57cec5SDimitry Andric     } else {
44330b57cec5SDimitry Andric       MachO::section Sect = getSection(Sec);
44340b57cec5SDimitry Andric       Offset = Sect.reloff;
44350b57cec5SDimitry Andric     }
44360b57cec5SDimitry Andric   } else {
44370b57cec5SDimitry Andric     MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
44380b57cec5SDimitry Andric     if (Rel.d.a == 0)
44390b57cec5SDimitry Andric       Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
44400b57cec5SDimitry Andric     else
44410b57cec5SDimitry Andric       Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
44420b57cec5SDimitry Andric   }
44430b57cec5SDimitry Andric 
44440b57cec5SDimitry Andric   auto P = reinterpret_cast<const MachO::any_relocation_info *>(
44450b57cec5SDimitry Andric       getPtr(*this, Offset)) + Rel.d.b;
44460b57cec5SDimitry Andric   return getStruct<MachO::any_relocation_info>(
44470b57cec5SDimitry Andric       *this, reinterpret_cast<const char *>(P));
44480b57cec5SDimitry Andric }
44490b57cec5SDimitry Andric 
44500b57cec5SDimitry Andric MachO::data_in_code_entry
getDice(DataRefImpl Rel) const44510b57cec5SDimitry Andric MachOObjectFile::getDice(DataRefImpl Rel) const {
44520b57cec5SDimitry Andric   const char *P = reinterpret_cast<const char *>(Rel.p);
44530b57cec5SDimitry Andric   return getStruct<MachO::data_in_code_entry>(*this, P);
44540b57cec5SDimitry Andric }
44550b57cec5SDimitry Andric 
getHeader() const44560b57cec5SDimitry Andric const MachO::mach_header &MachOObjectFile::getHeader() const {
44570b57cec5SDimitry Andric   return Header;
44580b57cec5SDimitry Andric }
44590b57cec5SDimitry Andric 
getHeader64() const44600b57cec5SDimitry Andric const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
44610b57cec5SDimitry Andric   assert(is64Bit());
44620b57cec5SDimitry Andric   return Header64;
44630b57cec5SDimitry Andric }
44640b57cec5SDimitry Andric 
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const44650b57cec5SDimitry Andric uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
44660b57cec5SDimitry Andric                                              const MachO::dysymtab_command &DLC,
44670b57cec5SDimitry Andric                                              unsigned Index) const {
44680b57cec5SDimitry Andric   uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
44690b57cec5SDimitry Andric   return getStruct<uint32_t>(*this, getPtr(*this, Offset));
44700b57cec5SDimitry Andric }
44710b57cec5SDimitry Andric 
44720b57cec5SDimitry Andric MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const44730b57cec5SDimitry Andric MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
44740b57cec5SDimitry Andric                                          unsigned Index) const {
44750b57cec5SDimitry Andric   uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
44760b57cec5SDimitry Andric   return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
44770b57cec5SDimitry Andric }
44780b57cec5SDimitry Andric 
getSymtabLoadCommand() const44790b57cec5SDimitry Andric MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
44800b57cec5SDimitry Andric   if (SymtabLoadCmd)
44810b57cec5SDimitry Andric     return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
44820b57cec5SDimitry Andric 
44830b57cec5SDimitry Andric   // If there is no SymtabLoadCmd return a load command with zero'ed fields.
44840b57cec5SDimitry Andric   MachO::symtab_command Cmd;
44850b57cec5SDimitry Andric   Cmd.cmd = MachO::LC_SYMTAB;
44860b57cec5SDimitry Andric   Cmd.cmdsize = sizeof(MachO::symtab_command);
44870b57cec5SDimitry Andric   Cmd.symoff = 0;
44880b57cec5SDimitry Andric   Cmd.nsyms = 0;
44890b57cec5SDimitry Andric   Cmd.stroff = 0;
44900b57cec5SDimitry Andric   Cmd.strsize = 0;
44910b57cec5SDimitry Andric   return Cmd;
44920b57cec5SDimitry Andric }
44930b57cec5SDimitry Andric 
getDysymtabLoadCommand() const44940b57cec5SDimitry Andric MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
44950b57cec5SDimitry Andric   if (DysymtabLoadCmd)
44960b57cec5SDimitry Andric     return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
44970b57cec5SDimitry Andric 
44980b57cec5SDimitry Andric   // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
44990b57cec5SDimitry Andric   MachO::dysymtab_command Cmd;
45000b57cec5SDimitry Andric   Cmd.cmd = MachO::LC_DYSYMTAB;
45010b57cec5SDimitry Andric   Cmd.cmdsize = sizeof(MachO::dysymtab_command);
45020b57cec5SDimitry Andric   Cmd.ilocalsym = 0;
45030b57cec5SDimitry Andric   Cmd.nlocalsym = 0;
45040b57cec5SDimitry Andric   Cmd.iextdefsym = 0;
45050b57cec5SDimitry Andric   Cmd.nextdefsym = 0;
45060b57cec5SDimitry Andric   Cmd.iundefsym = 0;
45070b57cec5SDimitry Andric   Cmd.nundefsym = 0;
45080b57cec5SDimitry Andric   Cmd.tocoff = 0;
45090b57cec5SDimitry Andric   Cmd.ntoc = 0;
45100b57cec5SDimitry Andric   Cmd.modtaboff = 0;
45110b57cec5SDimitry Andric   Cmd.nmodtab = 0;
45120b57cec5SDimitry Andric   Cmd.extrefsymoff = 0;
45130b57cec5SDimitry Andric   Cmd.nextrefsyms = 0;
45140b57cec5SDimitry Andric   Cmd.indirectsymoff = 0;
45150b57cec5SDimitry Andric   Cmd.nindirectsyms = 0;
45160b57cec5SDimitry Andric   Cmd.extreloff = 0;
45170b57cec5SDimitry Andric   Cmd.nextrel = 0;
45180b57cec5SDimitry Andric   Cmd.locreloff = 0;
45190b57cec5SDimitry Andric   Cmd.nlocrel = 0;
45200b57cec5SDimitry Andric   return Cmd;
45210b57cec5SDimitry Andric }
45220b57cec5SDimitry Andric 
45230b57cec5SDimitry Andric MachO::linkedit_data_command
getDataInCodeLoadCommand() const45240b57cec5SDimitry Andric MachOObjectFile::getDataInCodeLoadCommand() const {
45250b57cec5SDimitry Andric   if (DataInCodeLoadCmd)
45260b57cec5SDimitry Andric     return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
45270b57cec5SDimitry Andric 
45280b57cec5SDimitry Andric   // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
45290b57cec5SDimitry Andric   MachO::linkedit_data_command Cmd;
45300b57cec5SDimitry Andric   Cmd.cmd = MachO::LC_DATA_IN_CODE;
45310b57cec5SDimitry Andric   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
45320b57cec5SDimitry Andric   Cmd.dataoff = 0;
45330b57cec5SDimitry Andric   Cmd.datasize = 0;
45340b57cec5SDimitry Andric   return Cmd;
45350b57cec5SDimitry Andric }
45360b57cec5SDimitry Andric 
45370b57cec5SDimitry Andric MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const45380b57cec5SDimitry Andric MachOObjectFile::getLinkOptHintsLoadCommand() const {
45390b57cec5SDimitry Andric   if (LinkOptHintsLoadCmd)
45400b57cec5SDimitry Andric     return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
45410b57cec5SDimitry Andric 
45420b57cec5SDimitry Andric   // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
45430b57cec5SDimitry Andric   // fields.
45440b57cec5SDimitry Andric   MachO::linkedit_data_command Cmd;
45450b57cec5SDimitry Andric   Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
45460b57cec5SDimitry Andric   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
45470b57cec5SDimitry Andric   Cmd.dataoff = 0;
45480b57cec5SDimitry Andric   Cmd.datasize = 0;
45490b57cec5SDimitry Andric   return Cmd;
45500b57cec5SDimitry Andric }
45510b57cec5SDimitry Andric 
getDyldInfoRebaseOpcodes() const45520b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
45530b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
45540b57cec5SDimitry Andric     return None;
45550b57cec5SDimitry Andric 
45560b57cec5SDimitry Andric   auto DyldInfoOrErr =
45570b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45580b57cec5SDimitry Andric   if (!DyldInfoOrErr)
45590b57cec5SDimitry Andric     return None;
45600b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
45610b57cec5SDimitry Andric   const uint8_t *Ptr =
45620b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
45630b57cec5SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.rebase_size);
45640b57cec5SDimitry Andric }
45650b57cec5SDimitry Andric 
getDyldInfoBindOpcodes() const45660b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
45670b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
45680b57cec5SDimitry Andric     return None;
45690b57cec5SDimitry Andric 
45700b57cec5SDimitry Andric   auto DyldInfoOrErr =
45710b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45720b57cec5SDimitry Andric   if (!DyldInfoOrErr)
45730b57cec5SDimitry Andric     return None;
45740b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
45750b57cec5SDimitry Andric   const uint8_t *Ptr =
45760b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
45770b57cec5SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.bind_size);
45780b57cec5SDimitry Andric }
45790b57cec5SDimitry Andric 
getDyldInfoWeakBindOpcodes() const45800b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
45810b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
45820b57cec5SDimitry Andric     return None;
45830b57cec5SDimitry Andric 
45840b57cec5SDimitry Andric   auto DyldInfoOrErr =
45850b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45860b57cec5SDimitry Andric   if (!DyldInfoOrErr)
45870b57cec5SDimitry Andric     return None;
45880b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
45890b57cec5SDimitry Andric   const uint8_t *Ptr =
45900b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
45910b57cec5SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
45920b57cec5SDimitry Andric }
45930b57cec5SDimitry Andric 
getDyldInfoLazyBindOpcodes() const45940b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
45950b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
45960b57cec5SDimitry Andric     return None;
45970b57cec5SDimitry Andric 
45980b57cec5SDimitry Andric   auto DyldInfoOrErr =
45990b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
46000b57cec5SDimitry Andric   if (!DyldInfoOrErr)
46010b57cec5SDimitry Andric     return None;
46020b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
46030b57cec5SDimitry Andric   const uint8_t *Ptr =
46040b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
46050b57cec5SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
46060b57cec5SDimitry Andric }
46070b57cec5SDimitry Andric 
getDyldInfoExportsTrie() const46080b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
46090b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
46100b57cec5SDimitry Andric     return None;
46110b57cec5SDimitry Andric 
46120b57cec5SDimitry Andric   auto DyldInfoOrErr =
46130b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
46140b57cec5SDimitry Andric   if (!DyldInfoOrErr)
46150b57cec5SDimitry Andric     return None;
46160b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
46170b57cec5SDimitry Andric   const uint8_t *Ptr =
46180b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
46190b57cec5SDimitry Andric   return makeArrayRef(Ptr, DyldInfo.export_size);
46200b57cec5SDimitry Andric }
46210b57cec5SDimitry Andric 
getUuid() const46220b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
46230b57cec5SDimitry Andric   if (!UuidLoadCmd)
46240b57cec5SDimitry Andric     return None;
46250b57cec5SDimitry Andric   // Returning a pointer is fine as uuid doesn't need endian swapping.
46260b57cec5SDimitry Andric   const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
46270b57cec5SDimitry Andric   return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
46280b57cec5SDimitry Andric }
46290b57cec5SDimitry Andric 
getStringTableData() const46300b57cec5SDimitry Andric StringRef MachOObjectFile::getStringTableData() const {
46310b57cec5SDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
46320b57cec5SDimitry Andric   return getData().substr(S.stroff, S.strsize);
46330b57cec5SDimitry Andric }
46340b57cec5SDimitry Andric 
is64Bit() const46350b57cec5SDimitry Andric bool MachOObjectFile::is64Bit() const {
46360b57cec5SDimitry Andric   return getType() == getMachOType(false, true) ||
46370b57cec5SDimitry Andric     getType() == getMachOType(true, true);
46380b57cec5SDimitry Andric }
46390b57cec5SDimitry Andric 
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const46400b57cec5SDimitry Andric void MachOObjectFile::ReadULEB128s(uint64_t Index,
46410b57cec5SDimitry Andric                                    SmallVectorImpl<uint64_t> &Out) const {
46420b57cec5SDimitry Andric   DataExtractor extractor(ObjectFile::getData(), true, 0);
46430b57cec5SDimitry Andric 
46448bcb0991SDimitry Andric   uint64_t offset = Index;
46450b57cec5SDimitry Andric   uint64_t data = 0;
46460b57cec5SDimitry Andric   while (uint64_t delta = extractor.getULEB128(&offset)) {
46470b57cec5SDimitry Andric     data += delta;
46480b57cec5SDimitry Andric     Out.push_back(data);
46490b57cec5SDimitry Andric   }
46500b57cec5SDimitry Andric }
46510b57cec5SDimitry Andric 
isRelocatableObject() const46520b57cec5SDimitry Andric bool MachOObjectFile::isRelocatableObject() const {
46530b57cec5SDimitry Andric   return getHeader().filetype == MachO::MH_OBJECT;
46540b57cec5SDimitry Andric }
46550b57cec5SDimitry Andric 
46560b57cec5SDimitry Andric Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer,uint32_t UniversalCputype,uint32_t UniversalIndex)46570b57cec5SDimitry Andric ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
46580b57cec5SDimitry Andric                                   uint32_t UniversalCputype,
46590b57cec5SDimitry Andric                                   uint32_t UniversalIndex) {
46600b57cec5SDimitry Andric   StringRef Magic = Buffer.getBuffer().slice(0, 4);
46610b57cec5SDimitry Andric   if (Magic == "\xFE\xED\xFA\xCE")
46620b57cec5SDimitry Andric     return MachOObjectFile::create(Buffer, false, false,
46630b57cec5SDimitry Andric                                    UniversalCputype, UniversalIndex);
46640b57cec5SDimitry Andric   if (Magic == "\xCE\xFA\xED\xFE")
46650b57cec5SDimitry Andric     return MachOObjectFile::create(Buffer, true, false,
46660b57cec5SDimitry Andric                                    UniversalCputype, UniversalIndex);
46670b57cec5SDimitry Andric   if (Magic == "\xFE\xED\xFA\xCF")
46680b57cec5SDimitry Andric     return MachOObjectFile::create(Buffer, false, true,
46690b57cec5SDimitry Andric                                    UniversalCputype, UniversalIndex);
46700b57cec5SDimitry Andric   if (Magic == "\xCF\xFA\xED\xFE")
46710b57cec5SDimitry Andric     return MachOObjectFile::create(Buffer, true, true,
46720b57cec5SDimitry Andric                                    UniversalCputype, UniversalIndex);
46730b57cec5SDimitry Andric   return make_error<GenericBinaryError>("Unrecognized MachO magic number",
46740b57cec5SDimitry Andric                                         object_error::invalid_file_type);
46750b57cec5SDimitry Andric }
46760b57cec5SDimitry Andric 
mapDebugSectionName(StringRef Name) const46770b57cec5SDimitry Andric StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
46780b57cec5SDimitry Andric   return StringSwitch<StringRef>(Name)
46790b57cec5SDimitry Andric       .Case("debug_str_offs", "debug_str_offsets")
46800b57cec5SDimitry Andric       .Default(Name);
46810b57cec5SDimitry Andric }
4682