xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/STLExtras.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
190b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
20bdd1243dSDimitry Andric #include "llvm/ADT/bit.h"
210b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
221fd87a68SDimitry Andric #include "llvm/BinaryFormat/Swift.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"
290eae32dcSDimitry Andric #include "llvm/Support/Errc.h"
300b57cec5SDimitry Andric #include "llvm/Support/Error.h"
310b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
320eae32dcSDimitry Andric #include "llvm/Support/FileSystem.h"
330b57cec5SDimitry Andric #include "llvm/Support/Format.h"
340b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
3581ad6265SDimitry Andric #include "llvm/Support/MemoryBufferRef.h"
360eae32dcSDimitry Andric #include "llvm/Support/Path.h"
370b57cec5SDimitry Andric #include "llvm/Support/SwapByteOrder.h"
380b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
3906c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
4006c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
410b57cec5SDimitry Andric #include <algorithm>
420b57cec5SDimitry Andric #include <cassert>
430b57cec5SDimitry Andric #include <cstddef>
440b57cec5SDimitry Andric #include <cstdint>
450b57cec5SDimitry Andric #include <cstring>
460b57cec5SDimitry Andric #include <limits>
470b57cec5SDimitry Andric #include <list>
480b57cec5SDimitry Andric #include <memory>
490b57cec5SDimitry Andric #include <system_error>
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric using namespace llvm;
520b57cec5SDimitry Andric using namespace object;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric namespace {
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   struct section_base {
570b57cec5SDimitry Andric     char sectname[16];
580b57cec5SDimitry Andric     char segname[16];
590b57cec5SDimitry Andric   };
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric } // end anonymous namespace
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric static Error malformedError(const Twine &Msg) {
640b57cec5SDimitry Andric   return make_error<GenericBinaryError>("truncated or malformed object (" +
650b57cec5SDimitry Andric                                             Msg + ")",
660b57cec5SDimitry Andric                                         object_error::parse_failed);
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric // FIXME: Replace all uses of this function with getStructOrErr.
700b57cec5SDimitry Andric template <typename T>
710b57cec5SDimitry Andric static T getStruct(const MachOObjectFile &O, const char *P) {
720b57cec5SDimitry Andric   // Don't read before the beginning or past the end of the file
730b57cec5SDimitry Andric   if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
740b57cec5SDimitry Andric     report_fatal_error("Malformed MachO file.");
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   T Cmd;
770b57cec5SDimitry Andric   memcpy(&Cmd, P, sizeof(T));
780b57cec5SDimitry Andric   if (O.isLittleEndian() != sys::IsLittleEndianHost)
790b57cec5SDimitry Andric     MachO::swapStruct(Cmd);
800b57cec5SDimitry Andric   return Cmd;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric template <typename T>
840b57cec5SDimitry Andric static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
850b57cec5SDimitry Andric   // Don't read before the beginning or past the end of the file
860b57cec5SDimitry Andric   if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
870b57cec5SDimitry Andric     return malformedError("Structure read out-of-range");
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   T Cmd;
900b57cec5SDimitry Andric   memcpy(&Cmd, P, sizeof(T));
910b57cec5SDimitry Andric   if (O.isLittleEndian() != sys::IsLittleEndianHost)
920b57cec5SDimitry Andric     MachO::swapStruct(Cmd);
930b57cec5SDimitry Andric   return Cmd;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric static const char *
970b57cec5SDimitry Andric getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
980b57cec5SDimitry Andric               unsigned Sec) {
990b57cec5SDimitry Andric   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   bool Is64 = O.is64Bit();
1020b57cec5SDimitry Andric   unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
1030b57cec5SDimitry Andric                                     sizeof(MachO::segment_command);
1040b57cec5SDimitry Andric   unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
1050b57cec5SDimitry Andric                                 sizeof(MachO::section);
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
1080b57cec5SDimitry Andric   return reinterpret_cast<const char*>(SectionAddr);
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1115f757f3fSDimitry Andric static const char *getPtr(const MachOObjectFile &O, size_t Offset,
1125f757f3fSDimitry Andric                           size_t MachOFilesetEntryOffset = 0) {
1135f757f3fSDimitry Andric   assert(Offset <= O.getData().size() &&
1145f757f3fSDimitry Andric          MachOFilesetEntryOffset <= O.getData().size());
1155f757f3fSDimitry Andric   return O.getData().data() + Offset + MachOFilesetEntryOffset;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric static MachO::nlist_base
1190b57cec5SDimitry Andric getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
1200b57cec5SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
1210b57cec5SDimitry Andric   return getStruct<MachO::nlist_base>(O, P);
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric static StringRef parseSegmentOrSectionName(const char *P) {
1250b57cec5SDimitry Andric   if (P[15] == 0)
1260b57cec5SDimitry Andric     // Null terminated.
1270b57cec5SDimitry Andric     return P;
1280b57cec5SDimitry Andric   // Not null terminated, so this is a 16 char string.
1290b57cec5SDimitry Andric   return StringRef(P, 16);
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric static unsigned getCPUType(const MachOObjectFile &O) {
1330b57cec5SDimitry Andric   return O.getHeader().cputype;
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
136480093f4SDimitry Andric static unsigned getCPUSubType(const MachOObjectFile &O) {
137480093f4SDimitry Andric   return O.getHeader().cpusubtype;
138480093f4SDimitry Andric }
139480093f4SDimitry Andric 
1400b57cec5SDimitry Andric static uint32_t
1410b57cec5SDimitry Andric getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
1420b57cec5SDimitry Andric   return RE.r_word0;
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric static unsigned
1460b57cec5SDimitry Andric getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
1470b57cec5SDimitry Andric   return RE.r_word0 & 0xffffff;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric static bool getPlainRelocationPCRel(const MachOObjectFile &O,
1510b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) {
1520b57cec5SDimitry Andric   if (O.isLittleEndian())
1530b57cec5SDimitry Andric     return (RE.r_word1 >> 24) & 1;
1540b57cec5SDimitry Andric   return (RE.r_word1 >> 7) & 1;
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric static bool
1580b57cec5SDimitry Andric getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
1590b57cec5SDimitry Andric   return (RE.r_word0 >> 30) & 1;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric static unsigned getPlainRelocationLength(const MachOObjectFile &O,
1630b57cec5SDimitry Andric                                          const MachO::any_relocation_info &RE) {
1640b57cec5SDimitry Andric   if (O.isLittleEndian())
1650b57cec5SDimitry Andric     return (RE.r_word1 >> 25) & 3;
1660b57cec5SDimitry Andric   return (RE.r_word1 >> 5) & 3;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric static unsigned
1700b57cec5SDimitry Andric getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
1710b57cec5SDimitry Andric   return (RE.r_word0 >> 28) & 3;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric static unsigned getPlainRelocationType(const MachOObjectFile &O,
1750b57cec5SDimitry Andric                                        const MachO::any_relocation_info &RE) {
1760b57cec5SDimitry Andric   if (O.isLittleEndian())
1770b57cec5SDimitry Andric     return RE.r_word1 >> 28;
1780b57cec5SDimitry Andric   return RE.r_word1 & 0xf;
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric static uint32_t getSectionFlags(const MachOObjectFile &O,
1820b57cec5SDimitry Andric                                 DataRefImpl Sec) {
1830b57cec5SDimitry Andric   if (O.is64Bit()) {
1840b57cec5SDimitry Andric     MachO::section_64 Sect = O.getSection64(Sec);
1850b57cec5SDimitry Andric     return Sect.flags;
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric   MachO::section Sect = O.getSection(Sec);
1880b57cec5SDimitry Andric   return Sect.flags;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
1920b57cec5SDimitry Andric getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
1930b57cec5SDimitry Andric                    uint32_t LoadCommandIndex) {
1940b57cec5SDimitry Andric   if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
1950b57cec5SDimitry Andric     if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
1960b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
1970b57cec5SDimitry Andric                             " extends past end of file");
1980b57cec5SDimitry Andric     if (CmdOrErr->cmdsize < 8)
1990b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
2000b57cec5SDimitry Andric                             " with size less than 8 bytes");
2010b57cec5SDimitry Andric     return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
2020b57cec5SDimitry Andric   } else
2030b57cec5SDimitry Andric     return CmdOrErr.takeError();
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
2070b57cec5SDimitry Andric getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
2080b57cec5SDimitry Andric   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
2090b57cec5SDimitry Andric                                       : sizeof(MachO::mach_header);
2100b57cec5SDimitry Andric   if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
2110b57cec5SDimitry Andric     return malformedError("load command 0 extends past the end all load "
2120b57cec5SDimitry Andric                           "commands in the file");
2135f757f3fSDimitry Andric   return getLoadCommandInfo(
2145f757f3fSDimitry Andric       Obj, getPtr(Obj, HeaderSize, Obj.getMachOFilesetEntryOffset()), 0);
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
2180b57cec5SDimitry Andric getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
2190b57cec5SDimitry Andric                        const MachOObjectFile::LoadCommandInfo &L) {
2200b57cec5SDimitry Andric   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
2210b57cec5SDimitry Andric                                       : sizeof(MachO::mach_header);
2220b57cec5SDimitry Andric   if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
2235f757f3fSDimitry Andric       Obj.getData().data() + Obj.getMachOFilesetEntryOffset() + HeaderSize +
2245f757f3fSDimitry Andric           Obj.getHeader().sizeofcmds)
2250b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex + 1) +
2260b57cec5SDimitry Andric                           " extends past the end all load commands in the file");
2270b57cec5SDimitry Andric   return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric template <typename T>
2310b57cec5SDimitry Andric static void parseHeader(const MachOObjectFile &Obj, T &Header,
2320b57cec5SDimitry Andric                         Error &Err) {
2330b57cec5SDimitry Andric   if (sizeof(T) > Obj.getData().size()) {
2340b57cec5SDimitry Andric     Err = malformedError("the mach header extends past the end of the "
2350b57cec5SDimitry Andric                          "file");
2360b57cec5SDimitry Andric     return;
2370b57cec5SDimitry Andric   }
2385f757f3fSDimitry Andric   if (auto HeaderOrErr = getStructOrErr<T>(
2395f757f3fSDimitry Andric           Obj, getPtr(Obj, 0, Obj.getMachOFilesetEntryOffset())))
2400b57cec5SDimitry Andric     Header = *HeaderOrErr;
2410b57cec5SDimitry Andric   else
2420b57cec5SDimitry Andric     Err = HeaderOrErr.takeError();
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric // This is used to check for overlapping of Mach-O elements.
2460b57cec5SDimitry Andric struct MachOElement {
2470b57cec5SDimitry Andric   uint64_t Offset;
2480b57cec5SDimitry Andric   uint64_t Size;
2490b57cec5SDimitry Andric   const char *Name;
2500b57cec5SDimitry Andric };
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric static Error checkOverlappingElement(std::list<MachOElement> &Elements,
2530b57cec5SDimitry Andric                                      uint64_t Offset, uint64_t Size,
2540b57cec5SDimitry Andric                                      const char *Name) {
2550b57cec5SDimitry Andric   if (Size == 0)
2560b57cec5SDimitry Andric     return Error::success();
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   for (auto it = Elements.begin(); it != Elements.end(); ++it) {
259349cc55cSDimitry Andric     const auto &E = *it;
2600b57cec5SDimitry Andric     if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
2610b57cec5SDimitry Andric         (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
2620b57cec5SDimitry Andric         (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
2630b57cec5SDimitry Andric       return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
2640b57cec5SDimitry Andric                             " with a size of " + Twine(Size) + ", overlaps " +
2650b57cec5SDimitry Andric                             E.Name + " at offset " + Twine(E.Offset) + " with "
2660b57cec5SDimitry Andric                             "a size of " + Twine(E.Size));
2670b57cec5SDimitry Andric     auto nt = it;
2680b57cec5SDimitry Andric     nt++;
2690b57cec5SDimitry Andric     if (nt != Elements.end()) {
270349cc55cSDimitry Andric       const auto &N = *nt;
2710b57cec5SDimitry Andric       if (Offset + Size <= N.Offset) {
2720b57cec5SDimitry Andric         Elements.insert(nt, {Offset, Size, Name});
2730b57cec5SDimitry Andric         return Error::success();
2740b57cec5SDimitry Andric       }
2750b57cec5SDimitry Andric     }
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric   Elements.push_back({Offset, Size, Name});
2780b57cec5SDimitry Andric   return Error::success();
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
2820b57cec5SDimitry Andric // sections to \param Sections, and optionally sets
2830b57cec5SDimitry Andric // \param IsPageZeroSegment to true.
2840b57cec5SDimitry Andric template <typename Segment, typename Section>
2850b57cec5SDimitry Andric static Error parseSegmentLoadCommand(
2860b57cec5SDimitry Andric     const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
2870b57cec5SDimitry Andric     SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
2880b57cec5SDimitry Andric     uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
2890b57cec5SDimitry Andric     std::list<MachOElement> &Elements) {
2900b57cec5SDimitry Andric   const unsigned SegmentLoadSize = sizeof(Segment);
2910b57cec5SDimitry Andric   if (Load.C.cmdsize < SegmentLoadSize)
2920b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
2930b57cec5SDimitry Andric                           " " + CmdName + " cmdsize too small");
2940b57cec5SDimitry Andric   if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
2950b57cec5SDimitry Andric     Segment S = SegOrErr.get();
2960b57cec5SDimitry Andric     const unsigned SectionSize = sizeof(Section);
2970b57cec5SDimitry Andric     uint64_t FileSize = Obj.getData().size();
2980b57cec5SDimitry Andric     if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
2990b57cec5SDimitry Andric         S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
3000b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
3010b57cec5SDimitry Andric                             " inconsistent cmdsize in " + CmdName +
3020b57cec5SDimitry Andric                             " for the number of sections");
3030b57cec5SDimitry Andric     for (unsigned J = 0; J < S.nsects; ++J) {
3040b57cec5SDimitry Andric       const char *Sec = getSectionPtr(Obj, Load, J);
3050b57cec5SDimitry Andric       Sections.push_back(Sec);
3060b57cec5SDimitry Andric       auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
3070b57cec5SDimitry Andric       if (!SectionOrErr)
3080b57cec5SDimitry Andric         return SectionOrErr.takeError();
3090b57cec5SDimitry Andric       Section s = SectionOrErr.get();
3100b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3110b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3120b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3130b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
3140b57cec5SDimitry Andric           s.offset > FileSize)
3150b57cec5SDimitry Andric         return malformedError("offset field of section " + Twine(J) + " in " +
3160b57cec5SDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
3170b57cec5SDimitry Andric                               " extends past the end of the file");
3180b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3190b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3200b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3210b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
3220b57cec5SDimitry Andric           s.offset < SizeOfHeaders && s.size != 0)
3230b57cec5SDimitry Andric         return malformedError("offset field of section " + Twine(J) + " in " +
3240b57cec5SDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
3250b57cec5SDimitry Andric                               " not past the headers of the file");
3260b57cec5SDimitry Andric       uint64_t BigSize = s.offset;
3270b57cec5SDimitry Andric       BigSize += s.size;
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           BigSize > FileSize)
3330b57cec5SDimitry Andric         return malformedError("offset field plus size field of section " +
3340b57cec5SDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
3350b57cec5SDimitry Andric                               Twine(LoadCommandIndex) +
3360b57cec5SDimitry Andric                               " extends past the end of the file");
3370b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3380b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3390b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3400b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
3410b57cec5SDimitry Andric           s.size > S.filesize)
3420b57cec5SDimitry Andric         return malformedError("size field of section " +
3430b57cec5SDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
3440b57cec5SDimitry Andric                               Twine(LoadCommandIndex) +
3450b57cec5SDimitry Andric                               " greater than the segment");
3460b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3470b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
3480b57cec5SDimitry Andric           s.addr < S.vmaddr)
3490b57cec5SDimitry Andric         return malformedError("addr field of section " + Twine(J) + " in " +
3500b57cec5SDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
3510b57cec5SDimitry Andric                               " less than the segment's vmaddr");
3520b57cec5SDimitry Andric       BigSize = s.addr;
3530b57cec5SDimitry Andric       BigSize += s.size;
3540b57cec5SDimitry Andric       uint64_t BigEnd = S.vmaddr;
3550b57cec5SDimitry Andric       BigEnd += S.vmsize;
3560b57cec5SDimitry Andric       if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
3570b57cec5SDimitry Andric         return malformedError("addr field plus size of section " + Twine(J) +
3580b57cec5SDimitry Andric                               " in " + CmdName + " command " +
3590b57cec5SDimitry Andric                               Twine(LoadCommandIndex) +
3600b57cec5SDimitry Andric                               " greater than than "
3610b57cec5SDimitry Andric                               "the segment's vmaddr plus vmsize");
3620b57cec5SDimitry Andric       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
3630b57cec5SDimitry Andric           Obj.getHeader().filetype != MachO::MH_DSYM &&
3640b57cec5SDimitry Andric           s.flags != MachO::S_ZEROFILL &&
3650b57cec5SDimitry Andric           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
3660b57cec5SDimitry Andric         if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
3670b57cec5SDimitry Andric                                                 "section contents"))
3680b57cec5SDimitry Andric           return Err;
3690b57cec5SDimitry Andric       if (s.reloff > FileSize)
3700b57cec5SDimitry Andric         return malformedError("reloff field of section " + Twine(J) + " in " +
3710b57cec5SDimitry Andric                               CmdName + " command " + Twine(LoadCommandIndex) +
3720b57cec5SDimitry Andric                               " extends past the end of the file");
3730b57cec5SDimitry Andric       BigSize = s.nreloc;
3740b57cec5SDimitry Andric       BigSize *= sizeof(struct MachO::relocation_info);
3750b57cec5SDimitry Andric       BigSize += s.reloff;
3760b57cec5SDimitry Andric       if (BigSize > FileSize)
3770b57cec5SDimitry Andric         return malformedError("reloff field plus nreloc field times sizeof("
3780b57cec5SDimitry Andric                               "struct relocation_info) of section " +
3790b57cec5SDimitry Andric                               Twine(J) + " in " + CmdName + " command " +
3800b57cec5SDimitry Andric                               Twine(LoadCommandIndex) +
3810b57cec5SDimitry Andric                               " extends past the end of the file");
3820b57cec5SDimitry Andric       if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
3830b57cec5SDimitry Andric                                               sizeof(struct
3840b57cec5SDimitry Andric                                               MachO::relocation_info),
3850b57cec5SDimitry Andric                                               "section relocation entries"))
3860b57cec5SDimitry Andric         return Err;
3870b57cec5SDimitry Andric     }
3880b57cec5SDimitry Andric     if (S.fileoff > FileSize)
3890b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
3900b57cec5SDimitry Andric                             " fileoff field in " + CmdName +
3910b57cec5SDimitry Andric                             " extends past the end of the file");
3920b57cec5SDimitry Andric     uint64_t BigSize = S.fileoff;
3930b57cec5SDimitry Andric     BigSize += S.filesize;
3940b57cec5SDimitry Andric     if (BigSize > FileSize)
3950b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
3960b57cec5SDimitry Andric                             " fileoff field plus filesize field in " +
3970b57cec5SDimitry Andric                             CmdName + " extends past the end of the file");
3980b57cec5SDimitry Andric     if (S.vmsize != 0 && S.filesize > S.vmsize)
3990b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
4000b57cec5SDimitry Andric                             " filesize field in " + CmdName +
4010b57cec5SDimitry Andric                             " greater than vmsize field");
402*0fca6ea1SDimitry Andric     IsPageZeroSegment |= StringRef("__PAGEZERO") == S.segname;
4030b57cec5SDimitry Andric   } else
4040b57cec5SDimitry Andric     return SegOrErr.takeError();
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   return Error::success();
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric static Error checkSymtabCommand(const MachOObjectFile &Obj,
4100b57cec5SDimitry Andric                                 const MachOObjectFile::LoadCommandInfo &Load,
4110b57cec5SDimitry Andric                                 uint32_t LoadCommandIndex,
4120b57cec5SDimitry Andric                                 const char **SymtabLoadCmd,
4130b57cec5SDimitry Andric                                 std::list<MachOElement> &Elements) {
4140b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::symtab_command))
4150b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
4160b57cec5SDimitry Andric                           " LC_SYMTAB cmdsize too small");
4170b57cec5SDimitry Andric   if (*SymtabLoadCmd != nullptr)
4180b57cec5SDimitry Andric     return malformedError("more than one LC_SYMTAB command");
4190b57cec5SDimitry Andric   auto SymtabOrErr = getStructOrErr<MachO::symtab_command>(Obj, Load.Ptr);
4200b57cec5SDimitry Andric   if (!SymtabOrErr)
4210b57cec5SDimitry Andric     return SymtabOrErr.takeError();
4220b57cec5SDimitry Andric   MachO::symtab_command Symtab = SymtabOrErr.get();
4230b57cec5SDimitry Andric   if (Symtab.cmdsize != sizeof(MachO::symtab_command))
4240b57cec5SDimitry Andric     return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
4250b57cec5SDimitry Andric                           " has incorrect cmdsize");
4260b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
4270b57cec5SDimitry Andric   if (Symtab.symoff > FileSize)
4280b57cec5SDimitry Andric     return malformedError("symoff field of LC_SYMTAB command " +
4290b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
4300b57cec5SDimitry Andric                           "of the file");
4310b57cec5SDimitry Andric   uint64_t SymtabSize = Symtab.nsyms;
4320b57cec5SDimitry Andric   const char *struct_nlist_name;
4330b57cec5SDimitry Andric   if (Obj.is64Bit()) {
4340b57cec5SDimitry Andric     SymtabSize *= sizeof(MachO::nlist_64);
4350b57cec5SDimitry Andric     struct_nlist_name = "struct nlist_64";
4360b57cec5SDimitry Andric   } else {
4370b57cec5SDimitry Andric     SymtabSize *= sizeof(MachO::nlist);
4380b57cec5SDimitry Andric     struct_nlist_name = "struct nlist";
4390b57cec5SDimitry Andric   }
4400b57cec5SDimitry Andric   uint64_t BigSize = SymtabSize;
4410b57cec5SDimitry Andric   BigSize += Symtab.symoff;
4420b57cec5SDimitry Andric   if (BigSize > FileSize)
4430b57cec5SDimitry Andric     return malformedError("symoff field plus nsyms field times sizeof(" +
4440b57cec5SDimitry Andric                           Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
4450b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
4460b57cec5SDimitry Andric                           "of the file");
4470b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
4480b57cec5SDimitry Andric                                           "symbol table"))
4490b57cec5SDimitry Andric     return Err;
4500b57cec5SDimitry Andric   if (Symtab.stroff > FileSize)
4510b57cec5SDimitry Andric     return malformedError("stroff field of LC_SYMTAB command " +
4520b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end "
4530b57cec5SDimitry Andric                           "of the file");
4540b57cec5SDimitry Andric   BigSize = Symtab.stroff;
4550b57cec5SDimitry Andric   BigSize += Symtab.strsize;
4560b57cec5SDimitry Andric   if (BigSize > FileSize)
4570b57cec5SDimitry Andric     return malformedError("stroff field plus strsize field of LC_SYMTAB "
4580b57cec5SDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
4590b57cec5SDimitry Andric                           "past the end of the file");
4600b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
4610b57cec5SDimitry Andric                                           Symtab.strsize, "string table"))
4620b57cec5SDimitry Andric     return Err;
4630b57cec5SDimitry Andric   *SymtabLoadCmd = Load.Ptr;
4640b57cec5SDimitry Andric   return Error::success();
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric static Error checkDysymtabCommand(const MachOObjectFile &Obj,
4680b57cec5SDimitry Andric                                   const MachOObjectFile::LoadCommandInfo &Load,
4690b57cec5SDimitry Andric                                   uint32_t LoadCommandIndex,
4700b57cec5SDimitry Andric                                   const char **DysymtabLoadCmd,
4710b57cec5SDimitry Andric                                   std::list<MachOElement> &Elements) {
4720b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
4730b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
4740b57cec5SDimitry Andric                           " LC_DYSYMTAB cmdsize too small");
4750b57cec5SDimitry Andric   if (*DysymtabLoadCmd != nullptr)
4760b57cec5SDimitry Andric     return malformedError("more than one LC_DYSYMTAB command");
4770b57cec5SDimitry Andric   auto DysymtabOrErr =
4780b57cec5SDimitry Andric     getStructOrErr<MachO::dysymtab_command>(Obj, Load.Ptr);
4790b57cec5SDimitry Andric   if (!DysymtabOrErr)
4800b57cec5SDimitry Andric     return DysymtabOrErr.takeError();
4810b57cec5SDimitry Andric   MachO::dysymtab_command Dysymtab = DysymtabOrErr.get();
4820b57cec5SDimitry Andric   if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
4830b57cec5SDimitry Andric     return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
4840b57cec5SDimitry Andric                           " has incorrect cmdsize");
4850b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
4860b57cec5SDimitry Andric   if (Dysymtab.tocoff > FileSize)
4870b57cec5SDimitry Andric     return malformedError("tocoff field of LC_DYSYMTAB command " +
4880b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
4890b57cec5SDimitry Andric                           "the file");
4900b57cec5SDimitry Andric   uint64_t BigSize = Dysymtab.ntoc;
4910b57cec5SDimitry Andric   BigSize *= sizeof(MachO::dylib_table_of_contents);
4920b57cec5SDimitry Andric   BigSize += Dysymtab.tocoff;
4930b57cec5SDimitry Andric   if (BigSize > FileSize)
4940b57cec5SDimitry Andric     return malformedError("tocoff field plus ntoc field times sizeof(struct "
4950b57cec5SDimitry Andric                           "dylib_table_of_contents) of LC_DYSYMTAB command " +
4960b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
4970b57cec5SDimitry Andric                           "the file");
4980b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
4990b57cec5SDimitry Andric                                           Dysymtab.ntoc * sizeof(struct
5000b57cec5SDimitry Andric                                           MachO::dylib_table_of_contents),
5010b57cec5SDimitry Andric                                           "table of contents"))
5020b57cec5SDimitry Andric     return Err;
5030b57cec5SDimitry Andric   if (Dysymtab.modtaboff > FileSize)
5040b57cec5SDimitry Andric     return malformedError("modtaboff field of LC_DYSYMTAB command " +
5050b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5060b57cec5SDimitry Andric                           "the file");
5070b57cec5SDimitry Andric   BigSize = Dysymtab.nmodtab;
5080b57cec5SDimitry Andric   const char *struct_dylib_module_name;
5090b57cec5SDimitry Andric   uint64_t sizeof_modtab;
5100b57cec5SDimitry Andric   if (Obj.is64Bit()) {
5110b57cec5SDimitry Andric     sizeof_modtab = sizeof(MachO::dylib_module_64);
5120b57cec5SDimitry Andric     struct_dylib_module_name = "struct dylib_module_64";
5130b57cec5SDimitry Andric   } else {
5140b57cec5SDimitry Andric     sizeof_modtab = sizeof(MachO::dylib_module);
5150b57cec5SDimitry Andric     struct_dylib_module_name = "struct dylib_module";
5160b57cec5SDimitry Andric   }
5170b57cec5SDimitry Andric   BigSize *= sizeof_modtab;
5180b57cec5SDimitry Andric   BigSize += Dysymtab.modtaboff;
5190b57cec5SDimitry Andric   if (BigSize > FileSize)
5200b57cec5SDimitry Andric     return malformedError("modtaboff field plus nmodtab field times sizeof(" +
5210b57cec5SDimitry Andric                           Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
5220b57cec5SDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
5230b57cec5SDimitry Andric                           "past the end of the file");
5240b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
5250b57cec5SDimitry Andric                                           Dysymtab.nmodtab * sizeof_modtab,
5260b57cec5SDimitry Andric                                           "module table"))
5270b57cec5SDimitry Andric     return Err;
5280b57cec5SDimitry Andric   if (Dysymtab.extrefsymoff > FileSize)
5290b57cec5SDimitry Andric     return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
5300b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5310b57cec5SDimitry Andric                           "the file");
5320b57cec5SDimitry Andric   BigSize = Dysymtab.nextrefsyms;
5330b57cec5SDimitry Andric   BigSize *= sizeof(MachO::dylib_reference);
5340b57cec5SDimitry Andric   BigSize += Dysymtab.extrefsymoff;
5350b57cec5SDimitry Andric   if (BigSize > FileSize)
5360b57cec5SDimitry Andric     return malformedError("extrefsymoff field plus nextrefsyms field times "
5370b57cec5SDimitry Andric                           "sizeof(struct dylib_reference) of LC_DYSYMTAB "
5380b57cec5SDimitry Andric                           "command " + Twine(LoadCommandIndex) + " extends "
5390b57cec5SDimitry Andric                           "past the end of the file");
5400b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
5410b57cec5SDimitry Andric                                           Dysymtab.nextrefsyms *
5420b57cec5SDimitry Andric                                               sizeof(MachO::dylib_reference),
5430b57cec5SDimitry Andric                                           "reference table"))
5440b57cec5SDimitry Andric     return Err;
5450b57cec5SDimitry Andric   if (Dysymtab.indirectsymoff > FileSize)
5460b57cec5SDimitry Andric     return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
5470b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5480b57cec5SDimitry Andric                           "the file");
5490b57cec5SDimitry Andric   BigSize = Dysymtab.nindirectsyms;
5500b57cec5SDimitry Andric   BigSize *= sizeof(uint32_t);
5510b57cec5SDimitry Andric   BigSize += Dysymtab.indirectsymoff;
5520b57cec5SDimitry Andric   if (BigSize > FileSize)
5530b57cec5SDimitry Andric     return malformedError("indirectsymoff field plus nindirectsyms field times "
5540b57cec5SDimitry Andric                           "sizeof(uint32_t) of LC_DYSYMTAB command " +
5550b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5560b57cec5SDimitry Andric                           "the file");
5570b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
5580b57cec5SDimitry Andric                                           Dysymtab.nindirectsyms *
5590b57cec5SDimitry Andric                                           sizeof(uint32_t),
5600b57cec5SDimitry Andric                                           "indirect table"))
5610b57cec5SDimitry Andric     return Err;
5620b57cec5SDimitry Andric   if (Dysymtab.extreloff > FileSize)
5630b57cec5SDimitry Andric     return malformedError("extreloff field of LC_DYSYMTAB command " +
5640b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5650b57cec5SDimitry Andric                           "the file");
5660b57cec5SDimitry Andric   BigSize = Dysymtab.nextrel;
5670b57cec5SDimitry Andric   BigSize *= sizeof(MachO::relocation_info);
5680b57cec5SDimitry Andric   BigSize += Dysymtab.extreloff;
5690b57cec5SDimitry Andric   if (BigSize > FileSize)
5700b57cec5SDimitry Andric     return malformedError("extreloff field plus nextrel field times sizeof"
5710b57cec5SDimitry Andric                           "(struct relocation_info) of LC_DYSYMTAB command " +
5720b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5730b57cec5SDimitry Andric                           "the file");
5740b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
5750b57cec5SDimitry Andric                                           Dysymtab.nextrel *
5760b57cec5SDimitry Andric                                               sizeof(MachO::relocation_info),
5770b57cec5SDimitry Andric                                           "external relocation table"))
5780b57cec5SDimitry Andric     return Err;
5790b57cec5SDimitry Andric   if (Dysymtab.locreloff > FileSize)
5800b57cec5SDimitry Andric     return malformedError("locreloff field of LC_DYSYMTAB command " +
5810b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5820b57cec5SDimitry Andric                           "the file");
5830b57cec5SDimitry Andric   BigSize = Dysymtab.nlocrel;
5840b57cec5SDimitry Andric   BigSize *= sizeof(MachO::relocation_info);
5850b57cec5SDimitry Andric   BigSize += Dysymtab.locreloff;
5860b57cec5SDimitry Andric   if (BigSize > FileSize)
5870b57cec5SDimitry Andric     return malformedError("locreloff field plus nlocrel field times sizeof"
5880b57cec5SDimitry Andric                           "(struct relocation_info) of LC_DYSYMTAB command " +
5890b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
5900b57cec5SDimitry Andric                           "the file");
5910b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
5920b57cec5SDimitry Andric                                           Dysymtab.nlocrel *
5930b57cec5SDimitry Andric                                               sizeof(MachO::relocation_info),
5940b57cec5SDimitry Andric                                           "local relocation table"))
5950b57cec5SDimitry Andric     return Err;
5960b57cec5SDimitry Andric   *DysymtabLoadCmd = Load.Ptr;
5970b57cec5SDimitry Andric   return Error::success();
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
6010b57cec5SDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
6020b57cec5SDimitry Andric                                  uint32_t LoadCommandIndex,
6030b57cec5SDimitry Andric                                  const char **LoadCmd, const char *CmdName,
6040b57cec5SDimitry Andric                                  std::list<MachOElement> &Elements,
6050b57cec5SDimitry Andric                                  const char *ElementName) {
6060b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
6070b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
6080b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
6090b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
6100b57cec5SDimitry Andric     return malformedError("more than one " + Twine(CmdName) + " command");
6110b57cec5SDimitry Andric   auto LinkDataOrError =
6120b57cec5SDimitry Andric     getStructOrErr<MachO::linkedit_data_command>(Obj, Load.Ptr);
6130b57cec5SDimitry Andric   if (!LinkDataOrError)
6140b57cec5SDimitry Andric     return LinkDataOrError.takeError();
6150b57cec5SDimitry Andric   MachO::linkedit_data_command LinkData = LinkDataOrError.get();
6160b57cec5SDimitry Andric   if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
6170b57cec5SDimitry Andric     return malformedError(Twine(CmdName) + " command " +
6180b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " has incorrect cmdsize");
6190b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
6200b57cec5SDimitry Andric   if (LinkData.dataoff > FileSize)
6210b57cec5SDimitry Andric     return malformedError("dataoff field of " + Twine(CmdName) + " command " +
6220b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6230b57cec5SDimitry Andric                           "the file");
6240b57cec5SDimitry Andric   uint64_t BigSize = LinkData.dataoff;
6250b57cec5SDimitry Andric   BigSize += LinkData.datasize;
6260b57cec5SDimitry Andric   if (BigSize > FileSize)
6270b57cec5SDimitry Andric     return malformedError("dataoff field plus datasize field of " +
6280b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
6290b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6300b57cec5SDimitry Andric                           "the file");
6310b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
6320b57cec5SDimitry Andric                                           LinkData.datasize, ElementName))
6330b57cec5SDimitry Andric     return Err;
6340b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
6350b57cec5SDimitry Andric   return Error::success();
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
6390b57cec5SDimitry Andric                                   const MachOObjectFile::LoadCommandInfo &Load,
6400b57cec5SDimitry Andric                                   uint32_t LoadCommandIndex,
6410b57cec5SDimitry Andric                                   const char **LoadCmd, const char *CmdName,
6420b57cec5SDimitry Andric                                   std::list<MachOElement> &Elements) {
6430b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
6440b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
6450b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
6460b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
6470b57cec5SDimitry Andric     return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
6480b57cec5SDimitry Andric                           "command");
6490b57cec5SDimitry Andric   auto DyldInfoOrErr =
6500b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(Obj, Load.Ptr);
6510b57cec5SDimitry Andric   if (!DyldInfoOrErr)
6520b57cec5SDimitry Andric     return DyldInfoOrErr.takeError();
6530b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
6540b57cec5SDimitry Andric   if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
6550b57cec5SDimitry Andric     return malformedError(Twine(CmdName) + " command " +
6560b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " has incorrect cmdsize");
6570b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
6580b57cec5SDimitry Andric   if (DyldInfo.rebase_off > FileSize)
6590b57cec5SDimitry Andric     return malformedError("rebase_off field of " + Twine(CmdName) +
6600b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
6610b57cec5SDimitry Andric                           "past the end of the file");
6620b57cec5SDimitry Andric   uint64_t BigSize = DyldInfo.rebase_off;
6630b57cec5SDimitry Andric   BigSize += DyldInfo.rebase_size;
6640b57cec5SDimitry Andric   if (BigSize > FileSize)
6650b57cec5SDimitry Andric     return malformedError("rebase_off field plus rebase_size field of " +
6660b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
6670b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6680b57cec5SDimitry Andric                           "the file");
6690b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
6700b57cec5SDimitry Andric                                           DyldInfo.rebase_size,
6710b57cec5SDimitry Andric                                           "dyld rebase info"))
6720b57cec5SDimitry Andric     return Err;
6730b57cec5SDimitry Andric   if (DyldInfo.bind_off > FileSize)
6740b57cec5SDimitry Andric     return malformedError("bind_off field of " + Twine(CmdName) +
6750b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
6760b57cec5SDimitry Andric                           "past the end of the file");
6770b57cec5SDimitry Andric   BigSize = DyldInfo.bind_off;
6780b57cec5SDimitry Andric   BigSize += DyldInfo.bind_size;
6790b57cec5SDimitry Andric   if (BigSize > FileSize)
6800b57cec5SDimitry Andric     return malformedError("bind_off field plus bind_size field of " +
6810b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
6820b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6830b57cec5SDimitry Andric                           "the file");
6840b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
6850b57cec5SDimitry Andric                                           DyldInfo.bind_size,
6860b57cec5SDimitry Andric                                           "dyld bind info"))
6870b57cec5SDimitry Andric     return Err;
6880b57cec5SDimitry Andric   if (DyldInfo.weak_bind_off > FileSize)
6890b57cec5SDimitry Andric     return malformedError("weak_bind_off field of " + Twine(CmdName) +
6900b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
6910b57cec5SDimitry Andric                           "past the end of the file");
6920b57cec5SDimitry Andric   BigSize = DyldInfo.weak_bind_off;
6930b57cec5SDimitry Andric   BigSize += DyldInfo.weak_bind_size;
6940b57cec5SDimitry Andric   if (BigSize > FileSize)
6950b57cec5SDimitry Andric     return malformedError("weak_bind_off field plus weak_bind_size field of " +
6960b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
6970b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
6980b57cec5SDimitry Andric                           "the file");
6990b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
7000b57cec5SDimitry Andric                                           DyldInfo.weak_bind_size,
7010b57cec5SDimitry Andric                                           "dyld weak bind info"))
7020b57cec5SDimitry Andric     return Err;
7030b57cec5SDimitry Andric   if (DyldInfo.lazy_bind_off > FileSize)
7040b57cec5SDimitry Andric     return malformedError("lazy_bind_off field of " + Twine(CmdName) +
7050b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
7060b57cec5SDimitry Andric                           "past the end of the file");
7070b57cec5SDimitry Andric   BigSize = DyldInfo.lazy_bind_off;
7080b57cec5SDimitry Andric   BigSize += DyldInfo.lazy_bind_size;
7090b57cec5SDimitry Andric   if (BigSize > FileSize)
7100b57cec5SDimitry Andric     return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
7110b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
7120b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
7130b57cec5SDimitry Andric                           "the file");
7140b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
7150b57cec5SDimitry Andric                                           DyldInfo.lazy_bind_size,
7160b57cec5SDimitry Andric                                           "dyld lazy bind info"))
7170b57cec5SDimitry Andric     return Err;
7180b57cec5SDimitry Andric   if (DyldInfo.export_off > FileSize)
7190b57cec5SDimitry Andric     return malformedError("export_off field of " + Twine(CmdName) +
7200b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
7210b57cec5SDimitry Andric                           "past the end of the file");
7220b57cec5SDimitry Andric   BigSize = DyldInfo.export_off;
7230b57cec5SDimitry Andric   BigSize += DyldInfo.export_size;
7240b57cec5SDimitry Andric   if (BigSize > FileSize)
7250b57cec5SDimitry Andric     return malformedError("export_off field plus export_size field of " +
7260b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
7270b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
7280b57cec5SDimitry Andric                           "the file");
7290b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
7300b57cec5SDimitry Andric                                           DyldInfo.export_size,
7310b57cec5SDimitry Andric                                           "dyld export info"))
7320b57cec5SDimitry Andric     return Err;
7330b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
7340b57cec5SDimitry Andric   return Error::success();
7350b57cec5SDimitry Andric }
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric static Error checkDylibCommand(const MachOObjectFile &Obj,
7380b57cec5SDimitry Andric                                const MachOObjectFile::LoadCommandInfo &Load,
7390b57cec5SDimitry Andric                                uint32_t LoadCommandIndex, const char *CmdName) {
7400b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dylib_command))
7410b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7420b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
7430b57cec5SDimitry Andric   auto CommandOrErr = getStructOrErr<MachO::dylib_command>(Obj, Load.Ptr);
7440b57cec5SDimitry Andric   if (!CommandOrErr)
7450b57cec5SDimitry Andric     return CommandOrErr.takeError();
7460b57cec5SDimitry Andric   MachO::dylib_command D = CommandOrErr.get();
7470b57cec5SDimitry Andric   if (D.dylib.name < sizeof(MachO::dylib_command))
7480b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7490b57cec5SDimitry Andric                           CmdName + " name.offset field too small, not past "
7500b57cec5SDimitry Andric                           "the end of the dylib_command struct");
7510b57cec5SDimitry Andric   if (D.dylib.name >= D.cmdsize)
7520b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7530b57cec5SDimitry Andric                           CmdName + " name.offset field extends past the end "
7540b57cec5SDimitry Andric                           "of the load command");
7550b57cec5SDimitry Andric   // Make sure there is a null between the starting offset of the name and
7560b57cec5SDimitry Andric   // the end of the load command.
7570b57cec5SDimitry Andric   uint32_t i;
7580b57cec5SDimitry Andric   const char *P = (const char *)Load.Ptr;
7590b57cec5SDimitry Andric   for (i = D.dylib.name; i < D.cmdsize; i++)
7600b57cec5SDimitry Andric     if (P[i] == '\0')
7610b57cec5SDimitry Andric       break;
7620b57cec5SDimitry Andric   if (i >= D.cmdsize)
7630b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7640b57cec5SDimitry Andric                           CmdName + " library name extends past the end of the "
7650b57cec5SDimitry Andric                           "load command");
7660b57cec5SDimitry Andric   return Error::success();
7670b57cec5SDimitry Andric }
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric static Error checkDylibIdCommand(const MachOObjectFile &Obj,
7700b57cec5SDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
7710b57cec5SDimitry Andric                                  uint32_t LoadCommandIndex,
7720b57cec5SDimitry Andric                                  const char **LoadCmd) {
7730b57cec5SDimitry Andric   if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
7740b57cec5SDimitry Andric                                      "LC_ID_DYLIB"))
7750b57cec5SDimitry Andric     return Err;
7760b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
7770b57cec5SDimitry Andric     return malformedError("more than one LC_ID_DYLIB command");
7780b57cec5SDimitry Andric   if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
7790b57cec5SDimitry Andric       Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
7800b57cec5SDimitry Andric     return malformedError("LC_ID_DYLIB load command in non-dynamic library "
7810b57cec5SDimitry Andric                           "file type");
7820b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
7830b57cec5SDimitry Andric   return Error::success();
7840b57cec5SDimitry Andric }
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric static Error checkDyldCommand(const MachOObjectFile &Obj,
7870b57cec5SDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
7880b57cec5SDimitry Andric                               uint32_t LoadCommandIndex, const char *CmdName) {
7890b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
7900b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7910b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
7920b57cec5SDimitry Andric   auto CommandOrErr = getStructOrErr<MachO::dylinker_command>(Obj, Load.Ptr);
7930b57cec5SDimitry Andric   if (!CommandOrErr)
7940b57cec5SDimitry Andric     return CommandOrErr.takeError();
7950b57cec5SDimitry Andric   MachO::dylinker_command D = CommandOrErr.get();
7960b57cec5SDimitry Andric   if (D.name < sizeof(MachO::dylinker_command))
7970b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
7980b57cec5SDimitry Andric                           CmdName + " name.offset field too small, not past "
7990b57cec5SDimitry Andric                           "the end of the dylinker_command struct");
8000b57cec5SDimitry Andric   if (D.name >= D.cmdsize)
8010b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
8020b57cec5SDimitry Andric                           CmdName + " name.offset field extends past the end "
8030b57cec5SDimitry Andric                           "of the load command");
8040b57cec5SDimitry Andric   // Make sure there is a null between the starting offset of the name and
8050b57cec5SDimitry Andric   // the end of the load command.
8060b57cec5SDimitry Andric   uint32_t i;
8070b57cec5SDimitry Andric   const char *P = (const char *)Load.Ptr;
8080b57cec5SDimitry Andric   for (i = D.name; i < D.cmdsize; i++)
8090b57cec5SDimitry Andric     if (P[i] == '\0')
8100b57cec5SDimitry Andric       break;
8110b57cec5SDimitry Andric   if (i >= D.cmdsize)
8120b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
8130b57cec5SDimitry Andric                           CmdName + " dyld name extends past the end of the "
8140b57cec5SDimitry Andric                           "load command");
8150b57cec5SDimitry Andric   return Error::success();
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric static Error checkVersCommand(const MachOObjectFile &Obj,
8190b57cec5SDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
8200b57cec5SDimitry Andric                               uint32_t LoadCommandIndex,
8210b57cec5SDimitry Andric                               const char **LoadCmd, const char *CmdName) {
8220b57cec5SDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::version_min_command))
8230b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
8240b57cec5SDimitry Andric                           CmdName + " has incorrect cmdsize");
8250b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
8260b57cec5SDimitry Andric     return malformedError("more than one LC_VERSION_MIN_MACOSX, "
8270b57cec5SDimitry Andric                           "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
8280b57cec5SDimitry Andric                           "LC_VERSION_MIN_WATCHOS command");
8290b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
8300b57cec5SDimitry Andric   return Error::success();
8310b57cec5SDimitry Andric }
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric static Error checkNoteCommand(const MachOObjectFile &Obj,
8340b57cec5SDimitry Andric                               const MachOObjectFile::LoadCommandInfo &Load,
8350b57cec5SDimitry Andric                               uint32_t LoadCommandIndex,
8360b57cec5SDimitry Andric                               std::list<MachOElement> &Elements) {
8370b57cec5SDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::note_command))
8380b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8390b57cec5SDimitry Andric                           " LC_NOTE has incorrect cmdsize");
8400b57cec5SDimitry Andric   auto NoteCmdOrErr = getStructOrErr<MachO::note_command>(Obj, Load.Ptr);
8410b57cec5SDimitry Andric   if (!NoteCmdOrErr)
8420b57cec5SDimitry Andric     return NoteCmdOrErr.takeError();
8430b57cec5SDimitry Andric   MachO::note_command Nt = NoteCmdOrErr.get();
8440b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
8450b57cec5SDimitry Andric   if (Nt.offset > FileSize)
8460b57cec5SDimitry Andric     return malformedError("offset field of LC_NOTE command " +
8470b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends "
8480b57cec5SDimitry Andric                           "past the end of the file");
8490b57cec5SDimitry Andric   uint64_t BigSize = Nt.offset;
8500b57cec5SDimitry Andric   BigSize += Nt.size;
8510b57cec5SDimitry Andric   if (BigSize > FileSize)
8520b57cec5SDimitry Andric     return malformedError("size field plus offset field of LC_NOTE command " +
8530b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
8540b57cec5SDimitry Andric                           "the file");
8550b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
8560b57cec5SDimitry Andric                                           "LC_NOTE data"))
8570b57cec5SDimitry Andric     return Err;
8580b57cec5SDimitry Andric   return Error::success();
8590b57cec5SDimitry Andric }
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric static Error
8620b57cec5SDimitry Andric parseBuildVersionCommand(const MachOObjectFile &Obj,
8630b57cec5SDimitry Andric                          const MachOObjectFile::LoadCommandInfo &Load,
8640b57cec5SDimitry Andric                          SmallVectorImpl<const char*> &BuildTools,
8650b57cec5SDimitry Andric                          uint32_t LoadCommandIndex) {
8660b57cec5SDimitry Andric   auto BVCOrErr =
8670b57cec5SDimitry Andric     getStructOrErr<MachO::build_version_command>(Obj, Load.Ptr);
8680b57cec5SDimitry Andric   if (!BVCOrErr)
8690b57cec5SDimitry Andric     return BVCOrErr.takeError();
8700b57cec5SDimitry Andric   MachO::build_version_command BVC = BVCOrErr.get();
8710b57cec5SDimitry Andric   if (Load.C.cmdsize !=
8720b57cec5SDimitry Andric       sizeof(MachO::build_version_command) +
8730b57cec5SDimitry Andric           BVC.ntools * sizeof(MachO::build_tool_version))
8740b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8750b57cec5SDimitry Andric                           " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric   auto Start = Load.Ptr + sizeof(MachO::build_version_command);
8780b57cec5SDimitry Andric   BuildTools.resize(BVC.ntools);
8790b57cec5SDimitry Andric   for (unsigned i = 0; i < BVC.ntools; ++i)
8800b57cec5SDimitry Andric     BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric   return Error::success();
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric static Error checkRpathCommand(const MachOObjectFile &Obj,
8860b57cec5SDimitry Andric                                const MachOObjectFile::LoadCommandInfo &Load,
8870b57cec5SDimitry Andric                                uint32_t LoadCommandIndex) {
8880b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::rpath_command))
8890b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8900b57cec5SDimitry Andric                           " LC_RPATH cmdsize too small");
8910b57cec5SDimitry Andric   auto ROrErr = getStructOrErr<MachO::rpath_command>(Obj, Load.Ptr);
8920b57cec5SDimitry Andric   if (!ROrErr)
8930b57cec5SDimitry Andric     return ROrErr.takeError();
8940b57cec5SDimitry Andric   MachO::rpath_command R = ROrErr.get();
8950b57cec5SDimitry Andric   if (R.path < sizeof(MachO::rpath_command))
8960b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
8970b57cec5SDimitry Andric                           " LC_RPATH path.offset field too small, not past "
8980b57cec5SDimitry Andric                           "the end of the rpath_command struct");
8990b57cec5SDimitry Andric   if (R.path >= R.cmdsize)
9000b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
9010b57cec5SDimitry Andric                           " LC_RPATH path.offset field extends past the end "
9020b57cec5SDimitry Andric                           "of the load command");
9030b57cec5SDimitry Andric   // Make sure there is a null between the starting offset of the path and
9040b57cec5SDimitry Andric   // the end of the load command.
9050b57cec5SDimitry Andric   uint32_t i;
9060b57cec5SDimitry Andric   const char *P = (const char *)Load.Ptr;
9070b57cec5SDimitry Andric   for (i = R.path; i < R.cmdsize; i++)
9080b57cec5SDimitry Andric     if (P[i] == '\0')
9090b57cec5SDimitry Andric       break;
9100b57cec5SDimitry Andric   if (i >= R.cmdsize)
9110b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
9120b57cec5SDimitry Andric                           " LC_RPATH library name extends past the end of the "
9130b57cec5SDimitry Andric                           "load command");
9140b57cec5SDimitry Andric   return Error::success();
9150b57cec5SDimitry Andric }
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric static Error checkEncryptCommand(const MachOObjectFile &Obj,
9180b57cec5SDimitry Andric                                  const MachOObjectFile::LoadCommandInfo &Load,
9190b57cec5SDimitry Andric                                  uint32_t LoadCommandIndex,
9200b57cec5SDimitry Andric                                  uint64_t cryptoff, uint64_t cryptsize,
9210b57cec5SDimitry Andric                                  const char **LoadCmd, const char *CmdName) {
9220b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
9230b57cec5SDimitry Andric     return malformedError("more than one LC_ENCRYPTION_INFO and or "
9240b57cec5SDimitry Andric                           "LC_ENCRYPTION_INFO_64 command");
9250b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
9260b57cec5SDimitry Andric   if (cryptoff > FileSize)
9270b57cec5SDimitry Andric     return malformedError("cryptoff field of " + Twine(CmdName) +
9280b57cec5SDimitry Andric                           " command " + Twine(LoadCommandIndex) + " extends "
9290b57cec5SDimitry Andric                           "past the end of the file");
9300b57cec5SDimitry Andric   uint64_t BigSize = cryptoff;
9310b57cec5SDimitry Andric   BigSize += cryptsize;
9320b57cec5SDimitry Andric   if (BigSize > FileSize)
9330b57cec5SDimitry Andric     return malformedError("cryptoff field plus cryptsize field of " +
9340b57cec5SDimitry Andric                           Twine(CmdName) + " command " +
9350b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
9360b57cec5SDimitry Andric                           "the file");
9370b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
9380b57cec5SDimitry Andric   return Error::success();
9390b57cec5SDimitry Andric }
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
9420b57cec5SDimitry Andric                                    const MachOObjectFile::LoadCommandInfo &Load,
9430b57cec5SDimitry Andric                                    uint32_t LoadCommandIndex) {
9440b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
9450b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
9460b57cec5SDimitry Andric                           " LC_LINKER_OPTION cmdsize too small");
9470b57cec5SDimitry Andric   auto LinkOptionOrErr =
9480b57cec5SDimitry Andric     getStructOrErr<MachO::linker_option_command>(Obj, Load.Ptr);
9490b57cec5SDimitry Andric   if (!LinkOptionOrErr)
9500b57cec5SDimitry Andric     return LinkOptionOrErr.takeError();
9510b57cec5SDimitry Andric   MachO::linker_option_command L = LinkOptionOrErr.get();
9520b57cec5SDimitry Andric   // Make sure the count of strings is correct.
9530b57cec5SDimitry Andric   const char *string = (const char *)Load.Ptr +
9540b57cec5SDimitry Andric                        sizeof(struct MachO::linker_option_command);
9550b57cec5SDimitry Andric   uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
9560b57cec5SDimitry Andric   uint32_t i = 0;
9570b57cec5SDimitry Andric   while (left > 0) {
9580b57cec5SDimitry Andric     while (*string == '\0' && left > 0) {
9590b57cec5SDimitry Andric       string++;
9600b57cec5SDimitry Andric       left--;
9610b57cec5SDimitry Andric     }
9620b57cec5SDimitry Andric     if (left > 0) {
9630b57cec5SDimitry Andric       i++;
9640b57cec5SDimitry Andric       uint32_t NullPos = StringRef(string, left).find('\0');
9650b57cec5SDimitry Andric       if (0xffffffff == NullPos)
9660b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
9670b57cec5SDimitry Andric                               " LC_LINKER_OPTION string #" + Twine(i) +
9680b57cec5SDimitry Andric                               " is not NULL terminated");
9690b57cec5SDimitry Andric       uint32_t len = std::min(NullPos, left) + 1;
9700b57cec5SDimitry Andric       string += len;
9710b57cec5SDimitry Andric       left -= len;
9720b57cec5SDimitry Andric     }
9730b57cec5SDimitry Andric   }
9740b57cec5SDimitry Andric   if (L.count != i)
9750b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
9760b57cec5SDimitry Andric                           " LC_LINKER_OPTION string count " + Twine(L.count) +
9770b57cec5SDimitry Andric                           " does not match number of strings");
9780b57cec5SDimitry Andric   return Error::success();
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric static Error checkSubCommand(const MachOObjectFile &Obj,
9820b57cec5SDimitry Andric                              const MachOObjectFile::LoadCommandInfo &Load,
9830b57cec5SDimitry Andric                              uint32_t LoadCommandIndex, const char *CmdName,
9840b57cec5SDimitry Andric                              size_t SizeOfCmd, const char *CmdStructName,
9850b57cec5SDimitry Andric                              uint32_t PathOffset, const char *PathFieldName) {
9860b57cec5SDimitry Andric   if (PathOffset < SizeOfCmd)
9870b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
9880b57cec5SDimitry Andric                           CmdName + " " + PathFieldName + ".offset field too "
9890b57cec5SDimitry Andric                           "small, not past the end of the " + CmdStructName);
9900b57cec5SDimitry Andric   if (PathOffset >= Load.C.cmdsize)
9910b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
9920b57cec5SDimitry Andric                           CmdName + " " + PathFieldName + ".offset field "
9930b57cec5SDimitry Andric                           "extends past the end of the load command");
9940b57cec5SDimitry Andric   // Make sure there is a null between the starting offset of the path and
9950b57cec5SDimitry Andric   // the end of the load command.
9960b57cec5SDimitry Andric   uint32_t i;
9970b57cec5SDimitry Andric   const char *P = (const char *)Load.Ptr;
9980b57cec5SDimitry Andric   for (i = PathOffset; i < Load.C.cmdsize; i++)
9990b57cec5SDimitry Andric     if (P[i] == '\0')
10000b57cec5SDimitry Andric       break;
10010b57cec5SDimitry Andric   if (i >= Load.C.cmdsize)
10020b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
10030b57cec5SDimitry Andric                           CmdName + " " + PathFieldName + " name extends past "
10040b57cec5SDimitry Andric                           "the end of the load command");
10050b57cec5SDimitry Andric   return Error::success();
10060b57cec5SDimitry Andric }
10070b57cec5SDimitry Andric 
10080b57cec5SDimitry Andric static Error checkThreadCommand(const MachOObjectFile &Obj,
10090b57cec5SDimitry Andric                                 const MachOObjectFile::LoadCommandInfo &Load,
10100b57cec5SDimitry Andric                                 uint32_t LoadCommandIndex,
10110b57cec5SDimitry Andric                                 const char *CmdName) {
10120b57cec5SDimitry Andric   if (Load.C.cmdsize < sizeof(MachO::thread_command))
10130b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
10140b57cec5SDimitry Andric                           CmdName + " cmdsize too small");
10150b57cec5SDimitry Andric   auto ThreadCommandOrErr =
10160b57cec5SDimitry Andric     getStructOrErr<MachO::thread_command>(Obj, Load.Ptr);
10170b57cec5SDimitry Andric   if (!ThreadCommandOrErr)
10180b57cec5SDimitry Andric     return ThreadCommandOrErr.takeError();
10190b57cec5SDimitry Andric   MachO::thread_command T = ThreadCommandOrErr.get();
10200b57cec5SDimitry Andric   const char *state = Load.Ptr + sizeof(MachO::thread_command);
10210b57cec5SDimitry Andric   const char *end = Load.Ptr + T.cmdsize;
10220b57cec5SDimitry Andric   uint32_t nflavor = 0;
10230b57cec5SDimitry Andric   uint32_t cputype = getCPUType(Obj);
10240b57cec5SDimitry Andric   while (state < end) {
10250b57cec5SDimitry Andric     if(state + sizeof(uint32_t) > end)
10260b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
10270b57cec5SDimitry Andric                             "flavor in " + CmdName + " extends past end of "
10280b57cec5SDimitry Andric                             "command");
10290b57cec5SDimitry Andric     uint32_t flavor;
10300b57cec5SDimitry Andric     memcpy(&flavor, state, sizeof(uint32_t));
10310b57cec5SDimitry Andric     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
10320b57cec5SDimitry Andric       sys::swapByteOrder(flavor);
10330b57cec5SDimitry Andric     state += sizeof(uint32_t);
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric     if(state + sizeof(uint32_t) > end)
10360b57cec5SDimitry Andric       return malformedError("load command " + Twine(LoadCommandIndex) +
10370b57cec5SDimitry Andric                             " count in " + CmdName + " extends past end of "
10380b57cec5SDimitry Andric                             "command");
10390b57cec5SDimitry Andric     uint32_t count;
10400b57cec5SDimitry Andric     memcpy(&count, state, sizeof(uint32_t));
10410b57cec5SDimitry Andric     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
10420b57cec5SDimitry Andric       sys::swapByteOrder(count);
10430b57cec5SDimitry Andric     state += sizeof(uint32_t);
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric     if (cputype == MachO::CPU_TYPE_I386) {
10460b57cec5SDimitry Andric       if (flavor == MachO::x86_THREAD_STATE32) {
10470b57cec5SDimitry Andric         if (count != MachO::x86_THREAD_STATE32_COUNT)
10480b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10490b57cec5SDimitry Andric                                 " count not x86_THREAD_STATE32_COUNT for "
10500b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10510b57cec5SDimitry Andric                                 "a x86_THREAD_STATE32 flavor in " + CmdName +
10520b57cec5SDimitry Andric                                 " command");
10530b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_thread_state32_t) > end)
10540b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10550b57cec5SDimitry Andric                                 " x86_THREAD_STATE32 extends past end of "
10560b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
10570b57cec5SDimitry Andric         state += sizeof(MachO::x86_thread_state32_t);
10580b57cec5SDimitry Andric       } else {
10590b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
10600b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
10610b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
10620b57cec5SDimitry Andric                               CmdName + " command");
10630b57cec5SDimitry Andric       }
10640b57cec5SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_X86_64) {
10650b57cec5SDimitry Andric       if (flavor == MachO::x86_THREAD_STATE) {
10660b57cec5SDimitry Andric         if (count != MachO::x86_THREAD_STATE_COUNT)
10670b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10680b57cec5SDimitry Andric                                 " count not x86_THREAD_STATE_COUNT for "
10690b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10700b57cec5SDimitry Andric                                 "a x86_THREAD_STATE flavor in " + CmdName +
10710b57cec5SDimitry Andric                                 " command");
10720b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_thread_state_t) > end)
10730b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10740b57cec5SDimitry Andric                                 " x86_THREAD_STATE extends past end of "
10750b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
10760b57cec5SDimitry Andric         state += sizeof(MachO::x86_thread_state_t);
10770b57cec5SDimitry Andric       } else if (flavor == MachO::x86_FLOAT_STATE) {
10780b57cec5SDimitry Andric         if (count != MachO::x86_FLOAT_STATE_COUNT)
10790b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10800b57cec5SDimitry Andric                                 " count not x86_FLOAT_STATE_COUNT for "
10810b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10820b57cec5SDimitry Andric                                 "a x86_FLOAT_STATE flavor in " + CmdName +
10830b57cec5SDimitry Andric                                 " command");
10840b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_float_state_t) > end)
10850b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10860b57cec5SDimitry Andric                                 " x86_FLOAT_STATE extends past end of "
10870b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
10880b57cec5SDimitry Andric         state += sizeof(MachO::x86_float_state_t);
10890b57cec5SDimitry Andric       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
10900b57cec5SDimitry Andric         if (count != MachO::x86_EXCEPTION_STATE_COUNT)
10910b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10920b57cec5SDimitry Andric                                 " count not x86_EXCEPTION_STATE_COUNT for "
10930b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
10940b57cec5SDimitry Andric                                 "a x86_EXCEPTION_STATE flavor in " + CmdName +
10950b57cec5SDimitry Andric                                 " command");
10960b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_exception_state_t) > end)
10970b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
10980b57cec5SDimitry Andric                                 " x86_EXCEPTION_STATE extends past end of "
10990b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11000b57cec5SDimitry Andric         state += sizeof(MachO::x86_exception_state_t);
11010b57cec5SDimitry Andric       } else if (flavor == MachO::x86_THREAD_STATE64) {
11020b57cec5SDimitry Andric         if (count != MachO::x86_THREAD_STATE64_COUNT)
11030b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11040b57cec5SDimitry Andric                                 " count not x86_THREAD_STATE64_COUNT for "
11050b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11060b57cec5SDimitry Andric                                 "a x86_THREAD_STATE64 flavor in " + CmdName +
11070b57cec5SDimitry Andric                                 " command");
11080b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_thread_state64_t) > end)
11090b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11100b57cec5SDimitry Andric                                 " x86_THREAD_STATE64 extends past end of "
11110b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11120b57cec5SDimitry Andric         state += sizeof(MachO::x86_thread_state64_t);
11130b57cec5SDimitry Andric       } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
11140b57cec5SDimitry Andric         if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
11150b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11160b57cec5SDimitry Andric                                 " count not x86_EXCEPTION_STATE64_COUNT for "
11170b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11180b57cec5SDimitry Andric                                 "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
11190b57cec5SDimitry Andric                                 " command");
11200b57cec5SDimitry Andric         if (state + sizeof(MachO::x86_exception_state64_t) > end)
11210b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11220b57cec5SDimitry Andric                                 " x86_EXCEPTION_STATE64 extends past end of "
11230b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11240b57cec5SDimitry Andric         state += sizeof(MachO::x86_exception_state64_t);
11250b57cec5SDimitry Andric       } else {
11260b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
11270b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
11280b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
11290b57cec5SDimitry Andric                               CmdName + " command");
11300b57cec5SDimitry Andric       }
11310b57cec5SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_ARM) {
11320b57cec5SDimitry Andric       if (flavor == MachO::ARM_THREAD_STATE) {
11330b57cec5SDimitry Andric         if (count != MachO::ARM_THREAD_STATE_COUNT)
11340b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11350b57cec5SDimitry Andric                                 " count not ARM_THREAD_STATE_COUNT for "
11360b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11370b57cec5SDimitry Andric                                 "a ARM_THREAD_STATE flavor in " + CmdName +
11380b57cec5SDimitry Andric                                 " command");
11390b57cec5SDimitry Andric         if (state + sizeof(MachO::arm_thread_state32_t) > end)
11400b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11410b57cec5SDimitry Andric                                 " ARM_THREAD_STATE extends past end of "
11420b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11430b57cec5SDimitry Andric         state += sizeof(MachO::arm_thread_state32_t);
11440b57cec5SDimitry Andric       } else {
11450b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
11460b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
11470b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
11480b57cec5SDimitry Andric                               CmdName + " command");
11490b57cec5SDimitry Andric       }
11500b57cec5SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_ARM64 ||
11510b57cec5SDimitry Andric                cputype == MachO::CPU_TYPE_ARM64_32) {
11520b57cec5SDimitry Andric       if (flavor == MachO::ARM_THREAD_STATE64) {
11530b57cec5SDimitry Andric         if (count != MachO::ARM_THREAD_STATE64_COUNT)
11540b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11550b57cec5SDimitry Andric                                 " count not ARM_THREAD_STATE64_COUNT for "
11560b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11570b57cec5SDimitry Andric                                 "a ARM_THREAD_STATE64 flavor in " + CmdName +
11580b57cec5SDimitry Andric                                 " command");
11590b57cec5SDimitry Andric         if (state + sizeof(MachO::arm_thread_state64_t) > end)
11600b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11610b57cec5SDimitry Andric                                 " ARM_THREAD_STATE64 extends past end of "
11620b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11630b57cec5SDimitry Andric         state += sizeof(MachO::arm_thread_state64_t);
11640b57cec5SDimitry Andric       } else {
11650b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
11660b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
11670b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
11680b57cec5SDimitry Andric                               CmdName + " command");
11690b57cec5SDimitry Andric       }
11700b57cec5SDimitry Andric     } else if (cputype == MachO::CPU_TYPE_POWERPC) {
11710b57cec5SDimitry Andric       if (flavor == MachO::PPC_THREAD_STATE) {
11720b57cec5SDimitry Andric         if (count != MachO::PPC_THREAD_STATE_COUNT)
11730b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11740b57cec5SDimitry Andric                                 " count not PPC_THREAD_STATE_COUNT for "
11750b57cec5SDimitry Andric                                 "flavor number " + Twine(nflavor) + " which is "
11760b57cec5SDimitry Andric                                 "a PPC_THREAD_STATE flavor in " + CmdName +
11770b57cec5SDimitry Andric                                 " command");
11780b57cec5SDimitry Andric         if (state + sizeof(MachO::ppc_thread_state32_t) > end)
11790b57cec5SDimitry Andric           return malformedError("load command " + Twine(LoadCommandIndex) +
11800b57cec5SDimitry Andric                                 " PPC_THREAD_STATE extends past end of "
11810b57cec5SDimitry Andric                                 "command in " + CmdName + " command");
11820b57cec5SDimitry Andric         state += sizeof(MachO::ppc_thread_state32_t);
11830b57cec5SDimitry Andric       } else {
11840b57cec5SDimitry Andric         return malformedError("load command " + Twine(LoadCommandIndex) +
11850b57cec5SDimitry Andric                               " unknown flavor (" + Twine(flavor) + ") for "
11860b57cec5SDimitry Andric                               "flavor number " + Twine(nflavor) + " in " +
11870b57cec5SDimitry Andric                               CmdName + " command");
11880b57cec5SDimitry Andric       }
11890b57cec5SDimitry Andric     } else {
11900b57cec5SDimitry Andric       return malformedError("unknown cputype (" + Twine(cputype) + ") load "
11910b57cec5SDimitry Andric                             "command " + Twine(LoadCommandIndex) + " for " +
11920b57cec5SDimitry Andric                             CmdName + " command can't be checked");
11930b57cec5SDimitry Andric     }
11940b57cec5SDimitry Andric     nflavor++;
11950b57cec5SDimitry Andric   }
11960b57cec5SDimitry Andric   return Error::success();
11970b57cec5SDimitry Andric }
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
12000b57cec5SDimitry Andric                                        const MachOObjectFile::LoadCommandInfo
12010b57cec5SDimitry Andric                                          &Load,
12020b57cec5SDimitry Andric                                        uint32_t LoadCommandIndex,
12030b57cec5SDimitry Andric                                        const char **LoadCmd,
12040b57cec5SDimitry Andric                                        std::list<MachOElement> &Elements) {
12050b57cec5SDimitry Andric   if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
12060b57cec5SDimitry Andric     return malformedError("load command " + Twine(LoadCommandIndex) +
12070b57cec5SDimitry Andric                           " LC_TWOLEVEL_HINTS has incorrect cmdsize");
12080b57cec5SDimitry Andric   if (*LoadCmd != nullptr)
12090b57cec5SDimitry Andric     return malformedError("more than one LC_TWOLEVEL_HINTS command");
12100b57cec5SDimitry Andric   auto HintsOrErr = getStructOrErr<MachO::twolevel_hints_command>(Obj, Load.Ptr);
12110b57cec5SDimitry Andric   if(!HintsOrErr)
12120b57cec5SDimitry Andric     return HintsOrErr.takeError();
12130b57cec5SDimitry Andric   MachO::twolevel_hints_command Hints = HintsOrErr.get();
12140b57cec5SDimitry Andric   uint64_t FileSize = Obj.getData().size();
12150b57cec5SDimitry Andric   if (Hints.offset > FileSize)
12160b57cec5SDimitry Andric     return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
12170b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
12180b57cec5SDimitry Andric                           "the file");
12190b57cec5SDimitry Andric   uint64_t BigSize = Hints.nhints;
12200b57cec5SDimitry Andric   BigSize *= sizeof(MachO::twolevel_hint);
12210b57cec5SDimitry Andric   BigSize += Hints.offset;
12220b57cec5SDimitry Andric   if (BigSize > FileSize)
12230b57cec5SDimitry Andric     return malformedError("offset field plus nhints times sizeof(struct "
12240b57cec5SDimitry Andric                           "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
12250b57cec5SDimitry Andric                           Twine(LoadCommandIndex) + " extends past the end of "
12260b57cec5SDimitry Andric                           "the file");
12270b57cec5SDimitry Andric   if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
12280b57cec5SDimitry Andric                                           sizeof(MachO::twolevel_hint),
12290b57cec5SDimitry Andric                                           "two level hints"))
12300b57cec5SDimitry Andric     return Err;
12310b57cec5SDimitry Andric   *LoadCmd = Load.Ptr;
12320b57cec5SDimitry Andric   return Error::success();
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric 
12350b57cec5SDimitry Andric // Returns true if the libObject code does not support the load command and its
12360b57cec5SDimitry Andric // contents.  The cmd value it is treated as an unknown load command but with
12370b57cec5SDimitry Andric // an error message that says the cmd value is obsolete.
12380b57cec5SDimitry Andric static bool isLoadCommandObsolete(uint32_t cmd) {
12390b57cec5SDimitry Andric   if (cmd == MachO::LC_SYMSEG ||
12400b57cec5SDimitry Andric       cmd == MachO::LC_LOADFVMLIB ||
12410b57cec5SDimitry Andric       cmd == MachO::LC_IDFVMLIB ||
12420b57cec5SDimitry Andric       cmd == MachO::LC_IDENT ||
12430b57cec5SDimitry Andric       cmd == MachO::LC_FVMFILE ||
12440b57cec5SDimitry Andric       cmd == MachO::LC_PREPAGE ||
12450b57cec5SDimitry Andric       cmd == MachO::LC_PREBOUND_DYLIB ||
12460b57cec5SDimitry Andric       cmd == MachO::LC_TWOLEVEL_HINTS ||
12470b57cec5SDimitry Andric       cmd == MachO::LC_PREBIND_CKSUM)
12480b57cec5SDimitry Andric     return true;
12490b57cec5SDimitry Andric   return false;
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric Expected<std::unique_ptr<MachOObjectFile>>
12530b57cec5SDimitry Andric MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
12540b57cec5SDimitry Andric                         bool Is64Bits, uint32_t UniversalCputype,
12555f757f3fSDimitry Andric                         uint32_t UniversalIndex,
12565f757f3fSDimitry Andric                         size_t MachOFilesetEntryOffset) {
12570b57cec5SDimitry Andric   Error Err = Error::success();
12585f757f3fSDimitry Andric   std::unique_ptr<MachOObjectFile> Obj(new MachOObjectFile(
12595f757f3fSDimitry Andric       std::move(Object), IsLittleEndian, Is64Bits, Err, UniversalCputype,
12605f757f3fSDimitry Andric       UniversalIndex, MachOFilesetEntryOffset));
12610b57cec5SDimitry Andric   if (Err)
12620b57cec5SDimitry Andric     return std::move(Err);
12630b57cec5SDimitry Andric   return std::move(Obj);
12640b57cec5SDimitry Andric }
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
12670b57cec5SDimitry Andric                                  bool Is64bits, Error &Err,
12680b57cec5SDimitry Andric                                  uint32_t UniversalCputype,
12695f757f3fSDimitry Andric                                  uint32_t UniversalIndex,
12705f757f3fSDimitry Andric                                  size_t MachOFilesetEntryOffset)
12715f757f3fSDimitry Andric     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
12725f757f3fSDimitry Andric       MachOFilesetEntryOffset(MachOFilesetEntryOffset) {
12730b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
12740b57cec5SDimitry Andric   uint64_t SizeOfHeaders;
12750b57cec5SDimitry Andric   uint32_t cputype;
12760b57cec5SDimitry Andric   if (is64Bit()) {
12770b57cec5SDimitry Andric     parseHeader(*this, Header64, Err);
12780b57cec5SDimitry Andric     SizeOfHeaders = sizeof(MachO::mach_header_64);
12790b57cec5SDimitry Andric     cputype = Header64.cputype;
12800b57cec5SDimitry Andric   } else {
12810b57cec5SDimitry Andric     parseHeader(*this, Header, Err);
12820b57cec5SDimitry Andric     SizeOfHeaders = sizeof(MachO::mach_header);
12830b57cec5SDimitry Andric     cputype = Header.cputype;
12840b57cec5SDimitry Andric   }
12850b57cec5SDimitry Andric   if (Err)
12860b57cec5SDimitry Andric     return;
12870b57cec5SDimitry Andric   SizeOfHeaders += getHeader().sizeofcmds;
12880b57cec5SDimitry Andric   if (getData().data() + SizeOfHeaders > getData().end()) {
12890b57cec5SDimitry Andric     Err = malformedError("load commands extend past the end of the file");
12900b57cec5SDimitry Andric     return;
12910b57cec5SDimitry Andric   }
12920b57cec5SDimitry Andric   if (UniversalCputype != 0 && cputype != UniversalCputype) {
12930b57cec5SDimitry Andric     Err = malformedError("universal header architecture: " +
12940b57cec5SDimitry Andric                          Twine(UniversalIndex) + "'s cputype does not match "
12950b57cec5SDimitry Andric                          "object file's mach header");
12960b57cec5SDimitry Andric     return;
12970b57cec5SDimitry Andric   }
12980b57cec5SDimitry Andric   std::list<MachOElement> Elements;
12990b57cec5SDimitry Andric   Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
13000b57cec5SDimitry Andric 
13010b57cec5SDimitry Andric   uint32_t LoadCommandCount = getHeader().ncmds;
13020b57cec5SDimitry Andric   LoadCommandInfo Load;
13030b57cec5SDimitry Andric   if (LoadCommandCount != 0) {
13040b57cec5SDimitry Andric     if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
13050b57cec5SDimitry Andric       Load = *LoadOrErr;
13060b57cec5SDimitry Andric     else {
13070b57cec5SDimitry Andric       Err = LoadOrErr.takeError();
13080b57cec5SDimitry Andric       return;
13090b57cec5SDimitry Andric     }
13100b57cec5SDimitry Andric   }
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric   const char *DyldIdLoadCmd = nullptr;
13130b57cec5SDimitry Andric   const char *SplitInfoLoadCmd = nullptr;
13140b57cec5SDimitry Andric   const char *CodeSignDrsLoadCmd = nullptr;
13150b57cec5SDimitry Andric   const char *CodeSignLoadCmd = nullptr;
13160b57cec5SDimitry Andric   const char *VersLoadCmd = nullptr;
13170b57cec5SDimitry Andric   const char *SourceLoadCmd = nullptr;
13180b57cec5SDimitry Andric   const char *EntryPointLoadCmd = nullptr;
13190b57cec5SDimitry Andric   const char *EncryptLoadCmd = nullptr;
13200b57cec5SDimitry Andric   const char *RoutinesLoadCmd = nullptr;
13210b57cec5SDimitry Andric   const char *UnixThreadLoadCmd = nullptr;
13220b57cec5SDimitry Andric   const char *TwoLevelHintsLoadCmd = nullptr;
13230b57cec5SDimitry Andric   for (unsigned I = 0; I < LoadCommandCount; ++I) {
13240b57cec5SDimitry Andric     if (is64Bit()) {
13250b57cec5SDimitry Andric       if (Load.C.cmdsize % 8 != 0) {
13260b57cec5SDimitry Andric         // We have a hack here to allow 64-bit Mach-O core files to have
13270b57cec5SDimitry Andric         // LC_THREAD commands that are only a multiple of 4 and not 8 to be
13280b57cec5SDimitry Andric         // allowed since the macOS kernel produces them.
13290b57cec5SDimitry Andric         if (getHeader().filetype != MachO::MH_CORE ||
13300b57cec5SDimitry Andric             Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
13310b57cec5SDimitry Andric           Err = malformedError("load command " + Twine(I) + " cmdsize not a "
13320b57cec5SDimitry Andric                                "multiple of 8");
13330b57cec5SDimitry Andric           return;
13340b57cec5SDimitry Andric         }
13350b57cec5SDimitry Andric       }
13360b57cec5SDimitry Andric     } else {
13370b57cec5SDimitry Andric       if (Load.C.cmdsize % 4 != 0) {
13380b57cec5SDimitry Andric         Err = malformedError("load command " + Twine(I) + " cmdsize not a "
13390b57cec5SDimitry Andric                              "multiple of 4");
13400b57cec5SDimitry Andric         return;
13410b57cec5SDimitry Andric       }
13420b57cec5SDimitry Andric     }
13430b57cec5SDimitry Andric     LoadCommands.push_back(Load);
13440b57cec5SDimitry Andric     if (Load.C.cmd == MachO::LC_SYMTAB) {
13450b57cec5SDimitry Andric       if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
13460b57cec5SDimitry Andric         return;
13470b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
13480b57cec5SDimitry Andric       if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
13490b57cec5SDimitry Andric                                       Elements)))
13500b57cec5SDimitry Andric         return;
13510b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
13520b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
13530b57cec5SDimitry Andric                                           "LC_DATA_IN_CODE", Elements,
13540b57cec5SDimitry Andric                                           "data in code info")))
13550b57cec5SDimitry Andric         return;
13560b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
13570b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
13580b57cec5SDimitry Andric                                           "LC_LINKER_OPTIMIZATION_HINT",
13590b57cec5SDimitry Andric                                           Elements, "linker optimization "
13600b57cec5SDimitry Andric                                           "hints")))
13610b57cec5SDimitry Andric         return;
13620b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
13630b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
13640b57cec5SDimitry Andric                                           "LC_FUNCTION_STARTS", Elements,
13650b57cec5SDimitry Andric                                           "function starts data")))
13660b57cec5SDimitry Andric         return;
13670b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
13680b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
13690b57cec5SDimitry Andric                                           "LC_SEGMENT_SPLIT_INFO", Elements,
13700b57cec5SDimitry Andric                                           "split info data")))
13710b57cec5SDimitry Andric         return;
13720b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
13730b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
13740b57cec5SDimitry Andric                                           "LC_DYLIB_CODE_SIGN_DRS", Elements,
13750b57cec5SDimitry Andric                                           "code signing RDs data")))
13760b57cec5SDimitry Andric         return;
13770b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
13780b57cec5SDimitry Andric       if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
13790b57cec5SDimitry Andric                                           "LC_CODE_SIGNATURE", Elements,
13800b57cec5SDimitry Andric                                           "code signature data")))
13810b57cec5SDimitry Andric         return;
13820b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
13830b57cec5SDimitry Andric       if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
13840b57cec5SDimitry Andric                                       "LC_DYLD_INFO", Elements)))
13850b57cec5SDimitry Andric         return;
13860b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
13870b57cec5SDimitry Andric       if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
13880b57cec5SDimitry Andric                                       "LC_DYLD_INFO_ONLY", Elements)))
13890b57cec5SDimitry Andric         return;
139081ad6265SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) {
139181ad6265SDimitry Andric       if ((Err = checkLinkeditDataCommand(
139281ad6265SDimitry Andric                *this, Load, I, &DyldChainedFixupsLoadCmd,
139381ad6265SDimitry Andric                "LC_DYLD_CHAINED_FIXUPS", Elements, "chained fixups")))
139481ad6265SDimitry Andric         return;
1395bdd1243dSDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE) {
1396bdd1243dSDimitry Andric       if ((Err = checkLinkeditDataCommand(
1397bdd1243dSDimitry Andric                *this, Load, I, &DyldExportsTrieLoadCmd, "LC_DYLD_EXPORTS_TRIE",
1398bdd1243dSDimitry Andric                Elements, "exports trie")))
1399bdd1243dSDimitry Andric         return;
14000b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_UUID) {
14010b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
14020b57cec5SDimitry Andric         Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
14030b57cec5SDimitry Andric                              "cmdsize");
14040b57cec5SDimitry Andric         return;
14050b57cec5SDimitry Andric       }
14060b57cec5SDimitry Andric       if (UuidLoadCmd) {
14070b57cec5SDimitry Andric         Err = malformedError("more than one LC_UUID command");
14080b57cec5SDimitry Andric         return;
14090b57cec5SDimitry Andric       }
14100b57cec5SDimitry Andric       UuidLoadCmd = Load.Ptr;
14110b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
14120b57cec5SDimitry Andric       if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
14130b57cec5SDimitry Andric                                          MachO::section_64>(
14140b57cec5SDimitry Andric                    *this, Load, Sections, HasPageZeroSegment, I,
14150b57cec5SDimitry Andric                    "LC_SEGMENT_64", SizeOfHeaders, Elements)))
14160b57cec5SDimitry Andric         return;
14170b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
14180b57cec5SDimitry Andric       if ((Err = parseSegmentLoadCommand<MachO::segment_command,
14190b57cec5SDimitry Andric                                          MachO::section>(
14200b57cec5SDimitry Andric                    *this, Load, Sections, HasPageZeroSegment, I,
14210b57cec5SDimitry Andric                    "LC_SEGMENT", SizeOfHeaders, Elements)))
14220b57cec5SDimitry Andric         return;
14230b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
14240b57cec5SDimitry Andric       if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
14250b57cec5SDimitry Andric         return;
14260b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
14270b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
14280b57cec5SDimitry Andric         return;
14290b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14300b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
14310b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
14320b57cec5SDimitry Andric         return;
14330b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14340b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
14350b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
14360b57cec5SDimitry Andric         return;
14370b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14380b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
14390b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
14400b57cec5SDimitry Andric         return;
14410b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14420b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
14430b57cec5SDimitry Andric       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
14440b57cec5SDimitry Andric         return;
14450b57cec5SDimitry Andric       Libraries.push_back(Load.Ptr);
14460b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
14470b57cec5SDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
14480b57cec5SDimitry Andric         return;
14490b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
14500b57cec5SDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
14510b57cec5SDimitry Andric         return;
14520b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
14530b57cec5SDimitry Andric       if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
14540b57cec5SDimitry Andric         return;
14550b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
14560b57cec5SDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
14570b57cec5SDimitry Andric                                   "LC_VERSION_MIN_MACOSX")))
14580b57cec5SDimitry Andric         return;
14590b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
14600b57cec5SDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
14610b57cec5SDimitry Andric                                   "LC_VERSION_MIN_IPHONEOS")))
14620b57cec5SDimitry Andric         return;
14630b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
14640b57cec5SDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
14650b57cec5SDimitry Andric                                   "LC_VERSION_MIN_TVOS")))
14660b57cec5SDimitry Andric         return;
14670b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
14680b57cec5SDimitry Andric       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
14690b57cec5SDimitry Andric                                   "LC_VERSION_MIN_WATCHOS")))
14700b57cec5SDimitry Andric         return;
14710b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_NOTE) {
14720b57cec5SDimitry Andric       if ((Err = checkNoteCommand(*this, Load, I, Elements)))
14730b57cec5SDimitry Andric         return;
14740b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
14750b57cec5SDimitry Andric       if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
14760b57cec5SDimitry Andric         return;
14770b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_RPATH) {
14780b57cec5SDimitry Andric       if ((Err = checkRpathCommand(*this, Load, I)))
14790b57cec5SDimitry Andric         return;
14800b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
14810b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
14820b57cec5SDimitry Andric         Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
14830b57cec5SDimitry Andric                              " has incorrect cmdsize");
14840b57cec5SDimitry Andric         return;
14850b57cec5SDimitry Andric       }
14860b57cec5SDimitry Andric       if (SourceLoadCmd) {
14870b57cec5SDimitry Andric         Err = malformedError("more than one LC_SOURCE_VERSION command");
14880b57cec5SDimitry Andric         return;
14890b57cec5SDimitry Andric       }
14900b57cec5SDimitry Andric       SourceLoadCmd = Load.Ptr;
14910b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_MAIN) {
14920b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
14930b57cec5SDimitry Andric         Err = malformedError("LC_MAIN command " + Twine(I) +
14940b57cec5SDimitry Andric                              " has incorrect cmdsize");
14950b57cec5SDimitry Andric         return;
14960b57cec5SDimitry Andric       }
14970b57cec5SDimitry Andric       if (EntryPointLoadCmd) {
14980b57cec5SDimitry Andric         Err = malformedError("more than one LC_MAIN command");
14990b57cec5SDimitry Andric         return;
15000b57cec5SDimitry Andric       }
15010b57cec5SDimitry Andric       EntryPointLoadCmd = Load.Ptr;
15020b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
15030b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
15040b57cec5SDimitry Andric         Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
15050b57cec5SDimitry Andric                              " has incorrect cmdsize");
15060b57cec5SDimitry Andric         return;
15070b57cec5SDimitry Andric       }
15080b57cec5SDimitry Andric       MachO::encryption_info_command E =
15090b57cec5SDimitry Andric         getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
15100b57cec5SDimitry Andric       if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
15110b57cec5SDimitry Andric                                      &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
15120b57cec5SDimitry Andric         return;
15130b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
15140b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
15150b57cec5SDimitry Andric         Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
15160b57cec5SDimitry Andric                              " has incorrect cmdsize");
15170b57cec5SDimitry Andric         return;
15180b57cec5SDimitry Andric       }
15190b57cec5SDimitry Andric       MachO::encryption_info_command_64 E =
15200b57cec5SDimitry Andric         getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
15210b57cec5SDimitry Andric       if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
15220b57cec5SDimitry Andric                                      &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
15230b57cec5SDimitry Andric         return;
15240b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
15250b57cec5SDimitry Andric       if ((Err = checkLinkerOptCommand(*this, Load, I)))
15260b57cec5SDimitry Andric         return;
15270b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
15280b57cec5SDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
15290b57cec5SDimitry Andric         Err =  malformedError("load command " + Twine(I) +
15300b57cec5SDimitry Andric                               " LC_SUB_FRAMEWORK cmdsize too small");
15310b57cec5SDimitry Andric         return;
15320b57cec5SDimitry Andric       }
15330b57cec5SDimitry Andric       MachO::sub_framework_command S =
15340b57cec5SDimitry Andric         getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
15350b57cec5SDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
15360b57cec5SDimitry Andric                                  sizeof(MachO::sub_framework_command),
15370b57cec5SDimitry Andric                                  "sub_framework_command", S.umbrella,
15380b57cec5SDimitry Andric                                  "umbrella")))
15390b57cec5SDimitry Andric         return;
15400b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
15410b57cec5SDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
15420b57cec5SDimitry Andric         Err =  malformedError("load command " + Twine(I) +
15430b57cec5SDimitry Andric                               " LC_SUB_UMBRELLA cmdsize too small");
15440b57cec5SDimitry Andric         return;
15450b57cec5SDimitry Andric       }
15460b57cec5SDimitry Andric       MachO::sub_umbrella_command S =
15470b57cec5SDimitry Andric         getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
15480b57cec5SDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
15490b57cec5SDimitry Andric                                  sizeof(MachO::sub_umbrella_command),
15500b57cec5SDimitry Andric                                  "sub_umbrella_command", S.sub_umbrella,
15510b57cec5SDimitry Andric                                  "sub_umbrella")))
15520b57cec5SDimitry Andric         return;
15530b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
15540b57cec5SDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
15550b57cec5SDimitry Andric         Err =  malformedError("load command " + Twine(I) +
15560b57cec5SDimitry Andric                               " LC_SUB_LIBRARY cmdsize too small");
15570b57cec5SDimitry Andric         return;
15580b57cec5SDimitry Andric       }
15590b57cec5SDimitry Andric       MachO::sub_library_command S =
15600b57cec5SDimitry Andric         getStruct<MachO::sub_library_command>(*this, Load.Ptr);
15610b57cec5SDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
15620b57cec5SDimitry Andric                                  sizeof(MachO::sub_library_command),
15630b57cec5SDimitry Andric                                  "sub_library_command", S.sub_library,
15640b57cec5SDimitry Andric                                  "sub_library")))
15650b57cec5SDimitry Andric         return;
15660b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
15670b57cec5SDimitry Andric       if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
15680b57cec5SDimitry Andric         Err =  malformedError("load command " + Twine(I) +
15690b57cec5SDimitry Andric                               " LC_SUB_CLIENT cmdsize too small");
15700b57cec5SDimitry Andric         return;
15710b57cec5SDimitry Andric       }
15720b57cec5SDimitry Andric       MachO::sub_client_command S =
15730b57cec5SDimitry Andric         getStruct<MachO::sub_client_command>(*this, Load.Ptr);
15740b57cec5SDimitry Andric       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
15750b57cec5SDimitry Andric                                  sizeof(MachO::sub_client_command),
15760b57cec5SDimitry Andric                                  "sub_client_command", S.client, "client")))
15770b57cec5SDimitry Andric         return;
15780b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ROUTINES) {
15790b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
15800b57cec5SDimitry Andric         Err = malformedError("LC_ROUTINES command " + Twine(I) +
15810b57cec5SDimitry Andric                              " has incorrect cmdsize");
15820b57cec5SDimitry Andric         return;
15830b57cec5SDimitry Andric       }
15840b57cec5SDimitry Andric       if (RoutinesLoadCmd) {
15850b57cec5SDimitry Andric         Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
15860b57cec5SDimitry Andric                              "command");
15870b57cec5SDimitry Andric         return;
15880b57cec5SDimitry Andric       }
15890b57cec5SDimitry Andric       RoutinesLoadCmd = Load.Ptr;
15900b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
15910b57cec5SDimitry Andric       if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
15920b57cec5SDimitry Andric         Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
15930b57cec5SDimitry Andric                              " has incorrect cmdsize");
15940b57cec5SDimitry Andric         return;
15950b57cec5SDimitry Andric       }
15960b57cec5SDimitry Andric       if (RoutinesLoadCmd) {
15970b57cec5SDimitry Andric         Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
15980b57cec5SDimitry Andric                              "command");
15990b57cec5SDimitry Andric         return;
16000b57cec5SDimitry Andric       }
16010b57cec5SDimitry Andric       RoutinesLoadCmd = Load.Ptr;
16020b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
16030b57cec5SDimitry Andric       if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
16040b57cec5SDimitry Andric         return;
16050b57cec5SDimitry Andric       if (UnixThreadLoadCmd) {
16060b57cec5SDimitry Andric         Err = malformedError("more than one LC_UNIXTHREAD command");
16070b57cec5SDimitry Andric         return;
16080b57cec5SDimitry Andric       }
16090b57cec5SDimitry Andric       UnixThreadLoadCmd = Load.Ptr;
16100b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_THREAD) {
16110b57cec5SDimitry Andric       if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
16120b57cec5SDimitry Andric         return;
16130b57cec5SDimitry Andric     // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
16140b57cec5SDimitry Andric     } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
16150b57cec5SDimitry Andric       if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
16160b57cec5SDimitry Andric                                            &TwoLevelHintsLoadCmd, Elements)))
16170b57cec5SDimitry Andric         return;
1618e8d8bef9SDimitry Andric     } else if (Load.C.cmd == MachO::LC_IDENT) {
1619e8d8bef9SDimitry Andric       // Note: LC_IDENT is ignored.
1620e8d8bef9SDimitry Andric       continue;
16210b57cec5SDimitry Andric     } else if (isLoadCommandObsolete(Load.C.cmd)) {
16220b57cec5SDimitry Andric       Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
16230b57cec5SDimitry Andric                            Twine(Load.C.cmd) + " is obsolete and not "
16240b57cec5SDimitry Andric                            "supported");
16250b57cec5SDimitry Andric       return;
16260b57cec5SDimitry Andric     }
16270b57cec5SDimitry Andric     // TODO: generate a error for unknown load commands by default.  But still
16280b57cec5SDimitry Andric     // need work out an approach to allow or not allow unknown values like this
16290b57cec5SDimitry Andric     // as an option for some uses like lldb.
16300b57cec5SDimitry Andric     if (I < LoadCommandCount - 1) {
16310b57cec5SDimitry Andric       if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
16320b57cec5SDimitry Andric         Load = *LoadOrErr;
16330b57cec5SDimitry Andric       else {
16340b57cec5SDimitry Andric         Err = LoadOrErr.takeError();
16350b57cec5SDimitry Andric         return;
16360b57cec5SDimitry Andric       }
16370b57cec5SDimitry Andric     }
16380b57cec5SDimitry Andric   }
16390b57cec5SDimitry Andric   if (!SymtabLoadCmd) {
16400b57cec5SDimitry Andric     if (DysymtabLoadCmd) {
16410b57cec5SDimitry Andric       Err = malformedError("contains LC_DYSYMTAB load command without a "
16420b57cec5SDimitry Andric                            "LC_SYMTAB load command");
16430b57cec5SDimitry Andric       return;
16440b57cec5SDimitry Andric     }
16450b57cec5SDimitry Andric   } else if (DysymtabLoadCmd) {
16460b57cec5SDimitry Andric     MachO::symtab_command Symtab =
16470b57cec5SDimitry Andric       getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
16480b57cec5SDimitry Andric     MachO::dysymtab_command Dysymtab =
16490b57cec5SDimitry Andric       getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
16500b57cec5SDimitry Andric     if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
16510b57cec5SDimitry Andric       Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
16520b57cec5SDimitry Andric                            "extends past the end of the symbol table");
16530b57cec5SDimitry Andric       return;
16540b57cec5SDimitry Andric     }
16550b57cec5SDimitry Andric     uint64_t BigSize = Dysymtab.ilocalsym;
16560b57cec5SDimitry Andric     BigSize += Dysymtab.nlocalsym;
16570b57cec5SDimitry Andric     if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
16580b57cec5SDimitry Andric       Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
16590b57cec5SDimitry Andric                            "command extends past the end of the symbol table");
16600b57cec5SDimitry Andric       return;
16610b57cec5SDimitry Andric     }
16620b57cec5SDimitry Andric     if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
16630b57cec5SDimitry Andric       Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
16640b57cec5SDimitry Andric                            "extends past the end of the symbol table");
16650b57cec5SDimitry Andric       return;
16660b57cec5SDimitry Andric     }
16670b57cec5SDimitry Andric     BigSize = Dysymtab.iextdefsym;
16680b57cec5SDimitry Andric     BigSize += Dysymtab.nextdefsym;
16690b57cec5SDimitry Andric     if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
16700b57cec5SDimitry Andric       Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
16710b57cec5SDimitry Andric                            "load command extends past the end of the symbol "
16720b57cec5SDimitry Andric                            "table");
16730b57cec5SDimitry Andric       return;
16740b57cec5SDimitry Andric     }
16750b57cec5SDimitry Andric     if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
16760b57cec5SDimitry Andric       Err = malformedError("iundefsym in LC_DYSYMTAB load command "
16770b57cec5SDimitry Andric                            "extends past the end of the symbol table");
16780b57cec5SDimitry Andric       return;
16790b57cec5SDimitry Andric     }
16800b57cec5SDimitry Andric     BigSize = Dysymtab.iundefsym;
16810b57cec5SDimitry Andric     BigSize += Dysymtab.nundefsym;
16820b57cec5SDimitry Andric     if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
16830b57cec5SDimitry Andric       Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
16840b57cec5SDimitry Andric                            " command extends past the end of the symbol table");
16850b57cec5SDimitry Andric       return;
16860b57cec5SDimitry Andric     }
16870b57cec5SDimitry Andric   }
16880b57cec5SDimitry Andric   if ((getHeader().filetype == MachO::MH_DYLIB ||
16890b57cec5SDimitry Andric        getHeader().filetype == MachO::MH_DYLIB_STUB) &&
16900b57cec5SDimitry Andric        DyldIdLoadCmd == nullptr) {
16910b57cec5SDimitry Andric     Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
16920b57cec5SDimitry Andric                          "filetype");
16930b57cec5SDimitry Andric     return;
16940b57cec5SDimitry Andric   }
16950b57cec5SDimitry Andric   assert(LoadCommands.size() == LoadCommandCount);
16960b57cec5SDimitry Andric 
16970b57cec5SDimitry Andric   Err = Error::success();
16980b57cec5SDimitry Andric }
16990b57cec5SDimitry Andric 
17000b57cec5SDimitry Andric Error MachOObjectFile::checkSymbolTable() const {
17010b57cec5SDimitry Andric   uint32_t Flags = 0;
17020b57cec5SDimitry Andric   if (is64Bit()) {
17030b57cec5SDimitry Andric     MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
17040b57cec5SDimitry Andric     Flags = H_64.flags;
17050b57cec5SDimitry Andric   } else {
17060b57cec5SDimitry Andric     MachO::mach_header H = MachOObjectFile::getHeader();
17070b57cec5SDimitry Andric     Flags = H.flags;
17080b57cec5SDimitry Andric   }
17090b57cec5SDimitry Andric   uint8_t NType = 0;
17100b57cec5SDimitry Andric   uint8_t NSect = 0;
17110b57cec5SDimitry Andric   uint16_t NDesc = 0;
17120b57cec5SDimitry Andric   uint32_t NStrx = 0;
17130b57cec5SDimitry Andric   uint64_t NValue = 0;
17140b57cec5SDimitry Andric   uint32_t SymbolIndex = 0;
17150b57cec5SDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
17160b57cec5SDimitry Andric   for (const SymbolRef &Symbol : symbols()) {
17170b57cec5SDimitry Andric     DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
17180b57cec5SDimitry Andric     if (is64Bit()) {
17190b57cec5SDimitry Andric       MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
17200b57cec5SDimitry Andric       NType = STE_64.n_type;
17210b57cec5SDimitry Andric       NSect = STE_64.n_sect;
17220b57cec5SDimitry Andric       NDesc = STE_64.n_desc;
17230b57cec5SDimitry Andric       NStrx = STE_64.n_strx;
17240b57cec5SDimitry Andric       NValue = STE_64.n_value;
17250b57cec5SDimitry Andric     } else {
17260b57cec5SDimitry Andric       MachO::nlist STE = getSymbolTableEntry(SymDRI);
17270b57cec5SDimitry Andric       NType = STE.n_type;
17280b57cec5SDimitry Andric       NSect = STE.n_sect;
17290b57cec5SDimitry Andric       NDesc = STE.n_desc;
17300b57cec5SDimitry Andric       NStrx = STE.n_strx;
17310b57cec5SDimitry Andric       NValue = STE.n_value;
17320b57cec5SDimitry Andric     }
17330b57cec5SDimitry Andric     if ((NType & MachO::N_STAB) == 0) {
17340b57cec5SDimitry Andric       if ((NType & MachO::N_TYPE) == MachO::N_SECT) {
17350b57cec5SDimitry Andric         if (NSect == 0 || NSect > Sections.size())
17360b57cec5SDimitry Andric           return malformedError("bad section index: " + Twine((int)NSect) +
17370b57cec5SDimitry Andric                                 " for symbol at index " + Twine(SymbolIndex));
17380b57cec5SDimitry Andric       }
17390b57cec5SDimitry Andric       if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
17400b57cec5SDimitry Andric         if (NValue >= S.strsize)
17410b57cec5SDimitry Andric           return malformedError("bad n_value: " + Twine((int)NValue) + " past "
17420b57cec5SDimitry Andric                                 "the end of string table, for N_INDR symbol at "
17430b57cec5SDimitry Andric                                 "index " + Twine(SymbolIndex));
17440b57cec5SDimitry Andric       }
17450b57cec5SDimitry Andric       if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
17460b57cec5SDimitry Andric           (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
17470b57cec5SDimitry Andric            (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
17480b57cec5SDimitry Andric             uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
17490b57cec5SDimitry Andric             if (LibraryOrdinal != 0 &&
17500b57cec5SDimitry Andric                 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
17510b57cec5SDimitry Andric                 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
17520b57cec5SDimitry Andric                 LibraryOrdinal - 1 >= Libraries.size() ) {
17530b57cec5SDimitry Andric               return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
17540b57cec5SDimitry Andric                                     " for symbol at index " + Twine(SymbolIndex));
17550b57cec5SDimitry Andric             }
17560b57cec5SDimitry Andric           }
17570b57cec5SDimitry Andric     }
17580b57cec5SDimitry Andric     if (NStrx >= S.strsize)
17590b57cec5SDimitry Andric       return malformedError("bad string table index: " + Twine((int)NStrx) +
17600b57cec5SDimitry Andric                             " past the end of string table, for symbol at "
17610b57cec5SDimitry Andric                             "index " + Twine(SymbolIndex));
17620b57cec5SDimitry Andric     SymbolIndex++;
17630b57cec5SDimitry Andric   }
17640b57cec5SDimitry Andric   return Error::success();
17650b57cec5SDimitry Andric }
17660b57cec5SDimitry Andric 
17670b57cec5SDimitry Andric void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
17680b57cec5SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
17690b57cec5SDimitry Andric     sizeof(MachO::nlist_64) :
17700b57cec5SDimitry Andric     sizeof(MachO::nlist);
17710b57cec5SDimitry Andric   Symb.p += SymbolTableEntrySize;
17720b57cec5SDimitry Andric }
17730b57cec5SDimitry Andric 
17740b57cec5SDimitry Andric Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
17750b57cec5SDimitry Andric   StringRef StringTable = getStringTableData();
17760b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
17770b57cec5SDimitry Andric   if (Entry.n_strx == 0)
17780b57cec5SDimitry Andric     // A n_strx value of 0 indicates that no name is associated with a
17790b57cec5SDimitry Andric     // particular symbol table entry.
17800b57cec5SDimitry Andric     return StringRef();
17810b57cec5SDimitry Andric   const char *Start = &StringTable.data()[Entry.n_strx];
17820b57cec5SDimitry Andric   if (Start < getData().begin() || Start >= getData().end()) {
17830b57cec5SDimitry Andric     return malformedError("bad string index: " + Twine(Entry.n_strx) +
17840b57cec5SDimitry Andric                           " for symbol at index " + Twine(getSymbolIndex(Symb)));
17850b57cec5SDimitry Andric   }
17860b57cec5SDimitry Andric   return StringRef(Start);
17870b57cec5SDimitry Andric }
17880b57cec5SDimitry Andric 
17890b57cec5SDimitry Andric unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
17900b57cec5SDimitry Andric   DataRefImpl DRI = Sec.getRawDataRefImpl();
17910b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, DRI);
17920b57cec5SDimitry Andric   return Flags & MachO::SECTION_TYPE;
17930b57cec5SDimitry Andric }
17940b57cec5SDimitry Andric 
17950b57cec5SDimitry Andric uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
17960b57cec5SDimitry Andric   if (is64Bit()) {
17970b57cec5SDimitry Andric     MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
17980b57cec5SDimitry Andric     return Entry.n_value;
17990b57cec5SDimitry Andric   }
18000b57cec5SDimitry Andric   MachO::nlist Entry = getSymbolTableEntry(Sym);
18010b57cec5SDimitry Andric   return Entry.n_value;
18020b57cec5SDimitry Andric }
18030b57cec5SDimitry Andric 
18040b57cec5SDimitry Andric // getIndirectName() returns the name of the alias'ed symbol who's string table
18050b57cec5SDimitry Andric // index is in the n_value field.
18060b57cec5SDimitry Andric std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
18070b57cec5SDimitry Andric                                                  StringRef &Res) const {
18080b57cec5SDimitry Andric   StringRef StringTable = getStringTableData();
18090b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
18100b57cec5SDimitry Andric   if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
18110b57cec5SDimitry Andric     return object_error::parse_failed;
18120b57cec5SDimitry Andric   uint64_t NValue = getNValue(Symb);
18130b57cec5SDimitry Andric   if (NValue >= StringTable.size())
18140b57cec5SDimitry Andric     return object_error::parse_failed;
18150b57cec5SDimitry Andric   const char *Start = &StringTable.data()[NValue];
18160b57cec5SDimitry Andric   Res = StringRef(Start);
18170b57cec5SDimitry Andric   return std::error_code();
18180b57cec5SDimitry Andric }
18190b57cec5SDimitry Andric 
18200b57cec5SDimitry Andric uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
18210b57cec5SDimitry Andric   return getNValue(Sym);
18220b57cec5SDimitry Andric }
18230b57cec5SDimitry Andric 
18240b57cec5SDimitry Andric Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
18250b57cec5SDimitry Andric   return getSymbolValue(Sym);
18260b57cec5SDimitry Andric }
18270b57cec5SDimitry Andric 
18280b57cec5SDimitry Andric uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
18295ffd83dbSDimitry Andric   uint32_t Flags = cantFail(getSymbolFlags(DRI));
18305ffd83dbSDimitry Andric   if (Flags & SymbolRef::SF_Common) {
18310b57cec5SDimitry Andric     MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
18320b57cec5SDimitry Andric     return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
18330b57cec5SDimitry Andric   }
18340b57cec5SDimitry Andric   return 0;
18350b57cec5SDimitry Andric }
18360b57cec5SDimitry Andric 
18370b57cec5SDimitry Andric uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
18380b57cec5SDimitry Andric   return getNValue(DRI);
18390b57cec5SDimitry Andric }
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric Expected<SymbolRef::Type>
18420b57cec5SDimitry Andric MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
18430b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
18440b57cec5SDimitry Andric   uint8_t n_type = Entry.n_type;
18450b57cec5SDimitry Andric 
18460b57cec5SDimitry Andric   // If this is a STAB debugging symbol, we can do nothing more.
18470b57cec5SDimitry Andric   if (n_type & MachO::N_STAB)
18480b57cec5SDimitry Andric     return SymbolRef::ST_Debug;
18490b57cec5SDimitry Andric 
18500b57cec5SDimitry Andric   switch (n_type & MachO::N_TYPE) {
18510b57cec5SDimitry Andric     case MachO::N_UNDF :
18520b57cec5SDimitry Andric       return SymbolRef::ST_Unknown;
18530b57cec5SDimitry Andric     case MachO::N_SECT :
18540b57cec5SDimitry Andric       Expected<section_iterator> SecOrError = getSymbolSection(Symb);
18550b57cec5SDimitry Andric       if (!SecOrError)
18560b57cec5SDimitry Andric         return SecOrError.takeError();
18570b57cec5SDimitry Andric       section_iterator Sec = *SecOrError;
1858fe6060f1SDimitry Andric       if (Sec == section_end())
1859fe6060f1SDimitry Andric         return SymbolRef::ST_Other;
18600b57cec5SDimitry Andric       if (Sec->isData() || Sec->isBSS())
18610b57cec5SDimitry Andric         return SymbolRef::ST_Data;
18620b57cec5SDimitry Andric       return SymbolRef::ST_Function;
18630b57cec5SDimitry Andric   }
18640b57cec5SDimitry Andric   return SymbolRef::ST_Other;
18650b57cec5SDimitry Andric }
18660b57cec5SDimitry Andric 
18675ffd83dbSDimitry Andric Expected<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
18680b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric   uint8_t MachOType = Entry.n_type;
18710b57cec5SDimitry Andric   uint16_t MachOFlags = Entry.n_desc;
18720b57cec5SDimitry Andric 
18730b57cec5SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
18740b57cec5SDimitry Andric 
18750b57cec5SDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
18760b57cec5SDimitry Andric     Result |= SymbolRef::SF_Indirect;
18770b57cec5SDimitry Andric 
18780b57cec5SDimitry Andric   if (MachOType & MachO::N_STAB)
18790b57cec5SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
18800b57cec5SDimitry Andric 
18810b57cec5SDimitry Andric   if (MachOType & MachO::N_EXT) {
18820b57cec5SDimitry Andric     Result |= SymbolRef::SF_Global;
18830b57cec5SDimitry Andric     if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
18840b57cec5SDimitry Andric       if (getNValue(DRI))
18850b57cec5SDimitry Andric         Result |= SymbolRef::SF_Common;
18860b57cec5SDimitry Andric       else
18870b57cec5SDimitry Andric         Result |= SymbolRef::SF_Undefined;
18880b57cec5SDimitry Andric     }
18890b57cec5SDimitry Andric 
1890bdd1243dSDimitry Andric     if (MachOType & MachO::N_PEXT)
1891bdd1243dSDimitry Andric       Result |= SymbolRef::SF_Hidden;
1892bdd1243dSDimitry Andric     else
18930b57cec5SDimitry Andric       Result |= SymbolRef::SF_Exported;
1894bdd1243dSDimitry Andric 
1895bdd1243dSDimitry Andric   } else if (MachOType & MachO::N_PEXT)
1896bdd1243dSDimitry Andric     Result |= SymbolRef::SF_Hidden;
18970b57cec5SDimitry Andric 
18980b57cec5SDimitry Andric   if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
18990b57cec5SDimitry Andric     Result |= SymbolRef::SF_Weak;
19000b57cec5SDimitry Andric 
19010b57cec5SDimitry Andric   if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
19020b57cec5SDimitry Andric     Result |= SymbolRef::SF_Thumb;
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric   if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
19050b57cec5SDimitry Andric     Result |= SymbolRef::SF_Absolute;
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric   return Result;
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric Expected<section_iterator>
19110b57cec5SDimitry Andric MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
19120b57cec5SDimitry Andric   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
19130b57cec5SDimitry Andric   uint8_t index = Entry.n_sect;
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric   if (index == 0)
19160b57cec5SDimitry Andric     return section_end();
19170b57cec5SDimitry Andric   DataRefImpl DRI;
19180b57cec5SDimitry Andric   DRI.d.a = index - 1;
19190b57cec5SDimitry Andric   if (DRI.d.a >= Sections.size()){
19200b57cec5SDimitry Andric     return malformedError("bad section index: " + Twine((int)index) +
19210b57cec5SDimitry Andric                           " for symbol at index " + Twine(getSymbolIndex(Symb)));
19220b57cec5SDimitry Andric   }
19230b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
19240b57cec5SDimitry Andric }
19250b57cec5SDimitry Andric 
19260b57cec5SDimitry Andric unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
19270b57cec5SDimitry Andric   MachO::nlist_base Entry =
19280b57cec5SDimitry Andric       getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
19290b57cec5SDimitry Andric   return Entry.n_sect - 1;
19300b57cec5SDimitry Andric }
19310b57cec5SDimitry Andric 
19320b57cec5SDimitry Andric void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
19330b57cec5SDimitry Andric   Sec.d.a++;
19340b57cec5SDimitry Andric }
19350b57cec5SDimitry Andric 
19360b57cec5SDimitry Andric Expected<StringRef> MachOObjectFile::getSectionName(DataRefImpl Sec) const {
19370b57cec5SDimitry Andric   ArrayRef<char> Raw = getSectionRawName(Sec);
19380b57cec5SDimitry Andric   return parseSegmentOrSectionName(Raw.data());
19390b57cec5SDimitry Andric }
19400b57cec5SDimitry Andric 
19410b57cec5SDimitry Andric uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
19420b57cec5SDimitry Andric   if (is64Bit())
19430b57cec5SDimitry Andric     return getSection64(Sec).addr;
19440b57cec5SDimitry Andric   return getSection(Sec).addr;
19450b57cec5SDimitry Andric }
19460b57cec5SDimitry Andric 
19470b57cec5SDimitry Andric uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
19480b57cec5SDimitry Andric   return Sec.d.a;
19490b57cec5SDimitry Andric }
19500b57cec5SDimitry Andric 
19510b57cec5SDimitry Andric uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
19520b57cec5SDimitry Andric   // In the case if a malformed Mach-O file where the section offset is past
19530b57cec5SDimitry Andric   // the end of the file or some part of the section size is past the end of
19540b57cec5SDimitry Andric   // the file return a size of zero or a size that covers the rest of the file
19550b57cec5SDimitry Andric   // but does not extend past the end of the file.
19560b57cec5SDimitry Andric   uint32_t SectOffset, SectType;
19570b57cec5SDimitry Andric   uint64_t SectSize;
19580b57cec5SDimitry Andric 
19590b57cec5SDimitry Andric   if (is64Bit()) {
19600b57cec5SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
19610b57cec5SDimitry Andric     SectOffset = Sect.offset;
19620b57cec5SDimitry Andric     SectSize = Sect.size;
19630b57cec5SDimitry Andric     SectType = Sect.flags & MachO::SECTION_TYPE;
19640b57cec5SDimitry Andric   } else {
19650b57cec5SDimitry Andric     MachO::section Sect = getSection(Sec);
19660b57cec5SDimitry Andric     SectOffset = Sect.offset;
19670b57cec5SDimitry Andric     SectSize = Sect.size;
19680b57cec5SDimitry Andric     SectType = Sect.flags & MachO::SECTION_TYPE;
19690b57cec5SDimitry Andric   }
19700b57cec5SDimitry Andric   if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
19710b57cec5SDimitry Andric     return SectSize;
19720b57cec5SDimitry Andric   uint64_t FileSize = getData().size();
19730b57cec5SDimitry Andric   if (SectOffset > FileSize)
19740b57cec5SDimitry Andric     return 0;
19750b57cec5SDimitry Andric   if (FileSize - SectOffset < SectSize)
19760b57cec5SDimitry Andric     return FileSize - SectOffset;
19770b57cec5SDimitry Andric   return SectSize;
19780b57cec5SDimitry Andric }
19790b57cec5SDimitry Andric 
19808bcb0991SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset,
19818bcb0991SDimitry Andric                                                       uint64_t Size) const {
19828bcb0991SDimitry Andric   return arrayRefFromStringRef(getData().substr(Offset, Size));
19838bcb0991SDimitry Andric }
19848bcb0991SDimitry Andric 
19850b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
19860b57cec5SDimitry Andric MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
19870b57cec5SDimitry Andric   uint32_t Offset;
19880b57cec5SDimitry Andric   uint64_t Size;
19890b57cec5SDimitry Andric 
19900b57cec5SDimitry Andric   if (is64Bit()) {
19910b57cec5SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
19920b57cec5SDimitry Andric     Offset = Sect.offset;
19930b57cec5SDimitry Andric     Size = Sect.size;
19940b57cec5SDimitry Andric   } else {
19950b57cec5SDimitry Andric     MachO::section Sect = getSection(Sec);
19960b57cec5SDimitry Andric     Offset = Sect.offset;
19970b57cec5SDimitry Andric     Size = Sect.size;
19980b57cec5SDimitry Andric   }
19990b57cec5SDimitry Andric 
20008bcb0991SDimitry Andric   return getSectionContents(Offset, Size);
20010b57cec5SDimitry Andric }
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
20040b57cec5SDimitry Andric   uint32_t Align;
20050b57cec5SDimitry Andric   if (is64Bit()) {
20060b57cec5SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
20070b57cec5SDimitry Andric     Align = Sect.align;
20080b57cec5SDimitry Andric   } else {
20090b57cec5SDimitry Andric     MachO::section Sect = getSection(Sec);
20100b57cec5SDimitry Andric     Align = Sect.align;
20110b57cec5SDimitry Andric   }
20120b57cec5SDimitry Andric 
20130b57cec5SDimitry Andric   return uint64_t(1) << Align;
20140b57cec5SDimitry Andric }
20150b57cec5SDimitry Andric 
20160b57cec5SDimitry Andric Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
20170b57cec5SDimitry Andric   if (SectionIndex < 1 || SectionIndex > Sections.size())
20180b57cec5SDimitry Andric     return malformedError("bad section index: " + Twine((int)SectionIndex));
20190b57cec5SDimitry Andric 
20200b57cec5SDimitry Andric   DataRefImpl DRI;
20210b57cec5SDimitry Andric   DRI.d.a = SectionIndex - 1;
20220b57cec5SDimitry Andric   return SectionRef(DRI, this);
20230b57cec5SDimitry Andric }
20240b57cec5SDimitry Andric 
20250b57cec5SDimitry Andric Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
20260b57cec5SDimitry Andric   for (const SectionRef &Section : sections()) {
20278bcb0991SDimitry Andric     auto NameOrErr = Section.getName();
20288bcb0991SDimitry Andric     if (!NameOrErr)
20298bcb0991SDimitry Andric       return NameOrErr.takeError();
20308bcb0991SDimitry Andric     if (*NameOrErr == SectionName)
20310b57cec5SDimitry Andric       return Section;
20320b57cec5SDimitry Andric   }
20330b57cec5SDimitry Andric   return errorCodeToError(object_error::parse_failed);
20340b57cec5SDimitry Andric }
20350b57cec5SDimitry Andric 
20360b57cec5SDimitry Andric bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
20370b57cec5SDimitry Andric   return false;
20380b57cec5SDimitry Andric }
20390b57cec5SDimitry Andric 
20400b57cec5SDimitry Andric bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
20410b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
20420b57cec5SDimitry Andric   return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
20430b57cec5SDimitry Andric }
20440b57cec5SDimitry Andric 
20450b57cec5SDimitry Andric bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
20460b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
20470b57cec5SDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
20480b57cec5SDimitry Andric   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
20490b57cec5SDimitry Andric          !(SectionType == MachO::S_ZEROFILL ||
20500b57cec5SDimitry Andric            SectionType == MachO::S_GB_ZEROFILL);
20510b57cec5SDimitry Andric }
20520b57cec5SDimitry Andric 
20530b57cec5SDimitry Andric bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
20540b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
20550b57cec5SDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
20560b57cec5SDimitry Andric   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
20570b57cec5SDimitry Andric          (SectionType == MachO::S_ZEROFILL ||
20580b57cec5SDimitry Andric           SectionType == MachO::S_GB_ZEROFILL);
20590b57cec5SDimitry Andric }
20600b57cec5SDimitry Andric 
2061fe6060f1SDimitry Andric bool MachOObjectFile::isDebugSection(DataRefImpl Sec) const {
2062fe6060f1SDimitry Andric   Expected<StringRef> SectionNameOrErr = getSectionName(Sec);
2063fe6060f1SDimitry Andric   if (!SectionNameOrErr) {
2064fe6060f1SDimitry Andric     // TODO: Report the error message properly.
2065fe6060f1SDimitry Andric     consumeError(SectionNameOrErr.takeError());
2066fe6060f1SDimitry Andric     return false;
2067fe6060f1SDimitry Andric   }
2068fe6060f1SDimitry Andric   StringRef SectionName = SectionNameOrErr.get();
20695f757f3fSDimitry Andric   return SectionName.starts_with("__debug") ||
20705f757f3fSDimitry Andric          SectionName.starts_with("__zdebug") ||
20715f757f3fSDimitry Andric          SectionName.starts_with("__apple") || SectionName == "__gdb_index" ||
2072e8d8bef9SDimitry Andric          SectionName == "__swift_ast";
20735ffd83dbSDimitry Andric }
20745ffd83dbSDimitry Andric 
2075349cc55cSDimitry Andric namespace {
2076349cc55cSDimitry Andric template <typename LoadCommandType>
2077349cc55cSDimitry Andric ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
2078349cc55cSDimitry Andric                                      MachOObjectFile::LoadCommandInfo LoadCmd,
2079349cc55cSDimitry Andric                                      StringRef SegmentName) {
2080349cc55cSDimitry Andric   auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);
2081349cc55cSDimitry Andric   if (!SegmentOrErr) {
2082349cc55cSDimitry Andric     consumeError(SegmentOrErr.takeError());
2083349cc55cSDimitry Andric     return {};
2084349cc55cSDimitry Andric   }
2085349cc55cSDimitry Andric   auto &Segment = SegmentOrErr.get();
20865f757f3fSDimitry Andric   if (StringRef(Segment.segname, 16).starts_with(SegmentName))
2087349cc55cSDimitry Andric     return arrayRefFromStringRef(Obj.getData().slice(
2088349cc55cSDimitry Andric         Segment.fileoff, Segment.fileoff + Segment.filesize));
2089349cc55cSDimitry Andric   return {};
2090349cc55cSDimitry Andric }
2091bdd1243dSDimitry Andric 
2092bdd1243dSDimitry Andric template <typename LoadCommandType>
2093bdd1243dSDimitry Andric ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
2094bdd1243dSDimitry Andric                                      MachOObjectFile::LoadCommandInfo LoadCmd) {
2095bdd1243dSDimitry Andric   auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);
2096bdd1243dSDimitry Andric   if (!SegmentOrErr) {
2097bdd1243dSDimitry Andric     consumeError(SegmentOrErr.takeError());
2098bdd1243dSDimitry Andric     return {};
2099bdd1243dSDimitry Andric   }
2100bdd1243dSDimitry Andric   auto &Segment = SegmentOrErr.get();
2101bdd1243dSDimitry Andric   return arrayRefFromStringRef(
2102bdd1243dSDimitry Andric       Obj.getData().slice(Segment.fileoff, Segment.fileoff + Segment.filesize));
2103bdd1243dSDimitry Andric }
2104349cc55cSDimitry Andric } // namespace
2105349cc55cSDimitry Andric 
2106349cc55cSDimitry Andric ArrayRef<uint8_t>
2107349cc55cSDimitry Andric MachOObjectFile::getSegmentContents(StringRef SegmentName) const {
2108349cc55cSDimitry Andric   for (auto LoadCmd : load_commands()) {
2109349cc55cSDimitry Andric     ArrayRef<uint8_t> Contents;
2110349cc55cSDimitry Andric     switch (LoadCmd.C.cmd) {
2111349cc55cSDimitry Andric     case MachO::LC_SEGMENT:
2112349cc55cSDimitry Andric       Contents = ::getSegmentContents<MachO::segment_command>(*this, LoadCmd,
2113349cc55cSDimitry Andric                                                               SegmentName);
2114349cc55cSDimitry Andric       break;
2115349cc55cSDimitry Andric     case MachO::LC_SEGMENT_64:
2116349cc55cSDimitry Andric       Contents = ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd,
2117349cc55cSDimitry Andric                                                                  SegmentName);
2118349cc55cSDimitry Andric       break;
2119349cc55cSDimitry Andric     default:
2120349cc55cSDimitry Andric       continue;
2121349cc55cSDimitry Andric     }
2122349cc55cSDimitry Andric     if (!Contents.empty())
2123349cc55cSDimitry Andric       return Contents;
2124349cc55cSDimitry Andric   }
2125349cc55cSDimitry Andric   return {};
2126349cc55cSDimitry Andric }
2127349cc55cSDimitry Andric 
2128bdd1243dSDimitry Andric ArrayRef<uint8_t>
2129bdd1243dSDimitry Andric MachOObjectFile::getSegmentContents(size_t SegmentIndex) const {
2130bdd1243dSDimitry Andric   size_t Idx = 0;
2131bdd1243dSDimitry Andric   for (auto LoadCmd : load_commands()) {
2132bdd1243dSDimitry Andric     switch (LoadCmd.C.cmd) {
2133bdd1243dSDimitry Andric     case MachO::LC_SEGMENT:
2134bdd1243dSDimitry Andric       if (Idx == SegmentIndex)
2135bdd1243dSDimitry Andric         return ::getSegmentContents<MachO::segment_command>(*this, LoadCmd);
2136bdd1243dSDimitry Andric       ++Idx;
2137bdd1243dSDimitry Andric       break;
2138bdd1243dSDimitry Andric     case MachO::LC_SEGMENT_64:
2139bdd1243dSDimitry Andric       if (Idx == SegmentIndex)
2140bdd1243dSDimitry Andric         return ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd);
2141bdd1243dSDimitry Andric       ++Idx;
2142bdd1243dSDimitry Andric       break;
2143bdd1243dSDimitry Andric     default:
2144bdd1243dSDimitry Andric       continue;
2145bdd1243dSDimitry Andric     }
2146bdd1243dSDimitry Andric   }
2147bdd1243dSDimitry Andric   return {};
2148bdd1243dSDimitry Andric }
2149bdd1243dSDimitry Andric 
21500b57cec5SDimitry Andric unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
21510b57cec5SDimitry Andric   return Sec.getRawDataRefImpl().d.a;
21520b57cec5SDimitry Andric }
21530b57cec5SDimitry Andric 
21540b57cec5SDimitry Andric bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
21550b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(*this, Sec);
21560b57cec5SDimitry Andric   unsigned SectionType = Flags & MachO::SECTION_TYPE;
21570b57cec5SDimitry Andric   return SectionType == MachO::S_ZEROFILL ||
21580b57cec5SDimitry Andric          SectionType == MachO::S_GB_ZEROFILL;
21590b57cec5SDimitry Andric }
21600b57cec5SDimitry Andric 
21610b57cec5SDimitry Andric bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
21620b57cec5SDimitry Andric   StringRef SegmentName = getSectionFinalSegmentName(Sec);
21630b57cec5SDimitry Andric   if (Expected<StringRef> NameOrErr = getSectionName(Sec))
21640b57cec5SDimitry Andric     return (SegmentName == "__LLVM" && *NameOrErr == "__bitcode");
21650b57cec5SDimitry Andric   return false;
21660b57cec5SDimitry Andric }
21670b57cec5SDimitry Andric 
21680b57cec5SDimitry Andric bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
21690b57cec5SDimitry Andric   if (is64Bit())
21700b57cec5SDimitry Andric     return getSection64(Sec).offset == 0;
21710b57cec5SDimitry Andric   return getSection(Sec).offset == 0;
21720b57cec5SDimitry Andric }
21730b57cec5SDimitry Andric 
21740b57cec5SDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
21750b57cec5SDimitry Andric   DataRefImpl Ret;
21760b57cec5SDimitry Andric   Ret.d.a = Sec.d.a;
21770b57cec5SDimitry Andric   Ret.d.b = 0;
21780b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
21790b57cec5SDimitry Andric }
21800b57cec5SDimitry Andric 
21810b57cec5SDimitry Andric relocation_iterator
21820b57cec5SDimitry Andric MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
21830b57cec5SDimitry Andric   uint32_t Num;
21840b57cec5SDimitry Andric   if (is64Bit()) {
21850b57cec5SDimitry Andric     MachO::section_64 Sect = getSection64(Sec);
21860b57cec5SDimitry Andric     Num = Sect.nreloc;
21870b57cec5SDimitry Andric   } else {
21880b57cec5SDimitry Andric     MachO::section Sect = getSection(Sec);
21890b57cec5SDimitry Andric     Num = Sect.nreloc;
21900b57cec5SDimitry Andric   }
21910b57cec5SDimitry Andric 
21920b57cec5SDimitry Andric   DataRefImpl Ret;
21930b57cec5SDimitry Andric   Ret.d.a = Sec.d.a;
21940b57cec5SDimitry Andric   Ret.d.b = Num;
21950b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
21960b57cec5SDimitry Andric }
21970b57cec5SDimitry Andric 
21980b57cec5SDimitry Andric relocation_iterator MachOObjectFile::extrel_begin() const {
21990b57cec5SDimitry Andric   DataRefImpl Ret;
22000b57cec5SDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
22010b57cec5SDimitry Andric   Ret.d.a = 0; // Would normally be a section index.
22020b57cec5SDimitry Andric   Ret.d.b = 0; // Index into the external relocations
22030b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
22040b57cec5SDimitry Andric }
22050b57cec5SDimitry Andric 
22060b57cec5SDimitry Andric relocation_iterator MachOObjectFile::extrel_end() const {
22070b57cec5SDimitry Andric   MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
22080b57cec5SDimitry Andric   DataRefImpl Ret;
22090b57cec5SDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
22100b57cec5SDimitry Andric   Ret.d.a = 0; // Would normally be a section index.
22110b57cec5SDimitry Andric   Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
22120b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
22130b57cec5SDimitry Andric }
22140b57cec5SDimitry Andric 
22150b57cec5SDimitry Andric relocation_iterator MachOObjectFile::locrel_begin() const {
22160b57cec5SDimitry Andric   DataRefImpl Ret;
22170b57cec5SDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
22180b57cec5SDimitry Andric   Ret.d.a = 1; // Would normally be a section index.
22190b57cec5SDimitry Andric   Ret.d.b = 0; // Index into the local relocations
22200b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
22210b57cec5SDimitry Andric }
22220b57cec5SDimitry Andric 
22230b57cec5SDimitry Andric relocation_iterator MachOObjectFile::locrel_end() const {
22240b57cec5SDimitry Andric   MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
22250b57cec5SDimitry Andric   DataRefImpl Ret;
22260b57cec5SDimitry Andric   // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
22270b57cec5SDimitry Andric   Ret.d.a = 1; // Would normally be a section index.
22280b57cec5SDimitry Andric   Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
22290b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
22300b57cec5SDimitry Andric }
22310b57cec5SDimitry Andric 
22320b57cec5SDimitry Andric void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
22330b57cec5SDimitry Andric   ++Rel.d.b;
22340b57cec5SDimitry Andric }
22350b57cec5SDimitry Andric 
22360b57cec5SDimitry Andric uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
22370b57cec5SDimitry Andric   assert((getHeader().filetype == MachO::MH_OBJECT ||
22380b57cec5SDimitry Andric           getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
22390b57cec5SDimitry Andric          "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
22400b57cec5SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
22410b57cec5SDimitry Andric   return getAnyRelocationAddress(RE);
22420b57cec5SDimitry Andric }
22430b57cec5SDimitry Andric 
22440b57cec5SDimitry Andric symbol_iterator
22450b57cec5SDimitry Andric MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
22460b57cec5SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
22470b57cec5SDimitry Andric   if (isRelocationScattered(RE))
22480b57cec5SDimitry Andric     return symbol_end();
22490b57cec5SDimitry Andric 
22500b57cec5SDimitry Andric   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
22510b57cec5SDimitry Andric   bool isExtern = getPlainRelocationExternal(RE);
22520b57cec5SDimitry Andric   if (!isExtern)
22530b57cec5SDimitry Andric     return symbol_end();
22540b57cec5SDimitry Andric 
22550b57cec5SDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
22560b57cec5SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
22570b57cec5SDimitry Andric     sizeof(MachO::nlist_64) :
22580b57cec5SDimitry Andric     sizeof(MachO::nlist);
22590b57cec5SDimitry Andric   uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
22600b57cec5SDimitry Andric   DataRefImpl Sym;
22610b57cec5SDimitry Andric   Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
22620b57cec5SDimitry Andric   return symbol_iterator(SymbolRef(Sym, this));
22630b57cec5SDimitry Andric }
22640b57cec5SDimitry Andric 
22650b57cec5SDimitry Andric section_iterator
22660b57cec5SDimitry Andric MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
22670b57cec5SDimitry Andric   return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
22680b57cec5SDimitry Andric }
22690b57cec5SDimitry Andric 
22700b57cec5SDimitry Andric uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
22710b57cec5SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
22720b57cec5SDimitry Andric   return getAnyRelocationType(RE);
22730b57cec5SDimitry Andric }
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric void MachOObjectFile::getRelocationTypeName(
22760b57cec5SDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
22770b57cec5SDimitry Andric   StringRef res;
22780b57cec5SDimitry Andric   uint64_t RType = getRelocationType(Rel);
22790b57cec5SDimitry Andric 
22800b57cec5SDimitry Andric   unsigned Arch = this->getArch();
22810b57cec5SDimitry Andric 
22820b57cec5SDimitry Andric   switch (Arch) {
22830b57cec5SDimitry Andric     case Triple::x86: {
22840b57cec5SDimitry Andric       static const char *const Table[] =  {
22850b57cec5SDimitry Andric         "GENERIC_RELOC_VANILLA",
22860b57cec5SDimitry Andric         "GENERIC_RELOC_PAIR",
22870b57cec5SDimitry Andric         "GENERIC_RELOC_SECTDIFF",
22880b57cec5SDimitry Andric         "GENERIC_RELOC_PB_LA_PTR",
22890b57cec5SDimitry Andric         "GENERIC_RELOC_LOCAL_SECTDIFF",
22900b57cec5SDimitry Andric         "GENERIC_RELOC_TLV" };
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric       if (RType > 5)
22930b57cec5SDimitry Andric         res = "Unknown";
22940b57cec5SDimitry Andric       else
22950b57cec5SDimitry Andric         res = Table[RType];
22960b57cec5SDimitry Andric       break;
22970b57cec5SDimitry Andric     }
22980b57cec5SDimitry Andric     case Triple::x86_64: {
22990b57cec5SDimitry Andric       static const char *const Table[] =  {
23000b57cec5SDimitry Andric         "X86_64_RELOC_UNSIGNED",
23010b57cec5SDimitry Andric         "X86_64_RELOC_SIGNED",
23020b57cec5SDimitry Andric         "X86_64_RELOC_BRANCH",
23030b57cec5SDimitry Andric         "X86_64_RELOC_GOT_LOAD",
23040b57cec5SDimitry Andric         "X86_64_RELOC_GOT",
23050b57cec5SDimitry Andric         "X86_64_RELOC_SUBTRACTOR",
23060b57cec5SDimitry Andric         "X86_64_RELOC_SIGNED_1",
23070b57cec5SDimitry Andric         "X86_64_RELOC_SIGNED_2",
23080b57cec5SDimitry Andric         "X86_64_RELOC_SIGNED_4",
23090b57cec5SDimitry Andric         "X86_64_RELOC_TLV" };
23100b57cec5SDimitry Andric 
23110b57cec5SDimitry Andric       if (RType > 9)
23120b57cec5SDimitry Andric         res = "Unknown";
23130b57cec5SDimitry Andric       else
23140b57cec5SDimitry Andric         res = Table[RType];
23150b57cec5SDimitry Andric       break;
23160b57cec5SDimitry Andric     }
23170b57cec5SDimitry Andric     case Triple::arm: {
23180b57cec5SDimitry Andric       static const char *const Table[] =  {
23190b57cec5SDimitry Andric         "ARM_RELOC_VANILLA",
23200b57cec5SDimitry Andric         "ARM_RELOC_PAIR",
23210b57cec5SDimitry Andric         "ARM_RELOC_SECTDIFF",
23220b57cec5SDimitry Andric         "ARM_RELOC_LOCAL_SECTDIFF",
23230b57cec5SDimitry Andric         "ARM_RELOC_PB_LA_PTR",
23240b57cec5SDimitry Andric         "ARM_RELOC_BR24",
23250b57cec5SDimitry Andric         "ARM_THUMB_RELOC_BR22",
23260b57cec5SDimitry Andric         "ARM_THUMB_32BIT_BRANCH",
23270b57cec5SDimitry Andric         "ARM_RELOC_HALF",
23280b57cec5SDimitry Andric         "ARM_RELOC_HALF_SECTDIFF" };
23290b57cec5SDimitry Andric 
23300b57cec5SDimitry Andric       if (RType > 9)
23310b57cec5SDimitry Andric         res = "Unknown";
23320b57cec5SDimitry Andric       else
23330b57cec5SDimitry Andric         res = Table[RType];
23340b57cec5SDimitry Andric       break;
23350b57cec5SDimitry Andric     }
23360b57cec5SDimitry Andric     case Triple::aarch64:
23370b57cec5SDimitry Andric     case Triple::aarch64_32: {
23380b57cec5SDimitry Andric       static const char *const Table[] = {
23390b57cec5SDimitry Andric         "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
23400b57cec5SDimitry Andric         "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
23410b57cec5SDimitry Andric         "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
23420b57cec5SDimitry Andric         "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
23430b57cec5SDimitry Andric         "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
23440b57cec5SDimitry Andric         "ARM64_RELOC_ADDEND"
23450b57cec5SDimitry Andric       };
23460b57cec5SDimitry Andric 
2347bdd1243dSDimitry Andric       if (RType >= std::size(Table))
23480b57cec5SDimitry Andric         res = "Unknown";
23490b57cec5SDimitry Andric       else
23500b57cec5SDimitry Andric         res = Table[RType];
23510b57cec5SDimitry Andric       break;
23520b57cec5SDimitry Andric     }
23530b57cec5SDimitry Andric     case Triple::ppc: {
23540b57cec5SDimitry Andric       static const char *const Table[] =  {
23550b57cec5SDimitry Andric         "PPC_RELOC_VANILLA",
23560b57cec5SDimitry Andric         "PPC_RELOC_PAIR",
23570b57cec5SDimitry Andric         "PPC_RELOC_BR14",
23580b57cec5SDimitry Andric         "PPC_RELOC_BR24",
23590b57cec5SDimitry Andric         "PPC_RELOC_HI16",
23600b57cec5SDimitry Andric         "PPC_RELOC_LO16",
23610b57cec5SDimitry Andric         "PPC_RELOC_HA16",
23620b57cec5SDimitry Andric         "PPC_RELOC_LO14",
23630b57cec5SDimitry Andric         "PPC_RELOC_SECTDIFF",
23640b57cec5SDimitry Andric         "PPC_RELOC_PB_LA_PTR",
23650b57cec5SDimitry Andric         "PPC_RELOC_HI16_SECTDIFF",
23660b57cec5SDimitry Andric         "PPC_RELOC_LO16_SECTDIFF",
23670b57cec5SDimitry Andric         "PPC_RELOC_HA16_SECTDIFF",
23680b57cec5SDimitry Andric         "PPC_RELOC_JBSR",
23690b57cec5SDimitry Andric         "PPC_RELOC_LO14_SECTDIFF",
23700b57cec5SDimitry Andric         "PPC_RELOC_LOCAL_SECTDIFF" };
23710b57cec5SDimitry Andric 
23720b57cec5SDimitry Andric       if (RType > 15)
23730b57cec5SDimitry Andric         res = "Unknown";
23740b57cec5SDimitry Andric       else
23750b57cec5SDimitry Andric         res = Table[RType];
23760b57cec5SDimitry Andric       break;
23770b57cec5SDimitry Andric     }
23780b57cec5SDimitry Andric     case Triple::UnknownArch:
23790b57cec5SDimitry Andric       res = "Unknown";
23800b57cec5SDimitry Andric       break;
23810b57cec5SDimitry Andric   }
23820b57cec5SDimitry Andric   Result.append(res.begin(), res.end());
23830b57cec5SDimitry Andric }
23840b57cec5SDimitry Andric 
23850b57cec5SDimitry Andric uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
23860b57cec5SDimitry Andric   MachO::any_relocation_info RE = getRelocation(Rel);
23870b57cec5SDimitry Andric   return getAnyRelocationLength(RE);
23880b57cec5SDimitry Andric }
23890b57cec5SDimitry Andric 
23900b57cec5SDimitry Andric //
23910b57cec5SDimitry Andric // guessLibraryShortName() is passed a name of a dynamic library and returns a
23920b57cec5SDimitry Andric // guess on what the short name is.  Then name is returned as a substring of the
23930b57cec5SDimitry Andric // StringRef Name passed in.  The name of the dynamic library is recognized as
23940b57cec5SDimitry Andric // a framework if it has one of the two following forms:
23950b57cec5SDimitry Andric //      Foo.framework/Versions/A/Foo
23960b57cec5SDimitry Andric //      Foo.framework/Foo
23970b57cec5SDimitry Andric // Where A and Foo can be any string.  And may contain a trailing suffix
23980b57cec5SDimitry Andric // starting with an underbar.  If the Name is recognized as a framework then
23990b57cec5SDimitry Andric // isFramework is set to true else it is set to false.  If the Name has a
24000b57cec5SDimitry Andric // suffix then Suffix is set to the substring in Name that contains the suffix
24010b57cec5SDimitry Andric // else it is set to a NULL StringRef.
24020b57cec5SDimitry Andric //
24030b57cec5SDimitry Andric // The Name of the dynamic library is recognized as a library name if it has
24040b57cec5SDimitry Andric // one of the two following forms:
24050b57cec5SDimitry Andric //      libFoo.A.dylib
24060b57cec5SDimitry Andric //      libFoo.dylib
24070b57cec5SDimitry Andric //
24080b57cec5SDimitry Andric // The library may have a suffix trailing the name Foo of the form:
24090b57cec5SDimitry Andric //      libFoo_profile.A.dylib
24100b57cec5SDimitry Andric //      libFoo_profile.dylib
24110b57cec5SDimitry Andric // These dyld image suffixes are separated from the short name by a '_'
24120b57cec5SDimitry Andric // character. Because the '_' character is commonly used to separate words in
24130b57cec5SDimitry Andric // filenames guessLibraryShortName() cannot reliably separate a dylib's short
24140b57cec5SDimitry Andric // name from an arbitrary image suffix; imagine if both the short name and the
24150b57cec5SDimitry Andric // suffix contains an '_' character! To better deal with this ambiguity,
24160b57cec5SDimitry Andric // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
24170b57cec5SDimitry Andric // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
24180b57cec5SDimitry Andric // guessing incorrectly.
24190b57cec5SDimitry Andric //
24200b57cec5SDimitry Andric // The Name of the dynamic library is also recognized as a library name if it
24210b57cec5SDimitry Andric // has the following form:
24220b57cec5SDimitry Andric //      Foo.qtx
24230b57cec5SDimitry Andric //
24240b57cec5SDimitry Andric // If the Name of the dynamic library is none of the forms above then a NULL
24250b57cec5SDimitry Andric // StringRef is returned.
24260b57cec5SDimitry Andric StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
24270b57cec5SDimitry Andric                                                  bool &isFramework,
24280b57cec5SDimitry Andric                                                  StringRef &Suffix) {
24290b57cec5SDimitry Andric   StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
24300b57cec5SDimitry Andric   size_t a, b, c, d, Idx;
24310b57cec5SDimitry Andric 
24320b57cec5SDimitry Andric   isFramework = false;
24330b57cec5SDimitry Andric   Suffix = StringRef();
24340b57cec5SDimitry Andric 
24350b57cec5SDimitry Andric   // Pull off the last component and make Foo point to it
24360b57cec5SDimitry Andric   a = Name.rfind('/');
24370b57cec5SDimitry Andric   if (a == Name.npos || a == 0)
24380b57cec5SDimitry Andric     goto guess_library;
24390b57cec5SDimitry Andric   Foo = Name.slice(a+1, Name.npos);
24400b57cec5SDimitry Andric 
24410b57cec5SDimitry Andric   // Look for a suffix starting with a '_'
24420b57cec5SDimitry Andric   Idx = Foo.rfind('_');
24430b57cec5SDimitry Andric   if (Idx != Foo.npos && Foo.size() >= 2) {
24440b57cec5SDimitry Andric     Suffix = Foo.slice(Idx, Foo.npos);
24450b57cec5SDimitry Andric     if (Suffix != "_debug" && Suffix != "_profile")
24460b57cec5SDimitry Andric       Suffix = StringRef();
24470b57cec5SDimitry Andric     else
24480b57cec5SDimitry Andric       Foo = Foo.slice(0, Idx);
24490b57cec5SDimitry Andric   }
24500b57cec5SDimitry Andric 
24510b57cec5SDimitry Andric   // First look for the form Foo.framework/Foo
24520b57cec5SDimitry Andric   b = Name.rfind('/', a);
24530b57cec5SDimitry Andric   if (b == Name.npos)
24540b57cec5SDimitry Andric     Idx = 0;
24550b57cec5SDimitry Andric   else
24560b57cec5SDimitry Andric     Idx = b+1;
24570b57cec5SDimitry Andric   F = Name.slice(Idx, Idx + Foo.size());
24580b57cec5SDimitry Andric   DotFramework = Name.slice(Idx + Foo.size(),
24590b57cec5SDimitry Andric                             Idx + Foo.size() + sizeof(".framework/")-1);
24600b57cec5SDimitry Andric   if (F == Foo && DotFramework == ".framework/") {
24610b57cec5SDimitry Andric     isFramework = true;
24620b57cec5SDimitry Andric     return Foo;
24630b57cec5SDimitry Andric   }
24640b57cec5SDimitry Andric 
24650b57cec5SDimitry Andric   // Next look for the form Foo.framework/Versions/A/Foo
24660b57cec5SDimitry Andric   if (b == Name.npos)
24670b57cec5SDimitry Andric     goto guess_library;
24680b57cec5SDimitry Andric   c =  Name.rfind('/', b);
24690b57cec5SDimitry Andric   if (c == Name.npos || c == 0)
24700b57cec5SDimitry Andric     goto guess_library;
24710b57cec5SDimitry Andric   V = Name.slice(c+1, Name.npos);
24725f757f3fSDimitry Andric   if (!V.starts_with("Versions/"))
24730b57cec5SDimitry Andric     goto guess_library;
24740b57cec5SDimitry Andric   d =  Name.rfind('/', c);
24750b57cec5SDimitry Andric   if (d == Name.npos)
24760b57cec5SDimitry Andric     Idx = 0;
24770b57cec5SDimitry Andric   else
24780b57cec5SDimitry Andric     Idx = d+1;
24790b57cec5SDimitry Andric   F = Name.slice(Idx, Idx + Foo.size());
24800b57cec5SDimitry Andric   DotFramework = Name.slice(Idx + Foo.size(),
24810b57cec5SDimitry Andric                             Idx + Foo.size() + sizeof(".framework/")-1);
24820b57cec5SDimitry Andric   if (F == Foo && DotFramework == ".framework/") {
24830b57cec5SDimitry Andric     isFramework = true;
24840b57cec5SDimitry Andric     return Foo;
24850b57cec5SDimitry Andric   }
24860b57cec5SDimitry Andric 
24870b57cec5SDimitry Andric guess_library:
24880b57cec5SDimitry Andric   // pull off the suffix after the "." and make a point to it
24890b57cec5SDimitry Andric   a = Name.rfind('.');
24900b57cec5SDimitry Andric   if (a == Name.npos || a == 0)
24910b57cec5SDimitry Andric     return StringRef();
24920b57cec5SDimitry Andric   Dylib = Name.slice(a, Name.npos);
24930b57cec5SDimitry Andric   if (Dylib != ".dylib")
24940b57cec5SDimitry Andric     goto guess_qtx;
24950b57cec5SDimitry Andric 
24960b57cec5SDimitry Andric   // First pull off the version letter for the form Foo.A.dylib if any.
24970b57cec5SDimitry Andric   if (a >= 3) {
24980b57cec5SDimitry Andric     Dot = Name.slice(a-2, a-1);
24990b57cec5SDimitry Andric     if (Dot == ".")
25000b57cec5SDimitry Andric       a = a - 2;
25010b57cec5SDimitry Andric   }
25020b57cec5SDimitry Andric 
25030b57cec5SDimitry Andric   b = Name.rfind('/', a);
25040b57cec5SDimitry Andric   if (b == Name.npos)
25050b57cec5SDimitry Andric     b = 0;
25060b57cec5SDimitry Andric   else
25070b57cec5SDimitry Andric     b = b+1;
25080b57cec5SDimitry Andric   // ignore any suffix after an underbar like Foo_profile.A.dylib
25090b57cec5SDimitry Andric   Idx = Name.rfind('_');
25100b57cec5SDimitry Andric   if (Idx != Name.npos && Idx != b) {
25110b57cec5SDimitry Andric     Lib = Name.slice(b, Idx);
25120b57cec5SDimitry Andric     Suffix = Name.slice(Idx, a);
25130b57cec5SDimitry Andric     if (Suffix != "_debug" && Suffix != "_profile") {
25140b57cec5SDimitry Andric       Suffix = StringRef();
25150b57cec5SDimitry Andric       Lib = Name.slice(b, a);
25160b57cec5SDimitry Andric     }
25170b57cec5SDimitry Andric   }
25180b57cec5SDimitry Andric   else
25190b57cec5SDimitry Andric     Lib = Name.slice(b, a);
25200b57cec5SDimitry Andric   // There are incorrect library names of the form:
25210b57cec5SDimitry Andric   // libATS.A_profile.dylib so check for these.
25220b57cec5SDimitry Andric   if (Lib.size() >= 3) {
25230b57cec5SDimitry Andric     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
25240b57cec5SDimitry Andric     if (Dot == ".")
25250b57cec5SDimitry Andric       Lib = Lib.slice(0, Lib.size()-2);
25260b57cec5SDimitry Andric   }
25270b57cec5SDimitry Andric   return Lib;
25280b57cec5SDimitry Andric 
25290b57cec5SDimitry Andric guess_qtx:
25300b57cec5SDimitry Andric   Qtx = Name.slice(a, Name.npos);
25310b57cec5SDimitry Andric   if (Qtx != ".qtx")
25320b57cec5SDimitry Andric     return StringRef();
25330b57cec5SDimitry Andric   b = Name.rfind('/', a);
25340b57cec5SDimitry Andric   if (b == Name.npos)
25350b57cec5SDimitry Andric     Lib = Name.slice(0, a);
25360b57cec5SDimitry Andric   else
25370b57cec5SDimitry Andric     Lib = Name.slice(b+1, a);
25380b57cec5SDimitry Andric   // There are library names of the form: QT.A.qtx so check for these.
25390b57cec5SDimitry Andric   if (Lib.size() >= 3) {
25400b57cec5SDimitry Andric     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
25410b57cec5SDimitry Andric     if (Dot == ".")
25420b57cec5SDimitry Andric       Lib = Lib.slice(0, Lib.size()-2);
25430b57cec5SDimitry Andric   }
25440b57cec5SDimitry Andric   return Lib;
25450b57cec5SDimitry Andric }
25460b57cec5SDimitry Andric 
25470b57cec5SDimitry Andric // getLibraryShortNameByIndex() is used to get the short name of the library
25480b57cec5SDimitry Andric // for an undefined symbol in a linked Mach-O binary that was linked with the
25490b57cec5SDimitry Andric // normal two-level namespace default (that is MH_TWOLEVEL in the header).
25500b57cec5SDimitry Andric // It is passed the index (0 - based) of the library as translated from
25510b57cec5SDimitry Andric // GET_LIBRARY_ORDINAL (1 - based).
25520b57cec5SDimitry Andric std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
25530b57cec5SDimitry Andric                                                          StringRef &Res) const {
25540b57cec5SDimitry Andric   if (Index >= Libraries.size())
25550b57cec5SDimitry Andric     return object_error::parse_failed;
25560b57cec5SDimitry Andric 
25570b57cec5SDimitry Andric   // If the cache of LibrariesShortNames is not built up do that first for
25580b57cec5SDimitry Andric   // all the Libraries.
25590b57cec5SDimitry Andric   if (LibrariesShortNames.size() == 0) {
25600b57cec5SDimitry Andric     for (unsigned i = 0; i < Libraries.size(); i++) {
25610b57cec5SDimitry Andric       auto CommandOrErr =
25620b57cec5SDimitry Andric         getStructOrErr<MachO::dylib_command>(*this, Libraries[i]);
25630b57cec5SDimitry Andric       if (!CommandOrErr)
25640b57cec5SDimitry Andric         return object_error::parse_failed;
25650b57cec5SDimitry Andric       MachO::dylib_command D = CommandOrErr.get();
25660b57cec5SDimitry Andric       if (D.dylib.name >= D.cmdsize)
25670b57cec5SDimitry Andric         return object_error::parse_failed;
25680b57cec5SDimitry Andric       const char *P = (const char *)(Libraries[i]) + D.dylib.name;
25690b57cec5SDimitry Andric       StringRef Name = StringRef(P);
25700b57cec5SDimitry Andric       if (D.dylib.name+Name.size() >= D.cmdsize)
25710b57cec5SDimitry Andric         return object_error::parse_failed;
25720b57cec5SDimitry Andric       StringRef Suffix;
25730b57cec5SDimitry Andric       bool isFramework;
25740b57cec5SDimitry Andric       StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
25750b57cec5SDimitry Andric       if (shortName.empty())
25760b57cec5SDimitry Andric         LibrariesShortNames.push_back(Name);
25770b57cec5SDimitry Andric       else
25780b57cec5SDimitry Andric         LibrariesShortNames.push_back(shortName);
25790b57cec5SDimitry Andric     }
25800b57cec5SDimitry Andric   }
25810b57cec5SDimitry Andric 
25820b57cec5SDimitry Andric   Res = LibrariesShortNames[Index];
25830b57cec5SDimitry Andric   return std::error_code();
25840b57cec5SDimitry Andric }
25850b57cec5SDimitry Andric 
25860b57cec5SDimitry Andric uint32_t MachOObjectFile::getLibraryCount() const {
25870b57cec5SDimitry Andric   return Libraries.size();
25880b57cec5SDimitry Andric }
25890b57cec5SDimitry Andric 
25900b57cec5SDimitry Andric section_iterator
25910b57cec5SDimitry Andric MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
25920b57cec5SDimitry Andric   DataRefImpl Sec;
25930b57cec5SDimitry Andric   Sec.d.a = Rel->getRawDataRefImpl().d.a;
25940b57cec5SDimitry Andric   return section_iterator(SectionRef(Sec, this));
25950b57cec5SDimitry Andric }
25960b57cec5SDimitry Andric 
25970b57cec5SDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_begin() const {
25980b57cec5SDimitry Andric   DataRefImpl DRI;
25990b57cec5SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
26000b57cec5SDimitry Andric   if (!SymtabLoadCmd || Symtab.nsyms == 0)
26010b57cec5SDimitry Andric     return basic_symbol_iterator(SymbolRef(DRI, this));
26020b57cec5SDimitry Andric 
26030b57cec5SDimitry Andric   return getSymbolByIndex(0);
26040b57cec5SDimitry Andric }
26050b57cec5SDimitry Andric 
26060b57cec5SDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_end() const {
26070b57cec5SDimitry Andric   DataRefImpl DRI;
26080b57cec5SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
26090b57cec5SDimitry Andric   if (!SymtabLoadCmd || Symtab.nsyms == 0)
26100b57cec5SDimitry Andric     return basic_symbol_iterator(SymbolRef(DRI, this));
26110b57cec5SDimitry Andric 
26120b57cec5SDimitry Andric   unsigned SymbolTableEntrySize = is64Bit() ?
26130b57cec5SDimitry Andric     sizeof(MachO::nlist_64) :
26140b57cec5SDimitry Andric     sizeof(MachO::nlist);
26150b57cec5SDimitry Andric   unsigned Offset = Symtab.symoff +
26160b57cec5SDimitry Andric     Symtab.nsyms * SymbolTableEntrySize;
26170b57cec5SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
26180b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(DRI, this));
26190b57cec5SDimitry Andric }
26200b57cec5SDimitry Andric 
26210b57cec5SDimitry Andric symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
26220b57cec5SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
26230b57cec5SDimitry Andric   if (!SymtabLoadCmd || Index >= Symtab.nsyms)
26240b57cec5SDimitry Andric     report_fatal_error("Requested symbol index is out of range.");
26250b57cec5SDimitry Andric   unsigned SymbolTableEntrySize =
26260b57cec5SDimitry Andric     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
26270b57cec5SDimitry Andric   DataRefImpl DRI;
26280b57cec5SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
26290b57cec5SDimitry Andric   DRI.p += Index * SymbolTableEntrySize;
26300b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(DRI, this));
26310b57cec5SDimitry Andric }
26320b57cec5SDimitry Andric 
26330b57cec5SDimitry Andric uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
26340b57cec5SDimitry Andric   MachO::symtab_command Symtab = getSymtabLoadCommand();
26350b57cec5SDimitry Andric   if (!SymtabLoadCmd)
26360b57cec5SDimitry Andric     report_fatal_error("getSymbolIndex() called with no symbol table symbol");
26370b57cec5SDimitry Andric   unsigned SymbolTableEntrySize =
26380b57cec5SDimitry Andric     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
26390b57cec5SDimitry Andric   DataRefImpl DRIstart;
26400b57cec5SDimitry Andric   DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
26410b57cec5SDimitry Andric   uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
26420b57cec5SDimitry Andric   return Index;
26430b57cec5SDimitry Andric }
26440b57cec5SDimitry Andric 
26450b57cec5SDimitry Andric section_iterator MachOObjectFile::section_begin() const {
26460b57cec5SDimitry Andric   DataRefImpl DRI;
26470b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
26480b57cec5SDimitry Andric }
26490b57cec5SDimitry Andric 
26500b57cec5SDimitry Andric section_iterator MachOObjectFile::section_end() const {
26510b57cec5SDimitry Andric   DataRefImpl DRI;
26520b57cec5SDimitry Andric   DRI.d.a = Sections.size();
26530b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
26540b57cec5SDimitry Andric }
26550b57cec5SDimitry Andric 
26560b57cec5SDimitry Andric uint8_t MachOObjectFile::getBytesInAddress() const {
26570b57cec5SDimitry Andric   return is64Bit() ? 8 : 4;
26580b57cec5SDimitry Andric }
26590b57cec5SDimitry Andric 
26600b57cec5SDimitry Andric StringRef MachOObjectFile::getFileFormatName() const {
26610b57cec5SDimitry Andric   unsigned CPUType = getCPUType(*this);
26620b57cec5SDimitry Andric   if (!is64Bit()) {
26630b57cec5SDimitry Andric     switch (CPUType) {
26640b57cec5SDimitry Andric     case MachO::CPU_TYPE_I386:
26650b57cec5SDimitry Andric       return "Mach-O 32-bit i386";
26660b57cec5SDimitry Andric     case MachO::CPU_TYPE_ARM:
26670b57cec5SDimitry Andric       return "Mach-O arm";
26680b57cec5SDimitry Andric     case MachO::CPU_TYPE_ARM64_32:
26690b57cec5SDimitry Andric       return "Mach-O arm64 (ILP32)";
26700b57cec5SDimitry Andric     case MachO::CPU_TYPE_POWERPC:
26710b57cec5SDimitry Andric       return "Mach-O 32-bit ppc";
26720b57cec5SDimitry Andric     default:
26730b57cec5SDimitry Andric       return "Mach-O 32-bit unknown";
26740b57cec5SDimitry Andric     }
26750b57cec5SDimitry Andric   }
26760b57cec5SDimitry Andric 
26770b57cec5SDimitry Andric   switch (CPUType) {
26780b57cec5SDimitry Andric   case MachO::CPU_TYPE_X86_64:
26790b57cec5SDimitry Andric     return "Mach-O 64-bit x86-64";
26800b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64:
26810b57cec5SDimitry Andric     return "Mach-O arm64";
26820b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
26830b57cec5SDimitry Andric     return "Mach-O 64-bit ppc64";
26840b57cec5SDimitry Andric   default:
26850b57cec5SDimitry Andric     return "Mach-O 64-bit unknown";
26860b57cec5SDimitry Andric   }
26870b57cec5SDimitry Andric }
26880b57cec5SDimitry Andric 
2689480093f4SDimitry Andric Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
26900b57cec5SDimitry Andric   switch (CPUType) {
26910b57cec5SDimitry Andric   case MachO::CPU_TYPE_I386:
26920b57cec5SDimitry Andric     return Triple::x86;
26930b57cec5SDimitry Andric   case MachO::CPU_TYPE_X86_64:
26940b57cec5SDimitry Andric     return Triple::x86_64;
26950b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM:
26960b57cec5SDimitry Andric     return Triple::arm;
26970b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64:
26980b57cec5SDimitry Andric     return Triple::aarch64;
26990b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64_32:
27000b57cec5SDimitry Andric     return Triple::aarch64_32;
27010b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC:
27020b57cec5SDimitry Andric     return Triple::ppc;
27030b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
27040b57cec5SDimitry Andric     return Triple::ppc64;
27050b57cec5SDimitry Andric   default:
27060b57cec5SDimitry Andric     return Triple::UnknownArch;
27070b57cec5SDimitry Andric   }
27080b57cec5SDimitry Andric }
27090b57cec5SDimitry Andric 
27100b57cec5SDimitry Andric Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
27110b57cec5SDimitry Andric                                       const char **McpuDefault,
27120b57cec5SDimitry Andric                                       const char **ArchFlag) {
27130b57cec5SDimitry Andric   if (McpuDefault)
27140b57cec5SDimitry Andric     *McpuDefault = nullptr;
27150b57cec5SDimitry Andric   if (ArchFlag)
27160b57cec5SDimitry Andric     *ArchFlag = nullptr;
27170b57cec5SDimitry Andric 
27180b57cec5SDimitry Andric   switch (CPUType) {
27190b57cec5SDimitry Andric   case MachO::CPU_TYPE_I386:
27200b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
27210b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_I386_ALL:
27220b57cec5SDimitry Andric       if (ArchFlag)
27230b57cec5SDimitry Andric         *ArchFlag = "i386";
27240b57cec5SDimitry Andric       return Triple("i386-apple-darwin");
27250b57cec5SDimitry Andric     default:
27260b57cec5SDimitry Andric       return Triple();
27270b57cec5SDimitry Andric     }
27280b57cec5SDimitry Andric   case MachO::CPU_TYPE_X86_64:
27290b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
27300b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_X86_64_ALL:
27310b57cec5SDimitry Andric       if (ArchFlag)
27320b57cec5SDimitry Andric         *ArchFlag = "x86_64";
27330b57cec5SDimitry Andric       return Triple("x86_64-apple-darwin");
27340b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_X86_64_H:
27350b57cec5SDimitry Andric       if (ArchFlag)
27360b57cec5SDimitry Andric         *ArchFlag = "x86_64h";
27370b57cec5SDimitry Andric       return Triple("x86_64h-apple-darwin");
27380b57cec5SDimitry Andric     default:
27390b57cec5SDimitry Andric       return Triple();
27400b57cec5SDimitry Andric     }
27410b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM:
27420b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
27430b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V4T:
27440b57cec5SDimitry Andric       if (ArchFlag)
27450b57cec5SDimitry Andric         *ArchFlag = "armv4t";
27460b57cec5SDimitry Andric       return Triple("armv4t-apple-darwin");
27470b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
27480b57cec5SDimitry Andric       if (ArchFlag)
27490b57cec5SDimitry Andric         *ArchFlag = "armv5e";
27500b57cec5SDimitry Andric       return Triple("armv5e-apple-darwin");
27510b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_XSCALE:
27520b57cec5SDimitry Andric       if (ArchFlag)
27530b57cec5SDimitry Andric         *ArchFlag = "xscale";
27540b57cec5SDimitry Andric       return Triple("xscale-apple-darwin");
27550b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V6:
27560b57cec5SDimitry Andric       if (ArchFlag)
27570b57cec5SDimitry Andric         *ArchFlag = "armv6";
27580b57cec5SDimitry Andric       return Triple("armv6-apple-darwin");
27590b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V6M:
27600b57cec5SDimitry Andric       if (McpuDefault)
27610b57cec5SDimitry Andric         *McpuDefault = "cortex-m0";
27620b57cec5SDimitry Andric       if (ArchFlag)
27630b57cec5SDimitry Andric         *ArchFlag = "armv6m";
27640b57cec5SDimitry Andric       return Triple("armv6m-apple-darwin");
27650b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7:
27660b57cec5SDimitry Andric       if (ArchFlag)
27670b57cec5SDimitry Andric         *ArchFlag = "armv7";
27680b57cec5SDimitry Andric       return Triple("armv7-apple-darwin");
27690b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7EM:
27700b57cec5SDimitry Andric       if (McpuDefault)
27710b57cec5SDimitry Andric         *McpuDefault = "cortex-m4";
27720b57cec5SDimitry Andric       if (ArchFlag)
27730b57cec5SDimitry Andric         *ArchFlag = "armv7em";
27740b57cec5SDimitry Andric       return Triple("thumbv7em-apple-darwin");
27750b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7K:
27760b57cec5SDimitry Andric       if (McpuDefault)
27770b57cec5SDimitry Andric         *McpuDefault = "cortex-a7";
27780b57cec5SDimitry Andric       if (ArchFlag)
27790b57cec5SDimitry Andric         *ArchFlag = "armv7k";
27800b57cec5SDimitry Andric       return Triple("armv7k-apple-darwin");
27810b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7M:
27820b57cec5SDimitry Andric       if (McpuDefault)
27830b57cec5SDimitry Andric         *McpuDefault = "cortex-m3";
27840b57cec5SDimitry Andric       if (ArchFlag)
27850b57cec5SDimitry Andric         *ArchFlag = "armv7m";
27860b57cec5SDimitry Andric       return Triple("thumbv7m-apple-darwin");
27870b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM_V7S:
27880b57cec5SDimitry Andric       if (McpuDefault)
27890b57cec5SDimitry Andric         *McpuDefault = "cortex-a7";
27900b57cec5SDimitry Andric       if (ArchFlag)
27910b57cec5SDimitry Andric         *ArchFlag = "armv7s";
27920b57cec5SDimitry Andric       return Triple("armv7s-apple-darwin");
27930b57cec5SDimitry Andric     default:
27940b57cec5SDimitry Andric       return Triple();
27950b57cec5SDimitry Andric     }
27960b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64:
27970b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
27980b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM64_ALL:
27990b57cec5SDimitry Andric       if (McpuDefault)
28000b57cec5SDimitry Andric         *McpuDefault = "cyclone";
28010b57cec5SDimitry Andric       if (ArchFlag)
28020b57cec5SDimitry Andric         *ArchFlag = "arm64";
28030b57cec5SDimitry Andric       return Triple("arm64-apple-darwin");
2804e8d8bef9SDimitry Andric     case MachO::CPU_SUBTYPE_ARM64E:
2805e8d8bef9SDimitry Andric       if (McpuDefault)
2806e8d8bef9SDimitry Andric         *McpuDefault = "apple-a12";
2807e8d8bef9SDimitry Andric       if (ArchFlag)
2808e8d8bef9SDimitry Andric         *ArchFlag = "arm64e";
2809e8d8bef9SDimitry Andric       return Triple("arm64e-apple-darwin");
28100b57cec5SDimitry Andric     default:
28110b57cec5SDimitry Andric       return Triple();
28120b57cec5SDimitry Andric     }
28130b57cec5SDimitry Andric   case MachO::CPU_TYPE_ARM64_32:
28140b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
28150b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_ARM64_32_V8:
28160b57cec5SDimitry Andric       if (McpuDefault)
28170b57cec5SDimitry Andric         *McpuDefault = "cyclone";
28180b57cec5SDimitry Andric       if (ArchFlag)
28190b57cec5SDimitry Andric         *ArchFlag = "arm64_32";
28200b57cec5SDimitry Andric       return Triple("arm64_32-apple-darwin");
28210b57cec5SDimitry Andric     default:
28220b57cec5SDimitry Andric       return Triple();
28230b57cec5SDimitry Andric     }
28240b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC:
28250b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
28260b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_POWERPC_ALL:
28270b57cec5SDimitry Andric       if (ArchFlag)
28280b57cec5SDimitry Andric         *ArchFlag = "ppc";
28290b57cec5SDimitry Andric       return Triple("ppc-apple-darwin");
28300b57cec5SDimitry Andric     default:
28310b57cec5SDimitry Andric       return Triple();
28320b57cec5SDimitry Andric     }
28330b57cec5SDimitry Andric   case MachO::CPU_TYPE_POWERPC64:
28340b57cec5SDimitry Andric     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
28350b57cec5SDimitry Andric     case MachO::CPU_SUBTYPE_POWERPC_ALL:
28360b57cec5SDimitry Andric       if (ArchFlag)
28370b57cec5SDimitry Andric         *ArchFlag = "ppc64";
28380b57cec5SDimitry Andric       return Triple("ppc64-apple-darwin");
28390b57cec5SDimitry Andric     default:
28400b57cec5SDimitry Andric       return Triple();
28410b57cec5SDimitry Andric     }
28420b57cec5SDimitry Andric   default:
28430b57cec5SDimitry Andric     return Triple();
28440b57cec5SDimitry Andric   }
28450b57cec5SDimitry Andric }
28460b57cec5SDimitry Andric 
28470b57cec5SDimitry Andric Triple MachOObjectFile::getHostArch() {
28480b57cec5SDimitry Andric   return Triple(sys::getDefaultTargetTriple());
28490b57cec5SDimitry Andric }
28500b57cec5SDimitry Andric 
28510b57cec5SDimitry Andric bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
28528bcb0991SDimitry Andric   auto validArchs = getValidArchs();
2853e8d8bef9SDimitry Andric   return llvm::is_contained(validArchs, ArchFlag);
28540b57cec5SDimitry Andric }
28550b57cec5SDimitry Andric 
28568bcb0991SDimitry Andric ArrayRef<StringRef> MachOObjectFile::getValidArchs() {
2857e8d8bef9SDimitry Andric   static const std::array<StringRef, 18> ValidArchs = {{
2858e8d8bef9SDimitry Andric       "i386",
2859e8d8bef9SDimitry Andric       "x86_64",
2860e8d8bef9SDimitry Andric       "x86_64h",
2861e8d8bef9SDimitry Andric       "armv4t",
2862e8d8bef9SDimitry Andric       "arm",
2863e8d8bef9SDimitry Andric       "armv5e",
2864e8d8bef9SDimitry Andric       "armv6",
2865e8d8bef9SDimitry Andric       "armv6m",
2866e8d8bef9SDimitry Andric       "armv7",
2867e8d8bef9SDimitry Andric       "armv7em",
2868e8d8bef9SDimitry Andric       "armv7k",
2869e8d8bef9SDimitry Andric       "armv7m",
2870e8d8bef9SDimitry Andric       "armv7s",
2871e8d8bef9SDimitry Andric       "arm64",
2872e8d8bef9SDimitry Andric       "arm64e",
2873e8d8bef9SDimitry Andric       "arm64_32",
2874e8d8bef9SDimitry Andric       "ppc",
2875e8d8bef9SDimitry Andric       "ppc64",
28768bcb0991SDimitry Andric   }};
28778bcb0991SDimitry Andric 
2878e8d8bef9SDimitry Andric   return ValidArchs;
28798bcb0991SDimitry Andric }
28800b57cec5SDimitry Andric 
28810b57cec5SDimitry Andric Triple::ArchType MachOObjectFile::getArch() const {
2882480093f4SDimitry Andric   return getArch(getCPUType(*this), getCPUSubType(*this));
28830b57cec5SDimitry Andric }
28840b57cec5SDimitry Andric 
28850b57cec5SDimitry Andric Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
28860b57cec5SDimitry Andric   return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
28870b57cec5SDimitry Andric }
28880b57cec5SDimitry Andric 
28890b57cec5SDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
28900b57cec5SDimitry Andric   DataRefImpl DRI;
28910b57cec5SDimitry Andric   DRI.d.a = Index;
28920b57cec5SDimitry Andric   return section_rel_begin(DRI);
28930b57cec5SDimitry Andric }
28940b57cec5SDimitry Andric 
28950b57cec5SDimitry Andric relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
28960b57cec5SDimitry Andric   DataRefImpl DRI;
28970b57cec5SDimitry Andric   DRI.d.a = Index;
28980b57cec5SDimitry Andric   return section_rel_end(DRI);
28990b57cec5SDimitry Andric }
29000b57cec5SDimitry Andric 
29010b57cec5SDimitry Andric dice_iterator MachOObjectFile::begin_dices() const {
29020b57cec5SDimitry Andric   DataRefImpl DRI;
29030b57cec5SDimitry Andric   if (!DataInCodeLoadCmd)
29040b57cec5SDimitry Andric     return dice_iterator(DiceRef(DRI, this));
29050b57cec5SDimitry Andric 
29060b57cec5SDimitry Andric   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
29070b57cec5SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
29080b57cec5SDimitry Andric   return dice_iterator(DiceRef(DRI, this));
29090b57cec5SDimitry Andric }
29100b57cec5SDimitry Andric 
29110b57cec5SDimitry Andric dice_iterator MachOObjectFile::end_dices() const {
29120b57cec5SDimitry Andric   DataRefImpl DRI;
29130b57cec5SDimitry Andric   if (!DataInCodeLoadCmd)
29140b57cec5SDimitry Andric     return dice_iterator(DiceRef(DRI, this));
29150b57cec5SDimitry Andric 
29160b57cec5SDimitry Andric   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
29170b57cec5SDimitry Andric   unsigned Offset = DicLC.dataoff + DicLC.datasize;
29180b57cec5SDimitry Andric   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
29190b57cec5SDimitry Andric   return dice_iterator(DiceRef(DRI, this));
29200b57cec5SDimitry Andric }
29210b57cec5SDimitry Andric 
29220b57cec5SDimitry Andric ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
29230b57cec5SDimitry Andric                          ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
29240b57cec5SDimitry Andric 
29250b57cec5SDimitry Andric void ExportEntry::moveToFirst() {
29260b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
29270b57cec5SDimitry Andric   pushNode(0);
29280b57cec5SDimitry Andric   if (*E)
29290b57cec5SDimitry Andric     return;
29300b57cec5SDimitry Andric   pushDownUntilBottom();
29310b57cec5SDimitry Andric }
29320b57cec5SDimitry Andric 
29330b57cec5SDimitry Andric void ExportEntry::moveToEnd() {
29340b57cec5SDimitry Andric   Stack.clear();
29350b57cec5SDimitry Andric   Done = true;
29360b57cec5SDimitry Andric }
29370b57cec5SDimitry Andric 
29380b57cec5SDimitry Andric bool ExportEntry::operator==(const ExportEntry &Other) const {
29390b57cec5SDimitry Andric   // Common case, one at end, other iterating from begin.
29400b57cec5SDimitry Andric   if (Done || Other.Done)
29410b57cec5SDimitry Andric     return (Done == Other.Done);
29420b57cec5SDimitry Andric   // Not equal if different stack sizes.
29430b57cec5SDimitry Andric   if (Stack.size() != Other.Stack.size())
29440b57cec5SDimitry Andric     return false;
29450b57cec5SDimitry Andric   // Not equal if different cumulative strings.
29460b57cec5SDimitry Andric   if (!CumulativeString.equals(Other.CumulativeString))
29470b57cec5SDimitry Andric     return false;
29480b57cec5SDimitry Andric   // Equal if all nodes in both stacks match.
29490b57cec5SDimitry Andric   for (unsigned i=0; i < Stack.size(); ++i) {
29500b57cec5SDimitry Andric     if (Stack[i].Start != Other.Stack[i].Start)
29510b57cec5SDimitry Andric       return false;
29520b57cec5SDimitry Andric   }
29530b57cec5SDimitry Andric   return true;
29540b57cec5SDimitry Andric }
29550b57cec5SDimitry Andric 
29560b57cec5SDimitry Andric uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
29570b57cec5SDimitry Andric   unsigned Count;
29580b57cec5SDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
29590b57cec5SDimitry Andric   Ptr += Count;
29600b57cec5SDimitry Andric   if (Ptr > Trie.end())
29610b57cec5SDimitry Andric     Ptr = Trie.end();
29620b57cec5SDimitry Andric   return Result;
29630b57cec5SDimitry Andric }
29640b57cec5SDimitry Andric 
29650b57cec5SDimitry Andric StringRef ExportEntry::name() const {
29660b57cec5SDimitry Andric   return CumulativeString;
29670b57cec5SDimitry Andric }
29680b57cec5SDimitry Andric 
29690b57cec5SDimitry Andric uint64_t ExportEntry::flags() const {
29700b57cec5SDimitry Andric   return Stack.back().Flags;
29710b57cec5SDimitry Andric }
29720b57cec5SDimitry Andric 
29730b57cec5SDimitry Andric uint64_t ExportEntry::address() const {
29740b57cec5SDimitry Andric   return Stack.back().Address;
29750b57cec5SDimitry Andric }
29760b57cec5SDimitry Andric 
29770b57cec5SDimitry Andric uint64_t ExportEntry::other() const {
29780b57cec5SDimitry Andric   return Stack.back().Other;
29790b57cec5SDimitry Andric }
29800b57cec5SDimitry Andric 
29810b57cec5SDimitry Andric StringRef ExportEntry::otherName() const {
29820b57cec5SDimitry Andric   const char* ImportName = Stack.back().ImportName;
29830b57cec5SDimitry Andric   if (ImportName)
29840b57cec5SDimitry Andric     return StringRef(ImportName);
29850b57cec5SDimitry Andric   return StringRef();
29860b57cec5SDimitry Andric }
29870b57cec5SDimitry Andric 
29880b57cec5SDimitry Andric uint32_t ExportEntry::nodeOffset() const {
29890b57cec5SDimitry Andric   return Stack.back().Start - Trie.begin();
29900b57cec5SDimitry Andric }
29910b57cec5SDimitry Andric 
29920b57cec5SDimitry Andric ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
29930b57cec5SDimitry Andric     : Start(Ptr), Current(Ptr) {}
29940b57cec5SDimitry Andric 
29950b57cec5SDimitry Andric void ExportEntry::pushNode(uint64_t offset) {
29960b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
29970b57cec5SDimitry Andric   const uint8_t *Ptr = Trie.begin() + offset;
29980b57cec5SDimitry Andric   NodeState State(Ptr);
29995f757f3fSDimitry Andric   const char *error = nullptr;
30000b57cec5SDimitry Andric   uint64_t ExportInfoSize = readULEB128(State.Current, &error);
30010b57cec5SDimitry Andric   if (error) {
30020b57cec5SDimitry Andric     *E = malformedError("export info size " + Twine(error) +
30030b57cec5SDimitry Andric                         " in export trie data at node: 0x" +
30040b57cec5SDimitry Andric                         Twine::utohexstr(offset));
30050b57cec5SDimitry Andric     moveToEnd();
30060b57cec5SDimitry Andric     return;
30070b57cec5SDimitry Andric   }
30080b57cec5SDimitry Andric   State.IsExportNode = (ExportInfoSize != 0);
30090b57cec5SDimitry Andric   const uint8_t* Children = State.Current + ExportInfoSize;
30100b57cec5SDimitry Andric   if (Children > Trie.end()) {
30110b57cec5SDimitry Andric     *E = malformedError(
30120b57cec5SDimitry Andric         "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
30130b57cec5SDimitry Andric         " in export trie data at node: 0x" + Twine::utohexstr(offset) +
30140b57cec5SDimitry Andric         " too big and extends past end of trie data");
30150b57cec5SDimitry Andric     moveToEnd();
30160b57cec5SDimitry Andric     return;
30170b57cec5SDimitry Andric   }
30180b57cec5SDimitry Andric   if (State.IsExportNode) {
30190b57cec5SDimitry Andric     const uint8_t *ExportStart = State.Current;
30200b57cec5SDimitry Andric     State.Flags = readULEB128(State.Current, &error);
30210b57cec5SDimitry Andric     if (error) {
30220b57cec5SDimitry Andric       *E = malformedError("flags " + Twine(error) +
30230b57cec5SDimitry Andric                           " in export trie data at node: 0x" +
30240b57cec5SDimitry Andric                           Twine::utohexstr(offset));
30250b57cec5SDimitry Andric       moveToEnd();
30260b57cec5SDimitry Andric       return;
30270b57cec5SDimitry Andric     }
30280b57cec5SDimitry Andric     uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
30290b57cec5SDimitry Andric     if (State.Flags != 0 &&
30300b57cec5SDimitry Andric         (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
30310b57cec5SDimitry Andric          Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
30320b57cec5SDimitry Andric          Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
30330b57cec5SDimitry Andric       *E = malformedError(
30340b57cec5SDimitry Andric           "unsupported exported symbol kind: " + Twine((int)Kind) +
30350b57cec5SDimitry Andric           " in flags: 0x" + Twine::utohexstr(State.Flags) +
30360b57cec5SDimitry Andric           " in export trie data at node: 0x" + Twine::utohexstr(offset));
30370b57cec5SDimitry Andric       moveToEnd();
30380b57cec5SDimitry Andric       return;
30390b57cec5SDimitry Andric     }
30400b57cec5SDimitry Andric     if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
30410b57cec5SDimitry Andric       State.Address = 0;
30420b57cec5SDimitry Andric       State.Other = readULEB128(State.Current, &error); // dylib ordinal
30430b57cec5SDimitry Andric       if (error) {
30440b57cec5SDimitry Andric         *E = malformedError("dylib ordinal of re-export " + Twine(error) +
30450b57cec5SDimitry Andric                             " in export trie data at node: 0x" +
30460b57cec5SDimitry Andric                             Twine::utohexstr(offset));
30470b57cec5SDimitry Andric         moveToEnd();
30480b57cec5SDimitry Andric         return;
30490b57cec5SDimitry Andric       }
30500b57cec5SDimitry Andric       if (O != nullptr) {
305181ad6265SDimitry Andric         // Only positive numbers represent library ordinals. Zero and negative
305281ad6265SDimitry Andric         // numbers have special meaning (see BindSpecialDylib).
305381ad6265SDimitry Andric         if ((int64_t)State.Other > 0 && State.Other > O->getLibraryCount()) {
30540b57cec5SDimitry Andric           *E = malformedError(
30550b57cec5SDimitry Andric               "bad library ordinal: " + Twine((int)State.Other) + " (max " +
30560b57cec5SDimitry Andric               Twine((int)O->getLibraryCount()) +
30570b57cec5SDimitry Andric               ") in export trie data at node: 0x" + Twine::utohexstr(offset));
30580b57cec5SDimitry Andric           moveToEnd();
30590b57cec5SDimitry Andric           return;
30600b57cec5SDimitry Andric         }
30610b57cec5SDimitry Andric       }
30620b57cec5SDimitry Andric       State.ImportName = reinterpret_cast<const char*>(State.Current);
30630b57cec5SDimitry Andric       if (*State.ImportName == '\0') {
30640b57cec5SDimitry Andric         State.Current++;
30650b57cec5SDimitry Andric       } else {
30660b57cec5SDimitry Andric         const uint8_t *End = State.Current + 1;
30670b57cec5SDimitry Andric         if (End >= Trie.end()) {
30680b57cec5SDimitry Andric           *E = malformedError("import name of re-export in export trie data at "
30690b57cec5SDimitry Andric                               "node: 0x" +
30700b57cec5SDimitry Andric                               Twine::utohexstr(offset) +
30710b57cec5SDimitry Andric                               " starts past end of trie data");
30720b57cec5SDimitry Andric           moveToEnd();
30730b57cec5SDimitry Andric           return;
30740b57cec5SDimitry Andric         }
30750b57cec5SDimitry Andric         while(*End != '\0' && End < Trie.end())
30760b57cec5SDimitry Andric           End++;
30770b57cec5SDimitry Andric         if (*End != '\0') {
30780b57cec5SDimitry Andric           *E = malformedError("import name of re-export in export trie data at "
30790b57cec5SDimitry Andric                               "node: 0x" +
30800b57cec5SDimitry Andric                               Twine::utohexstr(offset) +
30810b57cec5SDimitry Andric                               " extends past end of trie data");
30820b57cec5SDimitry Andric           moveToEnd();
30830b57cec5SDimitry Andric           return;
30840b57cec5SDimitry Andric         }
30850b57cec5SDimitry Andric         State.Current = End + 1;
30860b57cec5SDimitry Andric       }
30870b57cec5SDimitry Andric     } else {
30880b57cec5SDimitry Andric       State.Address = readULEB128(State.Current, &error);
30890b57cec5SDimitry Andric       if (error) {
30900b57cec5SDimitry Andric         *E = malformedError("address " + Twine(error) +
30910b57cec5SDimitry Andric                             " in export trie data at node: 0x" +
30920b57cec5SDimitry Andric                             Twine::utohexstr(offset));
30930b57cec5SDimitry Andric         moveToEnd();
30940b57cec5SDimitry Andric         return;
30950b57cec5SDimitry Andric       }
30960b57cec5SDimitry Andric       if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
30970b57cec5SDimitry Andric         State.Other = readULEB128(State.Current, &error);
30980b57cec5SDimitry Andric         if (error) {
30990b57cec5SDimitry Andric           *E = malformedError("resolver of stub and resolver " + Twine(error) +
31000b57cec5SDimitry Andric                               " in export trie data at node: 0x" +
31010b57cec5SDimitry Andric                               Twine::utohexstr(offset));
31020b57cec5SDimitry Andric           moveToEnd();
31030b57cec5SDimitry Andric           return;
31040b57cec5SDimitry Andric         }
31050b57cec5SDimitry Andric       }
31060b57cec5SDimitry Andric     }
3107*0fca6ea1SDimitry Andric     if (ExportStart + ExportInfoSize < State.Current) {
31080b57cec5SDimitry Andric       *E = malformedError(
3109bdd1243dSDimitry Andric           "inconsistent export info size: 0x" +
31100b57cec5SDimitry Andric           Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
31110b57cec5SDimitry Andric           Twine::utohexstr(State.Current - ExportStart) +
31120b57cec5SDimitry Andric           " in export trie data at node: 0x" + Twine::utohexstr(offset));
31130b57cec5SDimitry Andric       moveToEnd();
31140b57cec5SDimitry Andric       return;
31150b57cec5SDimitry Andric     }
31160b57cec5SDimitry Andric   }
31170b57cec5SDimitry Andric   State.ChildCount = *Children;
31180b57cec5SDimitry Andric   if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
31190b57cec5SDimitry Andric     *E = malformedError("byte for count of childern in export trie data at "
31200b57cec5SDimitry Andric                         "node: 0x" +
31210b57cec5SDimitry Andric                         Twine::utohexstr(offset) +
31220b57cec5SDimitry Andric                         " extends past end of trie data");
31230b57cec5SDimitry Andric     moveToEnd();
31240b57cec5SDimitry Andric     return;
31250b57cec5SDimitry Andric   }
31260b57cec5SDimitry Andric   State.Current = Children + 1;
31270b57cec5SDimitry Andric   State.NextChildIndex = 0;
31280b57cec5SDimitry Andric   State.ParentStringLength = CumulativeString.size();
31290b57cec5SDimitry Andric   Stack.push_back(State);
31300b57cec5SDimitry Andric }
31310b57cec5SDimitry Andric 
31320b57cec5SDimitry Andric void ExportEntry::pushDownUntilBottom() {
31330b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
31345f757f3fSDimitry Andric   const char *error = nullptr;
31350b57cec5SDimitry Andric   while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
31360b57cec5SDimitry Andric     NodeState &Top = Stack.back();
31370b57cec5SDimitry Andric     CumulativeString.resize(Top.ParentStringLength);
31380b57cec5SDimitry Andric     for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
31390b57cec5SDimitry Andric       char C = *Top.Current;
31400b57cec5SDimitry Andric       CumulativeString.push_back(C);
31410b57cec5SDimitry Andric     }
31420b57cec5SDimitry Andric     if (Top.Current >= Trie.end()) {
31430b57cec5SDimitry Andric       *E = malformedError("edge sub-string in export trie data at node: 0x" +
31440b57cec5SDimitry Andric                           Twine::utohexstr(Top.Start - Trie.begin()) +
31450b57cec5SDimitry Andric                           " for child #" + Twine((int)Top.NextChildIndex) +
31460b57cec5SDimitry Andric                           " extends past end of trie data");
31470b57cec5SDimitry Andric       moveToEnd();
31480b57cec5SDimitry Andric       return;
31490b57cec5SDimitry Andric     }
31500b57cec5SDimitry Andric     Top.Current += 1;
31510b57cec5SDimitry Andric     uint64_t childNodeIndex = readULEB128(Top.Current, &error);
31520b57cec5SDimitry Andric     if (error) {
31530b57cec5SDimitry Andric       *E = malformedError("child node offset " + Twine(error) +
31540b57cec5SDimitry Andric                           " in export trie data at node: 0x" +
31550b57cec5SDimitry Andric                           Twine::utohexstr(Top.Start - Trie.begin()));
31560b57cec5SDimitry Andric       moveToEnd();
31570b57cec5SDimitry Andric       return;
31580b57cec5SDimitry Andric     }
31590b57cec5SDimitry Andric     for (const NodeState &node : nodes()) {
31600b57cec5SDimitry Andric       if (node.Start == Trie.begin() + childNodeIndex){
31610b57cec5SDimitry Andric         *E = malformedError("loop in childern in export trie data at node: 0x" +
31620b57cec5SDimitry Andric                             Twine::utohexstr(Top.Start - Trie.begin()) +
31630b57cec5SDimitry Andric                             " back to node: 0x" +
31640b57cec5SDimitry Andric                             Twine::utohexstr(childNodeIndex));
31650b57cec5SDimitry Andric         moveToEnd();
31660b57cec5SDimitry Andric         return;
31670b57cec5SDimitry Andric       }
31680b57cec5SDimitry Andric     }
31690b57cec5SDimitry Andric     Top.NextChildIndex += 1;
31700b57cec5SDimitry Andric     pushNode(childNodeIndex);
31710b57cec5SDimitry Andric     if (*E)
31720b57cec5SDimitry Andric       return;
31730b57cec5SDimitry Andric   }
31740b57cec5SDimitry Andric   if (!Stack.back().IsExportNode) {
31750b57cec5SDimitry Andric     *E = malformedError("node is not an export node in export trie data at "
31760b57cec5SDimitry Andric                         "node: 0x" +
31770b57cec5SDimitry Andric                         Twine::utohexstr(Stack.back().Start - Trie.begin()));
31780b57cec5SDimitry Andric     moveToEnd();
31790b57cec5SDimitry Andric     return;
31800b57cec5SDimitry Andric   }
31810b57cec5SDimitry Andric }
31820b57cec5SDimitry Andric 
31830b57cec5SDimitry Andric // We have a trie data structure and need a way to walk it that is compatible
31840b57cec5SDimitry Andric // with the C++ iterator model. The solution is a non-recursive depth first
31850b57cec5SDimitry Andric // traversal where the iterator contains a stack of parent nodes along with a
31860b57cec5SDimitry Andric // string that is the accumulation of all edge strings along the parent chain
31870b57cec5SDimitry Andric // to this point.
31880b57cec5SDimitry Andric //
31890b57cec5SDimitry Andric // There is one "export" node for each exported symbol.  But because some
31900b57cec5SDimitry Andric // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
31910b57cec5SDimitry Andric // node may have child nodes too.
31920b57cec5SDimitry Andric //
31930b57cec5SDimitry Andric // The algorithm for moveNext() is to keep moving down the leftmost unvisited
31940b57cec5SDimitry Andric // child until hitting a node with no children (which is an export node or
31950b57cec5SDimitry Andric // else the trie is malformed). On the way down, each node is pushed on the
31960b57cec5SDimitry Andric // stack ivar.  If there is no more ways down, it pops up one and tries to go
31970b57cec5SDimitry Andric // down a sibling path until a childless node is reached.
31980b57cec5SDimitry Andric void ExportEntry::moveNext() {
31990b57cec5SDimitry Andric   assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
32000b57cec5SDimitry Andric   if (!Stack.back().IsExportNode) {
32010b57cec5SDimitry Andric     *E = malformedError("node is not an export node in export trie data at "
32020b57cec5SDimitry Andric                         "node: 0x" +
32030b57cec5SDimitry Andric                         Twine::utohexstr(Stack.back().Start - Trie.begin()));
32040b57cec5SDimitry Andric     moveToEnd();
32050b57cec5SDimitry Andric     return;
32060b57cec5SDimitry Andric   }
32070b57cec5SDimitry Andric 
32080b57cec5SDimitry Andric   Stack.pop_back();
32090b57cec5SDimitry Andric   while (!Stack.empty()) {
32100b57cec5SDimitry Andric     NodeState &Top = Stack.back();
32110b57cec5SDimitry Andric     if (Top.NextChildIndex < Top.ChildCount) {
32120b57cec5SDimitry Andric       pushDownUntilBottom();
32130b57cec5SDimitry Andric       // Now at the next export node.
32140b57cec5SDimitry Andric       return;
32150b57cec5SDimitry Andric     } else {
32160b57cec5SDimitry Andric       if (Top.IsExportNode) {
32170b57cec5SDimitry Andric         // This node has no children but is itself an export node.
32180b57cec5SDimitry Andric         CumulativeString.resize(Top.ParentStringLength);
32190b57cec5SDimitry Andric         return;
32200b57cec5SDimitry Andric       }
32210b57cec5SDimitry Andric       Stack.pop_back();
32220b57cec5SDimitry Andric     }
32230b57cec5SDimitry Andric   }
32240b57cec5SDimitry Andric   Done = true;
32250b57cec5SDimitry Andric }
32260b57cec5SDimitry Andric 
32270b57cec5SDimitry Andric iterator_range<export_iterator>
32280b57cec5SDimitry Andric MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
32290b57cec5SDimitry Andric                          const MachOObjectFile *O) {
32300b57cec5SDimitry Andric   ExportEntry Start(&E, O, Trie);
32310b57cec5SDimitry Andric   if (Trie.empty())
32320b57cec5SDimitry Andric     Start.moveToEnd();
32330b57cec5SDimitry Andric   else
32340b57cec5SDimitry Andric     Start.moveToFirst();
32350b57cec5SDimitry Andric 
32360b57cec5SDimitry Andric   ExportEntry Finish(&E, O, Trie);
32370b57cec5SDimitry Andric   Finish.moveToEnd();
32380b57cec5SDimitry Andric 
32390b57cec5SDimitry Andric   return make_range(export_iterator(Start), export_iterator(Finish));
32400b57cec5SDimitry Andric }
32410b57cec5SDimitry Andric 
32420b57cec5SDimitry Andric iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3243bdd1243dSDimitry Andric   ArrayRef<uint8_t> Trie;
3244bdd1243dSDimitry Andric   if (DyldInfoLoadCmd)
3245bdd1243dSDimitry Andric     Trie = getDyldInfoExportsTrie();
3246bdd1243dSDimitry Andric   else if (DyldExportsTrieLoadCmd)
3247bdd1243dSDimitry Andric     Trie = getDyldExportsTrie();
3248bdd1243dSDimitry Andric 
3249bdd1243dSDimitry Andric   return exports(Err, Trie, this);
32500b57cec5SDimitry Andric }
32510b57cec5SDimitry Andric 
325281ad6265SDimitry Andric MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error *E,
325381ad6265SDimitry Andric                                                  const MachOObjectFile *O)
325481ad6265SDimitry Andric     : E(E), O(O) {
325581ad6265SDimitry Andric   // Cache the vmaddress of __TEXT
325681ad6265SDimitry Andric   for (const auto &Command : O->load_commands()) {
325781ad6265SDimitry Andric     if (Command.C.cmd == MachO::LC_SEGMENT) {
325881ad6265SDimitry Andric       MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
3259*0fca6ea1SDimitry Andric       if (StringRef(SLC.segname) == "__TEXT") {
326081ad6265SDimitry Andric         TextAddress = SLC.vmaddr;
326181ad6265SDimitry Andric         break;
326281ad6265SDimitry Andric       }
326381ad6265SDimitry Andric     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
326481ad6265SDimitry Andric       MachO::segment_command_64 SLC_64 = O->getSegment64LoadCommand(Command);
3265*0fca6ea1SDimitry Andric       if (StringRef(SLC_64.segname) == "__TEXT") {
326681ad6265SDimitry Andric         TextAddress = SLC_64.vmaddr;
326781ad6265SDimitry Andric         break;
326881ad6265SDimitry Andric       }
326981ad6265SDimitry Andric     }
327081ad6265SDimitry Andric   }
327181ad6265SDimitry Andric }
327281ad6265SDimitry Andric 
327381ad6265SDimitry Andric int32_t MachOAbstractFixupEntry::segmentIndex() const { return SegmentIndex; }
327481ad6265SDimitry Andric 
327581ad6265SDimitry Andric uint64_t MachOAbstractFixupEntry::segmentOffset() const {
327681ad6265SDimitry Andric   return SegmentOffset;
327781ad6265SDimitry Andric }
327881ad6265SDimitry Andric 
327981ad6265SDimitry Andric uint64_t MachOAbstractFixupEntry::segmentAddress() const {
328081ad6265SDimitry Andric   return O->BindRebaseAddress(SegmentIndex, 0);
328181ad6265SDimitry Andric }
328281ad6265SDimitry Andric 
328381ad6265SDimitry Andric StringRef MachOAbstractFixupEntry::segmentName() const {
328481ad6265SDimitry Andric   return O->BindRebaseSegmentName(SegmentIndex);
328581ad6265SDimitry Andric }
328681ad6265SDimitry Andric 
328781ad6265SDimitry Andric StringRef MachOAbstractFixupEntry::sectionName() const {
328881ad6265SDimitry Andric   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
328981ad6265SDimitry Andric }
329081ad6265SDimitry Andric 
329181ad6265SDimitry Andric uint64_t MachOAbstractFixupEntry::address() const {
329281ad6265SDimitry Andric   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
329381ad6265SDimitry Andric }
329481ad6265SDimitry Andric 
329581ad6265SDimitry Andric StringRef MachOAbstractFixupEntry::symbolName() const { return SymbolName; }
329681ad6265SDimitry Andric 
329781ad6265SDimitry Andric int64_t MachOAbstractFixupEntry::addend() const { return Addend; }
329881ad6265SDimitry Andric 
329981ad6265SDimitry Andric uint32_t MachOAbstractFixupEntry::flags() const { return Flags; }
330081ad6265SDimitry Andric 
330181ad6265SDimitry Andric int MachOAbstractFixupEntry::ordinal() const { return Ordinal; }
330281ad6265SDimitry Andric 
330381ad6265SDimitry Andric StringRef MachOAbstractFixupEntry::typeName() const { return "unknown"; }
330481ad6265SDimitry Andric 
330581ad6265SDimitry Andric void MachOAbstractFixupEntry::moveToFirst() {
330681ad6265SDimitry Andric   SegmentOffset = 0;
330781ad6265SDimitry Andric   SegmentIndex = -1;
330881ad6265SDimitry Andric   Ordinal = 0;
330981ad6265SDimitry Andric   Flags = 0;
331081ad6265SDimitry Andric   Addend = 0;
331181ad6265SDimitry Andric   Done = false;
331281ad6265SDimitry Andric }
331381ad6265SDimitry Andric 
331481ad6265SDimitry Andric void MachOAbstractFixupEntry::moveToEnd() { Done = true; }
331581ad6265SDimitry Andric 
3316bdd1243dSDimitry Andric void MachOAbstractFixupEntry::moveNext() {}
3317bdd1243dSDimitry Andric 
331881ad6265SDimitry Andric MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E,
331981ad6265SDimitry Andric                                                const MachOObjectFile *O,
332081ad6265SDimitry Andric                                                bool Parse)
332181ad6265SDimitry Andric     : MachOAbstractFixupEntry(E, O) {
332281ad6265SDimitry Andric   ErrorAsOutParameter e(E);
332381ad6265SDimitry Andric   if (!Parse)
332481ad6265SDimitry Andric     return;
3325bdd1243dSDimitry Andric 
3326bdd1243dSDimitry Andric   if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) {
332781ad6265SDimitry Andric     FixupTargets = *FixupTargetsOrErr;
3328bdd1243dSDimitry Andric   } else {
332981ad6265SDimitry Andric     *E = FixupTargetsOrErr.takeError();
333081ad6265SDimitry Andric     return;
333181ad6265SDimitry Andric   }
3332bdd1243dSDimitry Andric 
3333bdd1243dSDimitry Andric   if (auto SegmentsOrErr = O->getChainedFixupsSegments()) {
3334bdd1243dSDimitry Andric     Segments = std::move(SegmentsOrErr->second);
3335bdd1243dSDimitry Andric   } else {
3336bdd1243dSDimitry Andric     *E = SegmentsOrErr.takeError();
3337bdd1243dSDimitry Andric     return;
3338bdd1243dSDimitry Andric   }
3339bdd1243dSDimitry Andric }
3340bdd1243dSDimitry Andric 
3341bdd1243dSDimitry Andric void MachOChainedFixupEntry::findNextPageWithFixups() {
3342bdd1243dSDimitry Andric   auto FindInSegment = [this]() {
3343bdd1243dSDimitry Andric     const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];
3344bdd1243dSDimitry Andric     while (PageIndex < SegInfo.PageStarts.size() &&
3345bdd1243dSDimitry Andric            SegInfo.PageStarts[PageIndex] == MachO::DYLD_CHAINED_PTR_START_NONE)
3346bdd1243dSDimitry Andric       ++PageIndex;
3347bdd1243dSDimitry Andric     return PageIndex < SegInfo.PageStarts.size();
3348bdd1243dSDimitry Andric   };
3349bdd1243dSDimitry Andric 
3350bdd1243dSDimitry Andric   while (InfoSegIndex < Segments.size()) {
3351bdd1243dSDimitry Andric     if (FindInSegment()) {
3352bdd1243dSDimitry Andric       PageOffset = Segments[InfoSegIndex].PageStarts[PageIndex];
3353bdd1243dSDimitry Andric       SegmentData = O->getSegmentContents(Segments[InfoSegIndex].SegIdx);
3354bdd1243dSDimitry Andric       return;
3355bdd1243dSDimitry Andric     }
3356bdd1243dSDimitry Andric 
3357bdd1243dSDimitry Andric     InfoSegIndex++;
3358bdd1243dSDimitry Andric     PageIndex = 0;
3359bdd1243dSDimitry Andric   }
336081ad6265SDimitry Andric }
336181ad6265SDimitry Andric 
336281ad6265SDimitry Andric void MachOChainedFixupEntry::moveToFirst() {
336381ad6265SDimitry Andric   MachOAbstractFixupEntry::moveToFirst();
3364bdd1243dSDimitry Andric   if (Segments.empty()) {
3365bdd1243dSDimitry Andric     Done = true;
3366bdd1243dSDimitry Andric     return;
3367bdd1243dSDimitry Andric   }
3368bdd1243dSDimitry Andric 
3369bdd1243dSDimitry Andric   InfoSegIndex = 0;
3370bdd1243dSDimitry Andric   PageIndex = 0;
3371bdd1243dSDimitry Andric 
3372bdd1243dSDimitry Andric   findNextPageWithFixups();
337381ad6265SDimitry Andric   moveNext();
337481ad6265SDimitry Andric }
337581ad6265SDimitry Andric 
337681ad6265SDimitry Andric void MachOChainedFixupEntry::moveToEnd() {
337781ad6265SDimitry Andric   MachOAbstractFixupEntry::moveToEnd();
337881ad6265SDimitry Andric }
337981ad6265SDimitry Andric 
3380bdd1243dSDimitry Andric void MachOChainedFixupEntry::moveNext() {
3381bdd1243dSDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
3382bdd1243dSDimitry Andric 
3383bdd1243dSDimitry Andric   if (InfoSegIndex == Segments.size()) {
3384bdd1243dSDimitry Andric     Done = true;
3385bdd1243dSDimitry Andric     return;
3386bdd1243dSDimitry Andric   }
3387bdd1243dSDimitry Andric 
3388bdd1243dSDimitry Andric   const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];
3389bdd1243dSDimitry Andric   SegmentIndex = SegInfo.SegIdx;
3390bdd1243dSDimitry Andric   SegmentOffset = SegInfo.Header.page_size * PageIndex + PageOffset;
3391bdd1243dSDimitry Andric 
3392bdd1243dSDimitry Andric   // FIXME: Handle other pointer formats.
3393bdd1243dSDimitry Andric   uint16_t PointerFormat = SegInfo.Header.pointer_format;
3394bdd1243dSDimitry Andric   if (PointerFormat != MachO::DYLD_CHAINED_PTR_64 &&
3395bdd1243dSDimitry Andric       PointerFormat != MachO::DYLD_CHAINED_PTR_64_OFFSET) {
3396bdd1243dSDimitry Andric     *E = createError("segment " + Twine(SegmentIndex) +
3397bdd1243dSDimitry Andric                      " has unsupported chained fixup pointer_format " +
3398bdd1243dSDimitry Andric                      Twine(PointerFormat));
3399bdd1243dSDimitry Andric     moveToEnd();
3400bdd1243dSDimitry Andric     return;
3401bdd1243dSDimitry Andric   }
3402bdd1243dSDimitry Andric 
3403bdd1243dSDimitry Andric   Ordinal = 0;
3404bdd1243dSDimitry Andric   Flags = 0;
3405bdd1243dSDimitry Andric   Addend = 0;
3406bdd1243dSDimitry Andric   PointerValue = 0;
3407bdd1243dSDimitry Andric   SymbolName = {};
3408bdd1243dSDimitry Andric 
3409bdd1243dSDimitry Andric   if (SegmentOffset + sizeof(RawValue) > SegmentData.size()) {
3410bdd1243dSDimitry Andric     *E = malformedError("fixup in segment " + Twine(SegmentIndex) +
3411bdd1243dSDimitry Andric                         " at offset " + Twine(SegmentOffset) +
3412bdd1243dSDimitry Andric                         " extends past segment's end");
3413bdd1243dSDimitry Andric     moveToEnd();
3414bdd1243dSDimitry Andric     return;
3415bdd1243dSDimitry Andric   }
3416bdd1243dSDimitry Andric 
3417bdd1243dSDimitry Andric   static_assert(sizeof(RawValue) == sizeof(MachO::dyld_chained_import_addend));
3418bdd1243dSDimitry Andric   memcpy(&RawValue, SegmentData.data() + SegmentOffset, sizeof(RawValue));
3419bdd1243dSDimitry Andric   if (O->isLittleEndian() != sys::IsLittleEndianHost)
3420bdd1243dSDimitry Andric     sys::swapByteOrder(RawValue);
3421bdd1243dSDimitry Andric 
3422bdd1243dSDimitry Andric   // The bit extraction below assumes little-endian fixup entries.
3423bdd1243dSDimitry Andric   assert(O->isLittleEndian() && "big-endian object should have been rejected "
3424bdd1243dSDimitry Andric                                 "by getDyldChainedFixupTargets()");
3425bdd1243dSDimitry Andric   auto Field = [this](uint8_t Right, uint8_t Count) {
3426bdd1243dSDimitry Andric     return (RawValue >> Right) & ((1ULL << Count) - 1);
3427bdd1243dSDimitry Andric   };
3428bdd1243dSDimitry Andric 
3429bdd1243dSDimitry Andric   // The `bind` field (most significant bit) of the encoded fixup determines
3430bdd1243dSDimitry Andric   // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
3431bdd1243dSDimitry Andric   bool IsBind = Field(63, 1);
3432bdd1243dSDimitry Andric   Kind = IsBind ? FixupKind::Bind : FixupKind::Rebase;
3433bdd1243dSDimitry Andric   uint32_t Next = Field(51, 12);
3434bdd1243dSDimitry Andric   if (IsBind) {
3435bdd1243dSDimitry Andric     uint32_t ImportOrdinal = Field(0, 24);
3436bdd1243dSDimitry Andric     uint8_t InlineAddend = Field(24, 8);
3437bdd1243dSDimitry Andric 
3438bdd1243dSDimitry Andric     if (ImportOrdinal >= FixupTargets.size()) {
3439bdd1243dSDimitry Andric       *E = malformedError("fixup in segment " + Twine(SegmentIndex) +
3440bdd1243dSDimitry Andric                           " at offset " + Twine(SegmentOffset) +
3441bdd1243dSDimitry Andric                           "  has out-of range import ordinal " +
3442bdd1243dSDimitry Andric                           Twine(ImportOrdinal));
3443bdd1243dSDimitry Andric       moveToEnd();
3444bdd1243dSDimitry Andric       return;
3445bdd1243dSDimitry Andric     }
3446bdd1243dSDimitry Andric 
3447bdd1243dSDimitry Andric     ChainedFixupTarget &Target = FixupTargets[ImportOrdinal];
3448bdd1243dSDimitry Andric     Ordinal = Target.libOrdinal();
3449bdd1243dSDimitry Andric     Addend = InlineAddend ? InlineAddend : Target.addend();
3450bdd1243dSDimitry Andric     Flags = Target.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0;
3451bdd1243dSDimitry Andric     SymbolName = Target.symbolName();
3452bdd1243dSDimitry Andric   } else {
3453bdd1243dSDimitry Andric     uint64_t Target = Field(0, 36);
3454bdd1243dSDimitry Andric     uint64_t High8 = Field(36, 8);
3455bdd1243dSDimitry Andric 
3456bdd1243dSDimitry Andric     PointerValue = Target | (High8 << 56);
3457bdd1243dSDimitry Andric     if (PointerFormat == MachO::DYLD_CHAINED_PTR_64_OFFSET)
3458bdd1243dSDimitry Andric       PointerValue += textAddress();
3459bdd1243dSDimitry Andric   }
3460bdd1243dSDimitry Andric 
3461bdd1243dSDimitry Andric   // The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET).
3462bdd1243dSDimitry Andric   if (Next != 0) {
3463bdd1243dSDimitry Andric     PageOffset += 4 * Next;
3464bdd1243dSDimitry Andric   } else {
3465bdd1243dSDimitry Andric     ++PageIndex;
3466bdd1243dSDimitry Andric     findNextPageWithFixups();
3467bdd1243dSDimitry Andric   }
3468bdd1243dSDimitry Andric }
346981ad6265SDimitry Andric 
347081ad6265SDimitry Andric bool MachOChainedFixupEntry::operator==(
347181ad6265SDimitry Andric     const MachOChainedFixupEntry &Other) const {
3472bdd1243dSDimitry Andric   if (Done && Other.Done)
347381ad6265SDimitry Andric     return true;
3474bdd1243dSDimitry Andric   if (Done != Other.Done)
347581ad6265SDimitry Andric     return false;
3476bdd1243dSDimitry Andric   return InfoSegIndex == Other.InfoSegIndex && PageIndex == Other.PageIndex &&
3477bdd1243dSDimitry Andric          PageOffset == Other.PageOffset;
347881ad6265SDimitry Andric }
347981ad6265SDimitry Andric 
34800b57cec5SDimitry Andric MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
34810b57cec5SDimitry Andric                                    ArrayRef<uint8_t> Bytes, bool is64Bit)
34820b57cec5SDimitry Andric     : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
34830b57cec5SDimitry Andric       PointerSize(is64Bit ? 8 : 4) {}
34840b57cec5SDimitry Andric 
34850b57cec5SDimitry Andric void MachORebaseEntry::moveToFirst() {
34860b57cec5SDimitry Andric   Ptr = Opcodes.begin();
34870b57cec5SDimitry Andric   moveNext();
34880b57cec5SDimitry Andric }
34890b57cec5SDimitry Andric 
34900b57cec5SDimitry Andric void MachORebaseEntry::moveToEnd() {
34910b57cec5SDimitry Andric   Ptr = Opcodes.end();
34920b57cec5SDimitry Andric   RemainingLoopCount = 0;
34930b57cec5SDimitry Andric   Done = true;
34940b57cec5SDimitry Andric }
34950b57cec5SDimitry Andric 
34960b57cec5SDimitry Andric void MachORebaseEntry::moveNext() {
34970b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
34980b57cec5SDimitry Andric   // If in the middle of some loop, move to next rebasing in loop.
34990b57cec5SDimitry Andric   SegmentOffset += AdvanceAmount;
35000b57cec5SDimitry Andric   if (RemainingLoopCount) {
35010b57cec5SDimitry Andric     --RemainingLoopCount;
35020b57cec5SDimitry Andric     return;
35030b57cec5SDimitry Andric   }
3504*0fca6ea1SDimitry Andric 
3505*0fca6ea1SDimitry Andric   bool More = true;
3506*0fca6ea1SDimitry Andric   while (More) {
35070b57cec5SDimitry Andric     // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3508*0fca6ea1SDimitry Andric     // pointer size. Therefore it is possible to reach the end without ever
3509*0fca6ea1SDimitry Andric     // having seen REBASE_OPCODE_DONE.
35100b57cec5SDimitry Andric     if (Ptr == Opcodes.end()) {
35110b57cec5SDimitry Andric       Done = true;
35120b57cec5SDimitry Andric       return;
35130b57cec5SDimitry Andric     }
3514*0fca6ea1SDimitry Andric 
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::REBASE_IMMEDIATE_MASK;
35190b57cec5SDimitry Andric     uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
3520*0fca6ea1SDimitry Andric     uint64_t Count, Skip;
35210b57cec5SDimitry Andric     const char *error = nullptr;
35220b57cec5SDimitry Andric     switch (Opcode) {
35230b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DONE:
35240b57cec5SDimitry Andric       More = false;
35250b57cec5SDimitry Andric       Done = true;
35260b57cec5SDimitry Andric       moveToEnd();
35270b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
35280b57cec5SDimitry Andric       break;
35290b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_SET_TYPE_IMM:
35300b57cec5SDimitry Andric       RebaseType = ImmValue;
35310b57cec5SDimitry Andric       if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
35320b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
35330b57cec5SDimitry Andric                             Twine((int)RebaseType) + " for opcode at: 0x" +
35340b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35350b57cec5SDimitry Andric         moveToEnd();
35360b57cec5SDimitry Andric         return;
35370b57cec5SDimitry Andric       }
35380b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
35390b57cec5SDimitry Andric           "mach-o-rebase",
35400b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
35410b57cec5SDimitry Andric                  << "RebaseType=" << (int) RebaseType << "\n");
35420b57cec5SDimitry Andric       break;
35430b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
35440b57cec5SDimitry Andric       SegmentIndex = ImmValue;
35450b57cec5SDimitry Andric       SegmentOffset = readULEB128(&error);
35460b57cec5SDimitry Andric       if (error) {
35470b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
35480b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
35490b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35500b57cec5SDimitry Andric         moveToEnd();
35510b57cec5SDimitry Andric         return;
35520b57cec5SDimitry Andric       }
35530b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
35540b57cec5SDimitry Andric                                                PointerSize);
35550b57cec5SDimitry Andric       if (error) {
35560b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
35570b57cec5SDimitry Andric                             Twine(error) + " 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-rebase",
35640b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
35650b57cec5SDimitry Andric                  << "SegmentIndex=" << SegmentIndex << ", "
35660b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
35670b57cec5SDimitry Andric                  << "\n");
35680b57cec5SDimitry Andric       break;
35690b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
35700b57cec5SDimitry Andric       SegmentOffset += readULEB128(&error);
35710b57cec5SDimitry Andric       if (error) {
35720b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
35730b57cec5SDimitry Andric                             " for opcode at: 0x" +
35740b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35750b57cec5SDimitry Andric         moveToEnd();
35760b57cec5SDimitry Andric         return;
35770b57cec5SDimitry Andric       }
35780b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
35790b57cec5SDimitry Andric                                                PointerSize);
35800b57cec5SDimitry Andric       if (error) {
35810b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
35820b57cec5SDimitry Andric                             " for opcode at: 0x" +
35830b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35840b57cec5SDimitry Andric         moveToEnd();
35850b57cec5SDimitry Andric         return;
35860b57cec5SDimitry Andric       }
35870b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase",
35880b57cec5SDimitry Andric                       dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
35890b57cec5SDimitry Andric                              << format("SegmentOffset=0x%06X",
35900b57cec5SDimitry Andric                                        SegmentOffset) << "\n");
35910b57cec5SDimitry Andric       break;
35920b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
35930b57cec5SDimitry Andric       SegmentOffset += ImmValue * PointerSize;
35940b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
35950b57cec5SDimitry Andric                                                PointerSize);
35960b57cec5SDimitry Andric       if (error) {
35975ffd83dbSDimitry Andric         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
35980b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
35990b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36000b57cec5SDimitry Andric         moveToEnd();
36010b57cec5SDimitry Andric         return;
36020b57cec5SDimitry Andric       }
36030b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-rebase",
36040b57cec5SDimitry Andric                       dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
36050b57cec5SDimitry Andric                              << format("SegmentOffset=0x%06X",
36060b57cec5SDimitry Andric                                        SegmentOffset) << "\n");
36070b57cec5SDimitry Andric       break;
36080b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
36090b57cec5SDimitry Andric       AdvanceAmount = PointerSize;
36100b57cec5SDimitry Andric       Skip = 0;
36110b57cec5SDimitry Andric       Count = ImmValue;
36120b57cec5SDimitry Andric       if (ImmValue != 0)
36130b57cec5SDimitry Andric         RemainingLoopCount = ImmValue - 1;
36140b57cec5SDimitry Andric       else
36150b57cec5SDimitry Andric         RemainingLoopCount = 0;
36160b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
36170b57cec5SDimitry Andric                                                PointerSize, Count, Skip);
36180b57cec5SDimitry Andric       if (error) {
36190b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
36200b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36210b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36220b57cec5SDimitry Andric         moveToEnd();
36230b57cec5SDimitry Andric         return;
36240b57cec5SDimitry Andric       }
36250b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
36260b57cec5SDimitry Andric           "mach-o-rebase",
36270b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
36280b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
36290b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
36300b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
36310b57cec5SDimitry Andric                  << "\n");
36320b57cec5SDimitry Andric       return;
36330b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
36340b57cec5SDimitry Andric       AdvanceAmount = PointerSize;
36350b57cec5SDimitry Andric       Skip = 0;
36360b57cec5SDimitry Andric       Count = readULEB128(&error);
36370b57cec5SDimitry Andric       if (error) {
36380b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
36390b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36400b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36410b57cec5SDimitry Andric         moveToEnd();
36420b57cec5SDimitry Andric         return;
36430b57cec5SDimitry Andric       }
36440b57cec5SDimitry Andric       if (Count != 0)
36450b57cec5SDimitry Andric         RemainingLoopCount = Count - 1;
36460b57cec5SDimitry Andric       else
36470b57cec5SDimitry Andric         RemainingLoopCount = 0;
36480b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
36490b57cec5SDimitry Andric                                                PointerSize, Count, Skip);
36500b57cec5SDimitry Andric       if (error) {
36510b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
36520b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36530b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36540b57cec5SDimitry Andric         moveToEnd();
36550b57cec5SDimitry Andric         return;
36560b57cec5SDimitry Andric       }
36570b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
36580b57cec5SDimitry Andric           "mach-o-rebase",
36590b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
36600b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
36610b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
36620b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
36630b57cec5SDimitry Andric                  << "\n");
36640b57cec5SDimitry Andric       return;
36650b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
36660b57cec5SDimitry Andric       Skip = readULEB128(&error);
36670b57cec5SDimitry Andric       if (error) {
36680b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
36690b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36700b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36710b57cec5SDimitry Andric         moveToEnd();
36720b57cec5SDimitry Andric         return;
36730b57cec5SDimitry Andric       }
36740b57cec5SDimitry Andric       AdvanceAmount = Skip + PointerSize;
36750b57cec5SDimitry Andric       Count = 1;
36760b57cec5SDimitry Andric       RemainingLoopCount = 0;
36770b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
36780b57cec5SDimitry Andric                                                PointerSize, Count, Skip);
36790b57cec5SDimitry Andric       if (error) {
36800b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
36810b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
36820b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36830b57cec5SDimitry Andric         moveToEnd();
36840b57cec5SDimitry Andric         return;
36850b57cec5SDimitry Andric       }
36860b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
36870b57cec5SDimitry Andric           "mach-o-rebase",
36880b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
36890b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
36900b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
36910b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
36920b57cec5SDimitry Andric                  << "\n");
36930b57cec5SDimitry Andric       return;
36940b57cec5SDimitry Andric     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
36950b57cec5SDimitry Andric       Count = readULEB128(&error);
36960b57cec5SDimitry Andric       if (error) {
36970b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
36980b57cec5SDimitry Andric                             "ULEB " +
36990b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
37000b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37010b57cec5SDimitry Andric         moveToEnd();
37020b57cec5SDimitry Andric         return;
37030b57cec5SDimitry Andric       }
37040b57cec5SDimitry Andric       if (Count != 0)
37050b57cec5SDimitry Andric         RemainingLoopCount = Count - 1;
37060b57cec5SDimitry Andric       else
37070b57cec5SDimitry Andric         RemainingLoopCount = 0;
37080b57cec5SDimitry Andric       Skip = readULEB128(&error);
37090b57cec5SDimitry Andric       if (error) {
37100b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
37110b57cec5SDimitry Andric                             "ULEB " +
37120b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
37130b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37140b57cec5SDimitry Andric         moveToEnd();
37150b57cec5SDimitry Andric         return;
37160b57cec5SDimitry Andric       }
37170b57cec5SDimitry Andric       AdvanceAmount = Skip + PointerSize;
37180b57cec5SDimitry Andric 
37190b57cec5SDimitry Andric       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
37200b57cec5SDimitry Andric                                                PointerSize, Count, Skip);
37210b57cec5SDimitry Andric       if (error) {
37220b57cec5SDimitry Andric         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
37230b57cec5SDimitry Andric                             "ULEB " +
37240b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
37250b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37260b57cec5SDimitry Andric         moveToEnd();
37270b57cec5SDimitry Andric         return;
37280b57cec5SDimitry Andric       }
37290b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
37300b57cec5SDimitry Andric           "mach-o-rebase",
37310b57cec5SDimitry Andric           dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
37320b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
37330b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
37340b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
37350b57cec5SDimitry Andric                  << "\n");
37360b57cec5SDimitry Andric       return;
37370b57cec5SDimitry Andric     default:
37380b57cec5SDimitry Andric       *E = malformedError("bad rebase info (bad opcode value 0x" +
37390b57cec5SDimitry Andric                           Twine::utohexstr(Opcode) + " for opcode at: 0x" +
37400b57cec5SDimitry Andric                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37410b57cec5SDimitry Andric       moveToEnd();
37420b57cec5SDimitry Andric       return;
37430b57cec5SDimitry Andric     }
37440b57cec5SDimitry Andric   }
37450b57cec5SDimitry Andric }
37460b57cec5SDimitry Andric 
37470b57cec5SDimitry Andric uint64_t MachORebaseEntry::readULEB128(const char **error) {
37480b57cec5SDimitry Andric   unsigned Count;
37490b57cec5SDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
37500b57cec5SDimitry Andric   Ptr += Count;
37510b57cec5SDimitry Andric   if (Ptr > Opcodes.end())
37520b57cec5SDimitry Andric     Ptr = Opcodes.end();
37530b57cec5SDimitry Andric   return Result;
37540b57cec5SDimitry Andric }
37550b57cec5SDimitry Andric 
37560b57cec5SDimitry Andric int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
37570b57cec5SDimitry Andric 
37580b57cec5SDimitry Andric uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
37590b57cec5SDimitry Andric 
37600b57cec5SDimitry Andric StringRef MachORebaseEntry::typeName() const {
37610b57cec5SDimitry Andric   switch (RebaseType) {
37620b57cec5SDimitry Andric   case MachO::REBASE_TYPE_POINTER:
37630b57cec5SDimitry Andric     return "pointer";
37640b57cec5SDimitry Andric   case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
37650b57cec5SDimitry Andric     return "text abs32";
37660b57cec5SDimitry Andric   case MachO::REBASE_TYPE_TEXT_PCREL32:
37670b57cec5SDimitry Andric     return "text rel32";
37680b57cec5SDimitry Andric   }
37690b57cec5SDimitry Andric   return "unknown";
37700b57cec5SDimitry Andric }
37710b57cec5SDimitry Andric 
37720b57cec5SDimitry Andric // For use with the SegIndex of a checked Mach-O Rebase entry
37730b57cec5SDimitry Andric // to get the segment name.
37740b57cec5SDimitry Andric StringRef MachORebaseEntry::segmentName() const {
37750b57cec5SDimitry Andric   return O->BindRebaseSegmentName(SegmentIndex);
37760b57cec5SDimitry Andric }
37770b57cec5SDimitry Andric 
37780b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
37790b57cec5SDimitry Andric // to get the section name.
37800b57cec5SDimitry Andric StringRef MachORebaseEntry::sectionName() const {
37810b57cec5SDimitry Andric   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
37820b57cec5SDimitry Andric }
37830b57cec5SDimitry Andric 
37840b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
37850b57cec5SDimitry Andric // to get the address.
37860b57cec5SDimitry Andric uint64_t MachORebaseEntry::address() const {
37870b57cec5SDimitry Andric   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
37880b57cec5SDimitry Andric }
37890b57cec5SDimitry Andric 
37900b57cec5SDimitry Andric bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
37910b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
37920b57cec5SDimitry Andric   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
37930b57cec5SDimitry Andric #else
37940b57cec5SDimitry Andric   assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
37950b57cec5SDimitry Andric #endif
37960b57cec5SDimitry Andric   return (Ptr == Other.Ptr) &&
37970b57cec5SDimitry Andric          (RemainingLoopCount == Other.RemainingLoopCount) &&
37980b57cec5SDimitry Andric          (Done == Other.Done);
37990b57cec5SDimitry Andric }
38000b57cec5SDimitry Andric 
38010b57cec5SDimitry Andric iterator_range<rebase_iterator>
38020b57cec5SDimitry Andric MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
38030b57cec5SDimitry Andric                              ArrayRef<uint8_t> Opcodes, bool is64) {
38040b57cec5SDimitry Andric   if (O->BindRebaseSectionTable == nullptr)
38058bcb0991SDimitry Andric     O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
38060b57cec5SDimitry Andric   MachORebaseEntry Start(&Err, O, Opcodes, is64);
38070b57cec5SDimitry Andric   Start.moveToFirst();
38080b57cec5SDimitry Andric 
38090b57cec5SDimitry Andric   MachORebaseEntry Finish(&Err, O, Opcodes, is64);
38100b57cec5SDimitry Andric   Finish.moveToEnd();
38110b57cec5SDimitry Andric 
38120b57cec5SDimitry Andric   return make_range(rebase_iterator(Start), rebase_iterator(Finish));
38130b57cec5SDimitry Andric }
38140b57cec5SDimitry Andric 
38150b57cec5SDimitry Andric iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
38160b57cec5SDimitry Andric   return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
38170b57cec5SDimitry Andric }
38180b57cec5SDimitry Andric 
38190b57cec5SDimitry Andric MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
38200b57cec5SDimitry Andric                                ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
38210b57cec5SDimitry Andric     : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
38220b57cec5SDimitry Andric       PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
38230b57cec5SDimitry Andric 
38240b57cec5SDimitry Andric void MachOBindEntry::moveToFirst() {
38250b57cec5SDimitry Andric   Ptr = Opcodes.begin();
38260b57cec5SDimitry Andric   moveNext();
38270b57cec5SDimitry Andric }
38280b57cec5SDimitry Andric 
38290b57cec5SDimitry Andric void MachOBindEntry::moveToEnd() {
38300b57cec5SDimitry Andric   Ptr = Opcodes.end();
38310b57cec5SDimitry Andric   RemainingLoopCount = 0;
38320b57cec5SDimitry Andric   Done = true;
38330b57cec5SDimitry Andric }
38340b57cec5SDimitry Andric 
38350b57cec5SDimitry Andric void MachOBindEntry::moveNext() {
38360b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(E);
38370b57cec5SDimitry Andric   // If in the middle of some loop, move to next binding in loop.
38380b57cec5SDimitry Andric   SegmentOffset += AdvanceAmount;
38390b57cec5SDimitry Andric   if (RemainingLoopCount) {
38400b57cec5SDimitry Andric     --RemainingLoopCount;
38410b57cec5SDimitry Andric     return;
38420b57cec5SDimitry Andric   }
3843*0fca6ea1SDimitry Andric 
3844*0fca6ea1SDimitry Andric   bool More = true;
3845*0fca6ea1SDimitry Andric   while (More) {
38460b57cec5SDimitry Andric     // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3847*0fca6ea1SDimitry Andric     // pointer size. Therefore it is possible to reach the end without ever
3848*0fca6ea1SDimitry Andric     // having seen BIND_OPCODE_DONE.
38490b57cec5SDimitry Andric     if (Ptr == Opcodes.end()) {
38500b57cec5SDimitry Andric       Done = true;
38510b57cec5SDimitry Andric       return;
38520b57cec5SDimitry Andric     }
3853*0fca6ea1SDimitry Andric 
38540b57cec5SDimitry Andric     // Parse next opcode and set up next loop.
38550b57cec5SDimitry Andric     const uint8_t *OpcodeStart = Ptr;
38560b57cec5SDimitry Andric     uint8_t Byte = *Ptr++;
38570b57cec5SDimitry Andric     uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
38580b57cec5SDimitry Andric     uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
38590b57cec5SDimitry Andric     int8_t SignExtended;
38600b57cec5SDimitry Andric     const uint8_t *SymStart;
3861*0fca6ea1SDimitry Andric     uint64_t Count, Skip;
38620b57cec5SDimitry Andric     const char *error = nullptr;
38630b57cec5SDimitry Andric     switch (Opcode) {
38640b57cec5SDimitry Andric     case MachO::BIND_OPCODE_DONE:
38650b57cec5SDimitry Andric       if (TableKind == Kind::Lazy) {
38660b57cec5SDimitry Andric         // Lazying bindings have a DONE opcode between entries.  Need to ignore
38670b57cec5SDimitry Andric         // it to advance to next entry.  But need not if this is last entry.
38680b57cec5SDimitry Andric         bool NotLastEntry = false;
38690b57cec5SDimitry Andric         for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
38700b57cec5SDimitry Andric           if (*P) {
38710b57cec5SDimitry Andric             NotLastEntry = true;
38720b57cec5SDimitry Andric           }
38730b57cec5SDimitry Andric         }
38740b57cec5SDimitry Andric         if (NotLastEntry)
38750b57cec5SDimitry Andric           break;
38760b57cec5SDimitry Andric       }
38770b57cec5SDimitry Andric       More = false;
38780b57cec5SDimitry Andric       moveToEnd();
38790b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
38800b57cec5SDimitry Andric       break;
38810b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
38820b57cec5SDimitry Andric       if (TableKind == Kind::Weak) {
38830b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
38840b57cec5SDimitry Andric                             "weak bind table for opcode at: 0x" +
38850b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38860b57cec5SDimitry Andric         moveToEnd();
38870b57cec5SDimitry Andric         return;
38880b57cec5SDimitry Andric       }
38890b57cec5SDimitry Andric       Ordinal = ImmValue;
38900b57cec5SDimitry Andric       LibraryOrdinalSet = true;
38910b57cec5SDimitry Andric       if (ImmValue > O->getLibraryCount()) {
38920b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
38930b57cec5SDimitry Andric                             "library ordinal: " +
38940b57cec5SDimitry Andric                             Twine((int)ImmValue) + " (max " +
38950b57cec5SDimitry Andric                             Twine((int)O->getLibraryCount()) +
38960b57cec5SDimitry Andric                             ") for opcode at: 0x" +
38970b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38980b57cec5SDimitry Andric         moveToEnd();
38990b57cec5SDimitry Andric         return;
39000b57cec5SDimitry Andric       }
39010b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
39020b57cec5SDimitry Andric           "mach-o-bind",
39030b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
39040b57cec5SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
39050b57cec5SDimitry Andric       break;
39060b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
39070b57cec5SDimitry Andric       if (TableKind == Kind::Weak) {
39080b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
39090b57cec5SDimitry Andric                             "weak bind table for opcode at: 0x" +
39100b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39110b57cec5SDimitry Andric         moveToEnd();
39120b57cec5SDimitry Andric         return;
39130b57cec5SDimitry Andric       }
39140b57cec5SDimitry Andric       Ordinal = readULEB128(&error);
39150b57cec5SDimitry Andric       LibraryOrdinalSet = true;
39160b57cec5SDimitry Andric       if (error) {
39170b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
39180b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
39190b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39200b57cec5SDimitry Andric         moveToEnd();
39210b57cec5SDimitry Andric         return;
39220b57cec5SDimitry Andric       }
39230b57cec5SDimitry Andric       if (Ordinal > (int)O->getLibraryCount()) {
39240b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
39250b57cec5SDimitry Andric                             "library ordinal: " +
39260b57cec5SDimitry Andric                             Twine((int)Ordinal) + " (max " +
39270b57cec5SDimitry Andric                             Twine((int)O->getLibraryCount()) +
39280b57cec5SDimitry Andric                             ") for opcode at: 0x" +
39290b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39300b57cec5SDimitry Andric         moveToEnd();
39310b57cec5SDimitry Andric         return;
39320b57cec5SDimitry Andric       }
39330b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
39340b57cec5SDimitry Andric           "mach-o-bind",
39350b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
39360b57cec5SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
39370b57cec5SDimitry Andric       break;
39380b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
39390b57cec5SDimitry Andric       if (TableKind == Kind::Weak) {
39400b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
39410b57cec5SDimitry Andric                             "weak bind table for opcode at: 0x" +
39420b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39430b57cec5SDimitry Andric         moveToEnd();
39440b57cec5SDimitry Andric         return;
39450b57cec5SDimitry Andric       }
39460b57cec5SDimitry Andric       if (ImmValue) {
39470b57cec5SDimitry Andric         SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
39480b57cec5SDimitry Andric         Ordinal = SignExtended;
39490b57cec5SDimitry Andric         if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
39500b57cec5SDimitry Andric           *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
39510b57cec5SDimitry Andric                               "special ordinal: " +
39520b57cec5SDimitry Andric                               Twine((int)Ordinal) + " for opcode at: 0x" +
39530b57cec5SDimitry Andric                               Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39540b57cec5SDimitry Andric           moveToEnd();
39550b57cec5SDimitry Andric           return;
39560b57cec5SDimitry Andric         }
39570b57cec5SDimitry Andric       } else
39580b57cec5SDimitry Andric         Ordinal = 0;
39590b57cec5SDimitry Andric       LibraryOrdinalSet = true;
39600b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
39610b57cec5SDimitry Andric           "mach-o-bind",
39620b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
39630b57cec5SDimitry Andric                  << "Ordinal=" << Ordinal << "\n");
39640b57cec5SDimitry Andric       break;
39650b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
39660b57cec5SDimitry Andric       Flags = ImmValue;
39670b57cec5SDimitry Andric       SymStart = Ptr;
39680b57cec5SDimitry Andric       while (*Ptr && (Ptr < Opcodes.end())) {
39690b57cec5SDimitry Andric         ++Ptr;
39700b57cec5SDimitry Andric       }
39710b57cec5SDimitry Andric       if (Ptr == Opcodes.end()) {
39720b57cec5SDimitry Andric         *E = malformedError(
39730b57cec5SDimitry Andric             "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
39740b57cec5SDimitry Andric             "symbol name extends past opcodes for opcode at: 0x" +
39750b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39760b57cec5SDimitry Andric         moveToEnd();
39770b57cec5SDimitry Andric         return;
39780b57cec5SDimitry Andric       }
39790b57cec5SDimitry Andric       SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
39800b57cec5SDimitry Andric                              Ptr-SymStart);
39810b57cec5SDimitry Andric       ++Ptr;
39820b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
39830b57cec5SDimitry Andric           "mach-o-bind",
39840b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
39850b57cec5SDimitry Andric                  << "SymbolName=" << SymbolName << "\n");
39860b57cec5SDimitry Andric       if (TableKind == Kind::Weak) {
39870b57cec5SDimitry Andric         if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
39880b57cec5SDimitry Andric           return;
39890b57cec5SDimitry Andric       }
39900b57cec5SDimitry Andric       break;
39910b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_TYPE_IMM:
39920b57cec5SDimitry Andric       BindType = ImmValue;
39930b57cec5SDimitry Andric       if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
39940b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
39950b57cec5SDimitry Andric                             Twine((int)ImmValue) + " for opcode at: 0x" +
39960b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
39970b57cec5SDimitry Andric         moveToEnd();
39980b57cec5SDimitry Andric         return;
39990b57cec5SDimitry Andric       }
40000b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
40010b57cec5SDimitry Andric           "mach-o-bind",
40020b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
40030b57cec5SDimitry Andric                  << "BindType=" << (int)BindType << "\n");
40040b57cec5SDimitry Andric       break;
40050b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
40060b57cec5SDimitry Andric       Addend = readSLEB128(&error);
40070b57cec5SDimitry Andric       if (error) {
40080b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
40090b57cec5SDimitry Andric                             " for opcode at: 0x" +
40100b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
40110b57cec5SDimitry Andric         moveToEnd();
40120b57cec5SDimitry Andric         return;
40130b57cec5SDimitry Andric       }
40140b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
40150b57cec5SDimitry Andric           "mach-o-bind",
40160b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
40170b57cec5SDimitry Andric                  << "Addend=" << Addend << "\n");
40180b57cec5SDimitry Andric       break;
40190b57cec5SDimitry Andric     case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
40200b57cec5SDimitry Andric       SegmentIndex = ImmValue;
40210b57cec5SDimitry Andric       SegmentOffset = readULEB128(&error);
40220b57cec5SDimitry Andric       if (error) {
40230b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
40240b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
40250b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
40260b57cec5SDimitry Andric         moveToEnd();
40270b57cec5SDimitry Andric         return;
40280b57cec5SDimitry Andric       }
40290b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
40300b57cec5SDimitry Andric                                              PointerSize);
40310b57cec5SDimitry Andric       if (error) {
40320b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
40330b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
40340b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
40350b57cec5SDimitry Andric         moveToEnd();
40360b57cec5SDimitry Andric         return;
40370b57cec5SDimitry Andric       }
40380b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
40390b57cec5SDimitry Andric           "mach-o-bind",
40400b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
40410b57cec5SDimitry Andric                  << "SegmentIndex=" << SegmentIndex << ", "
40420b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
40430b57cec5SDimitry Andric                  << "\n");
40440b57cec5SDimitry Andric       break;
40450b57cec5SDimitry Andric     case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
40460b57cec5SDimitry Andric       SegmentOffset += readULEB128(&error);
40470b57cec5SDimitry Andric       if (error) {
40480b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
40490b57cec5SDimitry Andric                             " for opcode at: 0x" +
40500b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
40510b57cec5SDimitry Andric         moveToEnd();
40520b57cec5SDimitry Andric         return;
40530b57cec5SDimitry Andric       }
40540b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
40550b57cec5SDimitry Andric                                              PointerSize);
40560b57cec5SDimitry Andric       if (error) {
40570b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
40580b57cec5SDimitry Andric                             " for opcode at: 0x" +
40590b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
40600b57cec5SDimitry Andric         moveToEnd();
40610b57cec5SDimitry Andric         return;
40620b57cec5SDimitry Andric       }
40630b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
40640b57cec5SDimitry Andric                       dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
40650b57cec5SDimitry Andric                              << format("SegmentOffset=0x%06X",
40660b57cec5SDimitry Andric                                        SegmentOffset) << "\n");
40670b57cec5SDimitry Andric       break;
40680b57cec5SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND:
40690b57cec5SDimitry Andric       AdvanceAmount = PointerSize;
40700b57cec5SDimitry Andric       RemainingLoopCount = 0;
40710b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
40720b57cec5SDimitry Andric                                              PointerSize);
40730b57cec5SDimitry Andric       if (error) {
40740b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
40750b57cec5SDimitry Andric                             " for opcode at: 0x" +
40760b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
40770b57cec5SDimitry Andric         moveToEnd();
40780b57cec5SDimitry Andric         return;
40790b57cec5SDimitry Andric       }
40800b57cec5SDimitry Andric       if (SymbolName == StringRef()) {
40810b57cec5SDimitry Andric         *E = malformedError(
40820b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND missing preceding "
40830b57cec5SDimitry Andric             "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
40840b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
40850b57cec5SDimitry Andric         moveToEnd();
40860b57cec5SDimitry Andric         return;
40870b57cec5SDimitry Andric       }
40880b57cec5SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
40890b57cec5SDimitry Andric         *E =
40900b57cec5SDimitry Andric             malformedError("for BIND_OPCODE_DO_BIND missing preceding "
40910b57cec5SDimitry Andric                            "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
40920b57cec5SDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
40930b57cec5SDimitry Andric         moveToEnd();
40940b57cec5SDimitry Andric         return;
40950b57cec5SDimitry Andric       }
40960b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
40970b57cec5SDimitry Andric                       dbgs() << "BIND_OPCODE_DO_BIND: "
40980b57cec5SDimitry Andric                              << format("SegmentOffset=0x%06X",
40990b57cec5SDimitry Andric                                        SegmentOffset) << "\n");
41000b57cec5SDimitry Andric       return;
41010b57cec5SDimitry Andric      case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
41020b57cec5SDimitry Andric       if (TableKind == Kind::Lazy) {
41030b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
41040b57cec5SDimitry Andric                             "lazy bind table for opcode at: 0x" +
41050b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41060b57cec5SDimitry Andric         moveToEnd();
41070b57cec5SDimitry Andric         return;
41080b57cec5SDimitry Andric       }
41090b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
41100b57cec5SDimitry Andric                                              PointerSize);
41110b57cec5SDimitry Andric       if (error) {
41120b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
41130b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
41140b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41150b57cec5SDimitry Andric         moveToEnd();
41160b57cec5SDimitry Andric         return;
41170b57cec5SDimitry Andric       }
41180b57cec5SDimitry Andric       if (SymbolName == StringRef()) {
41190b57cec5SDimitry Andric         *E = malformedError(
41200b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
41210b57cec5SDimitry Andric             "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
41220b57cec5SDimitry Andric             "at: 0x" +
41230b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41240b57cec5SDimitry Andric         moveToEnd();
41250b57cec5SDimitry Andric         return;
41260b57cec5SDimitry Andric       }
41270b57cec5SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
41280b57cec5SDimitry Andric         *E = malformedError(
41290b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
41300b57cec5SDimitry Andric             "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
41310b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41320b57cec5SDimitry Andric         moveToEnd();
41330b57cec5SDimitry Andric         return;
41340b57cec5SDimitry Andric       }
41350b57cec5SDimitry Andric       AdvanceAmount = readULEB128(&error) + PointerSize;
41360b57cec5SDimitry Andric       if (error) {
41370b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
41380b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
41390b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41400b57cec5SDimitry Andric         moveToEnd();
41410b57cec5SDimitry Andric         return;
41420b57cec5SDimitry Andric       }
41430b57cec5SDimitry Andric       // Note, this is not really an error until the next bind but make no sense
41440b57cec5SDimitry Andric       // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
41450b57cec5SDimitry Andric       // bind operation.
41460b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
41470b57cec5SDimitry Andric                                             AdvanceAmount, PointerSize);
41480b57cec5SDimitry Andric       if (error) {
41490b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
41500b57cec5SDimitry Andric                             "ULEB) " +
41510b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
41520b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41530b57cec5SDimitry Andric         moveToEnd();
41540b57cec5SDimitry Andric         return;
41550b57cec5SDimitry Andric       }
41560b57cec5SDimitry Andric       RemainingLoopCount = 0;
41570b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
41580b57cec5SDimitry Andric           "mach-o-bind",
41590b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
41600b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
41610b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
41620b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
41630b57cec5SDimitry Andric                  << "\n");
41640b57cec5SDimitry Andric       return;
41650b57cec5SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
41660b57cec5SDimitry Andric       if (TableKind == Kind::Lazy) {
41670b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
41680b57cec5SDimitry Andric                             "allowed in lazy bind table for opcode at: 0x" +
41690b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41700b57cec5SDimitry Andric         moveToEnd();
41710b57cec5SDimitry Andric         return;
41720b57cec5SDimitry Andric       }
41730b57cec5SDimitry Andric       if (SymbolName == StringRef()) {
41740b57cec5SDimitry Andric         *E = malformedError(
41750b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
41760b57cec5SDimitry Andric             "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
41770b57cec5SDimitry Andric             "opcode at: 0x" +
41780b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41790b57cec5SDimitry Andric         moveToEnd();
41800b57cec5SDimitry Andric         return;
41810b57cec5SDimitry Andric       }
41820b57cec5SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
41830b57cec5SDimitry Andric         *E = malformedError(
41840b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
41850b57cec5SDimitry Andric             "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
41860b57cec5SDimitry Andric             "at: 0x" +
41870b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41880b57cec5SDimitry Andric         moveToEnd();
41890b57cec5SDimitry Andric         return;
41900b57cec5SDimitry Andric       }
41910b57cec5SDimitry Andric       AdvanceAmount = ImmValue * PointerSize + PointerSize;
41920b57cec5SDimitry Andric       RemainingLoopCount = 0;
41930b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
41940b57cec5SDimitry Andric                                              AdvanceAmount, PointerSize);
41950b57cec5SDimitry Andric       if (error) {
41965ffd83dbSDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
41970b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
41980b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
41990b57cec5SDimitry Andric         moveToEnd();
42000b57cec5SDimitry Andric         return;
42010b57cec5SDimitry Andric       }
42020b57cec5SDimitry Andric       DEBUG_WITH_TYPE("mach-o-bind",
42030b57cec5SDimitry Andric                       dbgs()
42040b57cec5SDimitry Andric                       << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
42050b57cec5SDimitry Andric                       << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
42060b57cec5SDimitry Andric       return;
42070b57cec5SDimitry Andric     case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
42080b57cec5SDimitry Andric       if (TableKind == Kind::Lazy) {
42090b57cec5SDimitry Andric         *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
42100b57cec5SDimitry Andric                             "allowed in lazy bind table for opcode at: 0x" +
42110b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
42120b57cec5SDimitry Andric         moveToEnd();
42130b57cec5SDimitry Andric         return;
42140b57cec5SDimitry Andric       }
42150b57cec5SDimitry Andric       Count = readULEB128(&error);
42160b57cec5SDimitry Andric       if (Count != 0)
42170b57cec5SDimitry Andric         RemainingLoopCount = Count - 1;
42180b57cec5SDimitry Andric       else
42190b57cec5SDimitry Andric         RemainingLoopCount = 0;
42200b57cec5SDimitry Andric       if (error) {
42210b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
42220b57cec5SDimitry Andric                             " (count value) " +
42230b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
42240b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
42250b57cec5SDimitry Andric         moveToEnd();
42260b57cec5SDimitry Andric         return;
42270b57cec5SDimitry Andric       }
42280b57cec5SDimitry Andric       Skip = readULEB128(&error);
42290b57cec5SDimitry Andric       AdvanceAmount = Skip + PointerSize;
42300b57cec5SDimitry Andric       if (error) {
42310b57cec5SDimitry Andric         *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
42320b57cec5SDimitry Andric                             " (skip value) " +
42330b57cec5SDimitry Andric                             Twine(error) + " for opcode at: 0x" +
42340b57cec5SDimitry Andric                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
42350b57cec5SDimitry Andric         moveToEnd();
42360b57cec5SDimitry Andric         return;
42370b57cec5SDimitry Andric       }
42380b57cec5SDimitry Andric       if (SymbolName == StringRef()) {
42390b57cec5SDimitry Andric         *E = malformedError(
42400b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
42410b57cec5SDimitry Andric             "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
42420b57cec5SDimitry Andric             "opcode at: 0x" +
42430b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
42440b57cec5SDimitry Andric         moveToEnd();
42450b57cec5SDimitry Andric         return;
42460b57cec5SDimitry Andric       }
42470b57cec5SDimitry Andric       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
42480b57cec5SDimitry Andric         *E = malformedError(
42490b57cec5SDimitry Andric             "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
42500b57cec5SDimitry Andric             "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
42510b57cec5SDimitry Andric             "at: 0x" +
42520b57cec5SDimitry Andric             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
42530b57cec5SDimitry Andric         moveToEnd();
42540b57cec5SDimitry Andric         return;
42550b57cec5SDimitry Andric       }
42560b57cec5SDimitry Andric       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
42570b57cec5SDimitry Andric                                              PointerSize, Count, Skip);
42580b57cec5SDimitry Andric       if (error) {
42590b57cec5SDimitry Andric         *E =
42600b57cec5SDimitry Andric             malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
42610b57cec5SDimitry Andric                            Twine(error) + " for opcode at: 0x" +
42620b57cec5SDimitry Andric                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
42630b57cec5SDimitry Andric         moveToEnd();
42640b57cec5SDimitry Andric         return;
42650b57cec5SDimitry Andric       }
42660b57cec5SDimitry Andric       DEBUG_WITH_TYPE(
42670b57cec5SDimitry Andric           "mach-o-bind",
42680b57cec5SDimitry Andric           dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
42690b57cec5SDimitry Andric                  << format("SegmentOffset=0x%06X", SegmentOffset)
42700b57cec5SDimitry Andric                  << ", AdvanceAmount=" << AdvanceAmount
42710b57cec5SDimitry Andric                  << ", RemainingLoopCount=" << RemainingLoopCount
42720b57cec5SDimitry Andric                  << "\n");
42730b57cec5SDimitry Andric       return;
42740b57cec5SDimitry Andric     default:
42750b57cec5SDimitry Andric       *E = malformedError("bad bind info (bad opcode value 0x" +
42760b57cec5SDimitry Andric                           Twine::utohexstr(Opcode) + " for opcode at: 0x" +
42770b57cec5SDimitry Andric                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
42780b57cec5SDimitry Andric       moveToEnd();
42790b57cec5SDimitry Andric       return;
42800b57cec5SDimitry Andric     }
42810b57cec5SDimitry Andric   }
42820b57cec5SDimitry Andric }
42830b57cec5SDimitry Andric 
42840b57cec5SDimitry Andric uint64_t MachOBindEntry::readULEB128(const char **error) {
42850b57cec5SDimitry Andric   unsigned Count;
42860b57cec5SDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
42870b57cec5SDimitry Andric   Ptr += Count;
42880b57cec5SDimitry Andric   if (Ptr > Opcodes.end())
42890b57cec5SDimitry Andric     Ptr = Opcodes.end();
42900b57cec5SDimitry Andric   return Result;
42910b57cec5SDimitry Andric }
42920b57cec5SDimitry Andric 
42930b57cec5SDimitry Andric int64_t MachOBindEntry::readSLEB128(const char **error) {
42940b57cec5SDimitry Andric   unsigned Count;
42950b57cec5SDimitry Andric   int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
42960b57cec5SDimitry Andric   Ptr += Count;
42970b57cec5SDimitry Andric   if (Ptr > Opcodes.end())
42980b57cec5SDimitry Andric     Ptr = Opcodes.end();
42990b57cec5SDimitry Andric   return Result;
43000b57cec5SDimitry Andric }
43010b57cec5SDimitry Andric 
43020b57cec5SDimitry Andric int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
43030b57cec5SDimitry Andric 
43040b57cec5SDimitry Andric uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
43050b57cec5SDimitry Andric 
43060b57cec5SDimitry Andric StringRef MachOBindEntry::typeName() const {
43070b57cec5SDimitry Andric   switch (BindType) {
43080b57cec5SDimitry Andric   case MachO::BIND_TYPE_POINTER:
43090b57cec5SDimitry Andric     return "pointer";
43100b57cec5SDimitry Andric   case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
43110b57cec5SDimitry Andric     return "text abs32";
43120b57cec5SDimitry Andric   case MachO::BIND_TYPE_TEXT_PCREL32:
43130b57cec5SDimitry Andric     return "text rel32";
43140b57cec5SDimitry Andric   }
43150b57cec5SDimitry Andric   return "unknown";
43160b57cec5SDimitry Andric }
43170b57cec5SDimitry Andric 
43180b57cec5SDimitry Andric StringRef MachOBindEntry::symbolName() const { return SymbolName; }
43190b57cec5SDimitry Andric 
43200b57cec5SDimitry Andric int64_t MachOBindEntry::addend() const { return Addend; }
43210b57cec5SDimitry Andric 
43220b57cec5SDimitry Andric uint32_t MachOBindEntry::flags() const { return Flags; }
43230b57cec5SDimitry Andric 
43240b57cec5SDimitry Andric int MachOBindEntry::ordinal() const { return Ordinal; }
43250b57cec5SDimitry Andric 
43260b57cec5SDimitry Andric // For use with the SegIndex of a checked Mach-O Bind entry
43270b57cec5SDimitry Andric // to get the segment name.
43280b57cec5SDimitry Andric StringRef MachOBindEntry::segmentName() const {
43290b57cec5SDimitry Andric   return O->BindRebaseSegmentName(SegmentIndex);
43300b57cec5SDimitry Andric }
43310b57cec5SDimitry Andric 
43320b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
43330b57cec5SDimitry Andric // to get the section name.
43340b57cec5SDimitry Andric StringRef MachOBindEntry::sectionName() const {
43350b57cec5SDimitry Andric   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
43360b57cec5SDimitry Andric }
43370b57cec5SDimitry Andric 
43380b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
43390b57cec5SDimitry Andric // to get the address.
43400b57cec5SDimitry Andric uint64_t MachOBindEntry::address() const {
43410b57cec5SDimitry Andric   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
43420b57cec5SDimitry Andric }
43430b57cec5SDimitry Andric 
43440b57cec5SDimitry Andric bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
43450b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
43460b57cec5SDimitry Andric   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
43470b57cec5SDimitry Andric #else
43480b57cec5SDimitry Andric   assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
43490b57cec5SDimitry Andric #endif
43500b57cec5SDimitry Andric   return (Ptr == Other.Ptr) &&
43510b57cec5SDimitry Andric          (RemainingLoopCount == Other.RemainingLoopCount) &&
43520b57cec5SDimitry Andric          (Done == Other.Done);
43530b57cec5SDimitry Andric }
43540b57cec5SDimitry Andric 
43550b57cec5SDimitry Andric // Build table of sections so SegIndex/SegOffset pairs can be translated.
43560b57cec5SDimitry Andric BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
43570b57cec5SDimitry Andric   uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
43580b57cec5SDimitry Andric   StringRef CurSegName;
43590b57cec5SDimitry Andric   uint64_t CurSegAddress;
43600b57cec5SDimitry Andric   for (const SectionRef &Section : Obj->sections()) {
43610b57cec5SDimitry Andric     SectionInfo Info;
43628bcb0991SDimitry Andric     Expected<StringRef> NameOrErr = Section.getName();
43638bcb0991SDimitry Andric     if (!NameOrErr)
43648bcb0991SDimitry Andric       consumeError(NameOrErr.takeError());
43658bcb0991SDimitry Andric     else
43668bcb0991SDimitry Andric       Info.SectionName = *NameOrErr;
43670b57cec5SDimitry Andric     Info.Address = Section.getAddress();
43680b57cec5SDimitry Andric     Info.Size = Section.getSize();
43690b57cec5SDimitry Andric     Info.SegmentName =
43700b57cec5SDimitry Andric         Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
4371*0fca6ea1SDimitry Andric     if (Info.SegmentName != CurSegName) {
43720b57cec5SDimitry Andric       ++CurSegIndex;
43730b57cec5SDimitry Andric       CurSegName = Info.SegmentName;
43740b57cec5SDimitry Andric       CurSegAddress = Info.Address;
43750b57cec5SDimitry Andric     }
43760b57cec5SDimitry Andric     Info.SegmentIndex = CurSegIndex - 1;
43770b57cec5SDimitry Andric     Info.OffsetInSegment = Info.Address - CurSegAddress;
43780b57cec5SDimitry Andric     Info.SegmentStartAddress = CurSegAddress;
43790b57cec5SDimitry Andric     Sections.push_back(Info);
43800b57cec5SDimitry Andric   }
43810b57cec5SDimitry Andric   MaxSegIndex = CurSegIndex;
43820b57cec5SDimitry Andric }
43830b57cec5SDimitry Andric 
43840b57cec5SDimitry Andric // For use with a SegIndex, SegOffset, and PointerSize triple in
43850b57cec5SDimitry Andric // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
43860b57cec5SDimitry Andric //
43870b57cec5SDimitry Andric // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
43880b57cec5SDimitry Andric // that fully contains a pointer at that location. Multiple fixups in a bind
43890b57cec5SDimitry Andric // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
43900b57cec5SDimitry Andric // be tested via the Count and Skip parameters.
43910b57cec5SDimitry Andric const char *BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
43920b57cec5SDimitry Andric                                                   uint64_t SegOffset,
43930b57cec5SDimitry Andric                                                   uint8_t PointerSize,
4394*0fca6ea1SDimitry Andric                                                   uint64_t Count,
4395*0fca6ea1SDimitry Andric                                                   uint64_t Skip) {
43960b57cec5SDimitry Andric   if (SegIndex == -1)
43970b57cec5SDimitry Andric     return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
43980b57cec5SDimitry Andric   if (SegIndex >= MaxSegIndex)
43990b57cec5SDimitry Andric     return "bad segIndex (too large)";
4400*0fca6ea1SDimitry Andric   for (uint64_t i = 0; i < Count; ++i) {
4401*0fca6ea1SDimitry Andric     uint64_t Start = SegOffset + i * (PointerSize + Skip);
4402*0fca6ea1SDimitry Andric     uint64_t End = Start + PointerSize;
44030b57cec5SDimitry Andric     bool Found = false;
44040b57cec5SDimitry Andric     for (const SectionInfo &SI : Sections) {
44050b57cec5SDimitry Andric       if (SI.SegmentIndex != SegIndex)
44060b57cec5SDimitry Andric         continue;
44070b57cec5SDimitry Andric       if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
44080b57cec5SDimitry Andric         if (End <= SI.OffsetInSegment + SI.Size) {
44090b57cec5SDimitry Andric           Found = true;
44100b57cec5SDimitry Andric           break;
44110b57cec5SDimitry Andric         }
44120b57cec5SDimitry Andric         else
44130b57cec5SDimitry Andric           return "bad offset, extends beyond section boundary";
44140b57cec5SDimitry Andric       }
44150b57cec5SDimitry Andric     }
44160b57cec5SDimitry Andric     if (!Found)
44170b57cec5SDimitry Andric       return "bad offset, not in section";
44180b57cec5SDimitry Andric   }
44190b57cec5SDimitry Andric   return nullptr;
44200b57cec5SDimitry Andric }
44210b57cec5SDimitry Andric 
44220b57cec5SDimitry Andric // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
44230b57cec5SDimitry Andric // to get the segment name.
44240b57cec5SDimitry Andric StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
44250b57cec5SDimitry Andric   for (const SectionInfo &SI : Sections) {
44260b57cec5SDimitry Andric     if (SI.SegmentIndex == SegIndex)
44270b57cec5SDimitry Andric       return SI.SegmentName;
44280b57cec5SDimitry Andric   }
44290b57cec5SDimitry Andric   llvm_unreachable("invalid SegIndex");
44300b57cec5SDimitry Andric }
44310b57cec5SDimitry Andric 
44320b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
44330b57cec5SDimitry Andric // to get the SectionInfo.
44340b57cec5SDimitry Andric const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
44350b57cec5SDimitry Andric                                      int32_t SegIndex, uint64_t SegOffset) {
44360b57cec5SDimitry Andric   for (const SectionInfo &SI : Sections) {
44370b57cec5SDimitry Andric     if (SI.SegmentIndex != SegIndex)
44380b57cec5SDimitry Andric       continue;
44390b57cec5SDimitry Andric     if (SI.OffsetInSegment > SegOffset)
44400b57cec5SDimitry Andric       continue;
44410b57cec5SDimitry Andric     if (SegOffset >= (SI.OffsetInSegment + SI.Size))
44420b57cec5SDimitry Andric       continue;
44430b57cec5SDimitry Andric     return SI;
44440b57cec5SDimitry Andric   }
44450b57cec5SDimitry Andric   llvm_unreachable("SegIndex and SegOffset not in any section");
44460b57cec5SDimitry Andric }
44470b57cec5SDimitry Andric 
44480b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
44490b57cec5SDimitry Andric // entry to get the section name.
44500b57cec5SDimitry Andric StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
44510b57cec5SDimitry Andric                                          uint64_t SegOffset) {
44520b57cec5SDimitry Andric   return findSection(SegIndex, SegOffset).SectionName;
44530b57cec5SDimitry Andric }
44540b57cec5SDimitry Andric 
44550b57cec5SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
44560b57cec5SDimitry Andric // entry to get the address.
44570b57cec5SDimitry Andric uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
44580b57cec5SDimitry Andric   const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
44590b57cec5SDimitry Andric   return SI.SegmentStartAddress + OffsetInSeg;
44600b57cec5SDimitry Andric }
44610b57cec5SDimitry Andric 
44620b57cec5SDimitry Andric iterator_range<bind_iterator>
44630b57cec5SDimitry Andric MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
44640b57cec5SDimitry Andric                            ArrayRef<uint8_t> Opcodes, bool is64,
44650b57cec5SDimitry Andric                            MachOBindEntry::Kind BKind) {
44660b57cec5SDimitry Andric   if (O->BindRebaseSectionTable == nullptr)
44678bcb0991SDimitry Andric     O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
44680b57cec5SDimitry Andric   MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
44690b57cec5SDimitry Andric   Start.moveToFirst();
44700b57cec5SDimitry Andric 
44710b57cec5SDimitry Andric   MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
44720b57cec5SDimitry Andric   Finish.moveToEnd();
44730b57cec5SDimitry Andric 
44740b57cec5SDimitry Andric   return make_range(bind_iterator(Start), bind_iterator(Finish));
44750b57cec5SDimitry Andric }
44760b57cec5SDimitry Andric 
44770b57cec5SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
44780b57cec5SDimitry Andric   return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
44790b57cec5SDimitry Andric                    MachOBindEntry::Kind::Regular);
44800b57cec5SDimitry Andric }
44810b57cec5SDimitry Andric 
44820b57cec5SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
44830b57cec5SDimitry Andric   return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
44840b57cec5SDimitry Andric                    MachOBindEntry::Kind::Lazy);
44850b57cec5SDimitry Andric }
44860b57cec5SDimitry Andric 
44870b57cec5SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
44880b57cec5SDimitry Andric   return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
44890b57cec5SDimitry Andric                    MachOBindEntry::Kind::Weak);
44900b57cec5SDimitry Andric }
44910b57cec5SDimitry Andric 
449281ad6265SDimitry Andric iterator_range<fixup_iterator> MachOObjectFile::fixupTable(Error &Err) {
4493bdd1243dSDimitry Andric   if (BindRebaseSectionTable == nullptr)
4494bdd1243dSDimitry Andric     BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(this);
4495bdd1243dSDimitry Andric 
449681ad6265SDimitry Andric   MachOChainedFixupEntry Start(&Err, this, true);
449781ad6265SDimitry Andric   Start.moveToFirst();
449881ad6265SDimitry Andric 
449981ad6265SDimitry Andric   MachOChainedFixupEntry Finish(&Err, this, false);
450081ad6265SDimitry Andric   Finish.moveToEnd();
450181ad6265SDimitry Andric 
450281ad6265SDimitry Andric   return make_range(fixup_iterator(Start), fixup_iterator(Finish));
450381ad6265SDimitry Andric }
450481ad6265SDimitry Andric 
45050b57cec5SDimitry Andric MachOObjectFile::load_command_iterator
45060b57cec5SDimitry Andric MachOObjectFile::begin_load_commands() const {
45070b57cec5SDimitry Andric   return LoadCommands.begin();
45080b57cec5SDimitry Andric }
45090b57cec5SDimitry Andric 
45100b57cec5SDimitry Andric MachOObjectFile::load_command_iterator
45110b57cec5SDimitry Andric MachOObjectFile::end_load_commands() const {
45120b57cec5SDimitry Andric   return LoadCommands.end();
45130b57cec5SDimitry Andric }
45140b57cec5SDimitry Andric 
45150b57cec5SDimitry Andric iterator_range<MachOObjectFile::load_command_iterator>
45160b57cec5SDimitry Andric MachOObjectFile::load_commands() const {
45170b57cec5SDimitry Andric   return make_range(begin_load_commands(), end_load_commands());
45180b57cec5SDimitry Andric }
45190b57cec5SDimitry Andric 
45200b57cec5SDimitry Andric StringRef
45210b57cec5SDimitry Andric MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
45220b57cec5SDimitry Andric   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
45230b57cec5SDimitry Andric   return parseSegmentOrSectionName(Raw.data());
45240b57cec5SDimitry Andric }
45250b57cec5SDimitry Andric 
45260b57cec5SDimitry Andric ArrayRef<char>
45270b57cec5SDimitry Andric MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
45280b57cec5SDimitry Andric   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
45290b57cec5SDimitry Andric   const section_base *Base =
45300b57cec5SDimitry Andric     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4531bdd1243dSDimitry Andric   return ArrayRef(Base->sectname);
45320b57cec5SDimitry Andric }
45330b57cec5SDimitry Andric 
45340b57cec5SDimitry Andric ArrayRef<char>
45350b57cec5SDimitry Andric MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
45360b57cec5SDimitry Andric   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
45370b57cec5SDimitry Andric   const section_base *Base =
45380b57cec5SDimitry Andric     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4539bdd1243dSDimitry Andric   return ArrayRef(Base->segname);
45400b57cec5SDimitry Andric }
45410b57cec5SDimitry Andric 
45420b57cec5SDimitry Andric bool
45430b57cec5SDimitry Andric MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
45440b57cec5SDimitry Andric   const {
45450b57cec5SDimitry Andric   if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
45460b57cec5SDimitry Andric     return false;
45470b57cec5SDimitry Andric   return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
45480b57cec5SDimitry Andric }
45490b57cec5SDimitry Andric 
45500b57cec5SDimitry Andric unsigned MachOObjectFile::getPlainRelocationSymbolNum(
45510b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
45520b57cec5SDimitry Andric   if (isLittleEndian())
45530b57cec5SDimitry Andric     return RE.r_word1 & 0xffffff;
45540b57cec5SDimitry Andric   return RE.r_word1 >> 8;
45550b57cec5SDimitry Andric }
45560b57cec5SDimitry Andric 
45570b57cec5SDimitry Andric bool MachOObjectFile::getPlainRelocationExternal(
45580b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
45590b57cec5SDimitry Andric   if (isLittleEndian())
45600b57cec5SDimitry Andric     return (RE.r_word1 >> 27) & 1;
45610b57cec5SDimitry Andric   return (RE.r_word1 >> 4) & 1;
45620b57cec5SDimitry Andric }
45630b57cec5SDimitry Andric 
45640b57cec5SDimitry Andric bool MachOObjectFile::getScatteredRelocationScattered(
45650b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
45660b57cec5SDimitry Andric   return RE.r_word0 >> 31;
45670b57cec5SDimitry Andric }
45680b57cec5SDimitry Andric 
45690b57cec5SDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationValue(
45700b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
45710b57cec5SDimitry Andric   return RE.r_word1;
45720b57cec5SDimitry Andric }
45730b57cec5SDimitry Andric 
45740b57cec5SDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationType(
45750b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
45760b57cec5SDimitry Andric   return (RE.r_word0 >> 24) & 0xf;
45770b57cec5SDimitry Andric }
45780b57cec5SDimitry Andric 
45790b57cec5SDimitry Andric unsigned MachOObjectFile::getAnyRelocationAddress(
45800b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
45810b57cec5SDimitry Andric   if (isRelocationScattered(RE))
45820b57cec5SDimitry Andric     return getScatteredRelocationAddress(RE);
45830b57cec5SDimitry Andric   return getPlainRelocationAddress(RE);
45840b57cec5SDimitry Andric }
45850b57cec5SDimitry Andric 
45860b57cec5SDimitry Andric unsigned MachOObjectFile::getAnyRelocationPCRel(
45870b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
45880b57cec5SDimitry Andric   if (isRelocationScattered(RE))
45890b57cec5SDimitry Andric     return getScatteredRelocationPCRel(RE);
45900b57cec5SDimitry Andric   return getPlainRelocationPCRel(*this, RE);
45910b57cec5SDimitry Andric }
45920b57cec5SDimitry Andric 
45930b57cec5SDimitry Andric unsigned MachOObjectFile::getAnyRelocationLength(
45940b57cec5SDimitry Andric     const MachO::any_relocation_info &RE) const {
45950b57cec5SDimitry Andric   if (isRelocationScattered(RE))
45960b57cec5SDimitry Andric     return getScatteredRelocationLength(RE);
45970b57cec5SDimitry Andric   return getPlainRelocationLength(*this, RE);
45980b57cec5SDimitry Andric }
45990b57cec5SDimitry Andric 
46000b57cec5SDimitry Andric unsigned
46010b57cec5SDimitry Andric MachOObjectFile::getAnyRelocationType(
46020b57cec5SDimitry Andric                                    const MachO::any_relocation_info &RE) const {
46030b57cec5SDimitry Andric   if (isRelocationScattered(RE))
46040b57cec5SDimitry Andric     return getScatteredRelocationType(RE);
46050b57cec5SDimitry Andric   return getPlainRelocationType(*this, RE);
46060b57cec5SDimitry Andric }
46070b57cec5SDimitry Andric 
46080b57cec5SDimitry Andric SectionRef
46090b57cec5SDimitry Andric MachOObjectFile::getAnyRelocationSection(
46100b57cec5SDimitry Andric                                    const MachO::any_relocation_info &RE) const {
46110b57cec5SDimitry Andric   if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
46120b57cec5SDimitry Andric     return *section_end();
46130b57cec5SDimitry Andric   unsigned SecNum = getPlainRelocationSymbolNum(RE);
46140b57cec5SDimitry Andric   if (SecNum == MachO::R_ABS || SecNum > Sections.size())
46150b57cec5SDimitry Andric     return *section_end();
46160b57cec5SDimitry Andric   DataRefImpl DRI;
46170b57cec5SDimitry Andric   DRI.d.a = SecNum - 1;
46180b57cec5SDimitry Andric   return SectionRef(DRI, this);
46190b57cec5SDimitry Andric }
46200b57cec5SDimitry Andric 
46210b57cec5SDimitry Andric MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
46220b57cec5SDimitry Andric   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
46230b57cec5SDimitry Andric   return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
46240b57cec5SDimitry Andric }
46250b57cec5SDimitry Andric 
46260b57cec5SDimitry Andric MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
46270b57cec5SDimitry Andric   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
46280b57cec5SDimitry Andric   return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
46290b57cec5SDimitry Andric }
46300b57cec5SDimitry Andric 
46310b57cec5SDimitry Andric MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
46320b57cec5SDimitry Andric                                            unsigned Index) const {
46330b57cec5SDimitry Andric   const char *Sec = getSectionPtr(*this, L, Index);
46340b57cec5SDimitry Andric   return getStruct<MachO::section>(*this, Sec);
46350b57cec5SDimitry Andric }
46360b57cec5SDimitry Andric 
46370b57cec5SDimitry Andric MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
46380b57cec5SDimitry Andric                                                 unsigned Index) const {
46390b57cec5SDimitry Andric   const char *Sec = getSectionPtr(*this, L, Index);
46400b57cec5SDimitry Andric   return getStruct<MachO::section_64>(*this, Sec);
46410b57cec5SDimitry Andric }
46420b57cec5SDimitry Andric 
46430b57cec5SDimitry Andric MachO::nlist
46440b57cec5SDimitry Andric MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
46450b57cec5SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
46460b57cec5SDimitry Andric   return getStruct<MachO::nlist>(*this, P);
46470b57cec5SDimitry Andric }
46480b57cec5SDimitry Andric 
46490b57cec5SDimitry Andric MachO::nlist_64
46500b57cec5SDimitry Andric MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
46510b57cec5SDimitry Andric   const char *P = reinterpret_cast<const char *>(DRI.p);
46520b57cec5SDimitry Andric   return getStruct<MachO::nlist_64>(*this, P);
46530b57cec5SDimitry Andric }
46540b57cec5SDimitry Andric 
46550b57cec5SDimitry Andric MachO::linkedit_data_command
46560b57cec5SDimitry Andric MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
46570b57cec5SDimitry Andric   return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
46580b57cec5SDimitry Andric }
46590b57cec5SDimitry Andric 
46600b57cec5SDimitry Andric MachO::segment_command
46610b57cec5SDimitry Andric MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
46620b57cec5SDimitry Andric   return getStruct<MachO::segment_command>(*this, L.Ptr);
46630b57cec5SDimitry Andric }
46640b57cec5SDimitry Andric 
46650b57cec5SDimitry Andric MachO::segment_command_64
46660b57cec5SDimitry Andric MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
46670b57cec5SDimitry Andric   return getStruct<MachO::segment_command_64>(*this, L.Ptr);
46680b57cec5SDimitry Andric }
46690b57cec5SDimitry Andric 
46700b57cec5SDimitry Andric MachO::linker_option_command
46710b57cec5SDimitry Andric MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
46720b57cec5SDimitry Andric   return getStruct<MachO::linker_option_command>(*this, L.Ptr);
46730b57cec5SDimitry Andric }
46740b57cec5SDimitry Andric 
46750b57cec5SDimitry Andric MachO::version_min_command
46760b57cec5SDimitry Andric MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
46770b57cec5SDimitry Andric   return getStruct<MachO::version_min_command>(*this, L.Ptr);
46780b57cec5SDimitry Andric }
46790b57cec5SDimitry Andric 
46800b57cec5SDimitry Andric MachO::note_command
46810b57cec5SDimitry Andric MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
46820b57cec5SDimitry Andric   return getStruct<MachO::note_command>(*this, L.Ptr);
46830b57cec5SDimitry Andric }
46840b57cec5SDimitry Andric 
46850b57cec5SDimitry Andric MachO::build_version_command
46860b57cec5SDimitry Andric MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
46870b57cec5SDimitry Andric   return getStruct<MachO::build_version_command>(*this, L.Ptr);
46880b57cec5SDimitry Andric }
46890b57cec5SDimitry Andric 
46900b57cec5SDimitry Andric MachO::build_tool_version
46910b57cec5SDimitry Andric MachOObjectFile::getBuildToolVersion(unsigned index) const {
46920b57cec5SDimitry Andric   return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
46930b57cec5SDimitry Andric }
46940b57cec5SDimitry Andric 
46950b57cec5SDimitry Andric MachO::dylib_command
46960b57cec5SDimitry Andric MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
46970b57cec5SDimitry Andric   return getStruct<MachO::dylib_command>(*this, L.Ptr);
46980b57cec5SDimitry Andric }
46990b57cec5SDimitry Andric 
47000b57cec5SDimitry Andric MachO::dyld_info_command
47010b57cec5SDimitry Andric MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
47020b57cec5SDimitry Andric   return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
47030b57cec5SDimitry Andric }
47040b57cec5SDimitry Andric 
47050b57cec5SDimitry Andric MachO::dylinker_command
47060b57cec5SDimitry Andric MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
47070b57cec5SDimitry Andric   return getStruct<MachO::dylinker_command>(*this, L.Ptr);
47080b57cec5SDimitry Andric }
47090b57cec5SDimitry Andric 
47100b57cec5SDimitry Andric MachO::uuid_command
47110b57cec5SDimitry Andric MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
47120b57cec5SDimitry Andric   return getStruct<MachO::uuid_command>(*this, L.Ptr);
47130b57cec5SDimitry Andric }
47140b57cec5SDimitry Andric 
47150b57cec5SDimitry Andric MachO::rpath_command
47160b57cec5SDimitry Andric MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
47170b57cec5SDimitry Andric   return getStruct<MachO::rpath_command>(*this, L.Ptr);
47180b57cec5SDimitry Andric }
47190b57cec5SDimitry Andric 
47200b57cec5SDimitry Andric MachO::source_version_command
47210b57cec5SDimitry Andric MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
47220b57cec5SDimitry Andric   return getStruct<MachO::source_version_command>(*this, L.Ptr);
47230b57cec5SDimitry Andric }
47240b57cec5SDimitry Andric 
47250b57cec5SDimitry Andric MachO::entry_point_command
47260b57cec5SDimitry Andric MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
47270b57cec5SDimitry Andric   return getStruct<MachO::entry_point_command>(*this, L.Ptr);
47280b57cec5SDimitry Andric }
47290b57cec5SDimitry Andric 
47300b57cec5SDimitry Andric MachO::encryption_info_command
47310b57cec5SDimitry Andric MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
47320b57cec5SDimitry Andric   return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
47330b57cec5SDimitry Andric }
47340b57cec5SDimitry Andric 
47350b57cec5SDimitry Andric MachO::encryption_info_command_64
47360b57cec5SDimitry Andric MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
47370b57cec5SDimitry Andric   return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
47380b57cec5SDimitry Andric }
47390b57cec5SDimitry Andric 
47400b57cec5SDimitry Andric MachO::sub_framework_command
47410b57cec5SDimitry Andric MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
47420b57cec5SDimitry Andric   return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
47430b57cec5SDimitry Andric }
47440b57cec5SDimitry Andric 
47450b57cec5SDimitry Andric MachO::sub_umbrella_command
47460b57cec5SDimitry Andric MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
47470b57cec5SDimitry Andric   return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
47480b57cec5SDimitry Andric }
47490b57cec5SDimitry Andric 
47500b57cec5SDimitry Andric MachO::sub_library_command
47510b57cec5SDimitry Andric MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
47520b57cec5SDimitry Andric   return getStruct<MachO::sub_library_command>(*this, L.Ptr);
47530b57cec5SDimitry Andric }
47540b57cec5SDimitry Andric 
47550b57cec5SDimitry Andric MachO::sub_client_command
47560b57cec5SDimitry Andric MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
47570b57cec5SDimitry Andric   return getStruct<MachO::sub_client_command>(*this, L.Ptr);
47580b57cec5SDimitry Andric }
47590b57cec5SDimitry Andric 
47600b57cec5SDimitry Andric MachO::routines_command
47610b57cec5SDimitry Andric MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
47620b57cec5SDimitry Andric   return getStruct<MachO::routines_command>(*this, L.Ptr);
47630b57cec5SDimitry Andric }
47640b57cec5SDimitry Andric 
47650b57cec5SDimitry Andric MachO::routines_command_64
47660b57cec5SDimitry Andric MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
47670b57cec5SDimitry Andric   return getStruct<MachO::routines_command_64>(*this, L.Ptr);
47680b57cec5SDimitry Andric }
47690b57cec5SDimitry Andric 
47700b57cec5SDimitry Andric MachO::thread_command
47710b57cec5SDimitry Andric MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
47720b57cec5SDimitry Andric   return getStruct<MachO::thread_command>(*this, L.Ptr);
47730b57cec5SDimitry Andric }
47740b57cec5SDimitry Andric 
47755f757f3fSDimitry Andric MachO::fileset_entry_command
47765f757f3fSDimitry Andric MachOObjectFile::getFilesetEntryLoadCommand(const LoadCommandInfo &L) const {
47775f757f3fSDimitry Andric   return getStruct<MachO::fileset_entry_command>(*this, L.Ptr);
47785f757f3fSDimitry Andric }
47795f757f3fSDimitry Andric 
47800b57cec5SDimitry Andric MachO::any_relocation_info
47810b57cec5SDimitry Andric MachOObjectFile::getRelocation(DataRefImpl Rel) const {
47820b57cec5SDimitry Andric   uint32_t Offset;
47830b57cec5SDimitry Andric   if (getHeader().filetype == MachO::MH_OBJECT) {
47840b57cec5SDimitry Andric     DataRefImpl Sec;
47850b57cec5SDimitry Andric     Sec.d.a = Rel.d.a;
47860b57cec5SDimitry Andric     if (is64Bit()) {
47870b57cec5SDimitry Andric       MachO::section_64 Sect = getSection64(Sec);
47880b57cec5SDimitry Andric       Offset = Sect.reloff;
47890b57cec5SDimitry Andric     } else {
47900b57cec5SDimitry Andric       MachO::section Sect = getSection(Sec);
47910b57cec5SDimitry Andric       Offset = Sect.reloff;
47920b57cec5SDimitry Andric     }
47930b57cec5SDimitry Andric   } else {
47940b57cec5SDimitry Andric     MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
47950b57cec5SDimitry Andric     if (Rel.d.a == 0)
47960b57cec5SDimitry Andric       Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
47970b57cec5SDimitry Andric     else
47980b57cec5SDimitry Andric       Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
47990b57cec5SDimitry Andric   }
48000b57cec5SDimitry Andric 
48010b57cec5SDimitry Andric   auto P = reinterpret_cast<const MachO::any_relocation_info *>(
48020b57cec5SDimitry Andric       getPtr(*this, Offset)) + Rel.d.b;
48030b57cec5SDimitry Andric   return getStruct<MachO::any_relocation_info>(
48040b57cec5SDimitry Andric       *this, reinterpret_cast<const char *>(P));
48050b57cec5SDimitry Andric }
48060b57cec5SDimitry Andric 
48070b57cec5SDimitry Andric MachO::data_in_code_entry
48080b57cec5SDimitry Andric MachOObjectFile::getDice(DataRefImpl Rel) const {
48090b57cec5SDimitry Andric   const char *P = reinterpret_cast<const char *>(Rel.p);
48100b57cec5SDimitry Andric   return getStruct<MachO::data_in_code_entry>(*this, P);
48110b57cec5SDimitry Andric }
48120b57cec5SDimitry Andric 
48130b57cec5SDimitry Andric const MachO::mach_header &MachOObjectFile::getHeader() const {
48140b57cec5SDimitry Andric   return Header;
48150b57cec5SDimitry Andric }
48160b57cec5SDimitry Andric 
48170b57cec5SDimitry Andric const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
48180b57cec5SDimitry Andric   assert(is64Bit());
48190b57cec5SDimitry Andric   return Header64;
48200b57cec5SDimitry Andric }
48210b57cec5SDimitry Andric 
48220b57cec5SDimitry Andric uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
48230b57cec5SDimitry Andric                                              const MachO::dysymtab_command &DLC,
48240b57cec5SDimitry Andric                                              unsigned Index) const {
48250b57cec5SDimitry Andric   uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
48260b57cec5SDimitry Andric   return getStruct<uint32_t>(*this, getPtr(*this, Offset));
48270b57cec5SDimitry Andric }
48280b57cec5SDimitry Andric 
48290b57cec5SDimitry Andric MachO::data_in_code_entry
48300b57cec5SDimitry Andric MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
48310b57cec5SDimitry Andric                                          unsigned Index) const {
48320b57cec5SDimitry Andric   uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
48330b57cec5SDimitry Andric   return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
48340b57cec5SDimitry Andric }
48350b57cec5SDimitry Andric 
48360b57cec5SDimitry Andric MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
48370b57cec5SDimitry Andric   if (SymtabLoadCmd)
48380b57cec5SDimitry Andric     return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
48390b57cec5SDimitry Andric 
48400b57cec5SDimitry Andric   // If there is no SymtabLoadCmd return a load command with zero'ed fields.
48410b57cec5SDimitry Andric   MachO::symtab_command Cmd;
48420b57cec5SDimitry Andric   Cmd.cmd = MachO::LC_SYMTAB;
48430b57cec5SDimitry Andric   Cmd.cmdsize = sizeof(MachO::symtab_command);
48440b57cec5SDimitry Andric   Cmd.symoff = 0;
48450b57cec5SDimitry Andric   Cmd.nsyms = 0;
48460b57cec5SDimitry Andric   Cmd.stroff = 0;
48470b57cec5SDimitry Andric   Cmd.strsize = 0;
48480b57cec5SDimitry Andric   return Cmd;
48490b57cec5SDimitry Andric }
48500b57cec5SDimitry Andric 
48510b57cec5SDimitry Andric MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
48520b57cec5SDimitry Andric   if (DysymtabLoadCmd)
48530b57cec5SDimitry Andric     return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
48540b57cec5SDimitry Andric 
48550b57cec5SDimitry Andric   // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
48560b57cec5SDimitry Andric   MachO::dysymtab_command Cmd;
48570b57cec5SDimitry Andric   Cmd.cmd = MachO::LC_DYSYMTAB;
48580b57cec5SDimitry Andric   Cmd.cmdsize = sizeof(MachO::dysymtab_command);
48590b57cec5SDimitry Andric   Cmd.ilocalsym = 0;
48600b57cec5SDimitry Andric   Cmd.nlocalsym = 0;
48610b57cec5SDimitry Andric   Cmd.iextdefsym = 0;
48620b57cec5SDimitry Andric   Cmd.nextdefsym = 0;
48630b57cec5SDimitry Andric   Cmd.iundefsym = 0;
48640b57cec5SDimitry Andric   Cmd.nundefsym = 0;
48650b57cec5SDimitry Andric   Cmd.tocoff = 0;
48660b57cec5SDimitry Andric   Cmd.ntoc = 0;
48670b57cec5SDimitry Andric   Cmd.modtaboff = 0;
48680b57cec5SDimitry Andric   Cmd.nmodtab = 0;
48690b57cec5SDimitry Andric   Cmd.extrefsymoff = 0;
48700b57cec5SDimitry Andric   Cmd.nextrefsyms = 0;
48710b57cec5SDimitry Andric   Cmd.indirectsymoff = 0;
48720b57cec5SDimitry Andric   Cmd.nindirectsyms = 0;
48730b57cec5SDimitry Andric   Cmd.extreloff = 0;
48740b57cec5SDimitry Andric   Cmd.nextrel = 0;
48750b57cec5SDimitry Andric   Cmd.locreloff = 0;
48760b57cec5SDimitry Andric   Cmd.nlocrel = 0;
48770b57cec5SDimitry Andric   return Cmd;
48780b57cec5SDimitry Andric }
48790b57cec5SDimitry Andric 
48800b57cec5SDimitry Andric MachO::linkedit_data_command
48810b57cec5SDimitry Andric MachOObjectFile::getDataInCodeLoadCommand() const {
48820b57cec5SDimitry Andric   if (DataInCodeLoadCmd)
48830b57cec5SDimitry Andric     return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
48840b57cec5SDimitry Andric 
48850b57cec5SDimitry Andric   // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
48860b57cec5SDimitry Andric   MachO::linkedit_data_command Cmd;
48870b57cec5SDimitry Andric   Cmd.cmd = MachO::LC_DATA_IN_CODE;
48880b57cec5SDimitry Andric   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
48890b57cec5SDimitry Andric   Cmd.dataoff = 0;
48900b57cec5SDimitry Andric   Cmd.datasize = 0;
48910b57cec5SDimitry Andric   return Cmd;
48920b57cec5SDimitry Andric }
48930b57cec5SDimitry Andric 
48940b57cec5SDimitry Andric MachO::linkedit_data_command
48950b57cec5SDimitry Andric MachOObjectFile::getLinkOptHintsLoadCommand() const {
48960b57cec5SDimitry Andric   if (LinkOptHintsLoadCmd)
48970b57cec5SDimitry Andric     return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
48980b57cec5SDimitry Andric 
48990b57cec5SDimitry Andric   // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
49000b57cec5SDimitry Andric   // fields.
49010b57cec5SDimitry Andric   MachO::linkedit_data_command Cmd;
49020b57cec5SDimitry Andric   Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
49030b57cec5SDimitry Andric   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
49040b57cec5SDimitry Andric   Cmd.dataoff = 0;
49050b57cec5SDimitry Andric   Cmd.datasize = 0;
49060b57cec5SDimitry Andric   return Cmd;
49070b57cec5SDimitry Andric }
49080b57cec5SDimitry Andric 
49090b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
49100b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
4911bdd1243dSDimitry Andric     return std::nullopt;
49120b57cec5SDimitry Andric 
49130b57cec5SDimitry Andric   auto DyldInfoOrErr =
49140b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
49150b57cec5SDimitry Andric   if (!DyldInfoOrErr)
4916bdd1243dSDimitry Andric     return std::nullopt;
49170b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
49180b57cec5SDimitry Andric   const uint8_t *Ptr =
49190b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
4920bdd1243dSDimitry Andric   return ArrayRef(Ptr, DyldInfo.rebase_size);
49210b57cec5SDimitry Andric }
49220b57cec5SDimitry Andric 
49230b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
49240b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
4925bdd1243dSDimitry Andric     return std::nullopt;
49260b57cec5SDimitry Andric 
49270b57cec5SDimitry Andric   auto DyldInfoOrErr =
49280b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
49290b57cec5SDimitry Andric   if (!DyldInfoOrErr)
4930bdd1243dSDimitry Andric     return std::nullopt;
49310b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
49320b57cec5SDimitry Andric   const uint8_t *Ptr =
49330b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
4934bdd1243dSDimitry Andric   return ArrayRef(Ptr, DyldInfo.bind_size);
49350b57cec5SDimitry Andric }
49360b57cec5SDimitry Andric 
49370b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
49380b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
4939bdd1243dSDimitry Andric     return std::nullopt;
49400b57cec5SDimitry Andric 
49410b57cec5SDimitry Andric   auto DyldInfoOrErr =
49420b57cec5SDimitry Andric     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
49430b57cec5SDimitry Andric   if (!DyldInfoOrErr)
4944bdd1243dSDimitry Andric     return std::nullopt;
49450b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
49460b57cec5SDimitry Andric   const uint8_t *Ptr =
49470b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
4948bdd1243dSDimitry Andric   return ArrayRef(Ptr, DyldInfo.weak_bind_size);
49490b57cec5SDimitry Andric }
49500b57cec5SDimitry Andric 
49510b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
49520b57cec5SDimitry Andric   if (!DyldInfoLoadCmd)
4953bdd1243dSDimitry Andric     return std::nullopt;
49540b57cec5SDimitry Andric 
49550b57cec5SDimitry Andric   auto DyldInfoOrErr =
49560b57cec5SDimitry Andric       getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
49570b57cec5SDimitry Andric   if (!DyldInfoOrErr)
4958bdd1243dSDimitry Andric     return std::nullopt;
49590b57cec5SDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
49600b57cec5SDimitry Andric   const uint8_t *Ptr =
49610b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
4962bdd1243dSDimitry Andric   return ArrayRef(Ptr, DyldInfo.lazy_bind_size);
49630b57cec5SDimitry Andric }
49640b57cec5SDimitry Andric 
4965bdd1243dSDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4966bdd1243dSDimitry Andric   if (!DyldInfoLoadCmd)
4967bdd1243dSDimitry Andric     return std::nullopt;
4968bdd1243dSDimitry Andric 
4969bdd1243dSDimitry Andric   auto DyldInfoOrErr =
4970bdd1243dSDimitry Andric       getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4971bdd1243dSDimitry Andric   if (!DyldInfoOrErr)
4972bdd1243dSDimitry Andric     return std::nullopt;
4973bdd1243dSDimitry Andric   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4974bdd1243dSDimitry Andric   const uint8_t *Ptr =
4975bdd1243dSDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
4976bdd1243dSDimitry Andric   return ArrayRef(Ptr, DyldInfo.export_size);
4977bdd1243dSDimitry Andric }
4978bdd1243dSDimitry Andric 
4979bdd1243dSDimitry Andric Expected<std::optional<MachO::linkedit_data_command>>
4980bdd1243dSDimitry Andric MachOObjectFile::getChainedFixupsLoadCommand() const {
498181ad6265SDimitry Andric   // Load the dyld chained fixups load command.
498281ad6265SDimitry Andric   if (!DyldChainedFixupsLoadCmd)
4983bdd1243dSDimitry Andric     return std::nullopt;
498481ad6265SDimitry Andric   auto DyldChainedFixupsOrErr = getStructOrErr<MachO::linkedit_data_command>(
498581ad6265SDimitry Andric       *this, DyldChainedFixupsLoadCmd);
498681ad6265SDimitry Andric   if (!DyldChainedFixupsOrErr)
498781ad6265SDimitry Andric     return DyldChainedFixupsOrErr.takeError();
4988bdd1243dSDimitry Andric   const MachO::linkedit_data_command &DyldChainedFixups =
4989bdd1243dSDimitry Andric       *DyldChainedFixupsOrErr;
499081ad6265SDimitry Andric 
499181ad6265SDimitry Andric   // If the load command is present but the data offset has been zeroed out,
4992bdd1243dSDimitry Andric   // as is the case for dylib stubs, return std::nullopt (no error).
4993bdd1243dSDimitry Andric   if (!DyldChainedFixups.dataoff)
4994bdd1243dSDimitry Andric     return std::nullopt;
4995bdd1243dSDimitry Andric   return DyldChainedFixups;
4996bdd1243dSDimitry Andric }
4997bdd1243dSDimitry Andric 
4998bdd1243dSDimitry Andric Expected<std::optional<MachO::dyld_chained_fixups_header>>
4999bdd1243dSDimitry Andric MachOObjectFile::getChainedFixupsHeader() const {
5000bdd1243dSDimitry Andric   auto CFOrErr = getChainedFixupsLoadCommand();
5001bdd1243dSDimitry Andric   if (!CFOrErr)
5002bdd1243dSDimitry Andric     return CFOrErr.takeError();
5003bdd1243dSDimitry Andric   if (!CFOrErr->has_value())
5004bdd1243dSDimitry Andric     return std::nullopt;
5005bdd1243dSDimitry Andric 
5006bdd1243dSDimitry Andric   const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
5007bdd1243dSDimitry Andric 
500881ad6265SDimitry Andric   uint64_t CFHeaderOffset = DyldChainedFixups.dataoff;
5009bdd1243dSDimitry Andric   uint64_t CFSize = DyldChainedFixups.datasize;
501081ad6265SDimitry Andric 
501181ad6265SDimitry Andric   // Load the dyld chained fixups header.
501281ad6265SDimitry Andric   const char *CFHeaderPtr = getPtr(*this, CFHeaderOffset);
501381ad6265SDimitry Andric   auto CFHeaderOrErr =
501481ad6265SDimitry Andric       getStructOrErr<MachO::dyld_chained_fixups_header>(*this, CFHeaderPtr);
501581ad6265SDimitry Andric   if (!CFHeaderOrErr)
501681ad6265SDimitry Andric     return CFHeaderOrErr.takeError();
501781ad6265SDimitry Andric   MachO::dyld_chained_fixups_header CFHeader = CFHeaderOrErr.get();
501881ad6265SDimitry Andric 
501981ad6265SDimitry Andric   // Reject unknown chained fixup formats.
502081ad6265SDimitry Andric   if (CFHeader.fixups_version != 0)
502181ad6265SDimitry Andric     return malformedError(Twine("bad chained fixups: unknown version: ") +
502281ad6265SDimitry Andric                           Twine(CFHeader.fixups_version));
502381ad6265SDimitry Andric   if (CFHeader.imports_format < 1 || CFHeader.imports_format > 3)
502481ad6265SDimitry Andric     return malformedError(
502581ad6265SDimitry Andric         Twine("bad chained fixups: unknown imports format: ") +
502681ad6265SDimitry Andric         Twine(CFHeader.imports_format));
502781ad6265SDimitry Andric 
502881ad6265SDimitry Andric   // Validate the image format.
502981ad6265SDimitry Andric   //
503081ad6265SDimitry Andric   // Load the image starts.
503181ad6265SDimitry Andric   uint64_t CFImageStartsOffset = (CFHeaderOffset + CFHeader.starts_offset);
503281ad6265SDimitry Andric   if (CFHeader.starts_offset < sizeof(MachO::dyld_chained_fixups_header)) {
503381ad6265SDimitry Andric     return malformedError(Twine("bad chained fixups: image starts offset ") +
503481ad6265SDimitry Andric                           Twine(CFHeader.starts_offset) +
503581ad6265SDimitry Andric                           " overlaps with chained fixups header");
503681ad6265SDimitry Andric   }
5037bdd1243dSDimitry Andric   uint32_t EndOffset = CFHeaderOffset + CFSize;
503881ad6265SDimitry Andric   if (CFImageStartsOffset + sizeof(MachO::dyld_chained_starts_in_image) >
503981ad6265SDimitry Andric       EndOffset) {
504081ad6265SDimitry Andric     return malformedError(Twine("bad chained fixups: image starts end ") +
504181ad6265SDimitry Andric                           Twine(CFImageStartsOffset +
504281ad6265SDimitry Andric                                 sizeof(MachO::dyld_chained_starts_in_image)) +
504381ad6265SDimitry Andric                           " extends past end " + Twine(EndOffset));
504481ad6265SDimitry Andric   }
504581ad6265SDimitry Andric 
504681ad6265SDimitry Andric   return CFHeader;
504781ad6265SDimitry Andric }
504881ad6265SDimitry Andric 
5049bdd1243dSDimitry Andric Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>
5050bdd1243dSDimitry Andric MachOObjectFile::getChainedFixupsSegments() const {
5051bdd1243dSDimitry Andric   auto CFOrErr = getChainedFixupsLoadCommand();
5052bdd1243dSDimitry Andric   if (!CFOrErr)
5053bdd1243dSDimitry Andric     return CFOrErr.takeError();
5054bdd1243dSDimitry Andric 
5055bdd1243dSDimitry Andric   std::vector<ChainedFixupsSegment> Segments;
5056bdd1243dSDimitry Andric   if (!CFOrErr->has_value())
5057bdd1243dSDimitry Andric     return std::make_pair(0, Segments);
5058bdd1243dSDimitry Andric 
5059bdd1243dSDimitry Andric   const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
5060bdd1243dSDimitry Andric 
5061bdd1243dSDimitry Andric   auto HeaderOrErr = getChainedFixupsHeader();
5062bdd1243dSDimitry Andric   if (!HeaderOrErr)
5063bdd1243dSDimitry Andric     return HeaderOrErr.takeError();
5064bdd1243dSDimitry Andric   if (!HeaderOrErr->has_value())
5065bdd1243dSDimitry Andric     return std::make_pair(0, Segments);
5066bdd1243dSDimitry Andric   const MachO::dyld_chained_fixups_header &Header = **HeaderOrErr;
5067bdd1243dSDimitry Andric 
5068bdd1243dSDimitry Andric   const char *Contents = getPtr(*this, DyldChainedFixups.dataoff);
5069bdd1243dSDimitry Andric 
5070bdd1243dSDimitry Andric   auto ImageStartsOrErr = getStructOrErr<MachO::dyld_chained_starts_in_image>(
5071bdd1243dSDimitry Andric       *this, Contents + Header.starts_offset);
5072bdd1243dSDimitry Andric   if (!ImageStartsOrErr)
5073bdd1243dSDimitry Andric     return ImageStartsOrErr.takeError();
5074bdd1243dSDimitry Andric   const MachO::dyld_chained_starts_in_image &ImageStarts = *ImageStartsOrErr;
5075bdd1243dSDimitry Andric 
5076bdd1243dSDimitry Andric   const char *SegOffsPtr =
5077bdd1243dSDimitry Andric       Contents + Header.starts_offset +
5078bdd1243dSDimitry Andric       offsetof(MachO::dyld_chained_starts_in_image, seg_info_offset);
5079bdd1243dSDimitry Andric   const char *SegOffsEnd =
5080bdd1243dSDimitry Andric       SegOffsPtr + ImageStarts.seg_count * sizeof(uint32_t);
5081bdd1243dSDimitry Andric   if (SegOffsEnd > Contents + DyldChainedFixups.datasize)
5082bdd1243dSDimitry Andric     return malformedError(
5083bdd1243dSDimitry Andric         "bad chained fixups: seg_info_offset extends past end");
5084bdd1243dSDimitry Andric 
5085bdd1243dSDimitry Andric   const char *LastSegEnd = nullptr;
5086bdd1243dSDimitry Andric   for (size_t I = 0, N = ImageStarts.seg_count; I < N; ++I) {
5087bdd1243dSDimitry Andric     auto OffOrErr =
5088bdd1243dSDimitry Andric         getStructOrErr<uint32_t>(*this, SegOffsPtr + I * sizeof(uint32_t));
5089bdd1243dSDimitry Andric     if (!OffOrErr)
5090bdd1243dSDimitry Andric       return OffOrErr.takeError();
5091bdd1243dSDimitry Andric     // seg_info_offset == 0 means there is no associated starts_in_segment
5092bdd1243dSDimitry Andric     // entry.
5093bdd1243dSDimitry Andric     if (!*OffOrErr)
5094bdd1243dSDimitry Andric       continue;
5095bdd1243dSDimitry Andric 
5096bdd1243dSDimitry Andric     auto Fail = [&](Twine Message) {
5097bdd1243dSDimitry Andric       return malformedError("bad chained fixups: segment info" + Twine(I) +
5098bdd1243dSDimitry Andric                             " at offset " + Twine(*OffOrErr) + Message);
5099bdd1243dSDimitry Andric     };
5100bdd1243dSDimitry Andric 
5101bdd1243dSDimitry Andric     const char *SegPtr = Contents + Header.starts_offset + *OffOrErr;
5102bdd1243dSDimitry Andric     if (LastSegEnd && SegPtr < LastSegEnd)
5103bdd1243dSDimitry Andric       return Fail(" overlaps with previous segment info");
5104bdd1243dSDimitry Andric 
5105bdd1243dSDimitry Andric     auto SegOrErr =
5106bdd1243dSDimitry Andric         getStructOrErr<MachO::dyld_chained_starts_in_segment>(*this, SegPtr);
5107bdd1243dSDimitry Andric     if (!SegOrErr)
5108bdd1243dSDimitry Andric       return SegOrErr.takeError();
5109bdd1243dSDimitry Andric     const MachO::dyld_chained_starts_in_segment &Seg = *SegOrErr;
5110bdd1243dSDimitry Andric 
5111bdd1243dSDimitry Andric     LastSegEnd = SegPtr + Seg.size;
5112bdd1243dSDimitry Andric     if (Seg.pointer_format < 1 || Seg.pointer_format > 12)
5113bdd1243dSDimitry Andric       return Fail(" has unknown pointer format: " + Twine(Seg.pointer_format));
5114bdd1243dSDimitry Andric 
5115bdd1243dSDimitry Andric     const char *PageStart =
5116bdd1243dSDimitry Andric         SegPtr + offsetof(MachO::dyld_chained_starts_in_segment, page_start);
5117bdd1243dSDimitry Andric     const char *PageEnd = PageStart + Seg.page_count * sizeof(uint16_t);
5118bdd1243dSDimitry Andric     if (PageEnd > SegPtr + Seg.size)
5119bdd1243dSDimitry Andric       return Fail(" : page_starts extend past seg_info size");
5120bdd1243dSDimitry Andric 
5121bdd1243dSDimitry Andric     // FIXME: This does not account for multiple offsets on a single page
5122bdd1243dSDimitry Andric     //        (DYLD_CHAINED_PTR_START_MULTI; 32-bit only).
5123bdd1243dSDimitry Andric     std::vector<uint16_t> PageStarts;
5124bdd1243dSDimitry Andric     for (size_t PageIdx = 0; PageIdx < Seg.page_count; ++PageIdx) {
5125bdd1243dSDimitry Andric       uint16_t Start;
5126bdd1243dSDimitry Andric       memcpy(&Start, PageStart + PageIdx * sizeof(uint16_t), sizeof(uint16_t));
5127bdd1243dSDimitry Andric       if (isLittleEndian() != sys::IsLittleEndianHost)
5128bdd1243dSDimitry Andric         sys::swapByteOrder(Start);
5129bdd1243dSDimitry Andric       PageStarts.push_back(Start);
5130bdd1243dSDimitry Andric     }
5131bdd1243dSDimitry Andric 
5132bdd1243dSDimitry Andric     Segments.emplace_back(I, *OffOrErr, Seg, std::move(PageStarts));
5133bdd1243dSDimitry Andric   }
5134bdd1243dSDimitry Andric 
5135bdd1243dSDimitry Andric   return std::make_pair(ImageStarts.seg_count, Segments);
5136bdd1243dSDimitry Andric }
5137bdd1243dSDimitry Andric 
5138bdd1243dSDimitry Andric // The special library ordinals have a negative value, but they are encoded in
5139bdd1243dSDimitry Andric // an unsigned bitfield, so we need to sign extend the value.
5140bdd1243dSDimitry Andric template <typename T> static int getEncodedOrdinal(T Value) {
5141bdd1243dSDimitry Andric   if (Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE) ||
5142bdd1243dSDimitry Andric       Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) ||
5143bdd1243dSDimitry Andric       Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP))
5144bdd1243dSDimitry Andric     return SignExtend32<sizeof(T) * CHAR_BIT>(Value);
5145bdd1243dSDimitry Andric   return Value;
5146bdd1243dSDimitry Andric }
5147bdd1243dSDimitry Andric 
5148bdd1243dSDimitry Andric template <typename T, unsigned N>
5149bdd1243dSDimitry Andric static std::array<T, N> getArray(const MachOObjectFile &O, const void *Ptr) {
5150bdd1243dSDimitry Andric   std::array<T, N> RawValue;
5151bdd1243dSDimitry Andric   memcpy(RawValue.data(), Ptr, N * sizeof(T));
5152bdd1243dSDimitry Andric   if (O.isLittleEndian() != sys::IsLittleEndianHost)
5153bdd1243dSDimitry Andric     for (auto &Element : RawValue)
5154bdd1243dSDimitry Andric       sys::swapByteOrder(Element);
5155bdd1243dSDimitry Andric   return RawValue;
5156bdd1243dSDimitry Andric }
5157bdd1243dSDimitry Andric 
515881ad6265SDimitry Andric Expected<std::vector<ChainedFixupTarget>>
515981ad6265SDimitry Andric MachOObjectFile::getDyldChainedFixupTargets() const {
5160bdd1243dSDimitry Andric   auto CFOrErr = getChainedFixupsLoadCommand();
5161bdd1243dSDimitry Andric   if (!CFOrErr)
5162bdd1243dSDimitry Andric     return CFOrErr.takeError();
5163bdd1243dSDimitry Andric 
5164bdd1243dSDimitry Andric   std::vector<ChainedFixupTarget> Targets;
5165bdd1243dSDimitry Andric   if (!CFOrErr->has_value())
5166bdd1243dSDimitry Andric     return Targets;
5167bdd1243dSDimitry Andric 
5168bdd1243dSDimitry Andric   const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
5169bdd1243dSDimitry Andric 
517081ad6265SDimitry Andric   auto CFHeaderOrErr = getChainedFixupsHeader();
517181ad6265SDimitry Andric   if (!CFHeaderOrErr)
517281ad6265SDimitry Andric     return CFHeaderOrErr.takeError();
517381ad6265SDimitry Andric   if (!(*CFHeaderOrErr))
517481ad6265SDimitry Andric     return Targets;
5175bdd1243dSDimitry Andric   const MachO::dyld_chained_fixups_header &Header = **CFHeaderOrErr;
5176bdd1243dSDimitry Andric 
5177bdd1243dSDimitry Andric   size_t ImportSize = 0;
5178bdd1243dSDimitry Andric   if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT)
5179bdd1243dSDimitry Andric     ImportSize = sizeof(MachO::dyld_chained_import);
5180bdd1243dSDimitry Andric   else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND)
5181bdd1243dSDimitry Andric     ImportSize = sizeof(MachO::dyld_chained_import_addend);
5182bdd1243dSDimitry Andric   else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)
5183bdd1243dSDimitry Andric     ImportSize = sizeof(MachO::dyld_chained_import_addend64);
5184bdd1243dSDimitry Andric   else
5185bdd1243dSDimitry Andric     return malformedError("bad chained fixups: unknown imports format: " +
5186bdd1243dSDimitry Andric                           Twine(Header.imports_format));
5187bdd1243dSDimitry Andric 
5188bdd1243dSDimitry Andric   const char *Contents = getPtr(*this, DyldChainedFixups.dataoff);
5189bdd1243dSDimitry Andric   const char *Imports = Contents + Header.imports_offset;
5190bdd1243dSDimitry Andric   size_t ImportsEndOffset =
5191bdd1243dSDimitry Andric       Header.imports_offset + ImportSize * Header.imports_count;
5192bdd1243dSDimitry Andric   const char *ImportsEnd = Contents + ImportsEndOffset;
5193bdd1243dSDimitry Andric   const char *Symbols = Contents + Header.symbols_offset;
5194bdd1243dSDimitry Andric   const char *SymbolsEnd = Contents + DyldChainedFixups.datasize;
5195bdd1243dSDimitry Andric 
5196bdd1243dSDimitry Andric   if (ImportsEnd > Symbols)
5197bdd1243dSDimitry Andric     return malformedError("bad chained fixups: imports end " +
5198bdd1243dSDimitry Andric                           Twine(ImportsEndOffset) + " extends past end " +
5199bdd1243dSDimitry Andric                           Twine(DyldChainedFixups.datasize));
5200bdd1243dSDimitry Andric 
5201bdd1243dSDimitry Andric   if (ImportsEnd > Symbols)
5202bdd1243dSDimitry Andric     return malformedError("bad chained fixups: imports end " +
5203bdd1243dSDimitry Andric                           Twine(ImportsEndOffset) + " overlaps with symbols");
5204bdd1243dSDimitry Andric 
5205bdd1243dSDimitry Andric   // We use bit manipulation to extract data from the bitfields. This is correct
5206bdd1243dSDimitry Andric   // for both LE and BE hosts, but we assume that the object is little-endian.
5207bdd1243dSDimitry Andric   if (!isLittleEndian())
5208bdd1243dSDimitry Andric     return createError("parsing big-endian chained fixups is not implemented");
5209bdd1243dSDimitry Andric   for (const char *ImportPtr = Imports; ImportPtr < ImportsEnd;
5210bdd1243dSDimitry Andric        ImportPtr += ImportSize) {
5211bdd1243dSDimitry Andric     int LibOrdinal;
5212bdd1243dSDimitry Andric     bool WeakImport;
5213bdd1243dSDimitry Andric     uint32_t NameOffset;
5214bdd1243dSDimitry Andric     uint64_t Addend;
5215bdd1243dSDimitry Andric     if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT) {
5216bdd1243dSDimitry Andric       static_assert(sizeof(uint32_t) == sizeof(MachO::dyld_chained_import));
5217bdd1243dSDimitry Andric       auto RawValue = getArray<uint32_t, 1>(*this, ImportPtr);
5218bdd1243dSDimitry Andric 
5219bdd1243dSDimitry Andric       LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5220bdd1243dSDimitry Andric       WeakImport = (RawValue[0] >> 8) & 1;
5221bdd1243dSDimitry Andric       NameOffset = RawValue[0] >> 9;
5222bdd1243dSDimitry Andric       Addend = 0;
5223bdd1243dSDimitry Andric     } else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND) {
5224bdd1243dSDimitry Andric       static_assert(sizeof(uint64_t) ==
5225bdd1243dSDimitry Andric                     sizeof(MachO::dyld_chained_import_addend));
5226bdd1243dSDimitry Andric       auto RawValue = getArray<uint32_t, 2>(*this, ImportPtr);
5227bdd1243dSDimitry Andric 
5228bdd1243dSDimitry Andric       LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5229bdd1243dSDimitry Andric       WeakImport = (RawValue[0] >> 8) & 1;
5230bdd1243dSDimitry Andric       NameOffset = RawValue[0] >> 9;
5231bdd1243dSDimitry Andric       Addend = bit_cast<int32_t>(RawValue[1]);
5232bdd1243dSDimitry Andric     } else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64) {
5233bdd1243dSDimitry Andric       static_assert(2 * sizeof(uint64_t) ==
5234bdd1243dSDimitry Andric                     sizeof(MachO::dyld_chained_import_addend64));
5235bdd1243dSDimitry Andric       auto RawValue = getArray<uint64_t, 2>(*this, ImportPtr);
5236bdd1243dSDimitry Andric 
5237bdd1243dSDimitry Andric       LibOrdinal = getEncodedOrdinal<uint16_t>(RawValue[0] & 0xFFFF);
5238bdd1243dSDimitry Andric       NameOffset = (RawValue[0] >> 16) & 1;
5239bdd1243dSDimitry Andric       WeakImport = RawValue[0] >> 17;
5240bdd1243dSDimitry Andric       Addend = RawValue[1];
5241bdd1243dSDimitry Andric     } else {
5242bdd1243dSDimitry Andric       llvm_unreachable("Import format should have been checked");
524381ad6265SDimitry Andric     }
524481ad6265SDimitry Andric 
5245bdd1243dSDimitry Andric     const char *Str = Symbols + NameOffset;
5246bdd1243dSDimitry Andric     if (Str >= SymbolsEnd)
5247bdd1243dSDimitry Andric       return malformedError("bad chained fixups: symbol offset " +
5248bdd1243dSDimitry Andric                             Twine(NameOffset) + " extends past end " +
5249bdd1243dSDimitry Andric                             Twine(DyldChainedFixups.datasize));
5250bdd1243dSDimitry Andric     Targets.emplace_back(LibOrdinal, NameOffset, Str, Addend, WeakImport);
5251bdd1243dSDimitry Andric   }
52520b57cec5SDimitry Andric 
5253bdd1243dSDimitry Andric   return std::move(Targets);
5254bdd1243dSDimitry Andric }
5255bdd1243dSDimitry Andric 
5256bdd1243dSDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldExportsTrie() const {
5257bdd1243dSDimitry Andric   if (!DyldExportsTrieLoadCmd)
5258bdd1243dSDimitry Andric     return std::nullopt;
5259bdd1243dSDimitry Andric 
5260bdd1243dSDimitry Andric   auto DyldExportsTrieOrError = getStructOrErr<MachO::linkedit_data_command>(
5261bdd1243dSDimitry Andric       *this, DyldExportsTrieLoadCmd);
5262bdd1243dSDimitry Andric   if (!DyldExportsTrieOrError)
5263bdd1243dSDimitry Andric     return std::nullopt;
5264bdd1243dSDimitry Andric   MachO::linkedit_data_command DyldExportsTrie = DyldExportsTrieOrError.get();
52650b57cec5SDimitry Andric   const uint8_t *Ptr =
5266bdd1243dSDimitry Andric       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldExportsTrie.dataoff));
5267bdd1243dSDimitry Andric   return ArrayRef(Ptr, DyldExportsTrie.datasize);
52680b57cec5SDimitry Andric }
52690b57cec5SDimitry Andric 
527081ad6265SDimitry Andric SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const {
527181ad6265SDimitry Andric   if (!FuncStartsLoadCmd)
527281ad6265SDimitry Andric     return {};
527381ad6265SDimitry Andric 
527481ad6265SDimitry Andric   auto InfoOrErr =
527581ad6265SDimitry Andric       getStructOrErr<MachO::linkedit_data_command>(*this, FuncStartsLoadCmd);
527681ad6265SDimitry Andric   if (!InfoOrErr)
527781ad6265SDimitry Andric     return {};
527881ad6265SDimitry Andric 
527981ad6265SDimitry Andric   MachO::linkedit_data_command Info = InfoOrErr.get();
528081ad6265SDimitry Andric   SmallVector<uint64_t, 8> FunctionStarts;
528181ad6265SDimitry Andric   this->ReadULEB128s(Info.dataoff, FunctionStarts);
528281ad6265SDimitry Andric   return std::move(FunctionStarts);
528381ad6265SDimitry Andric }
528481ad6265SDimitry Andric 
52850b57cec5SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
52860b57cec5SDimitry Andric   if (!UuidLoadCmd)
5287bdd1243dSDimitry Andric     return std::nullopt;
52880b57cec5SDimitry Andric   // Returning a pointer is fine as uuid doesn't need endian swapping.
52890b57cec5SDimitry Andric   const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
5290bdd1243dSDimitry Andric   return ArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
52910b57cec5SDimitry Andric }
52920b57cec5SDimitry Andric 
52930b57cec5SDimitry Andric StringRef MachOObjectFile::getStringTableData() const {
52940b57cec5SDimitry Andric   MachO::symtab_command S = getSymtabLoadCommand();
52950b57cec5SDimitry Andric   return getData().substr(S.stroff, S.strsize);
52960b57cec5SDimitry Andric }
52970b57cec5SDimitry Andric 
52980b57cec5SDimitry Andric bool MachOObjectFile::is64Bit() const {
52990b57cec5SDimitry Andric   return getType() == getMachOType(false, true) ||
53000b57cec5SDimitry Andric     getType() == getMachOType(true, true);
53010b57cec5SDimitry Andric }
53020b57cec5SDimitry Andric 
53030b57cec5SDimitry Andric void MachOObjectFile::ReadULEB128s(uint64_t Index,
53040b57cec5SDimitry Andric                                    SmallVectorImpl<uint64_t> &Out) const {
53050b57cec5SDimitry Andric   DataExtractor extractor(ObjectFile::getData(), true, 0);
53060b57cec5SDimitry Andric 
53078bcb0991SDimitry Andric   uint64_t offset = Index;
53080b57cec5SDimitry Andric   uint64_t data = 0;
53090b57cec5SDimitry Andric   while (uint64_t delta = extractor.getULEB128(&offset)) {
53100b57cec5SDimitry Andric     data += delta;
53110b57cec5SDimitry Andric     Out.push_back(data);
53120b57cec5SDimitry Andric   }
53130b57cec5SDimitry Andric }
53140b57cec5SDimitry Andric 
53150b57cec5SDimitry Andric bool MachOObjectFile::isRelocatableObject() const {
53160b57cec5SDimitry Andric   return getHeader().filetype == MachO::MH_OBJECT;
53170b57cec5SDimitry Andric }
53180b57cec5SDimitry Andric 
53195f757f3fSDimitry Andric /// Create a MachOObjectFile instance from a given buffer.
53205f757f3fSDimitry Andric ///
53215f757f3fSDimitry Andric /// \param Buffer Memory buffer containing the MachO binary data.
53225f757f3fSDimitry Andric /// \param UniversalCputype CPU type when the MachO part of a universal binary.
53235f757f3fSDimitry Andric /// \param UniversalIndex Index of the MachO within a universal binary.
53245f757f3fSDimitry Andric /// \param MachOFilesetEntryOffset Offset of the MachO entry in a fileset MachO.
53255f757f3fSDimitry Andric /// \returns A std::unique_ptr to a MachOObjectFile instance on success.
53265f757f3fSDimitry Andric Expected<std::unique_ptr<MachOObjectFile>> ObjectFile::createMachOObjectFile(
53275f757f3fSDimitry Andric     MemoryBufferRef Buffer, uint32_t UniversalCputype, uint32_t UniversalIndex,
53285f757f3fSDimitry Andric     size_t MachOFilesetEntryOffset) {
53290b57cec5SDimitry Andric   StringRef Magic = Buffer.getBuffer().slice(0, 4);
53300b57cec5SDimitry Andric   if (Magic == "\xFE\xED\xFA\xCE")
53315f757f3fSDimitry Andric     return MachOObjectFile::create(Buffer, false, false, UniversalCputype,
53325f757f3fSDimitry Andric                                    UniversalIndex, MachOFilesetEntryOffset);
53330b57cec5SDimitry Andric   if (Magic == "\xCE\xFA\xED\xFE")
53345f757f3fSDimitry Andric     return MachOObjectFile::create(Buffer, true, false, UniversalCputype,
53355f757f3fSDimitry Andric                                    UniversalIndex, MachOFilesetEntryOffset);
53360b57cec5SDimitry Andric   if (Magic == "\xFE\xED\xFA\xCF")
53375f757f3fSDimitry Andric     return MachOObjectFile::create(Buffer, false, true, UniversalCputype,
53385f757f3fSDimitry Andric                                    UniversalIndex, MachOFilesetEntryOffset);
53390b57cec5SDimitry Andric   if (Magic == "\xCF\xFA\xED\xFE")
53405f757f3fSDimitry Andric     return MachOObjectFile::create(Buffer, true, true, UniversalCputype,
53415f757f3fSDimitry Andric                                    UniversalIndex, MachOFilesetEntryOffset);
53420b57cec5SDimitry Andric   return make_error<GenericBinaryError>("Unrecognized MachO magic number",
53430b57cec5SDimitry Andric                                         object_error::invalid_file_type);
53440b57cec5SDimitry Andric }
53450b57cec5SDimitry Andric 
53460b57cec5SDimitry Andric StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
53470b57cec5SDimitry Andric   return StringSwitch<StringRef>(Name)
53480b57cec5SDimitry Andric       .Case("debug_str_offs", "debug_str_offsets")
53490b57cec5SDimitry Andric       .Default(Name);
53500b57cec5SDimitry Andric }
53510eae32dcSDimitry Andric 
53520eae32dcSDimitry Andric Expected<std::vector<std::string>>
53530eae32dcSDimitry Andric MachOObjectFile::findDsymObjectMembers(StringRef Path) {
53540eae32dcSDimitry Andric   SmallString<256> BundlePath(Path);
53550eae32dcSDimitry Andric   // Normalize input path. This is necessary to accept `bundle.dSYM/`.
53560eae32dcSDimitry Andric   sys::path::remove_dots(BundlePath);
53570eae32dcSDimitry Andric   if (!sys::fs::is_directory(BundlePath) ||
53580eae32dcSDimitry Andric       sys::path::extension(BundlePath) != ".dSYM")
53590eae32dcSDimitry Andric     return std::vector<std::string>();
53600eae32dcSDimitry Andric   sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
53610eae32dcSDimitry Andric   bool IsDir;
53620eae32dcSDimitry Andric   auto EC = sys::fs::is_directory(BundlePath, IsDir);
53630eae32dcSDimitry Andric   if (EC == errc::no_such_file_or_directory || (!EC && !IsDir))
53640eae32dcSDimitry Andric     return createStringError(
53650eae32dcSDimitry Andric         EC, "%s: expected directory 'Contents/Resources/DWARF' in dSYM bundle",
53660eae32dcSDimitry Andric         Path.str().c_str());
53670eae32dcSDimitry Andric   if (EC)
53680eae32dcSDimitry Andric     return createFileError(BundlePath, errorCodeToError(EC));
53690eae32dcSDimitry Andric 
53700eae32dcSDimitry Andric   std::vector<std::string> ObjectPaths;
53710eae32dcSDimitry Andric   for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
53720eae32dcSDimitry Andric        Dir != DirEnd && !EC; Dir.increment(EC)) {
53730eae32dcSDimitry Andric     StringRef ObjectPath = Dir->path();
53740eae32dcSDimitry Andric     sys::fs::file_status Status;
53750eae32dcSDimitry Andric     if (auto EC = sys::fs::status(ObjectPath, Status))
53760eae32dcSDimitry Andric       return createFileError(ObjectPath, errorCodeToError(EC));
53770eae32dcSDimitry Andric     switch (Status.type()) {
53780eae32dcSDimitry Andric     case sys::fs::file_type::regular_file:
53790eae32dcSDimitry Andric     case sys::fs::file_type::symlink_file:
53800eae32dcSDimitry Andric     case sys::fs::file_type::type_unknown:
53810eae32dcSDimitry Andric       ObjectPaths.push_back(ObjectPath.str());
53820eae32dcSDimitry Andric       break;
53830eae32dcSDimitry Andric     default: /*ignore*/;
53840eae32dcSDimitry Andric     }
53850eae32dcSDimitry Andric   }
53860eae32dcSDimitry Andric   if (EC)
53870eae32dcSDimitry Andric     return createFileError(BundlePath, errorCodeToError(EC));
53880eae32dcSDimitry Andric   if (ObjectPaths.empty())
53890eae32dcSDimitry Andric     return createStringError(std::error_code(),
53900eae32dcSDimitry Andric                              "%s: no objects found in dSYM bundle",
53910eae32dcSDimitry Andric                              Path.str().c_str());
53920eae32dcSDimitry Andric   return ObjectPaths;
53930eae32dcSDimitry Andric }
53941fd87a68SDimitry Andric 
53951fd87a68SDimitry Andric llvm::binaryformat::Swift5ReflectionSectionKind
53961fd87a68SDimitry Andric MachOObjectFile::mapReflectionSectionNameToEnumValue(
53971fd87a68SDimitry Andric     StringRef SectionName) const {
53981fd87a68SDimitry Andric #define HANDLE_SWIFT_SECTION(KIND, MACHO, ELF, COFF)                           \
53991fd87a68SDimitry Andric   .Case(MACHO, llvm::binaryformat::Swift5ReflectionSectionKind::KIND)
54001fd87a68SDimitry Andric   return StringSwitch<llvm::binaryformat::Swift5ReflectionSectionKind>(
54011fd87a68SDimitry Andric              SectionName)
54021fd87a68SDimitry Andric #include "llvm/BinaryFormat/Swift.def"
54031fd87a68SDimitry Andric       .Default(llvm::binaryformat::Swift5ReflectionSectionKind::unknown);
54041fd87a68SDimitry Andric #undef HANDLE_SWIFT_SECTION
54051fd87a68SDimitry Andric }
540681ad6265SDimitry Andric 
540781ad6265SDimitry Andric bool MachOObjectFile::isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {
540881ad6265SDimitry Andric   switch (Arch) {
540981ad6265SDimitry Andric   case Triple::x86:
541081ad6265SDimitry Andric     return RelocType == MachO::GENERIC_RELOC_SECTDIFF ||
541181ad6265SDimitry Andric            RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
541281ad6265SDimitry Andric   case Triple::x86_64:
541381ad6265SDimitry Andric     return RelocType == MachO::X86_64_RELOC_SUBTRACTOR;
541481ad6265SDimitry Andric   case Triple::arm:
541581ad6265SDimitry Andric   case Triple::thumb:
541681ad6265SDimitry Andric     return RelocType == MachO::ARM_RELOC_SECTDIFF ||
541781ad6265SDimitry Andric            RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
541881ad6265SDimitry Andric            RelocType == MachO::ARM_RELOC_HALF ||
541981ad6265SDimitry Andric            RelocType == MachO::ARM_RELOC_HALF_SECTDIFF;
542081ad6265SDimitry Andric   case Triple::aarch64:
542181ad6265SDimitry Andric     return RelocType == MachO::ARM64_RELOC_SUBTRACTOR;
542281ad6265SDimitry Andric   default:
542381ad6265SDimitry Andric     return false;
542481ad6265SDimitry Andric   }
542581ad6265SDimitry Andric }
5426