109467b48Spatrick //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file defines the MachOObjectFile class, which binds the MachOObject
1009467b48Spatrick // class to the generic ObjectFile wrapper.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1509467b48Spatrick #include "llvm/ADT/STLExtras.h"
1609467b48Spatrick #include "llvm/ADT/SmallVector.h"
1709467b48Spatrick #include "llvm/ADT/StringRef.h"
1809467b48Spatrick #include "llvm/ADT/StringSwitch.h"
1909467b48Spatrick #include "llvm/ADT/Triple.h"
2009467b48Spatrick #include "llvm/ADT/Twine.h"
21*d415bd75Srobert #include "llvm/ADT/bit.h"
2209467b48Spatrick #include "llvm/BinaryFormat/MachO.h"
23*d415bd75Srobert #include "llvm/BinaryFormat/Swift.h"
2409467b48Spatrick #include "llvm/Object/Error.h"
2509467b48Spatrick #include "llvm/Object/MachO.h"
2609467b48Spatrick #include "llvm/Object/ObjectFile.h"
2709467b48Spatrick #include "llvm/Object/SymbolicFile.h"
2809467b48Spatrick #include "llvm/Support/DataExtractor.h"
2909467b48Spatrick #include "llvm/Support/Debug.h"
30*d415bd75Srobert #include "llvm/Support/Errc.h"
3109467b48Spatrick #include "llvm/Support/Error.h"
3209467b48Spatrick #include "llvm/Support/ErrorHandling.h"
33*d415bd75Srobert #include "llvm/Support/FileSystem.h"
3409467b48Spatrick #include "llvm/Support/Format.h"
3509467b48Spatrick #include "llvm/Support/Host.h"
3609467b48Spatrick #include "llvm/Support/LEB128.h"
37*d415bd75Srobert #include "llvm/Support/MemoryBufferRef.h"
38*d415bd75Srobert #include "llvm/Support/Path.h"
3909467b48Spatrick #include "llvm/Support/SwapByteOrder.h"
4009467b48Spatrick #include "llvm/Support/raw_ostream.h"
4109467b48Spatrick #include <algorithm>
4209467b48Spatrick #include <cassert>
4309467b48Spatrick #include <cstddef>
4409467b48Spatrick #include <cstdint>
4509467b48Spatrick #include <cstring>
4609467b48Spatrick #include <limits>
4709467b48Spatrick #include <list>
4809467b48Spatrick #include <memory>
4909467b48Spatrick #include <system_error>
5009467b48Spatrick 
5109467b48Spatrick using namespace llvm;
5209467b48Spatrick using namespace object;
5309467b48Spatrick 
5409467b48Spatrick namespace {
5509467b48Spatrick 
5609467b48Spatrick   struct section_base {
5709467b48Spatrick     char sectname[16];
5809467b48Spatrick     char segname[16];
5909467b48Spatrick   };
6009467b48Spatrick 
6109467b48Spatrick } // end anonymous namespace
6209467b48Spatrick 
malformedError(const Twine & Msg)6309467b48Spatrick static Error malformedError(const Twine &Msg) {
6409467b48Spatrick   return make_error<GenericBinaryError>("truncated or malformed object (" +
6509467b48Spatrick                                             Msg + ")",
6609467b48Spatrick                                         object_error::parse_failed);
6709467b48Spatrick }
6809467b48Spatrick 
6909467b48Spatrick // FIXME: Replace all uses of this function with getStructOrErr.
7009467b48Spatrick template <typename T>
getStruct(const MachOObjectFile & O,const char * P)7109467b48Spatrick static T getStruct(const MachOObjectFile &O, const char *P) {
7209467b48Spatrick   // Don't read before the beginning or past the end of the file
7309467b48Spatrick   if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
7409467b48Spatrick     report_fatal_error("Malformed MachO file.");
7509467b48Spatrick 
7609467b48Spatrick   T Cmd;
7709467b48Spatrick   memcpy(&Cmd, P, sizeof(T));
7809467b48Spatrick   if (O.isLittleEndian() != sys::IsLittleEndianHost)
7909467b48Spatrick     MachO::swapStruct(Cmd);
8009467b48Spatrick   return Cmd;
8109467b48Spatrick }
8209467b48Spatrick 
8309467b48Spatrick template <typename T>
getStructOrErr(const MachOObjectFile & O,const char * P)8409467b48Spatrick static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
8509467b48Spatrick   // Don't read before the beginning or past the end of the file
8609467b48Spatrick   if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
8709467b48Spatrick     return malformedError("Structure read out-of-range");
8809467b48Spatrick 
8909467b48Spatrick   T Cmd;
9009467b48Spatrick   memcpy(&Cmd, P, sizeof(T));
9109467b48Spatrick   if (O.isLittleEndian() != sys::IsLittleEndianHost)
9209467b48Spatrick     MachO::swapStruct(Cmd);
9309467b48Spatrick   return Cmd;
9409467b48Spatrick }
9509467b48Spatrick 
9609467b48Spatrick static const char *
getSectionPtr(const MachOObjectFile & O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)9709467b48Spatrick getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
9809467b48Spatrick               unsigned Sec) {
9909467b48Spatrick   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
10009467b48Spatrick 
10109467b48Spatrick   bool Is64 = O.is64Bit();
10209467b48Spatrick   unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
10309467b48Spatrick                                     sizeof(MachO::segment_command);
10409467b48Spatrick   unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
10509467b48Spatrick                                 sizeof(MachO::section);
10609467b48Spatrick 
10709467b48Spatrick   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
10809467b48Spatrick   return reinterpret_cast<const char*>(SectionAddr);
10909467b48Spatrick }
11009467b48Spatrick 
getPtr(const MachOObjectFile & O,size_t Offset)11109467b48Spatrick static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
11209467b48Spatrick   assert(Offset <= O.getData().size());
11309467b48Spatrick   return O.getData().data() + Offset;
11409467b48Spatrick }
11509467b48Spatrick 
11609467b48Spatrick static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile & O,DataRefImpl DRI)11709467b48Spatrick getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
11809467b48Spatrick   const char *P = reinterpret_cast<const char *>(DRI.p);
11909467b48Spatrick   return getStruct<MachO::nlist_base>(O, P);
12009467b48Spatrick }
12109467b48Spatrick 
parseSegmentOrSectionName(const char * P)12209467b48Spatrick static StringRef parseSegmentOrSectionName(const char *P) {
12309467b48Spatrick   if (P[15] == 0)
12409467b48Spatrick     // Null terminated.
12509467b48Spatrick     return P;
12609467b48Spatrick   // Not null terminated, so this is a 16 char string.
12709467b48Spatrick   return StringRef(P, 16);
12809467b48Spatrick }
12909467b48Spatrick 
getCPUType(const MachOObjectFile & O)13009467b48Spatrick static unsigned getCPUType(const MachOObjectFile &O) {
13109467b48Spatrick   return O.getHeader().cputype;
13209467b48Spatrick }
13309467b48Spatrick 
getCPUSubType(const MachOObjectFile & O)13409467b48Spatrick static unsigned getCPUSubType(const MachOObjectFile &O) {
13509467b48Spatrick   return O.getHeader().cpusubtype;
13609467b48Spatrick }
13709467b48Spatrick 
13809467b48Spatrick static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)13909467b48Spatrick getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
14009467b48Spatrick   return RE.r_word0;
14109467b48Spatrick }
14209467b48Spatrick 
14309467b48Spatrick static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)14409467b48Spatrick getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
14509467b48Spatrick   return RE.r_word0 & 0xffffff;
14609467b48Spatrick }
14709467b48Spatrick 
getPlainRelocationPCRel(const MachOObjectFile & O,const MachO::any_relocation_info & RE)14809467b48Spatrick static bool getPlainRelocationPCRel(const MachOObjectFile &O,
14909467b48Spatrick                                     const MachO::any_relocation_info &RE) {
15009467b48Spatrick   if (O.isLittleEndian())
15109467b48Spatrick     return (RE.r_word1 >> 24) & 1;
15209467b48Spatrick   return (RE.r_word1 >> 7) & 1;
15309467b48Spatrick }
15409467b48Spatrick 
15509467b48Spatrick static bool
getScatteredRelocationPCRel(const MachO::any_relocation_info & RE)15609467b48Spatrick getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
15709467b48Spatrick   return (RE.r_word0 >> 30) & 1;
15809467b48Spatrick }
15909467b48Spatrick 
getPlainRelocationLength(const MachOObjectFile & O,const MachO::any_relocation_info & RE)16009467b48Spatrick static unsigned getPlainRelocationLength(const MachOObjectFile &O,
16109467b48Spatrick                                          const MachO::any_relocation_info &RE) {
16209467b48Spatrick   if (O.isLittleEndian())
16309467b48Spatrick     return (RE.r_word1 >> 25) & 3;
16409467b48Spatrick   return (RE.r_word1 >> 5) & 3;
16509467b48Spatrick }
16609467b48Spatrick 
16709467b48Spatrick static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)16809467b48Spatrick getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
16909467b48Spatrick   return (RE.r_word0 >> 28) & 3;
17009467b48Spatrick }
17109467b48Spatrick 
getPlainRelocationType(const MachOObjectFile & O,const MachO::any_relocation_info & RE)17209467b48Spatrick static unsigned getPlainRelocationType(const MachOObjectFile &O,
17309467b48Spatrick                                        const MachO::any_relocation_info &RE) {
17409467b48Spatrick   if (O.isLittleEndian())
17509467b48Spatrick     return RE.r_word1 >> 28;
17609467b48Spatrick   return RE.r_word1 & 0xf;
17709467b48Spatrick }
17809467b48Spatrick 
getSectionFlags(const MachOObjectFile & O,DataRefImpl Sec)17909467b48Spatrick static uint32_t getSectionFlags(const MachOObjectFile &O,
18009467b48Spatrick                                 DataRefImpl Sec) {
18109467b48Spatrick   if (O.is64Bit()) {
18209467b48Spatrick     MachO::section_64 Sect = O.getSection64(Sec);
18309467b48Spatrick     return Sect.flags;
18409467b48Spatrick   }
18509467b48Spatrick   MachO::section Sect = O.getSection(Sec);
18609467b48Spatrick   return Sect.flags;
18709467b48Spatrick }
18809467b48Spatrick 
18909467b48Spatrick static Expected<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile & Obj,const char * Ptr,uint32_t LoadCommandIndex)19009467b48Spatrick getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
19109467b48Spatrick                    uint32_t LoadCommandIndex) {
19209467b48Spatrick   if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
19309467b48Spatrick     if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
19409467b48Spatrick       return malformedError("load command " + Twine(LoadCommandIndex) +
19509467b48Spatrick                             " extends past end of file");
19609467b48Spatrick     if (CmdOrErr->cmdsize < 8)
19709467b48Spatrick       return malformedError("load command " + Twine(LoadCommandIndex) +
19809467b48Spatrick                             " with size less than 8 bytes");
19909467b48Spatrick     return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
20009467b48Spatrick   } else
20109467b48Spatrick     return CmdOrErr.takeError();
20209467b48Spatrick }
20309467b48Spatrick 
20409467b48Spatrick static Expected<MachOObjectFile::LoadCommandInfo>
getFirstLoadCommandInfo(const MachOObjectFile & Obj)20509467b48Spatrick getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
20609467b48Spatrick   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
20709467b48Spatrick                                       : sizeof(MachO::mach_header);
20809467b48Spatrick   if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
20909467b48Spatrick     return malformedError("load command 0 extends past the end all load "
21009467b48Spatrick                           "commands in the file");
21109467b48Spatrick   return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
21209467b48Spatrick }
21309467b48Spatrick 
21409467b48Spatrick static Expected<MachOObjectFile::LoadCommandInfo>
getNextLoadCommandInfo(const MachOObjectFile & Obj,uint32_t LoadCommandIndex,const MachOObjectFile::LoadCommandInfo & L)21509467b48Spatrick getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
21609467b48Spatrick                        const MachOObjectFile::LoadCommandInfo &L) {
21709467b48Spatrick   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
21809467b48Spatrick                                       : sizeof(MachO::mach_header);
21909467b48Spatrick   if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
22009467b48Spatrick       Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
22109467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex + 1) +
22209467b48Spatrick                           " extends past the end all load commands in the file");
22309467b48Spatrick   return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
22409467b48Spatrick }
22509467b48Spatrick 
22609467b48Spatrick template <typename T>
parseHeader(const MachOObjectFile & Obj,T & Header,Error & Err)22709467b48Spatrick static void parseHeader(const MachOObjectFile &Obj, T &Header,
22809467b48Spatrick                         Error &Err) {
22909467b48Spatrick   if (sizeof(T) > Obj.getData().size()) {
23009467b48Spatrick     Err = malformedError("the mach header extends past the end of the "
23109467b48Spatrick                          "file");
23209467b48Spatrick     return;
23309467b48Spatrick   }
23409467b48Spatrick   if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
23509467b48Spatrick     Header = *HeaderOrErr;
23609467b48Spatrick   else
23709467b48Spatrick     Err = HeaderOrErr.takeError();
23809467b48Spatrick }
23909467b48Spatrick 
24009467b48Spatrick // This is used to check for overlapping of Mach-O elements.
24109467b48Spatrick struct MachOElement {
24209467b48Spatrick   uint64_t Offset;
24309467b48Spatrick   uint64_t Size;
24409467b48Spatrick   const char *Name;
24509467b48Spatrick };
24609467b48Spatrick 
checkOverlappingElement(std::list<MachOElement> & Elements,uint64_t Offset,uint64_t Size,const char * Name)24709467b48Spatrick static Error checkOverlappingElement(std::list<MachOElement> &Elements,
24809467b48Spatrick                                      uint64_t Offset, uint64_t Size,
24909467b48Spatrick                                      const char *Name) {
25009467b48Spatrick   if (Size == 0)
25109467b48Spatrick     return Error::success();
25209467b48Spatrick 
25309467b48Spatrick   for (auto it = Elements.begin(); it != Elements.end(); ++it) {
254*d415bd75Srobert     const auto &E = *it;
25509467b48Spatrick     if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
25609467b48Spatrick         (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
25709467b48Spatrick         (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
25809467b48Spatrick       return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
25909467b48Spatrick                             " with a size of " + Twine(Size) + ", overlaps " +
26009467b48Spatrick                             E.Name + " at offset " + Twine(E.Offset) + " with "
26109467b48Spatrick                             "a size of " + Twine(E.Size));
26209467b48Spatrick     auto nt = it;
26309467b48Spatrick     nt++;
26409467b48Spatrick     if (nt != Elements.end()) {
265*d415bd75Srobert       const auto &N = *nt;
26609467b48Spatrick       if (Offset + Size <= N.Offset) {
26709467b48Spatrick         Elements.insert(nt, {Offset, Size, Name});
26809467b48Spatrick         return Error::success();
26909467b48Spatrick       }
27009467b48Spatrick     }
27109467b48Spatrick   }
27209467b48Spatrick   Elements.push_back({Offset, Size, Name});
27309467b48Spatrick   return Error::success();
27409467b48Spatrick }
27509467b48Spatrick 
27609467b48Spatrick // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
27709467b48Spatrick // sections to \param Sections, and optionally sets
27809467b48Spatrick // \param IsPageZeroSegment to true.
27909467b48Spatrick template <typename Segment, typename Section>
parseSegmentLoadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & Sections,bool & IsPageZeroSegment,uint32_t LoadCommandIndex,const char * CmdName,uint64_t SizeOfHeaders,std::list<MachOElement> & Elements)28009467b48Spatrick static Error parseSegmentLoadCommand(
28109467b48Spatrick     const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
28209467b48Spatrick     SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
28309467b48Spatrick     uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
28409467b48Spatrick     std::list<MachOElement> &Elements) {
28509467b48Spatrick   const unsigned SegmentLoadSize = sizeof(Segment);
28609467b48Spatrick   if (Load.C.cmdsize < SegmentLoadSize)
28709467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
28809467b48Spatrick                           " " + CmdName + " cmdsize too small");
28909467b48Spatrick   if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
29009467b48Spatrick     Segment S = SegOrErr.get();
29109467b48Spatrick     const unsigned SectionSize = sizeof(Section);
29209467b48Spatrick     uint64_t FileSize = Obj.getData().size();
29309467b48Spatrick     if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
29409467b48Spatrick         S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
29509467b48Spatrick       return malformedError("load command " + Twine(LoadCommandIndex) +
29609467b48Spatrick                             " inconsistent cmdsize in " + CmdName +
29709467b48Spatrick                             " for the number of sections");
29809467b48Spatrick     for (unsigned J = 0; J < S.nsects; ++J) {
29909467b48Spatrick       const char *Sec = getSectionPtr(Obj, Load, J);
30009467b48Spatrick       Sections.push_back(Sec);
30109467b48Spatrick       auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
30209467b48Spatrick       if (!SectionOrErr)
30309467b48Spatrick         return SectionOrErr.takeError();
30409467b48Spatrick       Section s = SectionOrErr.get();
30509467b48Spatrick       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
30609467b48Spatrick           Obj.getHeader().filetype != MachO::MH_DSYM &&
30709467b48Spatrick           s.flags != MachO::S_ZEROFILL &&
30809467b48Spatrick           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
30909467b48Spatrick           s.offset > FileSize)
31009467b48Spatrick         return malformedError("offset field of section " + Twine(J) + " in " +
31109467b48Spatrick                               CmdName + " command " + Twine(LoadCommandIndex) +
31209467b48Spatrick                               " extends past the end of the file");
31309467b48Spatrick       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
31409467b48Spatrick           Obj.getHeader().filetype != MachO::MH_DSYM &&
31509467b48Spatrick           s.flags != MachO::S_ZEROFILL &&
31609467b48Spatrick           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
31709467b48Spatrick           s.offset < SizeOfHeaders && s.size != 0)
31809467b48Spatrick         return malformedError("offset field of section " + Twine(J) + " in " +
31909467b48Spatrick                               CmdName + " command " + Twine(LoadCommandIndex) +
32009467b48Spatrick                               " not past the headers of the file");
32109467b48Spatrick       uint64_t BigSize = s.offset;
32209467b48Spatrick       BigSize += s.size;
32309467b48Spatrick       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
32409467b48Spatrick           Obj.getHeader().filetype != MachO::MH_DSYM &&
32509467b48Spatrick           s.flags != MachO::S_ZEROFILL &&
32609467b48Spatrick           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
32709467b48Spatrick           BigSize > FileSize)
32809467b48Spatrick         return malformedError("offset field plus size field of section " +
32909467b48Spatrick                               Twine(J) + " in " + CmdName + " command " +
33009467b48Spatrick                               Twine(LoadCommandIndex) +
33109467b48Spatrick                               " extends past the end of the file");
33209467b48Spatrick       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
33309467b48Spatrick           Obj.getHeader().filetype != MachO::MH_DSYM &&
33409467b48Spatrick           s.flags != MachO::S_ZEROFILL &&
33509467b48Spatrick           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
33609467b48Spatrick           s.size > S.filesize)
33709467b48Spatrick         return malformedError("size field of section " +
33809467b48Spatrick                               Twine(J) + " in " + CmdName + " command " +
33909467b48Spatrick                               Twine(LoadCommandIndex) +
34009467b48Spatrick                               " greater than the segment");
34109467b48Spatrick       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
34209467b48Spatrick           Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
34309467b48Spatrick           s.addr < S.vmaddr)
34409467b48Spatrick         return malformedError("addr field of section " + Twine(J) + " in " +
34509467b48Spatrick                               CmdName + " command " + Twine(LoadCommandIndex) +
34609467b48Spatrick                               " less than the segment's vmaddr");
34709467b48Spatrick       BigSize = s.addr;
34809467b48Spatrick       BigSize += s.size;
34909467b48Spatrick       uint64_t BigEnd = S.vmaddr;
35009467b48Spatrick       BigEnd += S.vmsize;
35109467b48Spatrick       if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
35209467b48Spatrick         return malformedError("addr field plus size of section " + Twine(J) +
35309467b48Spatrick                               " in " + CmdName + " command " +
35409467b48Spatrick                               Twine(LoadCommandIndex) +
35509467b48Spatrick                               " greater than than "
35609467b48Spatrick                               "the segment's vmaddr plus vmsize");
35709467b48Spatrick       if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
35809467b48Spatrick           Obj.getHeader().filetype != MachO::MH_DSYM &&
35909467b48Spatrick           s.flags != MachO::S_ZEROFILL &&
36009467b48Spatrick           s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
36109467b48Spatrick         if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
36209467b48Spatrick                                                 "section contents"))
36309467b48Spatrick           return Err;
36409467b48Spatrick       if (s.reloff > FileSize)
36509467b48Spatrick         return malformedError("reloff field of section " + Twine(J) + " in " +
36609467b48Spatrick                               CmdName + " command " + Twine(LoadCommandIndex) +
36709467b48Spatrick                               " extends past the end of the file");
36809467b48Spatrick       BigSize = s.nreloc;
36909467b48Spatrick       BigSize *= sizeof(struct MachO::relocation_info);
37009467b48Spatrick       BigSize += s.reloff;
37109467b48Spatrick       if (BigSize > FileSize)
37209467b48Spatrick         return malformedError("reloff field plus nreloc field times sizeof("
37309467b48Spatrick                               "struct relocation_info) of section " +
37409467b48Spatrick                               Twine(J) + " in " + CmdName + " command " +
37509467b48Spatrick                               Twine(LoadCommandIndex) +
37609467b48Spatrick                               " extends past the end of the file");
37709467b48Spatrick       if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
37809467b48Spatrick                                               sizeof(struct
37909467b48Spatrick                                               MachO::relocation_info),
38009467b48Spatrick                                               "section relocation entries"))
38109467b48Spatrick         return Err;
38209467b48Spatrick     }
38309467b48Spatrick     if (S.fileoff > FileSize)
38409467b48Spatrick       return malformedError("load command " + Twine(LoadCommandIndex) +
38509467b48Spatrick                             " fileoff field in " + CmdName +
38609467b48Spatrick                             " extends past the end of the file");
38709467b48Spatrick     uint64_t BigSize = S.fileoff;
38809467b48Spatrick     BigSize += S.filesize;
38909467b48Spatrick     if (BigSize > FileSize)
39009467b48Spatrick       return malformedError("load command " + Twine(LoadCommandIndex) +
39109467b48Spatrick                             " fileoff field plus filesize field in " +
39209467b48Spatrick                             CmdName + " extends past the end of the file");
39309467b48Spatrick     if (S.vmsize != 0 && S.filesize > S.vmsize)
39409467b48Spatrick       return malformedError("load command " + Twine(LoadCommandIndex) +
39509467b48Spatrick                             " filesize field in " + CmdName +
39609467b48Spatrick                             " greater than vmsize field");
39709467b48Spatrick     IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
39809467b48Spatrick   } else
39909467b48Spatrick     return SegOrErr.takeError();
40009467b48Spatrick 
40109467b48Spatrick   return Error::success();
40209467b48Spatrick }
40309467b48Spatrick 
checkSymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** SymtabLoadCmd,std::list<MachOElement> & Elements)40409467b48Spatrick static Error checkSymtabCommand(const MachOObjectFile &Obj,
40509467b48Spatrick                                 const MachOObjectFile::LoadCommandInfo &Load,
40609467b48Spatrick                                 uint32_t LoadCommandIndex,
40709467b48Spatrick                                 const char **SymtabLoadCmd,
40809467b48Spatrick                                 std::list<MachOElement> &Elements) {
40909467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::symtab_command))
41009467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
41109467b48Spatrick                           " LC_SYMTAB cmdsize too small");
41209467b48Spatrick   if (*SymtabLoadCmd != nullptr)
41309467b48Spatrick     return malformedError("more than one LC_SYMTAB command");
41409467b48Spatrick   auto SymtabOrErr = getStructOrErr<MachO::symtab_command>(Obj, Load.Ptr);
41509467b48Spatrick   if (!SymtabOrErr)
41609467b48Spatrick     return SymtabOrErr.takeError();
41709467b48Spatrick   MachO::symtab_command Symtab = SymtabOrErr.get();
41809467b48Spatrick   if (Symtab.cmdsize != sizeof(MachO::symtab_command))
41909467b48Spatrick     return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
42009467b48Spatrick                           " has incorrect cmdsize");
42109467b48Spatrick   uint64_t FileSize = Obj.getData().size();
42209467b48Spatrick   if (Symtab.symoff > FileSize)
42309467b48Spatrick     return malformedError("symoff field of LC_SYMTAB command " +
42409467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end "
42509467b48Spatrick                           "of the file");
42609467b48Spatrick   uint64_t SymtabSize = Symtab.nsyms;
42709467b48Spatrick   const char *struct_nlist_name;
42809467b48Spatrick   if (Obj.is64Bit()) {
42909467b48Spatrick     SymtabSize *= sizeof(MachO::nlist_64);
43009467b48Spatrick     struct_nlist_name = "struct nlist_64";
43109467b48Spatrick   } else {
43209467b48Spatrick     SymtabSize *= sizeof(MachO::nlist);
43309467b48Spatrick     struct_nlist_name = "struct nlist";
43409467b48Spatrick   }
43509467b48Spatrick   uint64_t BigSize = SymtabSize;
43609467b48Spatrick   BigSize += Symtab.symoff;
43709467b48Spatrick   if (BigSize > FileSize)
43809467b48Spatrick     return malformedError("symoff field plus nsyms field times sizeof(" +
43909467b48Spatrick                           Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
44009467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end "
44109467b48Spatrick                           "of the file");
44209467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
44309467b48Spatrick                                           "symbol table"))
44409467b48Spatrick     return Err;
44509467b48Spatrick   if (Symtab.stroff > FileSize)
44609467b48Spatrick     return malformedError("stroff field of LC_SYMTAB command " +
44709467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end "
44809467b48Spatrick                           "of the file");
44909467b48Spatrick   BigSize = Symtab.stroff;
45009467b48Spatrick   BigSize += Symtab.strsize;
45109467b48Spatrick   if (BigSize > FileSize)
45209467b48Spatrick     return malformedError("stroff field plus strsize field of LC_SYMTAB "
45309467b48Spatrick                           "command " + Twine(LoadCommandIndex) + " extends "
45409467b48Spatrick                           "past the end of the file");
45509467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
45609467b48Spatrick                                           Symtab.strsize, "string table"))
45709467b48Spatrick     return Err;
45809467b48Spatrick   *SymtabLoadCmd = Load.Ptr;
45909467b48Spatrick   return Error::success();
46009467b48Spatrick }
46109467b48Spatrick 
checkDysymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** DysymtabLoadCmd,std::list<MachOElement> & Elements)46209467b48Spatrick static Error checkDysymtabCommand(const MachOObjectFile &Obj,
46309467b48Spatrick                                   const MachOObjectFile::LoadCommandInfo &Load,
46409467b48Spatrick                                   uint32_t LoadCommandIndex,
46509467b48Spatrick                                   const char **DysymtabLoadCmd,
46609467b48Spatrick                                   std::list<MachOElement> &Elements) {
46709467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
46809467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
46909467b48Spatrick                           " LC_DYSYMTAB cmdsize too small");
47009467b48Spatrick   if (*DysymtabLoadCmd != nullptr)
47109467b48Spatrick     return malformedError("more than one LC_DYSYMTAB command");
47209467b48Spatrick   auto DysymtabOrErr =
47309467b48Spatrick     getStructOrErr<MachO::dysymtab_command>(Obj, Load.Ptr);
47409467b48Spatrick   if (!DysymtabOrErr)
47509467b48Spatrick     return DysymtabOrErr.takeError();
47609467b48Spatrick   MachO::dysymtab_command Dysymtab = DysymtabOrErr.get();
47709467b48Spatrick   if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
47809467b48Spatrick     return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
47909467b48Spatrick                           " has incorrect cmdsize");
48009467b48Spatrick   uint64_t FileSize = Obj.getData().size();
48109467b48Spatrick   if (Dysymtab.tocoff > FileSize)
48209467b48Spatrick     return malformedError("tocoff field of LC_DYSYMTAB command " +
48309467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
48409467b48Spatrick                           "the file");
48509467b48Spatrick   uint64_t BigSize = Dysymtab.ntoc;
48609467b48Spatrick   BigSize *= sizeof(MachO::dylib_table_of_contents);
48709467b48Spatrick   BigSize += Dysymtab.tocoff;
48809467b48Spatrick   if (BigSize > FileSize)
48909467b48Spatrick     return malformedError("tocoff field plus ntoc field times sizeof(struct "
49009467b48Spatrick                           "dylib_table_of_contents) of LC_DYSYMTAB command " +
49109467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
49209467b48Spatrick                           "the file");
49309467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
49409467b48Spatrick                                           Dysymtab.ntoc * sizeof(struct
49509467b48Spatrick                                           MachO::dylib_table_of_contents),
49609467b48Spatrick                                           "table of contents"))
49709467b48Spatrick     return Err;
49809467b48Spatrick   if (Dysymtab.modtaboff > FileSize)
49909467b48Spatrick     return malformedError("modtaboff field of LC_DYSYMTAB command " +
50009467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
50109467b48Spatrick                           "the file");
50209467b48Spatrick   BigSize = Dysymtab.nmodtab;
50309467b48Spatrick   const char *struct_dylib_module_name;
50409467b48Spatrick   uint64_t sizeof_modtab;
50509467b48Spatrick   if (Obj.is64Bit()) {
50609467b48Spatrick     sizeof_modtab = sizeof(MachO::dylib_module_64);
50709467b48Spatrick     struct_dylib_module_name = "struct dylib_module_64";
50809467b48Spatrick   } else {
50909467b48Spatrick     sizeof_modtab = sizeof(MachO::dylib_module);
51009467b48Spatrick     struct_dylib_module_name = "struct dylib_module";
51109467b48Spatrick   }
51209467b48Spatrick   BigSize *= sizeof_modtab;
51309467b48Spatrick   BigSize += Dysymtab.modtaboff;
51409467b48Spatrick   if (BigSize > FileSize)
51509467b48Spatrick     return malformedError("modtaboff field plus nmodtab field times sizeof(" +
51609467b48Spatrick                           Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
51709467b48Spatrick                           "command " + Twine(LoadCommandIndex) + " extends "
51809467b48Spatrick                           "past the end of the file");
51909467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
52009467b48Spatrick                                           Dysymtab.nmodtab * sizeof_modtab,
52109467b48Spatrick                                           "module table"))
52209467b48Spatrick     return Err;
52309467b48Spatrick   if (Dysymtab.extrefsymoff > FileSize)
52409467b48Spatrick     return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
52509467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
52609467b48Spatrick                           "the file");
52709467b48Spatrick   BigSize = Dysymtab.nextrefsyms;
52809467b48Spatrick   BigSize *= sizeof(MachO::dylib_reference);
52909467b48Spatrick   BigSize += Dysymtab.extrefsymoff;
53009467b48Spatrick   if (BigSize > FileSize)
53109467b48Spatrick     return malformedError("extrefsymoff field plus nextrefsyms field times "
53209467b48Spatrick                           "sizeof(struct dylib_reference) of LC_DYSYMTAB "
53309467b48Spatrick                           "command " + Twine(LoadCommandIndex) + " extends "
53409467b48Spatrick                           "past the end of the file");
53509467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
53609467b48Spatrick                                           Dysymtab.nextrefsyms *
53709467b48Spatrick                                               sizeof(MachO::dylib_reference),
53809467b48Spatrick                                           "reference table"))
53909467b48Spatrick     return Err;
54009467b48Spatrick   if (Dysymtab.indirectsymoff > FileSize)
54109467b48Spatrick     return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
54209467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
54309467b48Spatrick                           "the file");
54409467b48Spatrick   BigSize = Dysymtab.nindirectsyms;
54509467b48Spatrick   BigSize *= sizeof(uint32_t);
54609467b48Spatrick   BigSize += Dysymtab.indirectsymoff;
54709467b48Spatrick   if (BigSize > FileSize)
54809467b48Spatrick     return malformedError("indirectsymoff field plus nindirectsyms field times "
54909467b48Spatrick                           "sizeof(uint32_t) of LC_DYSYMTAB command " +
55009467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
55109467b48Spatrick                           "the file");
55209467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
55309467b48Spatrick                                           Dysymtab.nindirectsyms *
55409467b48Spatrick                                           sizeof(uint32_t),
55509467b48Spatrick                                           "indirect table"))
55609467b48Spatrick     return Err;
55709467b48Spatrick   if (Dysymtab.extreloff > FileSize)
55809467b48Spatrick     return malformedError("extreloff field of LC_DYSYMTAB command " +
55909467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
56009467b48Spatrick                           "the file");
56109467b48Spatrick   BigSize = Dysymtab.nextrel;
56209467b48Spatrick   BigSize *= sizeof(MachO::relocation_info);
56309467b48Spatrick   BigSize += Dysymtab.extreloff;
56409467b48Spatrick   if (BigSize > FileSize)
56509467b48Spatrick     return malformedError("extreloff field plus nextrel field times sizeof"
56609467b48Spatrick                           "(struct relocation_info) of LC_DYSYMTAB command " +
56709467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
56809467b48Spatrick                           "the file");
56909467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
57009467b48Spatrick                                           Dysymtab.nextrel *
57109467b48Spatrick                                               sizeof(MachO::relocation_info),
57209467b48Spatrick                                           "external relocation table"))
57309467b48Spatrick     return Err;
57409467b48Spatrick   if (Dysymtab.locreloff > FileSize)
57509467b48Spatrick     return malformedError("locreloff field of LC_DYSYMTAB command " +
57609467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
57709467b48Spatrick                           "the file");
57809467b48Spatrick   BigSize = Dysymtab.nlocrel;
57909467b48Spatrick   BigSize *= sizeof(MachO::relocation_info);
58009467b48Spatrick   BigSize += Dysymtab.locreloff;
58109467b48Spatrick   if (BigSize > FileSize)
58209467b48Spatrick     return malformedError("locreloff field plus nlocrel field times sizeof"
58309467b48Spatrick                           "(struct relocation_info) of LC_DYSYMTAB command " +
58409467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
58509467b48Spatrick                           "the file");
58609467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
58709467b48Spatrick                                           Dysymtab.nlocrel *
58809467b48Spatrick                                               sizeof(MachO::relocation_info),
58909467b48Spatrick                                           "local relocation table"))
59009467b48Spatrick     return Err;
59109467b48Spatrick   *DysymtabLoadCmd = Load.Ptr;
59209467b48Spatrick   return Error::success();
59309467b48Spatrick }
59409467b48Spatrick 
checkLinkeditDataCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements,const char * ElementName)59509467b48Spatrick static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
59609467b48Spatrick                                  const MachOObjectFile::LoadCommandInfo &Load,
59709467b48Spatrick                                  uint32_t LoadCommandIndex,
59809467b48Spatrick                                  const char **LoadCmd, const char *CmdName,
59909467b48Spatrick                                  std::list<MachOElement> &Elements,
60009467b48Spatrick                                  const char *ElementName) {
60109467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
60209467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
60309467b48Spatrick                           CmdName + " cmdsize too small");
60409467b48Spatrick   if (*LoadCmd != nullptr)
60509467b48Spatrick     return malformedError("more than one " + Twine(CmdName) + " command");
60609467b48Spatrick   auto LinkDataOrError =
60709467b48Spatrick     getStructOrErr<MachO::linkedit_data_command>(Obj, Load.Ptr);
60809467b48Spatrick   if (!LinkDataOrError)
60909467b48Spatrick     return LinkDataOrError.takeError();
61009467b48Spatrick   MachO::linkedit_data_command LinkData = LinkDataOrError.get();
61109467b48Spatrick   if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
61209467b48Spatrick     return malformedError(Twine(CmdName) + " command " +
61309467b48Spatrick                           Twine(LoadCommandIndex) + " has incorrect cmdsize");
61409467b48Spatrick   uint64_t FileSize = Obj.getData().size();
61509467b48Spatrick   if (LinkData.dataoff > FileSize)
61609467b48Spatrick     return malformedError("dataoff field of " + Twine(CmdName) + " command " +
61709467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
61809467b48Spatrick                           "the file");
61909467b48Spatrick   uint64_t BigSize = LinkData.dataoff;
62009467b48Spatrick   BigSize += LinkData.datasize;
62109467b48Spatrick   if (BigSize > FileSize)
62209467b48Spatrick     return malformedError("dataoff field plus datasize field of " +
62309467b48Spatrick                           Twine(CmdName) + " command " +
62409467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
62509467b48Spatrick                           "the file");
62609467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
62709467b48Spatrick                                           LinkData.datasize, ElementName))
62809467b48Spatrick     return Err;
62909467b48Spatrick   *LoadCmd = Load.Ptr;
63009467b48Spatrick   return Error::success();
63109467b48Spatrick }
63209467b48Spatrick 
checkDyldInfoCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements)63309467b48Spatrick static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
63409467b48Spatrick                                   const MachOObjectFile::LoadCommandInfo &Load,
63509467b48Spatrick                                   uint32_t LoadCommandIndex,
63609467b48Spatrick                                   const char **LoadCmd, const char *CmdName,
63709467b48Spatrick                                   std::list<MachOElement> &Elements) {
63809467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
63909467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
64009467b48Spatrick                           CmdName + " cmdsize too small");
64109467b48Spatrick   if (*LoadCmd != nullptr)
64209467b48Spatrick     return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
64309467b48Spatrick                           "command");
64409467b48Spatrick   auto DyldInfoOrErr =
64509467b48Spatrick     getStructOrErr<MachO::dyld_info_command>(Obj, Load.Ptr);
64609467b48Spatrick   if (!DyldInfoOrErr)
64709467b48Spatrick     return DyldInfoOrErr.takeError();
64809467b48Spatrick   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
64909467b48Spatrick   if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
65009467b48Spatrick     return malformedError(Twine(CmdName) + " command " +
65109467b48Spatrick                           Twine(LoadCommandIndex) + " has incorrect cmdsize");
65209467b48Spatrick   uint64_t FileSize = Obj.getData().size();
65309467b48Spatrick   if (DyldInfo.rebase_off > FileSize)
65409467b48Spatrick     return malformedError("rebase_off field of " + Twine(CmdName) +
65509467b48Spatrick                           " command " + Twine(LoadCommandIndex) + " extends "
65609467b48Spatrick                           "past the end of the file");
65709467b48Spatrick   uint64_t BigSize = DyldInfo.rebase_off;
65809467b48Spatrick   BigSize += DyldInfo.rebase_size;
65909467b48Spatrick   if (BigSize > FileSize)
66009467b48Spatrick     return malformedError("rebase_off field plus rebase_size field of " +
66109467b48Spatrick                           Twine(CmdName) + " command " +
66209467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
66309467b48Spatrick                           "the file");
66409467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
66509467b48Spatrick                                           DyldInfo.rebase_size,
66609467b48Spatrick                                           "dyld rebase info"))
66709467b48Spatrick     return Err;
66809467b48Spatrick   if (DyldInfo.bind_off > FileSize)
66909467b48Spatrick     return malformedError("bind_off field of " + Twine(CmdName) +
67009467b48Spatrick                           " command " + Twine(LoadCommandIndex) + " extends "
67109467b48Spatrick                           "past the end of the file");
67209467b48Spatrick   BigSize = DyldInfo.bind_off;
67309467b48Spatrick   BigSize += DyldInfo.bind_size;
67409467b48Spatrick   if (BigSize > FileSize)
67509467b48Spatrick     return malformedError("bind_off field plus bind_size field of " +
67609467b48Spatrick                           Twine(CmdName) + " command " +
67709467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
67809467b48Spatrick                           "the file");
67909467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
68009467b48Spatrick                                           DyldInfo.bind_size,
68109467b48Spatrick                                           "dyld bind info"))
68209467b48Spatrick     return Err;
68309467b48Spatrick   if (DyldInfo.weak_bind_off > FileSize)
68409467b48Spatrick     return malformedError("weak_bind_off field of " + Twine(CmdName) +
68509467b48Spatrick                           " command " + Twine(LoadCommandIndex) + " extends "
68609467b48Spatrick                           "past the end of the file");
68709467b48Spatrick   BigSize = DyldInfo.weak_bind_off;
68809467b48Spatrick   BigSize += DyldInfo.weak_bind_size;
68909467b48Spatrick   if (BigSize > FileSize)
69009467b48Spatrick     return malformedError("weak_bind_off field plus weak_bind_size field of " +
69109467b48Spatrick                           Twine(CmdName) + " command " +
69209467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
69309467b48Spatrick                           "the file");
69409467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
69509467b48Spatrick                                           DyldInfo.weak_bind_size,
69609467b48Spatrick                                           "dyld weak bind info"))
69709467b48Spatrick     return Err;
69809467b48Spatrick   if (DyldInfo.lazy_bind_off > FileSize)
69909467b48Spatrick     return malformedError("lazy_bind_off field of " + Twine(CmdName) +
70009467b48Spatrick                           " command " + Twine(LoadCommandIndex) + " extends "
70109467b48Spatrick                           "past the end of the file");
70209467b48Spatrick   BigSize = DyldInfo.lazy_bind_off;
70309467b48Spatrick   BigSize += DyldInfo.lazy_bind_size;
70409467b48Spatrick   if (BigSize > FileSize)
70509467b48Spatrick     return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
70609467b48Spatrick                           Twine(CmdName) + " command " +
70709467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
70809467b48Spatrick                           "the file");
70909467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
71009467b48Spatrick                                           DyldInfo.lazy_bind_size,
71109467b48Spatrick                                           "dyld lazy bind info"))
71209467b48Spatrick     return Err;
71309467b48Spatrick   if (DyldInfo.export_off > FileSize)
71409467b48Spatrick     return malformedError("export_off field of " + Twine(CmdName) +
71509467b48Spatrick                           " command " + Twine(LoadCommandIndex) + " extends "
71609467b48Spatrick                           "past the end of the file");
71709467b48Spatrick   BigSize = DyldInfo.export_off;
71809467b48Spatrick   BigSize += DyldInfo.export_size;
71909467b48Spatrick   if (BigSize > FileSize)
72009467b48Spatrick     return malformedError("export_off field plus export_size field of " +
72109467b48Spatrick                           Twine(CmdName) + " command " +
72209467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
72309467b48Spatrick                           "the file");
72409467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
72509467b48Spatrick                                           DyldInfo.export_size,
72609467b48Spatrick                                           "dyld export info"))
72709467b48Spatrick     return Err;
72809467b48Spatrick   *LoadCmd = Load.Ptr;
72909467b48Spatrick   return Error::success();
73009467b48Spatrick }
73109467b48Spatrick 
checkDylibCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)73209467b48Spatrick static Error checkDylibCommand(const MachOObjectFile &Obj,
73309467b48Spatrick                                const MachOObjectFile::LoadCommandInfo &Load,
73409467b48Spatrick                                uint32_t LoadCommandIndex, const char *CmdName) {
73509467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::dylib_command))
73609467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
73709467b48Spatrick                           CmdName + " cmdsize too small");
73809467b48Spatrick   auto CommandOrErr = getStructOrErr<MachO::dylib_command>(Obj, Load.Ptr);
73909467b48Spatrick   if (!CommandOrErr)
74009467b48Spatrick     return CommandOrErr.takeError();
74109467b48Spatrick   MachO::dylib_command D = CommandOrErr.get();
74209467b48Spatrick   if (D.dylib.name < sizeof(MachO::dylib_command))
74309467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
74409467b48Spatrick                           CmdName + " name.offset field too small, not past "
74509467b48Spatrick                           "the end of the dylib_command struct");
74609467b48Spatrick   if (D.dylib.name >= D.cmdsize)
74709467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
74809467b48Spatrick                           CmdName + " name.offset field extends past the end "
74909467b48Spatrick                           "of the load command");
75009467b48Spatrick   // Make sure there is a null between the starting offset of the name and
75109467b48Spatrick   // the end of the load command.
75209467b48Spatrick   uint32_t i;
75309467b48Spatrick   const char *P = (const char *)Load.Ptr;
75409467b48Spatrick   for (i = D.dylib.name; i < D.cmdsize; i++)
75509467b48Spatrick     if (P[i] == '\0')
75609467b48Spatrick       break;
75709467b48Spatrick   if (i >= D.cmdsize)
75809467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
75909467b48Spatrick                           CmdName + " library name extends past the end of the "
76009467b48Spatrick                           "load command");
76109467b48Spatrick   return Error::success();
76209467b48Spatrick }
76309467b48Spatrick 
checkDylibIdCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd)76409467b48Spatrick static Error checkDylibIdCommand(const MachOObjectFile &Obj,
76509467b48Spatrick                                  const MachOObjectFile::LoadCommandInfo &Load,
76609467b48Spatrick                                  uint32_t LoadCommandIndex,
76709467b48Spatrick                                  const char **LoadCmd) {
76809467b48Spatrick   if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
76909467b48Spatrick                                      "LC_ID_DYLIB"))
77009467b48Spatrick     return Err;
77109467b48Spatrick   if (*LoadCmd != nullptr)
77209467b48Spatrick     return malformedError("more than one LC_ID_DYLIB command");
77309467b48Spatrick   if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
77409467b48Spatrick       Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
77509467b48Spatrick     return malformedError("LC_ID_DYLIB load command in non-dynamic library "
77609467b48Spatrick                           "file type");
77709467b48Spatrick   *LoadCmd = Load.Ptr;
77809467b48Spatrick   return Error::success();
77909467b48Spatrick }
78009467b48Spatrick 
checkDyldCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)78109467b48Spatrick static Error checkDyldCommand(const MachOObjectFile &Obj,
78209467b48Spatrick                               const MachOObjectFile::LoadCommandInfo &Load,
78309467b48Spatrick                               uint32_t LoadCommandIndex, const char *CmdName) {
78409467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
78509467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
78609467b48Spatrick                           CmdName + " cmdsize too small");
78709467b48Spatrick   auto CommandOrErr = getStructOrErr<MachO::dylinker_command>(Obj, Load.Ptr);
78809467b48Spatrick   if (!CommandOrErr)
78909467b48Spatrick     return CommandOrErr.takeError();
79009467b48Spatrick   MachO::dylinker_command D = CommandOrErr.get();
79109467b48Spatrick   if (D.name < sizeof(MachO::dylinker_command))
79209467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
79309467b48Spatrick                           CmdName + " name.offset field too small, not past "
79409467b48Spatrick                           "the end of the dylinker_command struct");
79509467b48Spatrick   if (D.name >= D.cmdsize)
79609467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
79709467b48Spatrick                           CmdName + " name.offset field extends past the end "
79809467b48Spatrick                           "of the load command");
79909467b48Spatrick   // Make sure there is a null between the starting offset of the name and
80009467b48Spatrick   // the end of the load command.
80109467b48Spatrick   uint32_t i;
80209467b48Spatrick   const char *P = (const char *)Load.Ptr;
80309467b48Spatrick   for (i = D.name; i < D.cmdsize; i++)
80409467b48Spatrick     if (P[i] == '\0')
80509467b48Spatrick       break;
80609467b48Spatrick   if (i >= D.cmdsize)
80709467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
80809467b48Spatrick                           CmdName + " dyld name extends past the end of the "
80909467b48Spatrick                           "load command");
81009467b48Spatrick   return Error::success();
81109467b48Spatrick }
81209467b48Spatrick 
checkVersCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName)81309467b48Spatrick static Error checkVersCommand(const MachOObjectFile &Obj,
81409467b48Spatrick                               const MachOObjectFile::LoadCommandInfo &Load,
81509467b48Spatrick                               uint32_t LoadCommandIndex,
81609467b48Spatrick                               const char **LoadCmd, const char *CmdName) {
81709467b48Spatrick   if (Load.C.cmdsize != sizeof(MachO::version_min_command))
81809467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
81909467b48Spatrick                           CmdName + " has incorrect cmdsize");
82009467b48Spatrick   if (*LoadCmd != nullptr)
82109467b48Spatrick     return malformedError("more than one LC_VERSION_MIN_MACOSX, "
82209467b48Spatrick                           "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
82309467b48Spatrick                           "LC_VERSION_MIN_WATCHOS command");
82409467b48Spatrick   *LoadCmd = Load.Ptr;
82509467b48Spatrick   return Error::success();
82609467b48Spatrick }
82709467b48Spatrick 
checkNoteCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,std::list<MachOElement> & Elements)82809467b48Spatrick static Error checkNoteCommand(const MachOObjectFile &Obj,
82909467b48Spatrick                               const MachOObjectFile::LoadCommandInfo &Load,
83009467b48Spatrick                               uint32_t LoadCommandIndex,
83109467b48Spatrick                               std::list<MachOElement> &Elements) {
83209467b48Spatrick   if (Load.C.cmdsize != sizeof(MachO::note_command))
83309467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
83409467b48Spatrick                           " LC_NOTE has incorrect cmdsize");
83509467b48Spatrick   auto NoteCmdOrErr = getStructOrErr<MachO::note_command>(Obj, Load.Ptr);
83609467b48Spatrick   if (!NoteCmdOrErr)
83709467b48Spatrick     return NoteCmdOrErr.takeError();
83809467b48Spatrick   MachO::note_command Nt = NoteCmdOrErr.get();
83909467b48Spatrick   uint64_t FileSize = Obj.getData().size();
84009467b48Spatrick   if (Nt.offset > FileSize)
84109467b48Spatrick     return malformedError("offset field of LC_NOTE command " +
84209467b48Spatrick                           Twine(LoadCommandIndex) + " extends "
84309467b48Spatrick                           "past the end of the file");
84409467b48Spatrick   uint64_t BigSize = Nt.offset;
84509467b48Spatrick   BigSize += Nt.size;
84609467b48Spatrick   if (BigSize > FileSize)
84709467b48Spatrick     return malformedError("size field plus offset field of LC_NOTE command " +
84809467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
84909467b48Spatrick                           "the file");
85009467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
85109467b48Spatrick                                           "LC_NOTE data"))
85209467b48Spatrick     return Err;
85309467b48Spatrick   return Error::success();
85409467b48Spatrick }
85509467b48Spatrick 
85609467b48Spatrick static Error
parseBuildVersionCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & BuildTools,uint32_t LoadCommandIndex)85709467b48Spatrick parseBuildVersionCommand(const MachOObjectFile &Obj,
85809467b48Spatrick                          const MachOObjectFile::LoadCommandInfo &Load,
85909467b48Spatrick                          SmallVectorImpl<const char*> &BuildTools,
86009467b48Spatrick                          uint32_t LoadCommandIndex) {
86109467b48Spatrick   auto BVCOrErr =
86209467b48Spatrick     getStructOrErr<MachO::build_version_command>(Obj, Load.Ptr);
86309467b48Spatrick   if (!BVCOrErr)
86409467b48Spatrick     return BVCOrErr.takeError();
86509467b48Spatrick   MachO::build_version_command BVC = BVCOrErr.get();
86609467b48Spatrick   if (Load.C.cmdsize !=
86709467b48Spatrick       sizeof(MachO::build_version_command) +
86809467b48Spatrick           BVC.ntools * sizeof(MachO::build_tool_version))
86909467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
87009467b48Spatrick                           " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
87109467b48Spatrick 
87209467b48Spatrick   auto Start = Load.Ptr + sizeof(MachO::build_version_command);
87309467b48Spatrick   BuildTools.resize(BVC.ntools);
87409467b48Spatrick   for (unsigned i = 0; i < BVC.ntools; ++i)
87509467b48Spatrick     BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
87609467b48Spatrick 
87709467b48Spatrick   return Error::success();
87809467b48Spatrick }
87909467b48Spatrick 
checkRpathCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)88009467b48Spatrick static Error checkRpathCommand(const MachOObjectFile &Obj,
88109467b48Spatrick                                const MachOObjectFile::LoadCommandInfo &Load,
88209467b48Spatrick                                uint32_t LoadCommandIndex) {
88309467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::rpath_command))
88409467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
88509467b48Spatrick                           " LC_RPATH cmdsize too small");
88609467b48Spatrick   auto ROrErr = getStructOrErr<MachO::rpath_command>(Obj, Load.Ptr);
88709467b48Spatrick   if (!ROrErr)
88809467b48Spatrick     return ROrErr.takeError();
88909467b48Spatrick   MachO::rpath_command R = ROrErr.get();
89009467b48Spatrick   if (R.path < sizeof(MachO::rpath_command))
89109467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
89209467b48Spatrick                           " LC_RPATH path.offset field too small, not past "
89309467b48Spatrick                           "the end of the rpath_command struct");
89409467b48Spatrick   if (R.path >= R.cmdsize)
89509467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
89609467b48Spatrick                           " LC_RPATH path.offset field extends past the end "
89709467b48Spatrick                           "of the load command");
89809467b48Spatrick   // Make sure there is a null between the starting offset of the path and
89909467b48Spatrick   // the end of the load command.
90009467b48Spatrick   uint32_t i;
90109467b48Spatrick   const char *P = (const char *)Load.Ptr;
90209467b48Spatrick   for (i = R.path; i < R.cmdsize; i++)
90309467b48Spatrick     if (P[i] == '\0')
90409467b48Spatrick       break;
90509467b48Spatrick   if (i >= R.cmdsize)
90609467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
90709467b48Spatrick                           " LC_RPATH library name extends past the end of the "
90809467b48Spatrick                           "load command");
90909467b48Spatrick   return Error::success();
91009467b48Spatrick }
91109467b48Spatrick 
checkEncryptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,uint64_t cryptoff,uint64_t cryptsize,const char ** LoadCmd,const char * CmdName)91209467b48Spatrick static Error checkEncryptCommand(const MachOObjectFile &Obj,
91309467b48Spatrick                                  const MachOObjectFile::LoadCommandInfo &Load,
91409467b48Spatrick                                  uint32_t LoadCommandIndex,
91509467b48Spatrick                                  uint64_t cryptoff, uint64_t cryptsize,
91609467b48Spatrick                                  const char **LoadCmd, const char *CmdName) {
91709467b48Spatrick   if (*LoadCmd != nullptr)
91809467b48Spatrick     return malformedError("more than one LC_ENCRYPTION_INFO and or "
91909467b48Spatrick                           "LC_ENCRYPTION_INFO_64 command");
92009467b48Spatrick   uint64_t FileSize = Obj.getData().size();
92109467b48Spatrick   if (cryptoff > FileSize)
92209467b48Spatrick     return malformedError("cryptoff field of " + Twine(CmdName) +
92309467b48Spatrick                           " command " + Twine(LoadCommandIndex) + " extends "
92409467b48Spatrick                           "past the end of the file");
92509467b48Spatrick   uint64_t BigSize = cryptoff;
92609467b48Spatrick   BigSize += cryptsize;
92709467b48Spatrick   if (BigSize > FileSize)
92809467b48Spatrick     return malformedError("cryptoff field plus cryptsize field of " +
92909467b48Spatrick                           Twine(CmdName) + " command " +
93009467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
93109467b48Spatrick                           "the file");
93209467b48Spatrick   *LoadCmd = Load.Ptr;
93309467b48Spatrick   return Error::success();
93409467b48Spatrick }
93509467b48Spatrick 
checkLinkerOptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)93609467b48Spatrick static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
93709467b48Spatrick                                    const MachOObjectFile::LoadCommandInfo &Load,
93809467b48Spatrick                                    uint32_t LoadCommandIndex) {
93909467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
94009467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
94109467b48Spatrick                           " LC_LINKER_OPTION cmdsize too small");
94209467b48Spatrick   auto LinkOptionOrErr =
94309467b48Spatrick     getStructOrErr<MachO::linker_option_command>(Obj, Load.Ptr);
94409467b48Spatrick   if (!LinkOptionOrErr)
94509467b48Spatrick     return LinkOptionOrErr.takeError();
94609467b48Spatrick   MachO::linker_option_command L = LinkOptionOrErr.get();
94709467b48Spatrick   // Make sure the count of strings is correct.
94809467b48Spatrick   const char *string = (const char *)Load.Ptr +
94909467b48Spatrick                        sizeof(struct MachO::linker_option_command);
95009467b48Spatrick   uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
95109467b48Spatrick   uint32_t i = 0;
95209467b48Spatrick   while (left > 0) {
95309467b48Spatrick     while (*string == '\0' && left > 0) {
95409467b48Spatrick       string++;
95509467b48Spatrick       left--;
95609467b48Spatrick     }
95709467b48Spatrick     if (left > 0) {
95809467b48Spatrick       i++;
95909467b48Spatrick       uint32_t NullPos = StringRef(string, left).find('\0');
96009467b48Spatrick       if (0xffffffff == NullPos)
96109467b48Spatrick         return malformedError("load command " + Twine(LoadCommandIndex) +
96209467b48Spatrick                               " LC_LINKER_OPTION string #" + Twine(i) +
96309467b48Spatrick                               " is not NULL terminated");
96409467b48Spatrick       uint32_t len = std::min(NullPos, left) + 1;
96509467b48Spatrick       string += len;
96609467b48Spatrick       left -= len;
96709467b48Spatrick     }
96809467b48Spatrick   }
96909467b48Spatrick   if (L.count != i)
97009467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
97109467b48Spatrick                           " LC_LINKER_OPTION string count " + Twine(L.count) +
97209467b48Spatrick                           " does not match number of strings");
97309467b48Spatrick   return Error::success();
97409467b48Spatrick }
97509467b48Spatrick 
checkSubCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName,size_t SizeOfCmd,const char * CmdStructName,uint32_t PathOffset,const char * PathFieldName)97609467b48Spatrick static Error checkSubCommand(const MachOObjectFile &Obj,
97709467b48Spatrick                              const MachOObjectFile::LoadCommandInfo &Load,
97809467b48Spatrick                              uint32_t LoadCommandIndex, const char *CmdName,
97909467b48Spatrick                              size_t SizeOfCmd, const char *CmdStructName,
98009467b48Spatrick                              uint32_t PathOffset, const char *PathFieldName) {
98109467b48Spatrick   if (PathOffset < SizeOfCmd)
98209467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
98309467b48Spatrick                           CmdName + " " + PathFieldName + ".offset field too "
98409467b48Spatrick                           "small, not past the end of the " + CmdStructName);
98509467b48Spatrick   if (PathOffset >= Load.C.cmdsize)
98609467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
98709467b48Spatrick                           CmdName + " " + PathFieldName + ".offset field "
98809467b48Spatrick                           "extends past the end of the load command");
98909467b48Spatrick   // Make sure there is a null between the starting offset of the path and
99009467b48Spatrick   // the end of the load command.
99109467b48Spatrick   uint32_t i;
99209467b48Spatrick   const char *P = (const char *)Load.Ptr;
99309467b48Spatrick   for (i = PathOffset; i < Load.C.cmdsize; i++)
99409467b48Spatrick     if (P[i] == '\0')
99509467b48Spatrick       break;
99609467b48Spatrick   if (i >= Load.C.cmdsize)
99709467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) + " " +
99809467b48Spatrick                           CmdName + " " + PathFieldName + " name extends past "
99909467b48Spatrick                           "the end of the load command");
100009467b48Spatrick   return Error::success();
100109467b48Spatrick }
100209467b48Spatrick 
checkThreadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)100309467b48Spatrick static Error checkThreadCommand(const MachOObjectFile &Obj,
100409467b48Spatrick                                 const MachOObjectFile::LoadCommandInfo &Load,
100509467b48Spatrick                                 uint32_t LoadCommandIndex,
100609467b48Spatrick                                 const char *CmdName) {
100709467b48Spatrick   if (Load.C.cmdsize < sizeof(MachO::thread_command))
100809467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
100909467b48Spatrick                           CmdName + " cmdsize too small");
101009467b48Spatrick   auto ThreadCommandOrErr =
101109467b48Spatrick     getStructOrErr<MachO::thread_command>(Obj, Load.Ptr);
101209467b48Spatrick   if (!ThreadCommandOrErr)
101309467b48Spatrick     return ThreadCommandOrErr.takeError();
101409467b48Spatrick   MachO::thread_command T = ThreadCommandOrErr.get();
101509467b48Spatrick   const char *state = Load.Ptr + sizeof(MachO::thread_command);
101609467b48Spatrick   const char *end = Load.Ptr + T.cmdsize;
101709467b48Spatrick   uint32_t nflavor = 0;
101809467b48Spatrick   uint32_t cputype = getCPUType(Obj);
101909467b48Spatrick   while (state < end) {
102009467b48Spatrick     if(state + sizeof(uint32_t) > end)
102109467b48Spatrick       return malformedError("load command " + Twine(LoadCommandIndex) +
102209467b48Spatrick                             "flavor in " + CmdName + " extends past end of "
102309467b48Spatrick                             "command");
102409467b48Spatrick     uint32_t flavor;
102509467b48Spatrick     memcpy(&flavor, state, sizeof(uint32_t));
102609467b48Spatrick     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
102709467b48Spatrick       sys::swapByteOrder(flavor);
102809467b48Spatrick     state += sizeof(uint32_t);
102909467b48Spatrick 
103009467b48Spatrick     if(state + sizeof(uint32_t) > end)
103109467b48Spatrick       return malformedError("load command " + Twine(LoadCommandIndex) +
103209467b48Spatrick                             " count in " + CmdName + " extends past end of "
103309467b48Spatrick                             "command");
103409467b48Spatrick     uint32_t count;
103509467b48Spatrick     memcpy(&count, state, sizeof(uint32_t));
103609467b48Spatrick     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
103709467b48Spatrick       sys::swapByteOrder(count);
103809467b48Spatrick     state += sizeof(uint32_t);
103909467b48Spatrick 
104009467b48Spatrick     if (cputype == MachO::CPU_TYPE_I386) {
104109467b48Spatrick       if (flavor == MachO::x86_THREAD_STATE32) {
104209467b48Spatrick         if (count != MachO::x86_THREAD_STATE32_COUNT)
104309467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
104409467b48Spatrick                                 " count not x86_THREAD_STATE32_COUNT for "
104509467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
104609467b48Spatrick                                 "a x86_THREAD_STATE32 flavor in " + CmdName +
104709467b48Spatrick                                 " command");
104809467b48Spatrick         if (state + sizeof(MachO::x86_thread_state32_t) > end)
104909467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
105009467b48Spatrick                                 " x86_THREAD_STATE32 extends past end of "
105109467b48Spatrick                                 "command in " + CmdName + " command");
105209467b48Spatrick         state += sizeof(MachO::x86_thread_state32_t);
105309467b48Spatrick       } else {
105409467b48Spatrick         return malformedError("load command " + Twine(LoadCommandIndex) +
105509467b48Spatrick                               " unknown flavor (" + Twine(flavor) + ") for "
105609467b48Spatrick                               "flavor number " + Twine(nflavor) + " in " +
105709467b48Spatrick                               CmdName + " command");
105809467b48Spatrick       }
105909467b48Spatrick     } else if (cputype == MachO::CPU_TYPE_X86_64) {
106009467b48Spatrick       if (flavor == MachO::x86_THREAD_STATE) {
106109467b48Spatrick         if (count != MachO::x86_THREAD_STATE_COUNT)
106209467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
106309467b48Spatrick                                 " count not x86_THREAD_STATE_COUNT for "
106409467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
106509467b48Spatrick                                 "a x86_THREAD_STATE flavor in " + CmdName +
106609467b48Spatrick                                 " command");
106709467b48Spatrick         if (state + sizeof(MachO::x86_thread_state_t) > end)
106809467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
106909467b48Spatrick                                 " x86_THREAD_STATE extends past end of "
107009467b48Spatrick                                 "command in " + CmdName + " command");
107109467b48Spatrick         state += sizeof(MachO::x86_thread_state_t);
107209467b48Spatrick       } else if (flavor == MachO::x86_FLOAT_STATE) {
107309467b48Spatrick         if (count != MachO::x86_FLOAT_STATE_COUNT)
107409467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
107509467b48Spatrick                                 " count not x86_FLOAT_STATE_COUNT for "
107609467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
107709467b48Spatrick                                 "a x86_FLOAT_STATE flavor in " + CmdName +
107809467b48Spatrick                                 " command");
107909467b48Spatrick         if (state + sizeof(MachO::x86_float_state_t) > end)
108009467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
108109467b48Spatrick                                 " x86_FLOAT_STATE extends past end of "
108209467b48Spatrick                                 "command in " + CmdName + " command");
108309467b48Spatrick         state += sizeof(MachO::x86_float_state_t);
108409467b48Spatrick       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
108509467b48Spatrick         if (count != MachO::x86_EXCEPTION_STATE_COUNT)
108609467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
108709467b48Spatrick                                 " count not x86_EXCEPTION_STATE_COUNT for "
108809467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
108909467b48Spatrick                                 "a x86_EXCEPTION_STATE flavor in " + CmdName +
109009467b48Spatrick                                 " command");
109109467b48Spatrick         if (state + sizeof(MachO::x86_exception_state_t) > end)
109209467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
109309467b48Spatrick                                 " x86_EXCEPTION_STATE extends past end of "
109409467b48Spatrick                                 "command in " + CmdName + " command");
109509467b48Spatrick         state += sizeof(MachO::x86_exception_state_t);
109609467b48Spatrick       } else if (flavor == MachO::x86_THREAD_STATE64) {
109709467b48Spatrick         if (count != MachO::x86_THREAD_STATE64_COUNT)
109809467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
109909467b48Spatrick                                 " count not x86_THREAD_STATE64_COUNT for "
110009467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
110109467b48Spatrick                                 "a x86_THREAD_STATE64 flavor in " + CmdName +
110209467b48Spatrick                                 " command");
110309467b48Spatrick         if (state + sizeof(MachO::x86_thread_state64_t) > end)
110409467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
110509467b48Spatrick                                 " x86_THREAD_STATE64 extends past end of "
110609467b48Spatrick                                 "command in " + CmdName + " command");
110709467b48Spatrick         state += sizeof(MachO::x86_thread_state64_t);
110809467b48Spatrick       } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
110909467b48Spatrick         if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
111009467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
111109467b48Spatrick                                 " count not x86_EXCEPTION_STATE64_COUNT for "
111209467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
111309467b48Spatrick                                 "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
111409467b48Spatrick                                 " command");
111509467b48Spatrick         if (state + sizeof(MachO::x86_exception_state64_t) > end)
111609467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
111709467b48Spatrick                                 " x86_EXCEPTION_STATE64 extends past end of "
111809467b48Spatrick                                 "command in " + CmdName + " command");
111909467b48Spatrick         state += sizeof(MachO::x86_exception_state64_t);
112009467b48Spatrick       } else {
112109467b48Spatrick         return malformedError("load command " + Twine(LoadCommandIndex) +
112209467b48Spatrick                               " unknown flavor (" + Twine(flavor) + ") for "
112309467b48Spatrick                               "flavor number " + Twine(nflavor) + " in " +
112409467b48Spatrick                               CmdName + " command");
112509467b48Spatrick       }
112609467b48Spatrick     } else if (cputype == MachO::CPU_TYPE_ARM) {
112709467b48Spatrick       if (flavor == MachO::ARM_THREAD_STATE) {
112809467b48Spatrick         if (count != MachO::ARM_THREAD_STATE_COUNT)
112909467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
113009467b48Spatrick                                 " count not ARM_THREAD_STATE_COUNT for "
113109467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
113209467b48Spatrick                                 "a ARM_THREAD_STATE flavor in " + CmdName +
113309467b48Spatrick                                 " command");
113409467b48Spatrick         if (state + sizeof(MachO::arm_thread_state32_t) > end)
113509467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
113609467b48Spatrick                                 " ARM_THREAD_STATE extends past end of "
113709467b48Spatrick                                 "command in " + CmdName + " command");
113809467b48Spatrick         state += sizeof(MachO::arm_thread_state32_t);
113909467b48Spatrick       } else {
114009467b48Spatrick         return malformedError("load command " + Twine(LoadCommandIndex) +
114109467b48Spatrick                               " unknown flavor (" + Twine(flavor) + ") for "
114209467b48Spatrick                               "flavor number " + Twine(nflavor) + " in " +
114309467b48Spatrick                               CmdName + " command");
114409467b48Spatrick       }
114509467b48Spatrick     } else if (cputype == MachO::CPU_TYPE_ARM64 ||
114609467b48Spatrick                cputype == MachO::CPU_TYPE_ARM64_32) {
114709467b48Spatrick       if (flavor == MachO::ARM_THREAD_STATE64) {
114809467b48Spatrick         if (count != MachO::ARM_THREAD_STATE64_COUNT)
114909467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
115009467b48Spatrick                                 " count not ARM_THREAD_STATE64_COUNT for "
115109467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
115209467b48Spatrick                                 "a ARM_THREAD_STATE64 flavor in " + CmdName +
115309467b48Spatrick                                 " command");
115409467b48Spatrick         if (state + sizeof(MachO::arm_thread_state64_t) > end)
115509467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
115609467b48Spatrick                                 " ARM_THREAD_STATE64 extends past end of "
115709467b48Spatrick                                 "command in " + CmdName + " command");
115809467b48Spatrick         state += sizeof(MachO::arm_thread_state64_t);
115909467b48Spatrick       } else {
116009467b48Spatrick         return malformedError("load command " + Twine(LoadCommandIndex) +
116109467b48Spatrick                               " unknown flavor (" + Twine(flavor) + ") for "
116209467b48Spatrick                               "flavor number " + Twine(nflavor) + " in " +
116309467b48Spatrick                               CmdName + " command");
116409467b48Spatrick       }
116509467b48Spatrick     } else if (cputype == MachO::CPU_TYPE_POWERPC) {
116609467b48Spatrick       if (flavor == MachO::PPC_THREAD_STATE) {
116709467b48Spatrick         if (count != MachO::PPC_THREAD_STATE_COUNT)
116809467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
116909467b48Spatrick                                 " count not PPC_THREAD_STATE_COUNT for "
117009467b48Spatrick                                 "flavor number " + Twine(nflavor) + " which is "
117109467b48Spatrick                                 "a PPC_THREAD_STATE flavor in " + CmdName +
117209467b48Spatrick                                 " command");
117309467b48Spatrick         if (state + sizeof(MachO::ppc_thread_state32_t) > end)
117409467b48Spatrick           return malformedError("load command " + Twine(LoadCommandIndex) +
117509467b48Spatrick                                 " PPC_THREAD_STATE extends past end of "
117609467b48Spatrick                                 "command in " + CmdName + " command");
117709467b48Spatrick         state += sizeof(MachO::ppc_thread_state32_t);
117809467b48Spatrick       } else {
117909467b48Spatrick         return malformedError("load command " + Twine(LoadCommandIndex) +
118009467b48Spatrick                               " unknown flavor (" + Twine(flavor) + ") for "
118109467b48Spatrick                               "flavor number " + Twine(nflavor) + " in " +
118209467b48Spatrick                               CmdName + " command");
118309467b48Spatrick       }
118409467b48Spatrick     } else {
118509467b48Spatrick       return malformedError("unknown cputype (" + Twine(cputype) + ") load "
118609467b48Spatrick                             "command " + Twine(LoadCommandIndex) + " for " +
118709467b48Spatrick                             CmdName + " command can't be checked");
118809467b48Spatrick     }
118909467b48Spatrick     nflavor++;
119009467b48Spatrick   }
119109467b48Spatrick   return Error::success();
119209467b48Spatrick }
119309467b48Spatrick 
checkTwoLevelHintsCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,std::list<MachOElement> & Elements)119409467b48Spatrick static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
119509467b48Spatrick                                        const MachOObjectFile::LoadCommandInfo
119609467b48Spatrick                                          &Load,
119709467b48Spatrick                                        uint32_t LoadCommandIndex,
119809467b48Spatrick                                        const char **LoadCmd,
119909467b48Spatrick                                        std::list<MachOElement> &Elements) {
120009467b48Spatrick   if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
120109467b48Spatrick     return malformedError("load command " + Twine(LoadCommandIndex) +
120209467b48Spatrick                           " LC_TWOLEVEL_HINTS has incorrect cmdsize");
120309467b48Spatrick   if (*LoadCmd != nullptr)
120409467b48Spatrick     return malformedError("more than one LC_TWOLEVEL_HINTS command");
120509467b48Spatrick   auto HintsOrErr = getStructOrErr<MachO::twolevel_hints_command>(Obj, Load.Ptr);
120609467b48Spatrick   if(!HintsOrErr)
120709467b48Spatrick     return HintsOrErr.takeError();
120809467b48Spatrick   MachO::twolevel_hints_command Hints = HintsOrErr.get();
120909467b48Spatrick   uint64_t FileSize = Obj.getData().size();
121009467b48Spatrick   if (Hints.offset > FileSize)
121109467b48Spatrick     return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
121209467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
121309467b48Spatrick                           "the file");
121409467b48Spatrick   uint64_t BigSize = Hints.nhints;
121509467b48Spatrick   BigSize *= sizeof(MachO::twolevel_hint);
121609467b48Spatrick   BigSize += Hints.offset;
121709467b48Spatrick   if (BigSize > FileSize)
121809467b48Spatrick     return malformedError("offset field plus nhints times sizeof(struct "
121909467b48Spatrick                           "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
122009467b48Spatrick                           Twine(LoadCommandIndex) + " extends past the end of "
122109467b48Spatrick                           "the file");
122209467b48Spatrick   if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
122309467b48Spatrick                                           sizeof(MachO::twolevel_hint),
122409467b48Spatrick                                           "two level hints"))
122509467b48Spatrick     return Err;
122609467b48Spatrick   *LoadCmd = Load.Ptr;
122709467b48Spatrick   return Error::success();
122809467b48Spatrick }
122909467b48Spatrick 
123009467b48Spatrick // Returns true if the libObject code does not support the load command and its
123109467b48Spatrick // contents.  The cmd value it is treated as an unknown load command but with
123209467b48Spatrick // an error message that says the cmd value is obsolete.
isLoadCommandObsolete(uint32_t cmd)123309467b48Spatrick static bool isLoadCommandObsolete(uint32_t cmd) {
123409467b48Spatrick   if (cmd == MachO::LC_SYMSEG ||
123509467b48Spatrick       cmd == MachO::LC_LOADFVMLIB ||
123609467b48Spatrick       cmd == MachO::LC_IDFVMLIB ||
123709467b48Spatrick       cmd == MachO::LC_IDENT ||
123809467b48Spatrick       cmd == MachO::LC_FVMFILE ||
123909467b48Spatrick       cmd == MachO::LC_PREPAGE ||
124009467b48Spatrick       cmd == MachO::LC_PREBOUND_DYLIB ||
124109467b48Spatrick       cmd == MachO::LC_TWOLEVEL_HINTS ||
124209467b48Spatrick       cmd == MachO::LC_PREBIND_CKSUM)
124309467b48Spatrick     return true;
124409467b48Spatrick   return false;
124509467b48Spatrick }
124609467b48Spatrick 
124709467b48Spatrick Expected<std::unique_ptr<MachOObjectFile>>
create(MemoryBufferRef Object,bool IsLittleEndian,bool Is64Bits,uint32_t UniversalCputype,uint32_t UniversalIndex)124809467b48Spatrick MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
124909467b48Spatrick                         bool Is64Bits, uint32_t UniversalCputype,
125009467b48Spatrick                         uint32_t UniversalIndex) {
125109467b48Spatrick   Error Err = Error::success();
125209467b48Spatrick   std::unique_ptr<MachOObjectFile> Obj(
125309467b48Spatrick       new MachOObjectFile(std::move(Object), IsLittleEndian,
125409467b48Spatrick                           Is64Bits, Err, UniversalCputype,
125509467b48Spatrick                           UniversalIndex));
125609467b48Spatrick   if (Err)
125709467b48Spatrick     return std::move(Err);
125809467b48Spatrick   return std::move(Obj);
125909467b48Spatrick }
126009467b48Spatrick 
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,Error & Err,uint32_t UniversalCputype,uint32_t UniversalIndex)126109467b48Spatrick MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
126209467b48Spatrick                                  bool Is64bits, Error &Err,
126309467b48Spatrick                                  uint32_t UniversalCputype,
126409467b48Spatrick                                  uint32_t UniversalIndex)
126509467b48Spatrick     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
126609467b48Spatrick   ErrorAsOutParameter ErrAsOutParam(&Err);
126709467b48Spatrick   uint64_t SizeOfHeaders;
126809467b48Spatrick   uint32_t cputype;
126909467b48Spatrick   if (is64Bit()) {
127009467b48Spatrick     parseHeader(*this, Header64, Err);
127109467b48Spatrick     SizeOfHeaders = sizeof(MachO::mach_header_64);
127209467b48Spatrick     cputype = Header64.cputype;
127309467b48Spatrick   } else {
127409467b48Spatrick     parseHeader(*this, Header, Err);
127509467b48Spatrick     SizeOfHeaders = sizeof(MachO::mach_header);
127609467b48Spatrick     cputype = Header.cputype;
127709467b48Spatrick   }
127809467b48Spatrick   if (Err)
127909467b48Spatrick     return;
128009467b48Spatrick   SizeOfHeaders += getHeader().sizeofcmds;
128109467b48Spatrick   if (getData().data() + SizeOfHeaders > getData().end()) {
128209467b48Spatrick     Err = malformedError("load commands extend past the end of the file");
128309467b48Spatrick     return;
128409467b48Spatrick   }
128509467b48Spatrick   if (UniversalCputype != 0 && cputype != UniversalCputype) {
128609467b48Spatrick     Err = malformedError("universal header architecture: " +
128709467b48Spatrick                          Twine(UniversalIndex) + "'s cputype does not match "
128809467b48Spatrick                          "object file's mach header");
128909467b48Spatrick     return;
129009467b48Spatrick   }
129109467b48Spatrick   std::list<MachOElement> Elements;
129209467b48Spatrick   Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
129309467b48Spatrick 
129409467b48Spatrick   uint32_t LoadCommandCount = getHeader().ncmds;
129509467b48Spatrick   LoadCommandInfo Load;
129609467b48Spatrick   if (LoadCommandCount != 0) {
129709467b48Spatrick     if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
129809467b48Spatrick       Load = *LoadOrErr;
129909467b48Spatrick     else {
130009467b48Spatrick       Err = LoadOrErr.takeError();
130109467b48Spatrick       return;
130209467b48Spatrick     }
130309467b48Spatrick   }
130409467b48Spatrick 
130509467b48Spatrick   const char *DyldIdLoadCmd = nullptr;
130609467b48Spatrick   const char *SplitInfoLoadCmd = nullptr;
130709467b48Spatrick   const char *CodeSignDrsLoadCmd = nullptr;
130809467b48Spatrick   const char *CodeSignLoadCmd = nullptr;
130909467b48Spatrick   const char *VersLoadCmd = nullptr;
131009467b48Spatrick   const char *SourceLoadCmd = nullptr;
131109467b48Spatrick   const char *EntryPointLoadCmd = nullptr;
131209467b48Spatrick   const char *EncryptLoadCmd = nullptr;
131309467b48Spatrick   const char *RoutinesLoadCmd = nullptr;
131409467b48Spatrick   const char *UnixThreadLoadCmd = nullptr;
131509467b48Spatrick   const char *TwoLevelHintsLoadCmd = nullptr;
131609467b48Spatrick   for (unsigned I = 0; I < LoadCommandCount; ++I) {
131709467b48Spatrick     if (is64Bit()) {
131809467b48Spatrick       if (Load.C.cmdsize % 8 != 0) {
131909467b48Spatrick         // We have a hack here to allow 64-bit Mach-O core files to have
132009467b48Spatrick         // LC_THREAD commands that are only a multiple of 4 and not 8 to be
132109467b48Spatrick         // allowed since the macOS kernel produces them.
132209467b48Spatrick         if (getHeader().filetype != MachO::MH_CORE ||
132309467b48Spatrick             Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
132409467b48Spatrick           Err = malformedError("load command " + Twine(I) + " cmdsize not a "
132509467b48Spatrick                                "multiple of 8");
132609467b48Spatrick           return;
132709467b48Spatrick         }
132809467b48Spatrick       }
132909467b48Spatrick     } else {
133009467b48Spatrick       if (Load.C.cmdsize % 4 != 0) {
133109467b48Spatrick         Err = malformedError("load command " + Twine(I) + " cmdsize not a "
133209467b48Spatrick                              "multiple of 4");
133309467b48Spatrick         return;
133409467b48Spatrick       }
133509467b48Spatrick     }
133609467b48Spatrick     LoadCommands.push_back(Load);
133709467b48Spatrick     if (Load.C.cmd == MachO::LC_SYMTAB) {
133809467b48Spatrick       if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
133909467b48Spatrick         return;
134009467b48Spatrick     } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
134109467b48Spatrick       if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
134209467b48Spatrick                                       Elements)))
134309467b48Spatrick         return;
134409467b48Spatrick     } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
134509467b48Spatrick       if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
134609467b48Spatrick                                           "LC_DATA_IN_CODE", Elements,
134709467b48Spatrick                                           "data in code info")))
134809467b48Spatrick         return;
134909467b48Spatrick     } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
135009467b48Spatrick       if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
135109467b48Spatrick                                           "LC_LINKER_OPTIMIZATION_HINT",
135209467b48Spatrick                                           Elements, "linker optimization "
135309467b48Spatrick                                           "hints")))
135409467b48Spatrick         return;
135509467b48Spatrick     } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
135609467b48Spatrick       if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
135709467b48Spatrick                                           "LC_FUNCTION_STARTS", Elements,
135809467b48Spatrick                                           "function starts data")))
135909467b48Spatrick         return;
136009467b48Spatrick     } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
136109467b48Spatrick       if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
136209467b48Spatrick                                           "LC_SEGMENT_SPLIT_INFO", Elements,
136309467b48Spatrick                                           "split info data")))
136409467b48Spatrick         return;
136509467b48Spatrick     } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
136609467b48Spatrick       if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
136709467b48Spatrick                                           "LC_DYLIB_CODE_SIGN_DRS", Elements,
136809467b48Spatrick                                           "code signing RDs data")))
136909467b48Spatrick         return;
137009467b48Spatrick     } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
137109467b48Spatrick       if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
137209467b48Spatrick                                           "LC_CODE_SIGNATURE", Elements,
137309467b48Spatrick                                           "code signature data")))
137409467b48Spatrick         return;
137509467b48Spatrick     } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
137609467b48Spatrick       if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
137709467b48Spatrick                                       "LC_DYLD_INFO", Elements)))
137809467b48Spatrick         return;
137909467b48Spatrick     } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
138009467b48Spatrick       if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
138109467b48Spatrick                                       "LC_DYLD_INFO_ONLY", Elements)))
138209467b48Spatrick         return;
1383*d415bd75Srobert     } else if (Load.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) {
1384*d415bd75Srobert       if ((Err = checkLinkeditDataCommand(
1385*d415bd75Srobert                *this, Load, I, &DyldChainedFixupsLoadCmd,
1386*d415bd75Srobert                "LC_DYLD_CHAINED_FIXUPS", Elements, "chained fixups")))
1387*d415bd75Srobert         return;
1388*d415bd75Srobert     } else if (Load.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE) {
1389*d415bd75Srobert       if ((Err = checkLinkeditDataCommand(
1390*d415bd75Srobert                *this, Load, I, &DyldExportsTrieLoadCmd, "LC_DYLD_EXPORTS_TRIE",
1391*d415bd75Srobert                Elements, "exports trie")))
1392*d415bd75Srobert         return;
139309467b48Spatrick     } else if (Load.C.cmd == MachO::LC_UUID) {
139409467b48Spatrick       if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
139509467b48Spatrick         Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
139609467b48Spatrick                              "cmdsize");
139709467b48Spatrick         return;
139809467b48Spatrick       }
139909467b48Spatrick       if (UuidLoadCmd) {
140009467b48Spatrick         Err = malformedError("more than one LC_UUID command");
140109467b48Spatrick         return;
140209467b48Spatrick       }
140309467b48Spatrick       UuidLoadCmd = Load.Ptr;
140409467b48Spatrick     } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
140509467b48Spatrick       if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
140609467b48Spatrick                                          MachO::section_64>(
140709467b48Spatrick                    *this, Load, Sections, HasPageZeroSegment, I,
140809467b48Spatrick                    "LC_SEGMENT_64", SizeOfHeaders, Elements)))
140909467b48Spatrick         return;
141009467b48Spatrick     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
141109467b48Spatrick       if ((Err = parseSegmentLoadCommand<MachO::segment_command,
141209467b48Spatrick                                          MachO::section>(
141309467b48Spatrick                    *this, Load, Sections, HasPageZeroSegment, I,
141409467b48Spatrick                    "LC_SEGMENT", SizeOfHeaders, Elements)))
141509467b48Spatrick         return;
141609467b48Spatrick     } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
141709467b48Spatrick       if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
141809467b48Spatrick         return;
141909467b48Spatrick     } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
142009467b48Spatrick       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
142109467b48Spatrick         return;
142209467b48Spatrick       Libraries.push_back(Load.Ptr);
142309467b48Spatrick     } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
142409467b48Spatrick       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
142509467b48Spatrick         return;
142609467b48Spatrick       Libraries.push_back(Load.Ptr);
142709467b48Spatrick     } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
142809467b48Spatrick       if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
142909467b48Spatrick         return;
143009467b48Spatrick       Libraries.push_back(Load.Ptr);
143109467b48Spatrick     } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
143209467b48Spatrick       if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
143309467b48Spatrick         return;
143409467b48Spatrick       Libraries.push_back(Load.Ptr);
143509467b48Spatrick     } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
143609467b48Spatrick       if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
143709467b48Spatrick         return;
143809467b48Spatrick       Libraries.push_back(Load.Ptr);
143909467b48Spatrick     } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
144009467b48Spatrick       if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
144109467b48Spatrick         return;
144209467b48Spatrick     } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
144309467b48Spatrick       if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
144409467b48Spatrick         return;
144509467b48Spatrick     } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
144609467b48Spatrick       if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
144709467b48Spatrick         return;
144809467b48Spatrick     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
144909467b48Spatrick       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
145009467b48Spatrick                                   "LC_VERSION_MIN_MACOSX")))
145109467b48Spatrick         return;
145209467b48Spatrick     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
145309467b48Spatrick       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
145409467b48Spatrick                                   "LC_VERSION_MIN_IPHONEOS")))
145509467b48Spatrick         return;
145609467b48Spatrick     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
145709467b48Spatrick       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
145809467b48Spatrick                                   "LC_VERSION_MIN_TVOS")))
145909467b48Spatrick         return;
146009467b48Spatrick     } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
146109467b48Spatrick       if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
146209467b48Spatrick                                   "LC_VERSION_MIN_WATCHOS")))
146309467b48Spatrick         return;
146409467b48Spatrick     } else if (Load.C.cmd == MachO::LC_NOTE) {
146509467b48Spatrick       if ((Err = checkNoteCommand(*this, Load, I, Elements)))
146609467b48Spatrick         return;
146709467b48Spatrick     } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
146809467b48Spatrick       if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
146909467b48Spatrick         return;
147009467b48Spatrick     } else if (Load.C.cmd == MachO::LC_RPATH) {
147109467b48Spatrick       if ((Err = checkRpathCommand(*this, Load, I)))
147209467b48Spatrick         return;
147309467b48Spatrick     } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
147409467b48Spatrick       if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
147509467b48Spatrick         Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
147609467b48Spatrick                              " has incorrect cmdsize");
147709467b48Spatrick         return;
147809467b48Spatrick       }
147909467b48Spatrick       if (SourceLoadCmd) {
148009467b48Spatrick         Err = malformedError("more than one LC_SOURCE_VERSION command");
148109467b48Spatrick         return;
148209467b48Spatrick       }
148309467b48Spatrick       SourceLoadCmd = Load.Ptr;
148409467b48Spatrick     } else if (Load.C.cmd == MachO::LC_MAIN) {
148509467b48Spatrick       if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
148609467b48Spatrick         Err = malformedError("LC_MAIN command " + Twine(I) +
148709467b48Spatrick                              " has incorrect cmdsize");
148809467b48Spatrick         return;
148909467b48Spatrick       }
149009467b48Spatrick       if (EntryPointLoadCmd) {
149109467b48Spatrick         Err = malformedError("more than one LC_MAIN command");
149209467b48Spatrick         return;
149309467b48Spatrick       }
149409467b48Spatrick       EntryPointLoadCmd = Load.Ptr;
149509467b48Spatrick     } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
149609467b48Spatrick       if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
149709467b48Spatrick         Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
149809467b48Spatrick                              " has incorrect cmdsize");
149909467b48Spatrick         return;
150009467b48Spatrick       }
150109467b48Spatrick       MachO::encryption_info_command E =
150209467b48Spatrick         getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
150309467b48Spatrick       if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
150409467b48Spatrick                                      &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
150509467b48Spatrick         return;
150609467b48Spatrick     } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
150709467b48Spatrick       if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
150809467b48Spatrick         Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
150909467b48Spatrick                              " has incorrect cmdsize");
151009467b48Spatrick         return;
151109467b48Spatrick       }
151209467b48Spatrick       MachO::encryption_info_command_64 E =
151309467b48Spatrick         getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
151409467b48Spatrick       if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
151509467b48Spatrick                                      &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
151609467b48Spatrick         return;
151709467b48Spatrick     } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
151809467b48Spatrick       if ((Err = checkLinkerOptCommand(*this, Load, I)))
151909467b48Spatrick         return;
152009467b48Spatrick     } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
152109467b48Spatrick       if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
152209467b48Spatrick         Err =  malformedError("load command " + Twine(I) +
152309467b48Spatrick                               " LC_SUB_FRAMEWORK cmdsize too small");
152409467b48Spatrick         return;
152509467b48Spatrick       }
152609467b48Spatrick       MachO::sub_framework_command S =
152709467b48Spatrick         getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
152809467b48Spatrick       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
152909467b48Spatrick                                  sizeof(MachO::sub_framework_command),
153009467b48Spatrick                                  "sub_framework_command", S.umbrella,
153109467b48Spatrick                                  "umbrella")))
153209467b48Spatrick         return;
153309467b48Spatrick     } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
153409467b48Spatrick       if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
153509467b48Spatrick         Err =  malformedError("load command " + Twine(I) +
153609467b48Spatrick                               " LC_SUB_UMBRELLA cmdsize too small");
153709467b48Spatrick         return;
153809467b48Spatrick       }
153909467b48Spatrick       MachO::sub_umbrella_command S =
154009467b48Spatrick         getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
154109467b48Spatrick       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
154209467b48Spatrick                                  sizeof(MachO::sub_umbrella_command),
154309467b48Spatrick                                  "sub_umbrella_command", S.sub_umbrella,
154409467b48Spatrick                                  "sub_umbrella")))
154509467b48Spatrick         return;
154609467b48Spatrick     } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
154709467b48Spatrick       if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
154809467b48Spatrick         Err =  malformedError("load command " + Twine(I) +
154909467b48Spatrick                               " LC_SUB_LIBRARY cmdsize too small");
155009467b48Spatrick         return;
155109467b48Spatrick       }
155209467b48Spatrick       MachO::sub_library_command S =
155309467b48Spatrick         getStruct<MachO::sub_library_command>(*this, Load.Ptr);
155409467b48Spatrick       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
155509467b48Spatrick                                  sizeof(MachO::sub_library_command),
155609467b48Spatrick                                  "sub_library_command", S.sub_library,
155709467b48Spatrick                                  "sub_library")))
155809467b48Spatrick         return;
155909467b48Spatrick     } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
156009467b48Spatrick       if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
156109467b48Spatrick         Err =  malformedError("load command " + Twine(I) +
156209467b48Spatrick                               " LC_SUB_CLIENT cmdsize too small");
156309467b48Spatrick         return;
156409467b48Spatrick       }
156509467b48Spatrick       MachO::sub_client_command S =
156609467b48Spatrick         getStruct<MachO::sub_client_command>(*this, Load.Ptr);
156709467b48Spatrick       if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
156809467b48Spatrick                                  sizeof(MachO::sub_client_command),
156909467b48Spatrick                                  "sub_client_command", S.client, "client")))
157009467b48Spatrick         return;
157109467b48Spatrick     } else if (Load.C.cmd == MachO::LC_ROUTINES) {
157209467b48Spatrick       if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
157309467b48Spatrick         Err = malformedError("LC_ROUTINES command " + Twine(I) +
157409467b48Spatrick                              " has incorrect cmdsize");
157509467b48Spatrick         return;
157609467b48Spatrick       }
157709467b48Spatrick       if (RoutinesLoadCmd) {
157809467b48Spatrick         Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
157909467b48Spatrick                              "command");
158009467b48Spatrick         return;
158109467b48Spatrick       }
158209467b48Spatrick       RoutinesLoadCmd = Load.Ptr;
158309467b48Spatrick     } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
158409467b48Spatrick       if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
158509467b48Spatrick         Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
158609467b48Spatrick                              " has incorrect cmdsize");
158709467b48Spatrick         return;
158809467b48Spatrick       }
158909467b48Spatrick       if (RoutinesLoadCmd) {
159009467b48Spatrick         Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
159109467b48Spatrick                              "command");
159209467b48Spatrick         return;
159309467b48Spatrick       }
159409467b48Spatrick       RoutinesLoadCmd = Load.Ptr;
159509467b48Spatrick     } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
159609467b48Spatrick       if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
159709467b48Spatrick         return;
159809467b48Spatrick       if (UnixThreadLoadCmd) {
159909467b48Spatrick         Err = malformedError("more than one LC_UNIXTHREAD command");
160009467b48Spatrick         return;
160109467b48Spatrick       }
160209467b48Spatrick       UnixThreadLoadCmd = Load.Ptr;
160309467b48Spatrick     } else if (Load.C.cmd == MachO::LC_THREAD) {
160409467b48Spatrick       if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
160509467b48Spatrick         return;
160609467b48Spatrick     // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
160709467b48Spatrick     } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
160809467b48Spatrick       if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
160909467b48Spatrick                                            &TwoLevelHintsLoadCmd, Elements)))
161009467b48Spatrick         return;
161173471bf0Spatrick     } else if (Load.C.cmd == MachO::LC_IDENT) {
161273471bf0Spatrick       // Note: LC_IDENT is ignored.
161373471bf0Spatrick       continue;
161409467b48Spatrick     } else if (isLoadCommandObsolete(Load.C.cmd)) {
161509467b48Spatrick       Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
161609467b48Spatrick                            Twine(Load.C.cmd) + " is obsolete and not "
161709467b48Spatrick                            "supported");
161809467b48Spatrick       return;
161909467b48Spatrick     }
162009467b48Spatrick     // TODO: generate a error for unknown load commands by default.  But still
162109467b48Spatrick     // need work out an approach to allow or not allow unknown values like this
162209467b48Spatrick     // as an option for some uses like lldb.
162309467b48Spatrick     if (I < LoadCommandCount - 1) {
162409467b48Spatrick       if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
162509467b48Spatrick         Load = *LoadOrErr;
162609467b48Spatrick       else {
162709467b48Spatrick         Err = LoadOrErr.takeError();
162809467b48Spatrick         return;
162909467b48Spatrick       }
163009467b48Spatrick     }
163109467b48Spatrick   }
163209467b48Spatrick   if (!SymtabLoadCmd) {
163309467b48Spatrick     if (DysymtabLoadCmd) {
163409467b48Spatrick       Err = malformedError("contains LC_DYSYMTAB load command without a "
163509467b48Spatrick                            "LC_SYMTAB load command");
163609467b48Spatrick       return;
163709467b48Spatrick     }
163809467b48Spatrick   } else if (DysymtabLoadCmd) {
163909467b48Spatrick     MachO::symtab_command Symtab =
164009467b48Spatrick       getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
164109467b48Spatrick     MachO::dysymtab_command Dysymtab =
164209467b48Spatrick       getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
164309467b48Spatrick     if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
164409467b48Spatrick       Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
164509467b48Spatrick                            "extends past the end of the symbol table");
164609467b48Spatrick       return;
164709467b48Spatrick     }
164809467b48Spatrick     uint64_t BigSize = Dysymtab.ilocalsym;
164909467b48Spatrick     BigSize += Dysymtab.nlocalsym;
165009467b48Spatrick     if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
165109467b48Spatrick       Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
165209467b48Spatrick                            "command extends past the end of the symbol table");
165309467b48Spatrick       return;
165409467b48Spatrick     }
165509467b48Spatrick     if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
165609467b48Spatrick       Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
165709467b48Spatrick                            "extends past the end of the symbol table");
165809467b48Spatrick       return;
165909467b48Spatrick     }
166009467b48Spatrick     BigSize = Dysymtab.iextdefsym;
166109467b48Spatrick     BigSize += Dysymtab.nextdefsym;
166209467b48Spatrick     if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
166309467b48Spatrick       Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
166409467b48Spatrick                            "load command extends past the end of the symbol "
166509467b48Spatrick                            "table");
166609467b48Spatrick       return;
166709467b48Spatrick     }
166809467b48Spatrick     if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
166909467b48Spatrick       Err = malformedError("iundefsym in LC_DYSYMTAB load command "
167009467b48Spatrick                            "extends past the end of the symbol table");
167109467b48Spatrick       return;
167209467b48Spatrick     }
167309467b48Spatrick     BigSize = Dysymtab.iundefsym;
167409467b48Spatrick     BigSize += Dysymtab.nundefsym;
167509467b48Spatrick     if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
167609467b48Spatrick       Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
167709467b48Spatrick                            " command extends past the end of the symbol table");
167809467b48Spatrick       return;
167909467b48Spatrick     }
168009467b48Spatrick   }
168109467b48Spatrick   if ((getHeader().filetype == MachO::MH_DYLIB ||
168209467b48Spatrick        getHeader().filetype == MachO::MH_DYLIB_STUB) &&
168309467b48Spatrick        DyldIdLoadCmd == nullptr) {
168409467b48Spatrick     Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
168509467b48Spatrick                          "filetype");
168609467b48Spatrick     return;
168709467b48Spatrick   }
168809467b48Spatrick   assert(LoadCommands.size() == LoadCommandCount);
168909467b48Spatrick 
169009467b48Spatrick   Err = Error::success();
169109467b48Spatrick }
169209467b48Spatrick 
checkSymbolTable() const169309467b48Spatrick Error MachOObjectFile::checkSymbolTable() const {
169409467b48Spatrick   uint32_t Flags = 0;
169509467b48Spatrick   if (is64Bit()) {
169609467b48Spatrick     MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
169709467b48Spatrick     Flags = H_64.flags;
169809467b48Spatrick   } else {
169909467b48Spatrick     MachO::mach_header H = MachOObjectFile::getHeader();
170009467b48Spatrick     Flags = H.flags;
170109467b48Spatrick   }
170209467b48Spatrick   uint8_t NType = 0;
170309467b48Spatrick   uint8_t NSect = 0;
170409467b48Spatrick   uint16_t NDesc = 0;
170509467b48Spatrick   uint32_t NStrx = 0;
170609467b48Spatrick   uint64_t NValue = 0;
170709467b48Spatrick   uint32_t SymbolIndex = 0;
170809467b48Spatrick   MachO::symtab_command S = getSymtabLoadCommand();
170909467b48Spatrick   for (const SymbolRef &Symbol : symbols()) {
171009467b48Spatrick     DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
171109467b48Spatrick     if (is64Bit()) {
171209467b48Spatrick       MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
171309467b48Spatrick       NType = STE_64.n_type;
171409467b48Spatrick       NSect = STE_64.n_sect;
171509467b48Spatrick       NDesc = STE_64.n_desc;
171609467b48Spatrick       NStrx = STE_64.n_strx;
171709467b48Spatrick       NValue = STE_64.n_value;
171809467b48Spatrick     } else {
171909467b48Spatrick       MachO::nlist STE = getSymbolTableEntry(SymDRI);
172009467b48Spatrick       NType = STE.n_type;
172109467b48Spatrick       NSect = STE.n_sect;
172209467b48Spatrick       NDesc = STE.n_desc;
172309467b48Spatrick       NStrx = STE.n_strx;
172409467b48Spatrick       NValue = STE.n_value;
172509467b48Spatrick     }
172609467b48Spatrick     if ((NType & MachO::N_STAB) == 0) {
172709467b48Spatrick       if ((NType & MachO::N_TYPE) == MachO::N_SECT) {
172809467b48Spatrick         if (NSect == 0 || NSect > Sections.size())
172909467b48Spatrick           return malformedError("bad section index: " + Twine((int)NSect) +
173009467b48Spatrick                                 " for symbol at index " + Twine(SymbolIndex));
173109467b48Spatrick       }
173209467b48Spatrick       if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
173309467b48Spatrick         if (NValue >= S.strsize)
173409467b48Spatrick           return malformedError("bad n_value: " + Twine((int)NValue) + " past "
173509467b48Spatrick                                 "the end of string table, for N_INDR symbol at "
173609467b48Spatrick                                 "index " + Twine(SymbolIndex));
173709467b48Spatrick       }
173809467b48Spatrick       if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
173909467b48Spatrick           (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
174009467b48Spatrick            (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
174109467b48Spatrick             uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
174209467b48Spatrick             if (LibraryOrdinal != 0 &&
174309467b48Spatrick                 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
174409467b48Spatrick                 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
174509467b48Spatrick                 LibraryOrdinal - 1 >= Libraries.size() ) {
174609467b48Spatrick               return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
174709467b48Spatrick                                     " for symbol at index " + Twine(SymbolIndex));
174809467b48Spatrick             }
174909467b48Spatrick           }
175009467b48Spatrick     }
175109467b48Spatrick     if (NStrx >= S.strsize)
175209467b48Spatrick       return malformedError("bad string table index: " + Twine((int)NStrx) +
175309467b48Spatrick                             " past the end of string table, for symbol at "
175409467b48Spatrick                             "index " + Twine(SymbolIndex));
175509467b48Spatrick     SymbolIndex++;
175609467b48Spatrick   }
175709467b48Spatrick   return Error::success();
175809467b48Spatrick }
175909467b48Spatrick 
moveSymbolNext(DataRefImpl & Symb) const176009467b48Spatrick void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
176109467b48Spatrick   unsigned SymbolTableEntrySize = is64Bit() ?
176209467b48Spatrick     sizeof(MachO::nlist_64) :
176309467b48Spatrick     sizeof(MachO::nlist);
176409467b48Spatrick   Symb.p += SymbolTableEntrySize;
176509467b48Spatrick }
176609467b48Spatrick 
getSymbolName(DataRefImpl Symb) const176709467b48Spatrick Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
176809467b48Spatrick   StringRef StringTable = getStringTableData();
176909467b48Spatrick   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
177009467b48Spatrick   if (Entry.n_strx == 0)
177109467b48Spatrick     // A n_strx value of 0 indicates that no name is associated with a
177209467b48Spatrick     // particular symbol table entry.
177309467b48Spatrick     return StringRef();
177409467b48Spatrick   const char *Start = &StringTable.data()[Entry.n_strx];
177509467b48Spatrick   if (Start < getData().begin() || Start >= getData().end()) {
177609467b48Spatrick     return malformedError("bad string index: " + Twine(Entry.n_strx) +
177709467b48Spatrick                           " for symbol at index " + Twine(getSymbolIndex(Symb)));
177809467b48Spatrick   }
177909467b48Spatrick   return StringRef(Start);
178009467b48Spatrick }
178109467b48Spatrick 
getSectionType(SectionRef Sec) const178209467b48Spatrick unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
178309467b48Spatrick   DataRefImpl DRI = Sec.getRawDataRefImpl();
178409467b48Spatrick   uint32_t Flags = getSectionFlags(*this, DRI);
178509467b48Spatrick   return Flags & MachO::SECTION_TYPE;
178609467b48Spatrick }
178709467b48Spatrick 
getNValue(DataRefImpl Sym) const178809467b48Spatrick uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
178909467b48Spatrick   if (is64Bit()) {
179009467b48Spatrick     MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
179109467b48Spatrick     return Entry.n_value;
179209467b48Spatrick   }
179309467b48Spatrick   MachO::nlist Entry = getSymbolTableEntry(Sym);
179409467b48Spatrick   return Entry.n_value;
179509467b48Spatrick }
179609467b48Spatrick 
179709467b48Spatrick // getIndirectName() returns the name of the alias'ed symbol who's string table
179809467b48Spatrick // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const179909467b48Spatrick std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
180009467b48Spatrick                                                  StringRef &Res) const {
180109467b48Spatrick   StringRef StringTable = getStringTableData();
180209467b48Spatrick   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
180309467b48Spatrick   if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
180409467b48Spatrick     return object_error::parse_failed;
180509467b48Spatrick   uint64_t NValue = getNValue(Symb);
180609467b48Spatrick   if (NValue >= StringTable.size())
180709467b48Spatrick     return object_error::parse_failed;
180809467b48Spatrick   const char *Start = &StringTable.data()[NValue];
180909467b48Spatrick   Res = StringRef(Start);
181009467b48Spatrick   return std::error_code();
181109467b48Spatrick }
181209467b48Spatrick 
getSymbolValueImpl(DataRefImpl Sym) const181309467b48Spatrick uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
181409467b48Spatrick   return getNValue(Sym);
181509467b48Spatrick }
181609467b48Spatrick 
getSymbolAddress(DataRefImpl Sym) const181709467b48Spatrick Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
181809467b48Spatrick   return getSymbolValue(Sym);
181909467b48Spatrick }
182009467b48Spatrick 
getSymbolAlignment(DataRefImpl DRI) const182109467b48Spatrick uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
1822097a140dSpatrick   uint32_t Flags = cantFail(getSymbolFlags(DRI));
1823097a140dSpatrick   if (Flags & SymbolRef::SF_Common) {
182409467b48Spatrick     MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
182509467b48Spatrick     return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
182609467b48Spatrick   }
182709467b48Spatrick   return 0;
182809467b48Spatrick }
182909467b48Spatrick 
getCommonSymbolSizeImpl(DataRefImpl DRI) const183009467b48Spatrick uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
183109467b48Spatrick   return getNValue(DRI);
183209467b48Spatrick }
183309467b48Spatrick 
183409467b48Spatrick Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const183509467b48Spatrick MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
183609467b48Spatrick   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
183709467b48Spatrick   uint8_t n_type = Entry.n_type;
183809467b48Spatrick 
183909467b48Spatrick   // If this is a STAB debugging symbol, we can do nothing more.
184009467b48Spatrick   if (n_type & MachO::N_STAB)
184109467b48Spatrick     return SymbolRef::ST_Debug;
184209467b48Spatrick 
184309467b48Spatrick   switch (n_type & MachO::N_TYPE) {
184409467b48Spatrick     case MachO::N_UNDF :
184509467b48Spatrick       return SymbolRef::ST_Unknown;
184609467b48Spatrick     case MachO::N_SECT :
184709467b48Spatrick       Expected<section_iterator> SecOrError = getSymbolSection(Symb);
184809467b48Spatrick       if (!SecOrError)
184909467b48Spatrick         return SecOrError.takeError();
185009467b48Spatrick       section_iterator Sec = *SecOrError;
185173471bf0Spatrick       if (Sec == section_end())
185273471bf0Spatrick         return SymbolRef::ST_Other;
185309467b48Spatrick       if (Sec->isData() || Sec->isBSS())
185409467b48Spatrick         return SymbolRef::ST_Data;
185509467b48Spatrick       return SymbolRef::ST_Function;
185609467b48Spatrick   }
185709467b48Spatrick   return SymbolRef::ST_Other;
185809467b48Spatrick }
185909467b48Spatrick 
getSymbolFlags(DataRefImpl DRI) const1860097a140dSpatrick Expected<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
186109467b48Spatrick   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
186209467b48Spatrick 
186309467b48Spatrick   uint8_t MachOType = Entry.n_type;
186409467b48Spatrick   uint16_t MachOFlags = Entry.n_desc;
186509467b48Spatrick 
186609467b48Spatrick   uint32_t Result = SymbolRef::SF_None;
186709467b48Spatrick 
186809467b48Spatrick   if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
186909467b48Spatrick     Result |= SymbolRef::SF_Indirect;
187009467b48Spatrick 
187109467b48Spatrick   if (MachOType & MachO::N_STAB)
187209467b48Spatrick     Result |= SymbolRef::SF_FormatSpecific;
187309467b48Spatrick 
187409467b48Spatrick   if (MachOType & MachO::N_EXT) {
187509467b48Spatrick     Result |= SymbolRef::SF_Global;
187609467b48Spatrick     if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
187709467b48Spatrick       if (getNValue(DRI))
187809467b48Spatrick         Result |= SymbolRef::SF_Common;
187909467b48Spatrick       else
188009467b48Spatrick         Result |= SymbolRef::SF_Undefined;
188109467b48Spatrick     }
188209467b48Spatrick 
1883*d415bd75Srobert     if (MachOType & MachO::N_PEXT)
1884*d415bd75Srobert       Result |= SymbolRef::SF_Hidden;
1885*d415bd75Srobert     else
188609467b48Spatrick       Result |= SymbolRef::SF_Exported;
1887*d415bd75Srobert 
1888*d415bd75Srobert   } else if (MachOType & MachO::N_PEXT)
1889*d415bd75Srobert     Result |= SymbolRef::SF_Hidden;
189009467b48Spatrick 
189109467b48Spatrick   if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
189209467b48Spatrick     Result |= SymbolRef::SF_Weak;
189309467b48Spatrick 
189409467b48Spatrick   if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
189509467b48Spatrick     Result |= SymbolRef::SF_Thumb;
189609467b48Spatrick 
189709467b48Spatrick   if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
189809467b48Spatrick     Result |= SymbolRef::SF_Absolute;
189909467b48Spatrick 
190009467b48Spatrick   return Result;
190109467b48Spatrick }
190209467b48Spatrick 
190309467b48Spatrick Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const190409467b48Spatrick MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
190509467b48Spatrick   MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
190609467b48Spatrick   uint8_t index = Entry.n_sect;
190709467b48Spatrick 
190809467b48Spatrick   if (index == 0)
190909467b48Spatrick     return section_end();
191009467b48Spatrick   DataRefImpl DRI;
191109467b48Spatrick   DRI.d.a = index - 1;
191209467b48Spatrick   if (DRI.d.a >= Sections.size()){
191309467b48Spatrick     return malformedError("bad section index: " + Twine((int)index) +
191409467b48Spatrick                           " for symbol at index " + Twine(getSymbolIndex(Symb)));
191509467b48Spatrick   }
191609467b48Spatrick   return section_iterator(SectionRef(DRI, this));
191709467b48Spatrick }
191809467b48Spatrick 
getSymbolSectionID(SymbolRef Sym) const191909467b48Spatrick unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
192009467b48Spatrick   MachO::nlist_base Entry =
192109467b48Spatrick       getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
192209467b48Spatrick   return Entry.n_sect - 1;
192309467b48Spatrick }
192409467b48Spatrick 
moveSectionNext(DataRefImpl & Sec) const192509467b48Spatrick void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
192609467b48Spatrick   Sec.d.a++;
192709467b48Spatrick }
192809467b48Spatrick 
getSectionName(DataRefImpl Sec) const192909467b48Spatrick Expected<StringRef> MachOObjectFile::getSectionName(DataRefImpl Sec) const {
193009467b48Spatrick   ArrayRef<char> Raw = getSectionRawName(Sec);
193109467b48Spatrick   return parseSegmentOrSectionName(Raw.data());
193209467b48Spatrick }
193309467b48Spatrick 
getSectionAddress(DataRefImpl Sec) const193409467b48Spatrick uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
193509467b48Spatrick   if (is64Bit())
193609467b48Spatrick     return getSection64(Sec).addr;
193709467b48Spatrick   return getSection(Sec).addr;
193809467b48Spatrick }
193909467b48Spatrick 
getSectionIndex(DataRefImpl Sec) const194009467b48Spatrick uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
194109467b48Spatrick   return Sec.d.a;
194209467b48Spatrick }
194309467b48Spatrick 
getSectionSize(DataRefImpl Sec) const194409467b48Spatrick uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
194509467b48Spatrick   // In the case if a malformed Mach-O file where the section offset is past
194609467b48Spatrick   // the end of the file or some part of the section size is past the end of
194709467b48Spatrick   // the file return a size of zero or a size that covers the rest of the file
194809467b48Spatrick   // but does not extend past the end of the file.
194909467b48Spatrick   uint32_t SectOffset, SectType;
195009467b48Spatrick   uint64_t SectSize;
195109467b48Spatrick 
195209467b48Spatrick   if (is64Bit()) {
195309467b48Spatrick     MachO::section_64 Sect = getSection64(Sec);
195409467b48Spatrick     SectOffset = Sect.offset;
195509467b48Spatrick     SectSize = Sect.size;
195609467b48Spatrick     SectType = Sect.flags & MachO::SECTION_TYPE;
195709467b48Spatrick   } else {
195809467b48Spatrick     MachO::section Sect = getSection(Sec);
195909467b48Spatrick     SectOffset = Sect.offset;
196009467b48Spatrick     SectSize = Sect.size;
196109467b48Spatrick     SectType = Sect.flags & MachO::SECTION_TYPE;
196209467b48Spatrick   }
196309467b48Spatrick   if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
196409467b48Spatrick     return SectSize;
196509467b48Spatrick   uint64_t FileSize = getData().size();
196609467b48Spatrick   if (SectOffset > FileSize)
196709467b48Spatrick     return 0;
196809467b48Spatrick   if (FileSize - SectOffset < SectSize)
196909467b48Spatrick     return FileSize - SectOffset;
197009467b48Spatrick   return SectSize;
197109467b48Spatrick }
197209467b48Spatrick 
getSectionContents(uint32_t Offset,uint64_t Size) const197309467b48Spatrick ArrayRef<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset,
197409467b48Spatrick                                                       uint64_t Size) const {
197509467b48Spatrick   return arrayRefFromStringRef(getData().substr(Offset, Size));
197609467b48Spatrick }
197709467b48Spatrick 
197809467b48Spatrick Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const197909467b48Spatrick MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
198009467b48Spatrick   uint32_t Offset;
198109467b48Spatrick   uint64_t Size;
198209467b48Spatrick 
198309467b48Spatrick   if (is64Bit()) {
198409467b48Spatrick     MachO::section_64 Sect = getSection64(Sec);
198509467b48Spatrick     Offset = Sect.offset;
198609467b48Spatrick     Size = Sect.size;
198709467b48Spatrick   } else {
198809467b48Spatrick     MachO::section Sect = getSection(Sec);
198909467b48Spatrick     Offset = Sect.offset;
199009467b48Spatrick     Size = Sect.size;
199109467b48Spatrick   }
199209467b48Spatrick 
199309467b48Spatrick   return getSectionContents(Offset, Size);
199409467b48Spatrick }
199509467b48Spatrick 
getSectionAlignment(DataRefImpl Sec) const199609467b48Spatrick uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
199709467b48Spatrick   uint32_t Align;
199809467b48Spatrick   if (is64Bit()) {
199909467b48Spatrick     MachO::section_64 Sect = getSection64(Sec);
200009467b48Spatrick     Align = Sect.align;
200109467b48Spatrick   } else {
200209467b48Spatrick     MachO::section Sect = getSection(Sec);
200309467b48Spatrick     Align = Sect.align;
200409467b48Spatrick   }
200509467b48Spatrick 
200609467b48Spatrick   return uint64_t(1) << Align;
200709467b48Spatrick }
200809467b48Spatrick 
getSection(unsigned SectionIndex) const200909467b48Spatrick Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
201009467b48Spatrick   if (SectionIndex < 1 || SectionIndex > Sections.size())
201109467b48Spatrick     return malformedError("bad section index: " + Twine((int)SectionIndex));
201209467b48Spatrick 
201309467b48Spatrick   DataRefImpl DRI;
201409467b48Spatrick   DRI.d.a = SectionIndex - 1;
201509467b48Spatrick   return SectionRef(DRI, this);
201609467b48Spatrick }
201709467b48Spatrick 
getSection(StringRef SectionName) const201809467b48Spatrick Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
201909467b48Spatrick   for (const SectionRef &Section : sections()) {
202009467b48Spatrick     auto NameOrErr = Section.getName();
202109467b48Spatrick     if (!NameOrErr)
202209467b48Spatrick       return NameOrErr.takeError();
202309467b48Spatrick     if (*NameOrErr == SectionName)
202409467b48Spatrick       return Section;
202509467b48Spatrick   }
202609467b48Spatrick   return errorCodeToError(object_error::parse_failed);
202709467b48Spatrick }
202809467b48Spatrick 
isSectionCompressed(DataRefImpl Sec) const202909467b48Spatrick bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
203009467b48Spatrick   return false;
203109467b48Spatrick }
203209467b48Spatrick 
isSectionText(DataRefImpl Sec) const203309467b48Spatrick bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
203409467b48Spatrick   uint32_t Flags = getSectionFlags(*this, Sec);
203509467b48Spatrick   return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
203609467b48Spatrick }
203709467b48Spatrick 
isSectionData(DataRefImpl Sec) const203809467b48Spatrick bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
203909467b48Spatrick   uint32_t Flags = getSectionFlags(*this, Sec);
204009467b48Spatrick   unsigned SectionType = Flags & MachO::SECTION_TYPE;
204109467b48Spatrick   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
204209467b48Spatrick          !(SectionType == MachO::S_ZEROFILL ||
204309467b48Spatrick            SectionType == MachO::S_GB_ZEROFILL);
204409467b48Spatrick }
204509467b48Spatrick 
isSectionBSS(DataRefImpl Sec) const204609467b48Spatrick bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
204709467b48Spatrick   uint32_t Flags = getSectionFlags(*this, Sec);
204809467b48Spatrick   unsigned SectionType = Flags & MachO::SECTION_TYPE;
204909467b48Spatrick   return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
205009467b48Spatrick          (SectionType == MachO::S_ZEROFILL ||
205109467b48Spatrick           SectionType == MachO::S_GB_ZEROFILL);
205209467b48Spatrick }
205309467b48Spatrick 
isDebugSection(DataRefImpl Sec) const205473471bf0Spatrick bool MachOObjectFile::isDebugSection(DataRefImpl Sec) const {
205573471bf0Spatrick   Expected<StringRef> SectionNameOrErr = getSectionName(Sec);
205673471bf0Spatrick   if (!SectionNameOrErr) {
205773471bf0Spatrick     // TODO: Report the error message properly.
205873471bf0Spatrick     consumeError(SectionNameOrErr.takeError());
205973471bf0Spatrick     return false;
206073471bf0Spatrick   }
206173471bf0Spatrick   StringRef SectionName = SectionNameOrErr.get();
2062097a140dSpatrick   return SectionName.startswith("__debug") ||
206373471bf0Spatrick          SectionName.startswith("__zdebug") ||
206473471bf0Spatrick          SectionName.startswith("__apple") || SectionName == "__gdb_index" ||
206573471bf0Spatrick          SectionName == "__swift_ast";
2066097a140dSpatrick }
2067097a140dSpatrick 
2068*d415bd75Srobert namespace {
2069*d415bd75Srobert template <typename LoadCommandType>
getSegmentContents(const MachOObjectFile & Obj,MachOObjectFile::LoadCommandInfo LoadCmd,StringRef SegmentName)2070*d415bd75Srobert ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
2071*d415bd75Srobert                                      MachOObjectFile::LoadCommandInfo LoadCmd,
2072*d415bd75Srobert                                      StringRef SegmentName) {
2073*d415bd75Srobert   auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);
2074*d415bd75Srobert   if (!SegmentOrErr) {
2075*d415bd75Srobert     consumeError(SegmentOrErr.takeError());
2076*d415bd75Srobert     return {};
2077*d415bd75Srobert   }
2078*d415bd75Srobert   auto &Segment = SegmentOrErr.get();
2079*d415bd75Srobert   if (StringRef(Segment.segname, 16).startswith(SegmentName))
2080*d415bd75Srobert     return arrayRefFromStringRef(Obj.getData().slice(
2081*d415bd75Srobert         Segment.fileoff, Segment.fileoff + Segment.filesize));
2082*d415bd75Srobert   return {};
2083*d415bd75Srobert }
2084*d415bd75Srobert 
2085*d415bd75Srobert template <typename LoadCommandType>
getSegmentContents(const MachOObjectFile & Obj,MachOObjectFile::LoadCommandInfo LoadCmd)2086*d415bd75Srobert ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
2087*d415bd75Srobert                                      MachOObjectFile::LoadCommandInfo LoadCmd) {
2088*d415bd75Srobert   auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);
2089*d415bd75Srobert   if (!SegmentOrErr) {
2090*d415bd75Srobert     consumeError(SegmentOrErr.takeError());
2091*d415bd75Srobert     return {};
2092*d415bd75Srobert   }
2093*d415bd75Srobert   auto &Segment = SegmentOrErr.get();
2094*d415bd75Srobert   return arrayRefFromStringRef(
2095*d415bd75Srobert       Obj.getData().slice(Segment.fileoff, Segment.fileoff + Segment.filesize));
2096*d415bd75Srobert }
2097*d415bd75Srobert } // namespace
2098*d415bd75Srobert 
2099*d415bd75Srobert ArrayRef<uint8_t>
getSegmentContents(StringRef SegmentName) const2100*d415bd75Srobert MachOObjectFile::getSegmentContents(StringRef SegmentName) const {
2101*d415bd75Srobert   for (auto LoadCmd : load_commands()) {
2102*d415bd75Srobert     ArrayRef<uint8_t> Contents;
2103*d415bd75Srobert     switch (LoadCmd.C.cmd) {
2104*d415bd75Srobert     case MachO::LC_SEGMENT:
2105*d415bd75Srobert       Contents = ::getSegmentContents<MachO::segment_command>(*this, LoadCmd,
2106*d415bd75Srobert                                                               SegmentName);
2107*d415bd75Srobert       break;
2108*d415bd75Srobert     case MachO::LC_SEGMENT_64:
2109*d415bd75Srobert       Contents = ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd,
2110*d415bd75Srobert                                                                  SegmentName);
2111*d415bd75Srobert       break;
2112*d415bd75Srobert     default:
2113*d415bd75Srobert       continue;
2114*d415bd75Srobert     }
2115*d415bd75Srobert     if (!Contents.empty())
2116*d415bd75Srobert       return Contents;
2117*d415bd75Srobert   }
2118*d415bd75Srobert   return {};
2119*d415bd75Srobert }
2120*d415bd75Srobert 
2121*d415bd75Srobert ArrayRef<uint8_t>
getSegmentContents(size_t SegmentIndex) const2122*d415bd75Srobert MachOObjectFile::getSegmentContents(size_t SegmentIndex) const {
2123*d415bd75Srobert   size_t Idx = 0;
2124*d415bd75Srobert   for (auto LoadCmd : load_commands()) {
2125*d415bd75Srobert     switch (LoadCmd.C.cmd) {
2126*d415bd75Srobert     case MachO::LC_SEGMENT:
2127*d415bd75Srobert       if (Idx == SegmentIndex)
2128*d415bd75Srobert         return ::getSegmentContents<MachO::segment_command>(*this, LoadCmd);
2129*d415bd75Srobert       ++Idx;
2130*d415bd75Srobert       break;
2131*d415bd75Srobert     case MachO::LC_SEGMENT_64:
2132*d415bd75Srobert       if (Idx == SegmentIndex)
2133*d415bd75Srobert         return ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd);
2134*d415bd75Srobert       ++Idx;
2135*d415bd75Srobert       break;
2136*d415bd75Srobert     default:
2137*d415bd75Srobert       continue;
2138*d415bd75Srobert     }
2139*d415bd75Srobert   }
2140*d415bd75Srobert   return {};
2141*d415bd75Srobert }
2142*d415bd75Srobert 
getSectionID(SectionRef Sec) const214309467b48Spatrick unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
214409467b48Spatrick   return Sec.getRawDataRefImpl().d.a;
214509467b48Spatrick }
214609467b48Spatrick 
isSectionVirtual(DataRefImpl Sec) const214709467b48Spatrick bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
214809467b48Spatrick   uint32_t Flags = getSectionFlags(*this, Sec);
214909467b48Spatrick   unsigned SectionType = Flags & MachO::SECTION_TYPE;
215009467b48Spatrick   return SectionType == MachO::S_ZEROFILL ||
215109467b48Spatrick          SectionType == MachO::S_GB_ZEROFILL;
215209467b48Spatrick }
215309467b48Spatrick 
isSectionBitcode(DataRefImpl Sec) const215409467b48Spatrick bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
215509467b48Spatrick   StringRef SegmentName = getSectionFinalSegmentName(Sec);
215609467b48Spatrick   if (Expected<StringRef> NameOrErr = getSectionName(Sec))
215709467b48Spatrick     return (SegmentName == "__LLVM" && *NameOrErr == "__bitcode");
215809467b48Spatrick   return false;
215909467b48Spatrick }
216009467b48Spatrick 
isSectionStripped(DataRefImpl Sec) const216109467b48Spatrick bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
216209467b48Spatrick   if (is64Bit())
216309467b48Spatrick     return getSection64(Sec).offset == 0;
216409467b48Spatrick   return getSection(Sec).offset == 0;
216509467b48Spatrick }
216609467b48Spatrick 
section_rel_begin(DataRefImpl Sec) const216709467b48Spatrick relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
216809467b48Spatrick   DataRefImpl Ret;
216909467b48Spatrick   Ret.d.a = Sec.d.a;
217009467b48Spatrick   Ret.d.b = 0;
217109467b48Spatrick   return relocation_iterator(RelocationRef(Ret, this));
217209467b48Spatrick }
217309467b48Spatrick 
217409467b48Spatrick relocation_iterator
section_rel_end(DataRefImpl Sec) const217509467b48Spatrick MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
217609467b48Spatrick   uint32_t Num;
217709467b48Spatrick   if (is64Bit()) {
217809467b48Spatrick     MachO::section_64 Sect = getSection64(Sec);
217909467b48Spatrick     Num = Sect.nreloc;
218009467b48Spatrick   } else {
218109467b48Spatrick     MachO::section Sect = getSection(Sec);
218209467b48Spatrick     Num = Sect.nreloc;
218309467b48Spatrick   }
218409467b48Spatrick 
218509467b48Spatrick   DataRefImpl Ret;
218609467b48Spatrick   Ret.d.a = Sec.d.a;
218709467b48Spatrick   Ret.d.b = Num;
218809467b48Spatrick   return relocation_iterator(RelocationRef(Ret, this));
218909467b48Spatrick }
219009467b48Spatrick 
extrel_begin() const219109467b48Spatrick relocation_iterator MachOObjectFile::extrel_begin() const {
219209467b48Spatrick   DataRefImpl Ret;
219309467b48Spatrick   // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
219409467b48Spatrick   Ret.d.a = 0; // Would normally be a section index.
219509467b48Spatrick   Ret.d.b = 0; // Index into the external relocations
219609467b48Spatrick   return relocation_iterator(RelocationRef(Ret, this));
219709467b48Spatrick }
219809467b48Spatrick 
extrel_end() const219909467b48Spatrick relocation_iterator MachOObjectFile::extrel_end() const {
220009467b48Spatrick   MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
220109467b48Spatrick   DataRefImpl Ret;
220209467b48Spatrick   // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
220309467b48Spatrick   Ret.d.a = 0; // Would normally be a section index.
220409467b48Spatrick   Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
220509467b48Spatrick   return relocation_iterator(RelocationRef(Ret, this));
220609467b48Spatrick }
220709467b48Spatrick 
locrel_begin() const220809467b48Spatrick relocation_iterator MachOObjectFile::locrel_begin() const {
220909467b48Spatrick   DataRefImpl Ret;
221009467b48Spatrick   // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
221109467b48Spatrick   Ret.d.a = 1; // Would normally be a section index.
221209467b48Spatrick   Ret.d.b = 0; // Index into the local relocations
221309467b48Spatrick   return relocation_iterator(RelocationRef(Ret, this));
221409467b48Spatrick }
221509467b48Spatrick 
locrel_end() const221609467b48Spatrick relocation_iterator MachOObjectFile::locrel_end() const {
221709467b48Spatrick   MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
221809467b48Spatrick   DataRefImpl Ret;
221909467b48Spatrick   // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
222009467b48Spatrick   Ret.d.a = 1; // Would normally be a section index.
222109467b48Spatrick   Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
222209467b48Spatrick   return relocation_iterator(RelocationRef(Ret, this));
222309467b48Spatrick }
222409467b48Spatrick 
moveRelocationNext(DataRefImpl & Rel) const222509467b48Spatrick void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
222609467b48Spatrick   ++Rel.d.b;
222709467b48Spatrick }
222809467b48Spatrick 
getRelocationOffset(DataRefImpl Rel) const222909467b48Spatrick uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
223009467b48Spatrick   assert((getHeader().filetype == MachO::MH_OBJECT ||
223109467b48Spatrick           getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
223209467b48Spatrick          "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
223309467b48Spatrick   MachO::any_relocation_info RE = getRelocation(Rel);
223409467b48Spatrick   return getAnyRelocationAddress(RE);
223509467b48Spatrick }
223609467b48Spatrick 
223709467b48Spatrick symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const223809467b48Spatrick MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
223909467b48Spatrick   MachO::any_relocation_info RE = getRelocation(Rel);
224009467b48Spatrick   if (isRelocationScattered(RE))
224109467b48Spatrick     return symbol_end();
224209467b48Spatrick 
224309467b48Spatrick   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
224409467b48Spatrick   bool isExtern = getPlainRelocationExternal(RE);
224509467b48Spatrick   if (!isExtern)
224609467b48Spatrick     return symbol_end();
224709467b48Spatrick 
224809467b48Spatrick   MachO::symtab_command S = getSymtabLoadCommand();
224909467b48Spatrick   unsigned SymbolTableEntrySize = is64Bit() ?
225009467b48Spatrick     sizeof(MachO::nlist_64) :
225109467b48Spatrick     sizeof(MachO::nlist);
225209467b48Spatrick   uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
225309467b48Spatrick   DataRefImpl Sym;
225409467b48Spatrick   Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
225509467b48Spatrick   return symbol_iterator(SymbolRef(Sym, this));
225609467b48Spatrick }
225709467b48Spatrick 
225809467b48Spatrick section_iterator
getRelocationSection(DataRefImpl Rel) const225909467b48Spatrick MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
226009467b48Spatrick   return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
226109467b48Spatrick }
226209467b48Spatrick 
getRelocationType(DataRefImpl Rel) const226309467b48Spatrick uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
226409467b48Spatrick   MachO::any_relocation_info RE = getRelocation(Rel);
226509467b48Spatrick   return getAnyRelocationType(RE);
226609467b48Spatrick }
226709467b48Spatrick 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const226809467b48Spatrick void MachOObjectFile::getRelocationTypeName(
226909467b48Spatrick     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
227009467b48Spatrick   StringRef res;
227109467b48Spatrick   uint64_t RType = getRelocationType(Rel);
227209467b48Spatrick 
227309467b48Spatrick   unsigned Arch = this->getArch();
227409467b48Spatrick 
227509467b48Spatrick   switch (Arch) {
227609467b48Spatrick     case Triple::x86: {
227709467b48Spatrick       static const char *const Table[] =  {
227809467b48Spatrick         "GENERIC_RELOC_VANILLA",
227909467b48Spatrick         "GENERIC_RELOC_PAIR",
228009467b48Spatrick         "GENERIC_RELOC_SECTDIFF",
228109467b48Spatrick         "GENERIC_RELOC_PB_LA_PTR",
228209467b48Spatrick         "GENERIC_RELOC_LOCAL_SECTDIFF",
228309467b48Spatrick         "GENERIC_RELOC_TLV" };
228409467b48Spatrick 
228509467b48Spatrick       if (RType > 5)
228609467b48Spatrick         res = "Unknown";
228709467b48Spatrick       else
228809467b48Spatrick         res = Table[RType];
228909467b48Spatrick       break;
229009467b48Spatrick     }
229109467b48Spatrick     case Triple::x86_64: {
229209467b48Spatrick       static const char *const Table[] =  {
229309467b48Spatrick         "X86_64_RELOC_UNSIGNED",
229409467b48Spatrick         "X86_64_RELOC_SIGNED",
229509467b48Spatrick         "X86_64_RELOC_BRANCH",
229609467b48Spatrick         "X86_64_RELOC_GOT_LOAD",
229709467b48Spatrick         "X86_64_RELOC_GOT",
229809467b48Spatrick         "X86_64_RELOC_SUBTRACTOR",
229909467b48Spatrick         "X86_64_RELOC_SIGNED_1",
230009467b48Spatrick         "X86_64_RELOC_SIGNED_2",
230109467b48Spatrick         "X86_64_RELOC_SIGNED_4",
230209467b48Spatrick         "X86_64_RELOC_TLV" };
230309467b48Spatrick 
230409467b48Spatrick       if (RType > 9)
230509467b48Spatrick         res = "Unknown";
230609467b48Spatrick       else
230709467b48Spatrick         res = Table[RType];
230809467b48Spatrick       break;
230909467b48Spatrick     }
231009467b48Spatrick     case Triple::arm: {
231109467b48Spatrick       static const char *const Table[] =  {
231209467b48Spatrick         "ARM_RELOC_VANILLA",
231309467b48Spatrick         "ARM_RELOC_PAIR",
231409467b48Spatrick         "ARM_RELOC_SECTDIFF",
231509467b48Spatrick         "ARM_RELOC_LOCAL_SECTDIFF",
231609467b48Spatrick         "ARM_RELOC_PB_LA_PTR",
231709467b48Spatrick         "ARM_RELOC_BR24",
231809467b48Spatrick         "ARM_THUMB_RELOC_BR22",
231909467b48Spatrick         "ARM_THUMB_32BIT_BRANCH",
232009467b48Spatrick         "ARM_RELOC_HALF",
232109467b48Spatrick         "ARM_RELOC_HALF_SECTDIFF" };
232209467b48Spatrick 
232309467b48Spatrick       if (RType > 9)
232409467b48Spatrick         res = "Unknown";
232509467b48Spatrick       else
232609467b48Spatrick         res = Table[RType];
232709467b48Spatrick       break;
232809467b48Spatrick     }
232909467b48Spatrick     case Triple::aarch64:
233009467b48Spatrick     case Triple::aarch64_32: {
233109467b48Spatrick       static const char *const Table[] = {
233209467b48Spatrick         "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
233309467b48Spatrick         "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
233409467b48Spatrick         "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
233509467b48Spatrick         "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
233609467b48Spatrick         "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
233709467b48Spatrick         "ARM64_RELOC_ADDEND"
233809467b48Spatrick       };
233909467b48Spatrick 
2340*d415bd75Srobert       if (RType >= std::size(Table))
234109467b48Spatrick         res = "Unknown";
234209467b48Spatrick       else
234309467b48Spatrick         res = Table[RType];
234409467b48Spatrick       break;
234509467b48Spatrick     }
234609467b48Spatrick     case Triple::ppc: {
234709467b48Spatrick       static const char *const Table[] =  {
234809467b48Spatrick         "PPC_RELOC_VANILLA",
234909467b48Spatrick         "PPC_RELOC_PAIR",
235009467b48Spatrick         "PPC_RELOC_BR14",
235109467b48Spatrick         "PPC_RELOC_BR24",
235209467b48Spatrick         "PPC_RELOC_HI16",
235309467b48Spatrick         "PPC_RELOC_LO16",
235409467b48Spatrick         "PPC_RELOC_HA16",
235509467b48Spatrick         "PPC_RELOC_LO14",
235609467b48Spatrick         "PPC_RELOC_SECTDIFF",
235709467b48Spatrick         "PPC_RELOC_PB_LA_PTR",
235809467b48Spatrick         "PPC_RELOC_HI16_SECTDIFF",
235909467b48Spatrick         "PPC_RELOC_LO16_SECTDIFF",
236009467b48Spatrick         "PPC_RELOC_HA16_SECTDIFF",
236109467b48Spatrick         "PPC_RELOC_JBSR",
236209467b48Spatrick         "PPC_RELOC_LO14_SECTDIFF",
236309467b48Spatrick         "PPC_RELOC_LOCAL_SECTDIFF" };
236409467b48Spatrick 
236509467b48Spatrick       if (RType > 15)
236609467b48Spatrick         res = "Unknown";
236709467b48Spatrick       else
236809467b48Spatrick         res = Table[RType];
236909467b48Spatrick       break;
237009467b48Spatrick     }
237109467b48Spatrick     case Triple::UnknownArch:
237209467b48Spatrick       res = "Unknown";
237309467b48Spatrick       break;
237409467b48Spatrick   }
237509467b48Spatrick   Result.append(res.begin(), res.end());
237609467b48Spatrick }
237709467b48Spatrick 
getRelocationLength(DataRefImpl Rel) const237809467b48Spatrick uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
237909467b48Spatrick   MachO::any_relocation_info RE = getRelocation(Rel);
238009467b48Spatrick   return getAnyRelocationLength(RE);
238109467b48Spatrick }
238209467b48Spatrick 
238309467b48Spatrick //
238409467b48Spatrick // guessLibraryShortName() is passed a name of a dynamic library and returns a
238509467b48Spatrick // guess on what the short name is.  Then name is returned as a substring of the
238609467b48Spatrick // StringRef Name passed in.  The name of the dynamic library is recognized as
238709467b48Spatrick // a framework if it has one of the two following forms:
238809467b48Spatrick //      Foo.framework/Versions/A/Foo
238909467b48Spatrick //      Foo.framework/Foo
239009467b48Spatrick // Where A and Foo can be any string.  And may contain a trailing suffix
239109467b48Spatrick // starting with an underbar.  If the Name is recognized as a framework then
239209467b48Spatrick // isFramework is set to true else it is set to false.  If the Name has a
239309467b48Spatrick // suffix then Suffix is set to the substring in Name that contains the suffix
239409467b48Spatrick // else it is set to a NULL StringRef.
239509467b48Spatrick //
239609467b48Spatrick // The Name of the dynamic library is recognized as a library name if it has
239709467b48Spatrick // one of the two following forms:
239809467b48Spatrick //      libFoo.A.dylib
239909467b48Spatrick //      libFoo.dylib
240009467b48Spatrick //
240109467b48Spatrick // The library may have a suffix trailing the name Foo of the form:
240209467b48Spatrick //      libFoo_profile.A.dylib
240309467b48Spatrick //      libFoo_profile.dylib
240409467b48Spatrick // These dyld image suffixes are separated from the short name by a '_'
240509467b48Spatrick // character. Because the '_' character is commonly used to separate words in
240609467b48Spatrick // filenames guessLibraryShortName() cannot reliably separate a dylib's short
240709467b48Spatrick // name from an arbitrary image suffix; imagine if both the short name and the
240809467b48Spatrick // suffix contains an '_' character! To better deal with this ambiguity,
240909467b48Spatrick // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
241009467b48Spatrick // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
241109467b48Spatrick // guessing incorrectly.
241209467b48Spatrick //
241309467b48Spatrick // The Name of the dynamic library is also recognized as a library name if it
241409467b48Spatrick // has the following form:
241509467b48Spatrick //      Foo.qtx
241609467b48Spatrick //
241709467b48Spatrick // If the Name of the dynamic library is none of the forms above then a NULL
241809467b48Spatrick // StringRef is returned.
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)241909467b48Spatrick StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
242009467b48Spatrick                                                  bool &isFramework,
242109467b48Spatrick                                                  StringRef &Suffix) {
242209467b48Spatrick   StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
242309467b48Spatrick   size_t a, b, c, d, Idx;
242409467b48Spatrick 
242509467b48Spatrick   isFramework = false;
242609467b48Spatrick   Suffix = StringRef();
242709467b48Spatrick 
242809467b48Spatrick   // Pull off the last component and make Foo point to it
242909467b48Spatrick   a = Name.rfind('/');
243009467b48Spatrick   if (a == Name.npos || a == 0)
243109467b48Spatrick     goto guess_library;
243209467b48Spatrick   Foo = Name.slice(a+1, Name.npos);
243309467b48Spatrick 
243409467b48Spatrick   // Look for a suffix starting with a '_'
243509467b48Spatrick   Idx = Foo.rfind('_');
243609467b48Spatrick   if (Idx != Foo.npos && Foo.size() >= 2) {
243709467b48Spatrick     Suffix = Foo.slice(Idx, Foo.npos);
243809467b48Spatrick     if (Suffix != "_debug" && Suffix != "_profile")
243909467b48Spatrick       Suffix = StringRef();
244009467b48Spatrick     else
244109467b48Spatrick       Foo = Foo.slice(0, Idx);
244209467b48Spatrick   }
244309467b48Spatrick 
244409467b48Spatrick   // First look for the form Foo.framework/Foo
244509467b48Spatrick   b = Name.rfind('/', a);
244609467b48Spatrick   if (b == Name.npos)
244709467b48Spatrick     Idx = 0;
244809467b48Spatrick   else
244909467b48Spatrick     Idx = b+1;
245009467b48Spatrick   F = Name.slice(Idx, Idx + Foo.size());
245109467b48Spatrick   DotFramework = Name.slice(Idx + Foo.size(),
245209467b48Spatrick                             Idx + Foo.size() + sizeof(".framework/")-1);
245309467b48Spatrick   if (F == Foo && DotFramework == ".framework/") {
245409467b48Spatrick     isFramework = true;
245509467b48Spatrick     return Foo;
245609467b48Spatrick   }
245709467b48Spatrick 
245809467b48Spatrick   // Next look for the form Foo.framework/Versions/A/Foo
245909467b48Spatrick   if (b == Name.npos)
246009467b48Spatrick     goto guess_library;
246109467b48Spatrick   c =  Name.rfind('/', b);
246209467b48Spatrick   if (c == Name.npos || c == 0)
246309467b48Spatrick     goto guess_library;
246409467b48Spatrick   V = Name.slice(c+1, Name.npos);
246509467b48Spatrick   if (!V.startswith("Versions/"))
246609467b48Spatrick     goto guess_library;
246709467b48Spatrick   d =  Name.rfind('/', c);
246809467b48Spatrick   if (d == Name.npos)
246909467b48Spatrick     Idx = 0;
247009467b48Spatrick   else
247109467b48Spatrick     Idx = d+1;
247209467b48Spatrick   F = Name.slice(Idx, Idx + Foo.size());
247309467b48Spatrick   DotFramework = Name.slice(Idx + Foo.size(),
247409467b48Spatrick                             Idx + Foo.size() + sizeof(".framework/")-1);
247509467b48Spatrick   if (F == Foo && DotFramework == ".framework/") {
247609467b48Spatrick     isFramework = true;
247709467b48Spatrick     return Foo;
247809467b48Spatrick   }
247909467b48Spatrick 
248009467b48Spatrick guess_library:
248109467b48Spatrick   // pull off the suffix after the "." and make a point to it
248209467b48Spatrick   a = Name.rfind('.');
248309467b48Spatrick   if (a == Name.npos || a == 0)
248409467b48Spatrick     return StringRef();
248509467b48Spatrick   Dylib = Name.slice(a, Name.npos);
248609467b48Spatrick   if (Dylib != ".dylib")
248709467b48Spatrick     goto guess_qtx;
248809467b48Spatrick 
248909467b48Spatrick   // First pull off the version letter for the form Foo.A.dylib if any.
249009467b48Spatrick   if (a >= 3) {
249109467b48Spatrick     Dot = Name.slice(a-2, a-1);
249209467b48Spatrick     if (Dot == ".")
249309467b48Spatrick       a = a - 2;
249409467b48Spatrick   }
249509467b48Spatrick 
249609467b48Spatrick   b = Name.rfind('/', a);
249709467b48Spatrick   if (b == Name.npos)
249809467b48Spatrick     b = 0;
249909467b48Spatrick   else
250009467b48Spatrick     b = b+1;
250109467b48Spatrick   // ignore any suffix after an underbar like Foo_profile.A.dylib
250209467b48Spatrick   Idx = Name.rfind('_');
250309467b48Spatrick   if (Idx != Name.npos && Idx != b) {
250409467b48Spatrick     Lib = Name.slice(b, Idx);
250509467b48Spatrick     Suffix = Name.slice(Idx, a);
250609467b48Spatrick     if (Suffix != "_debug" && Suffix != "_profile") {
250709467b48Spatrick       Suffix = StringRef();
250809467b48Spatrick       Lib = Name.slice(b, a);
250909467b48Spatrick     }
251009467b48Spatrick   }
251109467b48Spatrick   else
251209467b48Spatrick     Lib = Name.slice(b, a);
251309467b48Spatrick   // There are incorrect library names of the form:
251409467b48Spatrick   // libATS.A_profile.dylib so check for these.
251509467b48Spatrick   if (Lib.size() >= 3) {
251609467b48Spatrick     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
251709467b48Spatrick     if (Dot == ".")
251809467b48Spatrick       Lib = Lib.slice(0, Lib.size()-2);
251909467b48Spatrick   }
252009467b48Spatrick   return Lib;
252109467b48Spatrick 
252209467b48Spatrick guess_qtx:
252309467b48Spatrick   Qtx = Name.slice(a, Name.npos);
252409467b48Spatrick   if (Qtx != ".qtx")
252509467b48Spatrick     return StringRef();
252609467b48Spatrick   b = Name.rfind('/', a);
252709467b48Spatrick   if (b == Name.npos)
252809467b48Spatrick     Lib = Name.slice(0, a);
252909467b48Spatrick   else
253009467b48Spatrick     Lib = Name.slice(b+1, a);
253109467b48Spatrick   // There are library names of the form: QT.A.qtx so check for these.
253209467b48Spatrick   if (Lib.size() >= 3) {
253309467b48Spatrick     Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
253409467b48Spatrick     if (Dot == ".")
253509467b48Spatrick       Lib = Lib.slice(0, Lib.size()-2);
253609467b48Spatrick   }
253709467b48Spatrick   return Lib;
253809467b48Spatrick }
253909467b48Spatrick 
254009467b48Spatrick // getLibraryShortNameByIndex() is used to get the short name of the library
254109467b48Spatrick // for an undefined symbol in a linked Mach-O binary that was linked with the
254209467b48Spatrick // normal two-level namespace default (that is MH_TWOLEVEL in the header).
254309467b48Spatrick // It is passed the index (0 - based) of the library as translated from
254409467b48Spatrick // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const254509467b48Spatrick std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
254609467b48Spatrick                                                          StringRef &Res) const {
254709467b48Spatrick   if (Index >= Libraries.size())
254809467b48Spatrick     return object_error::parse_failed;
254909467b48Spatrick 
255009467b48Spatrick   // If the cache of LibrariesShortNames is not built up do that first for
255109467b48Spatrick   // all the Libraries.
255209467b48Spatrick   if (LibrariesShortNames.size() == 0) {
255309467b48Spatrick     for (unsigned i = 0; i < Libraries.size(); i++) {
255409467b48Spatrick       auto CommandOrErr =
255509467b48Spatrick         getStructOrErr<MachO::dylib_command>(*this, Libraries[i]);
255609467b48Spatrick       if (!CommandOrErr)
255709467b48Spatrick         return object_error::parse_failed;
255809467b48Spatrick       MachO::dylib_command D = CommandOrErr.get();
255909467b48Spatrick       if (D.dylib.name >= D.cmdsize)
256009467b48Spatrick         return object_error::parse_failed;
256109467b48Spatrick       const char *P = (const char *)(Libraries[i]) + D.dylib.name;
256209467b48Spatrick       StringRef Name = StringRef(P);
256309467b48Spatrick       if (D.dylib.name+Name.size() >= D.cmdsize)
256409467b48Spatrick         return object_error::parse_failed;
256509467b48Spatrick       StringRef Suffix;
256609467b48Spatrick       bool isFramework;
256709467b48Spatrick       StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
256809467b48Spatrick       if (shortName.empty())
256909467b48Spatrick         LibrariesShortNames.push_back(Name);
257009467b48Spatrick       else
257109467b48Spatrick         LibrariesShortNames.push_back(shortName);
257209467b48Spatrick     }
257309467b48Spatrick   }
257409467b48Spatrick 
257509467b48Spatrick   Res = LibrariesShortNames[Index];
257609467b48Spatrick   return std::error_code();
257709467b48Spatrick }
257809467b48Spatrick 
getLibraryCount() const257909467b48Spatrick uint32_t MachOObjectFile::getLibraryCount() const {
258009467b48Spatrick   return Libraries.size();
258109467b48Spatrick }
258209467b48Spatrick 
258309467b48Spatrick section_iterator
getRelocationRelocatedSection(relocation_iterator Rel) const258409467b48Spatrick MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
258509467b48Spatrick   DataRefImpl Sec;
258609467b48Spatrick   Sec.d.a = Rel->getRawDataRefImpl().d.a;
258709467b48Spatrick   return section_iterator(SectionRef(Sec, this));
258809467b48Spatrick }
258909467b48Spatrick 
symbol_begin() const259009467b48Spatrick basic_symbol_iterator MachOObjectFile::symbol_begin() const {
259109467b48Spatrick   DataRefImpl DRI;
259209467b48Spatrick   MachO::symtab_command Symtab = getSymtabLoadCommand();
259309467b48Spatrick   if (!SymtabLoadCmd || Symtab.nsyms == 0)
259409467b48Spatrick     return basic_symbol_iterator(SymbolRef(DRI, this));
259509467b48Spatrick 
259609467b48Spatrick   return getSymbolByIndex(0);
259709467b48Spatrick }
259809467b48Spatrick 
symbol_end() const259909467b48Spatrick basic_symbol_iterator MachOObjectFile::symbol_end() const {
260009467b48Spatrick   DataRefImpl DRI;
260109467b48Spatrick   MachO::symtab_command Symtab = getSymtabLoadCommand();
260209467b48Spatrick   if (!SymtabLoadCmd || Symtab.nsyms == 0)
260309467b48Spatrick     return basic_symbol_iterator(SymbolRef(DRI, this));
260409467b48Spatrick 
260509467b48Spatrick   unsigned SymbolTableEntrySize = is64Bit() ?
260609467b48Spatrick     sizeof(MachO::nlist_64) :
260709467b48Spatrick     sizeof(MachO::nlist);
260809467b48Spatrick   unsigned Offset = Symtab.symoff +
260909467b48Spatrick     Symtab.nsyms * SymbolTableEntrySize;
261009467b48Spatrick   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
261109467b48Spatrick   return basic_symbol_iterator(SymbolRef(DRI, this));
261209467b48Spatrick }
261309467b48Spatrick 
getSymbolByIndex(unsigned Index) const261409467b48Spatrick symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
261509467b48Spatrick   MachO::symtab_command Symtab = getSymtabLoadCommand();
261609467b48Spatrick   if (!SymtabLoadCmd || Index >= Symtab.nsyms)
261709467b48Spatrick     report_fatal_error("Requested symbol index is out of range.");
261809467b48Spatrick   unsigned SymbolTableEntrySize =
261909467b48Spatrick     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
262009467b48Spatrick   DataRefImpl DRI;
262109467b48Spatrick   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
262209467b48Spatrick   DRI.p += Index * SymbolTableEntrySize;
262309467b48Spatrick   return basic_symbol_iterator(SymbolRef(DRI, this));
262409467b48Spatrick }
262509467b48Spatrick 
getSymbolIndex(DataRefImpl Symb) const262609467b48Spatrick uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
262709467b48Spatrick   MachO::symtab_command Symtab = getSymtabLoadCommand();
262809467b48Spatrick   if (!SymtabLoadCmd)
262909467b48Spatrick     report_fatal_error("getSymbolIndex() called with no symbol table symbol");
263009467b48Spatrick   unsigned SymbolTableEntrySize =
263109467b48Spatrick     is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
263209467b48Spatrick   DataRefImpl DRIstart;
263309467b48Spatrick   DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
263409467b48Spatrick   uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
263509467b48Spatrick   return Index;
263609467b48Spatrick }
263709467b48Spatrick 
section_begin() const263809467b48Spatrick section_iterator MachOObjectFile::section_begin() const {
263909467b48Spatrick   DataRefImpl DRI;
264009467b48Spatrick   return section_iterator(SectionRef(DRI, this));
264109467b48Spatrick }
264209467b48Spatrick 
section_end() const264309467b48Spatrick section_iterator MachOObjectFile::section_end() const {
264409467b48Spatrick   DataRefImpl DRI;
264509467b48Spatrick   DRI.d.a = Sections.size();
264609467b48Spatrick   return section_iterator(SectionRef(DRI, this));
264709467b48Spatrick }
264809467b48Spatrick 
getBytesInAddress() const264909467b48Spatrick uint8_t MachOObjectFile::getBytesInAddress() const {
265009467b48Spatrick   return is64Bit() ? 8 : 4;
265109467b48Spatrick }
265209467b48Spatrick 
getFileFormatName() const265309467b48Spatrick StringRef MachOObjectFile::getFileFormatName() const {
265409467b48Spatrick   unsigned CPUType = getCPUType(*this);
265509467b48Spatrick   if (!is64Bit()) {
265609467b48Spatrick     switch (CPUType) {
265709467b48Spatrick     case MachO::CPU_TYPE_I386:
265809467b48Spatrick       return "Mach-O 32-bit i386";
265909467b48Spatrick     case MachO::CPU_TYPE_ARM:
266009467b48Spatrick       return "Mach-O arm";
266109467b48Spatrick     case MachO::CPU_TYPE_ARM64_32:
266209467b48Spatrick       return "Mach-O arm64 (ILP32)";
266309467b48Spatrick     case MachO::CPU_TYPE_POWERPC:
266409467b48Spatrick       return "Mach-O 32-bit ppc";
266509467b48Spatrick     default:
266609467b48Spatrick       return "Mach-O 32-bit unknown";
266709467b48Spatrick     }
266809467b48Spatrick   }
266909467b48Spatrick 
267009467b48Spatrick   switch (CPUType) {
267109467b48Spatrick   case MachO::CPU_TYPE_X86_64:
267209467b48Spatrick     return "Mach-O 64-bit x86-64";
267309467b48Spatrick   case MachO::CPU_TYPE_ARM64:
267409467b48Spatrick     return "Mach-O arm64";
267509467b48Spatrick   case MachO::CPU_TYPE_POWERPC64:
267609467b48Spatrick     return "Mach-O 64-bit ppc64";
267709467b48Spatrick   default:
267809467b48Spatrick     return "Mach-O 64-bit unknown";
267909467b48Spatrick   }
268009467b48Spatrick }
268109467b48Spatrick 
getArch(uint32_t CPUType,uint32_t CPUSubType)268209467b48Spatrick Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
268309467b48Spatrick   switch (CPUType) {
268409467b48Spatrick   case MachO::CPU_TYPE_I386:
268509467b48Spatrick     return Triple::x86;
268609467b48Spatrick   case MachO::CPU_TYPE_X86_64:
268709467b48Spatrick     return Triple::x86_64;
268809467b48Spatrick   case MachO::CPU_TYPE_ARM:
268909467b48Spatrick     return Triple::arm;
269009467b48Spatrick   case MachO::CPU_TYPE_ARM64:
269109467b48Spatrick     return Triple::aarch64;
269209467b48Spatrick   case MachO::CPU_TYPE_ARM64_32:
269309467b48Spatrick     return Triple::aarch64_32;
269409467b48Spatrick   case MachO::CPU_TYPE_POWERPC:
269509467b48Spatrick     return Triple::ppc;
269609467b48Spatrick   case MachO::CPU_TYPE_POWERPC64:
269709467b48Spatrick     return Triple::ppc64;
269809467b48Spatrick   default:
269909467b48Spatrick     return Triple::UnknownArch;
270009467b48Spatrick   }
270109467b48Spatrick }
270209467b48Spatrick 
getArchTriple(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,const char ** ArchFlag)270309467b48Spatrick Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
270409467b48Spatrick                                       const char **McpuDefault,
270509467b48Spatrick                                       const char **ArchFlag) {
270609467b48Spatrick   if (McpuDefault)
270709467b48Spatrick     *McpuDefault = nullptr;
270809467b48Spatrick   if (ArchFlag)
270909467b48Spatrick     *ArchFlag = nullptr;
271009467b48Spatrick 
271109467b48Spatrick   switch (CPUType) {
271209467b48Spatrick   case MachO::CPU_TYPE_I386:
271309467b48Spatrick     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
271409467b48Spatrick     case MachO::CPU_SUBTYPE_I386_ALL:
271509467b48Spatrick       if (ArchFlag)
271609467b48Spatrick         *ArchFlag = "i386";
271709467b48Spatrick       return Triple("i386-apple-darwin");
271809467b48Spatrick     default:
271909467b48Spatrick       return Triple();
272009467b48Spatrick     }
272109467b48Spatrick   case MachO::CPU_TYPE_X86_64:
272209467b48Spatrick     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
272309467b48Spatrick     case MachO::CPU_SUBTYPE_X86_64_ALL:
272409467b48Spatrick       if (ArchFlag)
272509467b48Spatrick         *ArchFlag = "x86_64";
272609467b48Spatrick       return Triple("x86_64-apple-darwin");
272709467b48Spatrick     case MachO::CPU_SUBTYPE_X86_64_H:
272809467b48Spatrick       if (ArchFlag)
272909467b48Spatrick         *ArchFlag = "x86_64h";
273009467b48Spatrick       return Triple("x86_64h-apple-darwin");
273109467b48Spatrick     default:
273209467b48Spatrick       return Triple();
273309467b48Spatrick     }
273409467b48Spatrick   case MachO::CPU_TYPE_ARM:
273509467b48Spatrick     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
273609467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V4T:
273709467b48Spatrick       if (ArchFlag)
273809467b48Spatrick         *ArchFlag = "armv4t";
273909467b48Spatrick       return Triple("armv4t-apple-darwin");
274009467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
274109467b48Spatrick       if (ArchFlag)
274209467b48Spatrick         *ArchFlag = "armv5e";
274309467b48Spatrick       return Triple("armv5e-apple-darwin");
274409467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_XSCALE:
274509467b48Spatrick       if (ArchFlag)
274609467b48Spatrick         *ArchFlag = "xscale";
274709467b48Spatrick       return Triple("xscale-apple-darwin");
274809467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V6:
274909467b48Spatrick       if (ArchFlag)
275009467b48Spatrick         *ArchFlag = "armv6";
275109467b48Spatrick       return Triple("armv6-apple-darwin");
275209467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V6M:
275309467b48Spatrick       if (McpuDefault)
275409467b48Spatrick         *McpuDefault = "cortex-m0";
275509467b48Spatrick       if (ArchFlag)
275609467b48Spatrick         *ArchFlag = "armv6m";
275709467b48Spatrick       return Triple("armv6m-apple-darwin");
275809467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V7:
275909467b48Spatrick       if (ArchFlag)
276009467b48Spatrick         *ArchFlag = "armv7";
276109467b48Spatrick       return Triple("armv7-apple-darwin");
276209467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V7EM:
276309467b48Spatrick       if (McpuDefault)
276409467b48Spatrick         *McpuDefault = "cortex-m4";
276509467b48Spatrick       if (ArchFlag)
276609467b48Spatrick         *ArchFlag = "armv7em";
276709467b48Spatrick       return Triple("thumbv7em-apple-darwin");
276809467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V7K:
276909467b48Spatrick       if (McpuDefault)
277009467b48Spatrick         *McpuDefault = "cortex-a7";
277109467b48Spatrick       if (ArchFlag)
277209467b48Spatrick         *ArchFlag = "armv7k";
277309467b48Spatrick       return Triple("armv7k-apple-darwin");
277409467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V7M:
277509467b48Spatrick       if (McpuDefault)
277609467b48Spatrick         *McpuDefault = "cortex-m3";
277709467b48Spatrick       if (ArchFlag)
277809467b48Spatrick         *ArchFlag = "armv7m";
277909467b48Spatrick       return Triple("thumbv7m-apple-darwin");
278009467b48Spatrick     case MachO::CPU_SUBTYPE_ARM_V7S:
278109467b48Spatrick       if (McpuDefault)
278209467b48Spatrick         *McpuDefault = "cortex-a7";
278309467b48Spatrick       if (ArchFlag)
278409467b48Spatrick         *ArchFlag = "armv7s";
278509467b48Spatrick       return Triple("armv7s-apple-darwin");
278609467b48Spatrick     default:
278709467b48Spatrick       return Triple();
278809467b48Spatrick     }
278909467b48Spatrick   case MachO::CPU_TYPE_ARM64:
279009467b48Spatrick     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
279109467b48Spatrick     case MachO::CPU_SUBTYPE_ARM64_ALL:
279209467b48Spatrick       if (McpuDefault)
279309467b48Spatrick         *McpuDefault = "cyclone";
279409467b48Spatrick       if (ArchFlag)
279509467b48Spatrick         *ArchFlag = "arm64";
279609467b48Spatrick       return Triple("arm64-apple-darwin");
279773471bf0Spatrick     case MachO::CPU_SUBTYPE_ARM64E:
279873471bf0Spatrick       if (McpuDefault)
279973471bf0Spatrick         *McpuDefault = "apple-a12";
280073471bf0Spatrick       if (ArchFlag)
280173471bf0Spatrick         *ArchFlag = "arm64e";
280273471bf0Spatrick       return Triple("arm64e-apple-darwin");
280309467b48Spatrick     default:
280409467b48Spatrick       return Triple();
280509467b48Spatrick     }
280609467b48Spatrick   case MachO::CPU_TYPE_ARM64_32:
280709467b48Spatrick     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
280809467b48Spatrick     case MachO::CPU_SUBTYPE_ARM64_32_V8:
280909467b48Spatrick       if (McpuDefault)
281009467b48Spatrick         *McpuDefault = "cyclone";
281109467b48Spatrick       if (ArchFlag)
281209467b48Spatrick         *ArchFlag = "arm64_32";
281309467b48Spatrick       return Triple("arm64_32-apple-darwin");
281409467b48Spatrick     default:
281509467b48Spatrick       return Triple();
281609467b48Spatrick     }
281709467b48Spatrick   case MachO::CPU_TYPE_POWERPC:
281809467b48Spatrick     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
281909467b48Spatrick     case MachO::CPU_SUBTYPE_POWERPC_ALL:
282009467b48Spatrick       if (ArchFlag)
282109467b48Spatrick         *ArchFlag = "ppc";
282209467b48Spatrick       return Triple("ppc-apple-darwin");
282309467b48Spatrick     default:
282409467b48Spatrick       return Triple();
282509467b48Spatrick     }
282609467b48Spatrick   case MachO::CPU_TYPE_POWERPC64:
282709467b48Spatrick     switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
282809467b48Spatrick     case MachO::CPU_SUBTYPE_POWERPC_ALL:
282909467b48Spatrick       if (ArchFlag)
283009467b48Spatrick         *ArchFlag = "ppc64";
283109467b48Spatrick       return Triple("ppc64-apple-darwin");
283209467b48Spatrick     default:
283309467b48Spatrick       return Triple();
283409467b48Spatrick     }
283509467b48Spatrick   default:
283609467b48Spatrick     return Triple();
283709467b48Spatrick   }
283809467b48Spatrick }
283909467b48Spatrick 
getHostArch()284009467b48Spatrick Triple MachOObjectFile::getHostArch() {
284109467b48Spatrick   return Triple(sys::getDefaultTargetTriple());
284209467b48Spatrick }
284309467b48Spatrick 
isValidArch(StringRef ArchFlag)284409467b48Spatrick bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
284509467b48Spatrick   auto validArchs = getValidArchs();
284673471bf0Spatrick   return llvm::is_contained(validArchs, ArchFlag);
284709467b48Spatrick }
284809467b48Spatrick 
getValidArchs()284909467b48Spatrick ArrayRef<StringRef> MachOObjectFile::getValidArchs() {
285073471bf0Spatrick   static const std::array<StringRef, 18> ValidArchs = {{
285173471bf0Spatrick       "i386",
285273471bf0Spatrick       "x86_64",
285373471bf0Spatrick       "x86_64h",
285473471bf0Spatrick       "armv4t",
285573471bf0Spatrick       "arm",
285673471bf0Spatrick       "armv5e",
285773471bf0Spatrick       "armv6",
285873471bf0Spatrick       "armv6m",
285973471bf0Spatrick       "armv7",
286073471bf0Spatrick       "armv7em",
286173471bf0Spatrick       "armv7k",
286273471bf0Spatrick       "armv7m",
286373471bf0Spatrick       "armv7s",
286473471bf0Spatrick       "arm64",
286573471bf0Spatrick       "arm64e",
286673471bf0Spatrick       "arm64_32",
286773471bf0Spatrick       "ppc",
286873471bf0Spatrick       "ppc64",
286909467b48Spatrick   }};
287009467b48Spatrick 
287173471bf0Spatrick   return ValidArchs;
287209467b48Spatrick }
287309467b48Spatrick 
getArch() const287409467b48Spatrick Triple::ArchType MachOObjectFile::getArch() const {
287509467b48Spatrick   return getArch(getCPUType(*this), getCPUSubType(*this));
287609467b48Spatrick }
287709467b48Spatrick 
getArchTriple(const char ** McpuDefault) const287809467b48Spatrick Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
287909467b48Spatrick   return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
288009467b48Spatrick }
288109467b48Spatrick 
section_rel_begin(unsigned Index) const288209467b48Spatrick relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
288309467b48Spatrick   DataRefImpl DRI;
288409467b48Spatrick   DRI.d.a = Index;
288509467b48Spatrick   return section_rel_begin(DRI);
288609467b48Spatrick }
288709467b48Spatrick 
section_rel_end(unsigned Index) const288809467b48Spatrick relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
288909467b48Spatrick   DataRefImpl DRI;
289009467b48Spatrick   DRI.d.a = Index;
289109467b48Spatrick   return section_rel_end(DRI);
289209467b48Spatrick }
289309467b48Spatrick 
begin_dices() const289409467b48Spatrick dice_iterator MachOObjectFile::begin_dices() const {
289509467b48Spatrick   DataRefImpl DRI;
289609467b48Spatrick   if (!DataInCodeLoadCmd)
289709467b48Spatrick     return dice_iterator(DiceRef(DRI, this));
289809467b48Spatrick 
289909467b48Spatrick   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
290009467b48Spatrick   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
290109467b48Spatrick   return dice_iterator(DiceRef(DRI, this));
290209467b48Spatrick }
290309467b48Spatrick 
end_dices() const290409467b48Spatrick dice_iterator MachOObjectFile::end_dices() const {
290509467b48Spatrick   DataRefImpl DRI;
290609467b48Spatrick   if (!DataInCodeLoadCmd)
290709467b48Spatrick     return dice_iterator(DiceRef(DRI, this));
290809467b48Spatrick 
290909467b48Spatrick   MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
291009467b48Spatrick   unsigned Offset = DicLC.dataoff + DicLC.datasize;
291109467b48Spatrick   DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
291209467b48Spatrick   return dice_iterator(DiceRef(DRI, this));
291309467b48Spatrick }
291409467b48Spatrick 
ExportEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> T)291509467b48Spatrick ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
291609467b48Spatrick                          ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
291709467b48Spatrick 
moveToFirst()291809467b48Spatrick void ExportEntry::moveToFirst() {
291909467b48Spatrick   ErrorAsOutParameter ErrAsOutParam(E);
292009467b48Spatrick   pushNode(0);
292109467b48Spatrick   if (*E)
292209467b48Spatrick     return;
292309467b48Spatrick   pushDownUntilBottom();
292409467b48Spatrick }
292509467b48Spatrick 
moveToEnd()292609467b48Spatrick void ExportEntry::moveToEnd() {
292709467b48Spatrick   Stack.clear();
292809467b48Spatrick   Done = true;
292909467b48Spatrick }
293009467b48Spatrick 
operator ==(const ExportEntry & Other) const293109467b48Spatrick bool ExportEntry::operator==(const ExportEntry &Other) const {
293209467b48Spatrick   // Common case, one at end, other iterating from begin.
293309467b48Spatrick   if (Done || Other.Done)
293409467b48Spatrick     return (Done == Other.Done);
293509467b48Spatrick   // Not equal if different stack sizes.
293609467b48Spatrick   if (Stack.size() != Other.Stack.size())
293709467b48Spatrick     return false;
293809467b48Spatrick   // Not equal if different cumulative strings.
293909467b48Spatrick   if (!CumulativeString.equals(Other.CumulativeString))
294009467b48Spatrick     return false;
294109467b48Spatrick   // Equal if all nodes in both stacks match.
294209467b48Spatrick   for (unsigned i=0; i < Stack.size(); ++i) {
294309467b48Spatrick     if (Stack[i].Start != Other.Stack[i].Start)
294409467b48Spatrick       return false;
294509467b48Spatrick   }
294609467b48Spatrick   return true;
294709467b48Spatrick }
294809467b48Spatrick 
readULEB128(const uint8_t * & Ptr,const char ** error)294909467b48Spatrick uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
295009467b48Spatrick   unsigned Count;
295109467b48Spatrick   uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
295209467b48Spatrick   Ptr += Count;
295309467b48Spatrick   if (Ptr > Trie.end())
295409467b48Spatrick     Ptr = Trie.end();
295509467b48Spatrick   return Result;
295609467b48Spatrick }
295709467b48Spatrick 
name() const295809467b48Spatrick StringRef ExportEntry::name() const {
295909467b48Spatrick   return CumulativeString;
296009467b48Spatrick }
296109467b48Spatrick 
flags() const296209467b48Spatrick uint64_t ExportEntry::flags() const {
296309467b48Spatrick   return Stack.back().Flags;
296409467b48Spatrick }
296509467b48Spatrick 
address() const296609467b48Spatrick uint64_t ExportEntry::address() const {
296709467b48Spatrick   return Stack.back().Address;
296809467b48Spatrick }
296909467b48Spatrick 
other() const297009467b48Spatrick uint64_t ExportEntry::other() const {
297109467b48Spatrick   return Stack.back().Other;
297209467b48Spatrick }
297309467b48Spatrick 
otherName() const297409467b48Spatrick StringRef ExportEntry::otherName() const {
297509467b48Spatrick   const char* ImportName = Stack.back().ImportName;
297609467b48Spatrick   if (ImportName)
297709467b48Spatrick     return StringRef(ImportName);
297809467b48Spatrick   return StringRef();
297909467b48Spatrick }
298009467b48Spatrick 
nodeOffset() const298109467b48Spatrick uint32_t ExportEntry::nodeOffset() const {
298209467b48Spatrick   return Stack.back().Start - Trie.begin();
298309467b48Spatrick }
298409467b48Spatrick 
NodeState(const uint8_t * Ptr)298509467b48Spatrick ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
298609467b48Spatrick     : Start(Ptr), Current(Ptr) {}
298709467b48Spatrick 
pushNode(uint64_t offset)298809467b48Spatrick void ExportEntry::pushNode(uint64_t offset) {
298909467b48Spatrick   ErrorAsOutParameter ErrAsOutParam(E);
299009467b48Spatrick   const uint8_t *Ptr = Trie.begin() + offset;
299109467b48Spatrick   NodeState State(Ptr);
299209467b48Spatrick   const char *error;
299309467b48Spatrick   uint64_t ExportInfoSize = readULEB128(State.Current, &error);
299409467b48Spatrick   if (error) {
299509467b48Spatrick     *E = malformedError("export info size " + Twine(error) +
299609467b48Spatrick                         " in export trie data at node: 0x" +
299709467b48Spatrick                         Twine::utohexstr(offset));
299809467b48Spatrick     moveToEnd();
299909467b48Spatrick     return;
300009467b48Spatrick   }
300109467b48Spatrick   State.IsExportNode = (ExportInfoSize != 0);
300209467b48Spatrick   const uint8_t* Children = State.Current + ExportInfoSize;
300309467b48Spatrick   if (Children > Trie.end()) {
300409467b48Spatrick     *E = malformedError(
300509467b48Spatrick         "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
300609467b48Spatrick         " in export trie data at node: 0x" + Twine::utohexstr(offset) +
300709467b48Spatrick         " too big and extends past end of trie data");
300809467b48Spatrick     moveToEnd();
300909467b48Spatrick     return;
301009467b48Spatrick   }
301109467b48Spatrick   if (State.IsExportNode) {
301209467b48Spatrick     const uint8_t *ExportStart = State.Current;
301309467b48Spatrick     State.Flags = readULEB128(State.Current, &error);
301409467b48Spatrick     if (error) {
301509467b48Spatrick       *E = malformedError("flags " + Twine(error) +
301609467b48Spatrick                           " in export trie data at node: 0x" +
301709467b48Spatrick                           Twine::utohexstr(offset));
301809467b48Spatrick       moveToEnd();
301909467b48Spatrick       return;
302009467b48Spatrick     }
302109467b48Spatrick     uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
302209467b48Spatrick     if (State.Flags != 0 &&
302309467b48Spatrick         (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
302409467b48Spatrick          Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
302509467b48Spatrick          Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
302609467b48Spatrick       *E = malformedError(
302709467b48Spatrick           "unsupported exported symbol kind: " + Twine((int)Kind) +
302809467b48Spatrick           " in flags: 0x" + Twine::utohexstr(State.Flags) +
302909467b48Spatrick           " in export trie data at node: 0x" + Twine::utohexstr(offset));
303009467b48Spatrick       moveToEnd();
303109467b48Spatrick       return;
303209467b48Spatrick     }
303309467b48Spatrick     if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
303409467b48Spatrick       State.Address = 0;
303509467b48Spatrick       State.Other = readULEB128(State.Current, &error); // dylib ordinal
303609467b48Spatrick       if (error) {
303709467b48Spatrick         *E = malformedError("dylib ordinal of re-export " + Twine(error) +
303809467b48Spatrick                             " in export trie data at node: 0x" +
303909467b48Spatrick                             Twine::utohexstr(offset));
304009467b48Spatrick         moveToEnd();
304109467b48Spatrick         return;
304209467b48Spatrick       }
304309467b48Spatrick       if (O != nullptr) {
3044*d415bd75Srobert         // Only positive numbers represent library ordinals. Zero and negative
3045*d415bd75Srobert         // numbers have special meaning (see BindSpecialDylib).
3046*d415bd75Srobert         if ((int64_t)State.Other > 0 && State.Other > O->getLibraryCount()) {
304709467b48Spatrick           *E = malformedError(
304809467b48Spatrick               "bad library ordinal: " + Twine((int)State.Other) + " (max " +
304909467b48Spatrick               Twine((int)O->getLibraryCount()) +
305009467b48Spatrick               ") in export trie data at node: 0x" + Twine::utohexstr(offset));
305109467b48Spatrick           moveToEnd();
305209467b48Spatrick           return;
305309467b48Spatrick         }
305409467b48Spatrick       }
305509467b48Spatrick       State.ImportName = reinterpret_cast<const char*>(State.Current);
305609467b48Spatrick       if (*State.ImportName == '\0') {
305709467b48Spatrick         State.Current++;
305809467b48Spatrick       } else {
305909467b48Spatrick         const uint8_t *End = State.Current + 1;
306009467b48Spatrick         if (End >= Trie.end()) {
306109467b48Spatrick           *E = malformedError("import name of re-export in export trie data at "
306209467b48Spatrick                               "node: 0x" +
306309467b48Spatrick                               Twine::utohexstr(offset) +
306409467b48Spatrick                               " starts past end of trie data");
306509467b48Spatrick           moveToEnd();
306609467b48Spatrick           return;
306709467b48Spatrick         }
306809467b48Spatrick         while(*End != '\0' && End < Trie.end())
306909467b48Spatrick           End++;
307009467b48Spatrick         if (*End != '\0') {
307109467b48Spatrick           *E = malformedError("import name of re-export in export trie data at "
307209467b48Spatrick                               "node: 0x" +
307309467b48Spatrick                               Twine::utohexstr(offset) +
307409467b48Spatrick                               " extends past end of trie data");
307509467b48Spatrick           moveToEnd();
307609467b48Spatrick           return;
307709467b48Spatrick         }
307809467b48Spatrick         State.Current = End + 1;
307909467b48Spatrick       }
308009467b48Spatrick     } else {
308109467b48Spatrick       State.Address = readULEB128(State.Current, &error);
308209467b48Spatrick       if (error) {
308309467b48Spatrick         *E = malformedError("address " + Twine(error) +
308409467b48Spatrick                             " in export trie data at node: 0x" +
308509467b48Spatrick                             Twine::utohexstr(offset));
308609467b48Spatrick         moveToEnd();
308709467b48Spatrick         return;
308809467b48Spatrick       }
308909467b48Spatrick       if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
309009467b48Spatrick         State.Other = readULEB128(State.Current, &error);
309109467b48Spatrick         if (error) {
309209467b48Spatrick           *E = malformedError("resolver of stub and resolver " + Twine(error) +
309309467b48Spatrick                               " in export trie data at node: 0x" +
309409467b48Spatrick                               Twine::utohexstr(offset));
309509467b48Spatrick           moveToEnd();
309609467b48Spatrick           return;
309709467b48Spatrick         }
309809467b48Spatrick       }
309909467b48Spatrick     }
310009467b48Spatrick     if(ExportStart + ExportInfoSize != State.Current) {
310109467b48Spatrick       *E = malformedError(
3102*d415bd75Srobert           "inconsistent export info size: 0x" +
310309467b48Spatrick           Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
310409467b48Spatrick           Twine::utohexstr(State.Current - ExportStart) +
310509467b48Spatrick           " in export trie data at node: 0x" + Twine::utohexstr(offset));
310609467b48Spatrick       moveToEnd();
310709467b48Spatrick       return;
310809467b48Spatrick     }
310909467b48Spatrick   }
311009467b48Spatrick   State.ChildCount = *Children;
311109467b48Spatrick   if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
311209467b48Spatrick     *E = malformedError("byte for count of childern in export trie data at "
311309467b48Spatrick                         "node: 0x" +
311409467b48Spatrick                         Twine::utohexstr(offset) +
311509467b48Spatrick                         " extends past end of trie data");
311609467b48Spatrick     moveToEnd();
311709467b48Spatrick     return;
311809467b48Spatrick   }
311909467b48Spatrick   State.Current = Children + 1;
312009467b48Spatrick   State.NextChildIndex = 0;
312109467b48Spatrick   State.ParentStringLength = CumulativeString.size();
312209467b48Spatrick   Stack.push_back(State);
312309467b48Spatrick }
312409467b48Spatrick 
pushDownUntilBottom()312509467b48Spatrick void ExportEntry::pushDownUntilBottom() {
312609467b48Spatrick   ErrorAsOutParameter ErrAsOutParam(E);
312709467b48Spatrick   const char *error;
312809467b48Spatrick   while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
312909467b48Spatrick     NodeState &Top = Stack.back();
313009467b48Spatrick     CumulativeString.resize(Top.ParentStringLength);
313109467b48Spatrick     for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
313209467b48Spatrick       char C = *Top.Current;
313309467b48Spatrick       CumulativeString.push_back(C);
313409467b48Spatrick     }
313509467b48Spatrick     if (Top.Current >= Trie.end()) {
313609467b48Spatrick       *E = malformedError("edge sub-string in export trie data at node: 0x" +
313709467b48Spatrick                           Twine::utohexstr(Top.Start - Trie.begin()) +
313809467b48Spatrick                           " for child #" + Twine((int)Top.NextChildIndex) +
313909467b48Spatrick                           " extends past end of trie data");
314009467b48Spatrick       moveToEnd();
314109467b48Spatrick       return;
314209467b48Spatrick     }
314309467b48Spatrick     Top.Current += 1;
314409467b48Spatrick     uint64_t childNodeIndex = readULEB128(Top.Current, &error);
314509467b48Spatrick     if (error) {
314609467b48Spatrick       *E = malformedError("child node offset " + Twine(error) +
314709467b48Spatrick                           " in export trie data at node: 0x" +
314809467b48Spatrick                           Twine::utohexstr(Top.Start - Trie.begin()));
314909467b48Spatrick       moveToEnd();
315009467b48Spatrick       return;
315109467b48Spatrick     }
315209467b48Spatrick     for (const NodeState &node : nodes()) {
315309467b48Spatrick       if (node.Start == Trie.begin() + childNodeIndex){
315409467b48Spatrick         *E = malformedError("loop in childern in export trie data at node: 0x" +
315509467b48Spatrick                             Twine::utohexstr(Top.Start - Trie.begin()) +
315609467b48Spatrick                             " back to node: 0x" +
315709467b48Spatrick                             Twine::utohexstr(childNodeIndex));
315809467b48Spatrick         moveToEnd();
315909467b48Spatrick         return;
316009467b48Spatrick       }
316109467b48Spatrick     }
316209467b48Spatrick     Top.NextChildIndex += 1;
316309467b48Spatrick     pushNode(childNodeIndex);
316409467b48Spatrick     if (*E)
316509467b48Spatrick       return;
316609467b48Spatrick   }
316709467b48Spatrick   if (!Stack.back().IsExportNode) {
316809467b48Spatrick     *E = malformedError("node is not an export node in export trie data at "
316909467b48Spatrick                         "node: 0x" +
317009467b48Spatrick                         Twine::utohexstr(Stack.back().Start - Trie.begin()));
317109467b48Spatrick     moveToEnd();
317209467b48Spatrick     return;
317309467b48Spatrick   }
317409467b48Spatrick }
317509467b48Spatrick 
317609467b48Spatrick // We have a trie data structure and need a way to walk it that is compatible
317709467b48Spatrick // with the C++ iterator model. The solution is a non-recursive depth first
317809467b48Spatrick // traversal where the iterator contains a stack of parent nodes along with a
317909467b48Spatrick // string that is the accumulation of all edge strings along the parent chain
318009467b48Spatrick // to this point.
318109467b48Spatrick //
318209467b48Spatrick // There is one "export" node for each exported symbol.  But because some
318309467b48Spatrick // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
318409467b48Spatrick // node may have child nodes too.
318509467b48Spatrick //
318609467b48Spatrick // The algorithm for moveNext() is to keep moving down the leftmost unvisited
318709467b48Spatrick // child until hitting a node with no children (which is an export node or
318809467b48Spatrick // else the trie is malformed). On the way down, each node is pushed on the
318909467b48Spatrick // stack ivar.  If there is no more ways down, it pops up one and tries to go
319009467b48Spatrick // down a sibling path until a childless node is reached.
moveNext()319109467b48Spatrick void ExportEntry::moveNext() {
319209467b48Spatrick   assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
319309467b48Spatrick   if (!Stack.back().IsExportNode) {
319409467b48Spatrick     *E = malformedError("node is not an export node in export trie data at "
319509467b48Spatrick                         "node: 0x" +
319609467b48Spatrick                         Twine::utohexstr(Stack.back().Start - Trie.begin()));
319709467b48Spatrick     moveToEnd();
319809467b48Spatrick     return;
319909467b48Spatrick   }
320009467b48Spatrick 
320109467b48Spatrick   Stack.pop_back();
320209467b48Spatrick   while (!Stack.empty()) {
320309467b48Spatrick     NodeState &Top = Stack.back();
320409467b48Spatrick     if (Top.NextChildIndex < Top.ChildCount) {
320509467b48Spatrick       pushDownUntilBottom();
320609467b48Spatrick       // Now at the next export node.
320709467b48Spatrick       return;
320809467b48Spatrick     } else {
320909467b48Spatrick       if (Top.IsExportNode) {
321009467b48Spatrick         // This node has no children but is itself an export node.
321109467b48Spatrick         CumulativeString.resize(Top.ParentStringLength);
321209467b48Spatrick         return;
321309467b48Spatrick       }
321409467b48Spatrick       Stack.pop_back();
321509467b48Spatrick     }
321609467b48Spatrick   }
321709467b48Spatrick   Done = true;
321809467b48Spatrick }
321909467b48Spatrick 
322009467b48Spatrick iterator_range<export_iterator>
exports(Error & E,ArrayRef<uint8_t> Trie,const MachOObjectFile * O)322109467b48Spatrick MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
322209467b48Spatrick                          const MachOObjectFile *O) {
322309467b48Spatrick   ExportEntry Start(&E, O, Trie);
322409467b48Spatrick   if (Trie.empty())
322509467b48Spatrick     Start.moveToEnd();
322609467b48Spatrick   else
322709467b48Spatrick     Start.moveToFirst();
322809467b48Spatrick 
322909467b48Spatrick   ExportEntry Finish(&E, O, Trie);
323009467b48Spatrick   Finish.moveToEnd();
323109467b48Spatrick 
323209467b48Spatrick   return make_range(export_iterator(Start), export_iterator(Finish));
323309467b48Spatrick }
323409467b48Spatrick 
exports(Error & Err) const323509467b48Spatrick iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3236*d415bd75Srobert   ArrayRef<uint8_t> Trie;
3237*d415bd75Srobert   if (DyldInfoLoadCmd)
3238*d415bd75Srobert     Trie = getDyldInfoExportsTrie();
3239*d415bd75Srobert   else if (DyldExportsTrieLoadCmd)
3240*d415bd75Srobert     Trie = getDyldExportsTrie();
3241*d415bd75Srobert 
3242*d415bd75Srobert   return exports(Err, Trie, this);
3243*d415bd75Srobert }
3244*d415bd75Srobert 
MachOAbstractFixupEntry(Error * E,const MachOObjectFile * O)3245*d415bd75Srobert MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error *E,
3246*d415bd75Srobert                                                  const MachOObjectFile *O)
3247*d415bd75Srobert     : E(E), O(O) {
3248*d415bd75Srobert   // Cache the vmaddress of __TEXT
3249*d415bd75Srobert   for (const auto &Command : O->load_commands()) {
3250*d415bd75Srobert     if (Command.C.cmd == MachO::LC_SEGMENT) {
3251*d415bd75Srobert       MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
3252*d415bd75Srobert       if (StringRef(SLC.segname) == StringRef("__TEXT")) {
3253*d415bd75Srobert         TextAddress = SLC.vmaddr;
3254*d415bd75Srobert         break;
3255*d415bd75Srobert       }
3256*d415bd75Srobert     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
3257*d415bd75Srobert       MachO::segment_command_64 SLC_64 = O->getSegment64LoadCommand(Command);
3258*d415bd75Srobert       if (StringRef(SLC_64.segname) == StringRef("__TEXT")) {
3259*d415bd75Srobert         TextAddress = SLC_64.vmaddr;
3260*d415bd75Srobert         break;
3261*d415bd75Srobert       }
3262*d415bd75Srobert     }
3263*d415bd75Srobert   }
3264*d415bd75Srobert }
3265*d415bd75Srobert 
segmentIndex() const3266*d415bd75Srobert int32_t MachOAbstractFixupEntry::segmentIndex() const { return SegmentIndex; }
3267*d415bd75Srobert 
segmentOffset() const3268*d415bd75Srobert uint64_t MachOAbstractFixupEntry::segmentOffset() const {
3269*d415bd75Srobert   return SegmentOffset;
3270*d415bd75Srobert }
3271*d415bd75Srobert 
segmentAddress() const3272*d415bd75Srobert uint64_t MachOAbstractFixupEntry::segmentAddress() const {
3273*d415bd75Srobert   return O->BindRebaseAddress(SegmentIndex, 0);
3274*d415bd75Srobert }
3275*d415bd75Srobert 
segmentName() const3276*d415bd75Srobert StringRef MachOAbstractFixupEntry::segmentName() const {
3277*d415bd75Srobert   return O->BindRebaseSegmentName(SegmentIndex);
3278*d415bd75Srobert }
3279*d415bd75Srobert 
sectionName() const3280*d415bd75Srobert StringRef MachOAbstractFixupEntry::sectionName() const {
3281*d415bd75Srobert   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3282*d415bd75Srobert }
3283*d415bd75Srobert 
address() const3284*d415bd75Srobert uint64_t MachOAbstractFixupEntry::address() const {
3285*d415bd75Srobert   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3286*d415bd75Srobert }
3287*d415bd75Srobert 
symbolName() const3288*d415bd75Srobert StringRef MachOAbstractFixupEntry::symbolName() const { return SymbolName; }
3289*d415bd75Srobert 
addend() const3290*d415bd75Srobert int64_t MachOAbstractFixupEntry::addend() const { return Addend; }
3291*d415bd75Srobert 
flags() const3292*d415bd75Srobert uint32_t MachOAbstractFixupEntry::flags() const { return Flags; }
3293*d415bd75Srobert 
ordinal() const3294*d415bd75Srobert int MachOAbstractFixupEntry::ordinal() const { return Ordinal; }
3295*d415bd75Srobert 
typeName() const3296*d415bd75Srobert StringRef MachOAbstractFixupEntry::typeName() const { return "unknown"; }
3297*d415bd75Srobert 
moveToFirst()3298*d415bd75Srobert void MachOAbstractFixupEntry::moveToFirst() {
3299*d415bd75Srobert   SegmentOffset = 0;
3300*d415bd75Srobert   SegmentIndex = -1;
3301*d415bd75Srobert   Ordinal = 0;
3302*d415bd75Srobert   Flags = 0;
3303*d415bd75Srobert   Addend = 0;
3304*d415bd75Srobert   Done = false;
3305*d415bd75Srobert }
3306*d415bd75Srobert 
moveToEnd()3307*d415bd75Srobert void MachOAbstractFixupEntry::moveToEnd() { Done = true; }
3308*d415bd75Srobert 
moveNext()3309*d415bd75Srobert void MachOAbstractFixupEntry::moveNext() {}
3310*d415bd75Srobert 
MachOChainedFixupEntry(Error * E,const MachOObjectFile * O,bool Parse)3311*d415bd75Srobert MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E,
3312*d415bd75Srobert                                                const MachOObjectFile *O,
3313*d415bd75Srobert                                                bool Parse)
3314*d415bd75Srobert     : MachOAbstractFixupEntry(E, O) {
3315*d415bd75Srobert   ErrorAsOutParameter e(E);
3316*d415bd75Srobert   if (!Parse)
3317*d415bd75Srobert     return;
3318*d415bd75Srobert 
3319*d415bd75Srobert   if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) {
3320*d415bd75Srobert     FixupTargets = *FixupTargetsOrErr;
3321*d415bd75Srobert   } else {
3322*d415bd75Srobert     *E = FixupTargetsOrErr.takeError();
3323*d415bd75Srobert     return;
3324*d415bd75Srobert   }
3325*d415bd75Srobert 
3326*d415bd75Srobert   if (auto SegmentsOrErr = O->getChainedFixupsSegments()) {
3327*d415bd75Srobert     Segments = std::move(SegmentsOrErr->second);
3328*d415bd75Srobert   } else {
3329*d415bd75Srobert     *E = SegmentsOrErr.takeError();
3330*d415bd75Srobert     return;
3331*d415bd75Srobert   }
3332*d415bd75Srobert }
3333*d415bd75Srobert 
findNextPageWithFixups()3334*d415bd75Srobert void MachOChainedFixupEntry::findNextPageWithFixups() {
3335*d415bd75Srobert   auto FindInSegment = [this]() {
3336*d415bd75Srobert     const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];
3337*d415bd75Srobert     while (PageIndex < SegInfo.PageStarts.size() &&
3338*d415bd75Srobert            SegInfo.PageStarts[PageIndex] == MachO::DYLD_CHAINED_PTR_START_NONE)
3339*d415bd75Srobert       ++PageIndex;
3340*d415bd75Srobert     return PageIndex < SegInfo.PageStarts.size();
3341*d415bd75Srobert   };
3342*d415bd75Srobert 
3343*d415bd75Srobert   while (InfoSegIndex < Segments.size()) {
3344*d415bd75Srobert     if (FindInSegment()) {
3345*d415bd75Srobert       PageOffset = Segments[InfoSegIndex].PageStarts[PageIndex];
3346*d415bd75Srobert       SegmentData = O->getSegmentContents(Segments[InfoSegIndex].SegIdx);
3347*d415bd75Srobert       return;
3348*d415bd75Srobert     }
3349*d415bd75Srobert 
3350*d415bd75Srobert     InfoSegIndex++;
3351*d415bd75Srobert     PageIndex = 0;
3352*d415bd75Srobert   }
3353*d415bd75Srobert }
3354*d415bd75Srobert 
moveToFirst()3355*d415bd75Srobert void MachOChainedFixupEntry::moveToFirst() {
3356*d415bd75Srobert   MachOAbstractFixupEntry::moveToFirst();
3357*d415bd75Srobert   if (Segments.empty()) {
3358*d415bd75Srobert     Done = true;
3359*d415bd75Srobert     return;
3360*d415bd75Srobert   }
3361*d415bd75Srobert 
3362*d415bd75Srobert   InfoSegIndex = 0;
3363*d415bd75Srobert   PageIndex = 0;
3364*d415bd75Srobert 
3365*d415bd75Srobert   findNextPageWithFixups();
3366*d415bd75Srobert   moveNext();
3367*d415bd75Srobert }
3368*d415bd75Srobert 
moveToEnd()3369*d415bd75Srobert void MachOChainedFixupEntry::moveToEnd() {
3370*d415bd75Srobert   MachOAbstractFixupEntry::moveToEnd();
3371*d415bd75Srobert }
3372*d415bd75Srobert 
moveNext()3373*d415bd75Srobert void MachOChainedFixupEntry::moveNext() {
3374*d415bd75Srobert   ErrorAsOutParameter ErrAsOutParam(E);
3375*d415bd75Srobert 
3376*d415bd75Srobert   if (InfoSegIndex == Segments.size()) {
3377*d415bd75Srobert     Done = true;
3378*d415bd75Srobert     return;
3379*d415bd75Srobert   }
3380*d415bd75Srobert 
3381*d415bd75Srobert   const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];
3382*d415bd75Srobert   SegmentIndex = SegInfo.SegIdx;
3383*d415bd75Srobert   SegmentOffset = SegInfo.Header.page_size * PageIndex + PageOffset;
3384*d415bd75Srobert 
3385*d415bd75Srobert   // FIXME: Handle other pointer formats.
3386*d415bd75Srobert   uint16_t PointerFormat = SegInfo.Header.pointer_format;
3387*d415bd75Srobert   if (PointerFormat != MachO::DYLD_CHAINED_PTR_64 &&
3388*d415bd75Srobert       PointerFormat != MachO::DYLD_CHAINED_PTR_64_OFFSET) {
3389*d415bd75Srobert     *E = createError("segment " + Twine(SegmentIndex) +
3390*d415bd75Srobert                      " has unsupported chained fixup pointer_format " +
3391*d415bd75Srobert                      Twine(PointerFormat));
3392*d415bd75Srobert     moveToEnd();
3393*d415bd75Srobert     return;
3394*d415bd75Srobert   }
3395*d415bd75Srobert 
3396*d415bd75Srobert   Ordinal = 0;
3397*d415bd75Srobert   Flags = 0;
3398*d415bd75Srobert   Addend = 0;
3399*d415bd75Srobert   PointerValue = 0;
3400*d415bd75Srobert   SymbolName = {};
3401*d415bd75Srobert 
3402*d415bd75Srobert   if (SegmentOffset + sizeof(RawValue) > SegmentData.size()) {
3403*d415bd75Srobert     *E = malformedError("fixup in segment " + Twine(SegmentIndex) +
3404*d415bd75Srobert                         " at offset " + Twine(SegmentOffset) +
3405*d415bd75Srobert                         " extends past segment's end");
3406*d415bd75Srobert     moveToEnd();
3407*d415bd75Srobert     return;
3408*d415bd75Srobert   }
3409*d415bd75Srobert 
3410*d415bd75Srobert   static_assert(sizeof(RawValue) == sizeof(MachO::dyld_chained_import_addend));
3411*d415bd75Srobert   memcpy(&RawValue, SegmentData.data() + SegmentOffset, sizeof(RawValue));
3412*d415bd75Srobert   if (O->isLittleEndian() != sys::IsLittleEndianHost)
3413*d415bd75Srobert     sys::swapByteOrder(RawValue);
3414*d415bd75Srobert 
3415*d415bd75Srobert   // The bit extraction below assumes little-endian fixup entries.
3416*d415bd75Srobert   assert(O->isLittleEndian() && "big-endian object should have been rejected "
3417*d415bd75Srobert                                 "by getDyldChainedFixupTargets()");
3418*d415bd75Srobert   auto Field = [this](uint8_t Right, uint8_t Count) {
3419*d415bd75Srobert     return (RawValue >> Right) & ((1ULL << Count) - 1);
3420*d415bd75Srobert   };
3421*d415bd75Srobert 
3422*d415bd75Srobert   // The `bind` field (most significant bit) of the encoded fixup determines
3423*d415bd75Srobert   // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
3424*d415bd75Srobert   bool IsBind = Field(63, 1);
3425*d415bd75Srobert   Kind = IsBind ? FixupKind::Bind : FixupKind::Rebase;
3426*d415bd75Srobert   uint32_t Next = Field(51, 12);
3427*d415bd75Srobert   if (IsBind) {
3428*d415bd75Srobert     uint32_t ImportOrdinal = Field(0, 24);
3429*d415bd75Srobert     uint8_t InlineAddend = Field(24, 8);
3430*d415bd75Srobert 
3431*d415bd75Srobert     if (ImportOrdinal >= FixupTargets.size()) {
3432*d415bd75Srobert       *E = malformedError("fixup in segment " + Twine(SegmentIndex) +
3433*d415bd75Srobert                           " at offset " + Twine(SegmentOffset) +
3434*d415bd75Srobert                           "  has out-of range import ordinal " +
3435*d415bd75Srobert                           Twine(ImportOrdinal));
3436*d415bd75Srobert       moveToEnd();
3437*d415bd75Srobert       return;
3438*d415bd75Srobert     }
3439*d415bd75Srobert 
3440*d415bd75Srobert     ChainedFixupTarget &Target = FixupTargets[ImportOrdinal];
3441*d415bd75Srobert     Ordinal = Target.libOrdinal();
3442*d415bd75Srobert     Addend = InlineAddend ? InlineAddend : Target.addend();
3443*d415bd75Srobert     Flags = Target.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0;
3444*d415bd75Srobert     SymbolName = Target.symbolName();
3445*d415bd75Srobert   } else {
3446*d415bd75Srobert     uint64_t Target = Field(0, 36);
3447*d415bd75Srobert     uint64_t High8 = Field(36, 8);
3448*d415bd75Srobert 
3449*d415bd75Srobert     PointerValue = Target | (High8 << 56);
3450*d415bd75Srobert     if (PointerFormat == MachO::DYLD_CHAINED_PTR_64_OFFSET)
3451*d415bd75Srobert       PointerValue += textAddress();
3452*d415bd75Srobert   }
3453*d415bd75Srobert 
3454*d415bd75Srobert   // The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET).
3455*d415bd75Srobert   if (Next != 0) {
3456*d415bd75Srobert     PageOffset += 4 * Next;
3457*d415bd75Srobert   } else {
3458*d415bd75Srobert     ++PageIndex;
3459*d415bd75Srobert     findNextPageWithFixups();
3460*d415bd75Srobert   }
3461*d415bd75Srobert }
3462*d415bd75Srobert 
operator ==(const MachOChainedFixupEntry & Other) const3463*d415bd75Srobert bool MachOChainedFixupEntry::operator==(
3464*d415bd75Srobert     const MachOChainedFixupEntry &Other) const {
3465*d415bd75Srobert   if (Done && Other.Done)
3466*d415bd75Srobert     return true;
3467*d415bd75Srobert   if (Done != Other.Done)
3468*d415bd75Srobert     return false;
3469*d415bd75Srobert   return InfoSegIndex == Other.InfoSegIndex && PageIndex == Other.PageIndex &&
3470*d415bd75Srobert          PageOffset == Other.PageOffset;
347109467b48Spatrick }
347209467b48Spatrick 
MachORebaseEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit)347309467b48Spatrick MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
347409467b48Spatrick                                    ArrayRef<uint8_t> Bytes, bool is64Bit)
347509467b48Spatrick     : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
347609467b48Spatrick       PointerSize(is64Bit ? 8 : 4) {}
347709467b48Spatrick 
moveToFirst()347809467b48Spatrick void MachORebaseEntry::moveToFirst() {
347909467b48Spatrick   Ptr = Opcodes.begin();
348009467b48Spatrick   moveNext();
348109467b48Spatrick }
348209467b48Spatrick 
moveToEnd()348309467b48Spatrick void MachORebaseEntry::moveToEnd() {
348409467b48Spatrick   Ptr = Opcodes.end();
348509467b48Spatrick   RemainingLoopCount = 0;
348609467b48Spatrick   Done = true;
348709467b48Spatrick }
348809467b48Spatrick 
moveNext()348909467b48Spatrick void MachORebaseEntry::moveNext() {
349009467b48Spatrick   ErrorAsOutParameter ErrAsOutParam(E);
349109467b48Spatrick   // If in the middle of some loop, move to next rebasing in loop.
349209467b48Spatrick   SegmentOffset += AdvanceAmount;
349309467b48Spatrick   if (RemainingLoopCount) {
349409467b48Spatrick     --RemainingLoopCount;
349509467b48Spatrick     return;
349609467b48Spatrick   }
349709467b48Spatrick   // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
349809467b48Spatrick   // pointer size. Therefore it is possible to reach the end without ever having
349909467b48Spatrick   // seen REBASE_OPCODE_DONE.
350009467b48Spatrick   if (Ptr == Opcodes.end()) {
350109467b48Spatrick     Done = true;
350209467b48Spatrick     return;
350309467b48Spatrick   }
350409467b48Spatrick   bool More = true;
350509467b48Spatrick   while (More) {
350609467b48Spatrick     // Parse next opcode and set up next loop.
350709467b48Spatrick     const uint8_t *OpcodeStart = Ptr;
350809467b48Spatrick     uint8_t Byte = *Ptr++;
350909467b48Spatrick     uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
351009467b48Spatrick     uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
351109467b48Spatrick     uint32_t Count, Skip;
351209467b48Spatrick     const char *error = nullptr;
351309467b48Spatrick     switch (Opcode) {
351409467b48Spatrick     case MachO::REBASE_OPCODE_DONE:
351509467b48Spatrick       More = false;
351609467b48Spatrick       Done = true;
351709467b48Spatrick       moveToEnd();
351809467b48Spatrick       DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
351909467b48Spatrick       break;
352009467b48Spatrick     case MachO::REBASE_OPCODE_SET_TYPE_IMM:
352109467b48Spatrick       RebaseType = ImmValue;
352209467b48Spatrick       if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
352309467b48Spatrick         *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
352409467b48Spatrick                             Twine((int)RebaseType) + " for opcode at: 0x" +
352509467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
352609467b48Spatrick         moveToEnd();
352709467b48Spatrick         return;
352809467b48Spatrick       }
352909467b48Spatrick       DEBUG_WITH_TYPE(
353009467b48Spatrick           "mach-o-rebase",
353109467b48Spatrick           dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
353209467b48Spatrick                  << "RebaseType=" << (int) RebaseType << "\n");
353309467b48Spatrick       break;
353409467b48Spatrick     case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
353509467b48Spatrick       SegmentIndex = ImmValue;
353609467b48Spatrick       SegmentOffset = readULEB128(&error);
353709467b48Spatrick       if (error) {
353809467b48Spatrick         *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
353909467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
354009467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
354109467b48Spatrick         moveToEnd();
354209467b48Spatrick         return;
354309467b48Spatrick       }
354409467b48Spatrick       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
354509467b48Spatrick                                                PointerSize);
354609467b48Spatrick       if (error) {
354709467b48Spatrick         *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
354809467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
354909467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
355009467b48Spatrick         moveToEnd();
355109467b48Spatrick         return;
355209467b48Spatrick       }
355309467b48Spatrick       DEBUG_WITH_TYPE(
355409467b48Spatrick           "mach-o-rebase",
355509467b48Spatrick           dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
355609467b48Spatrick                  << "SegmentIndex=" << SegmentIndex << ", "
355709467b48Spatrick                  << format("SegmentOffset=0x%06X", SegmentOffset)
355809467b48Spatrick                  << "\n");
355909467b48Spatrick       break;
356009467b48Spatrick     case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
356109467b48Spatrick       SegmentOffset += readULEB128(&error);
356209467b48Spatrick       if (error) {
356309467b48Spatrick         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
356409467b48Spatrick                             " for opcode at: 0x" +
356509467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
356609467b48Spatrick         moveToEnd();
356709467b48Spatrick         return;
356809467b48Spatrick       }
356909467b48Spatrick       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
357009467b48Spatrick                                                PointerSize);
357109467b48Spatrick       if (error) {
357209467b48Spatrick         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
357309467b48Spatrick                             " for opcode at: 0x" +
357409467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
357509467b48Spatrick         moveToEnd();
357609467b48Spatrick         return;
357709467b48Spatrick       }
357809467b48Spatrick       DEBUG_WITH_TYPE("mach-o-rebase",
357909467b48Spatrick                       dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
358009467b48Spatrick                              << format("SegmentOffset=0x%06X",
358109467b48Spatrick                                        SegmentOffset) << "\n");
358209467b48Spatrick       break;
358309467b48Spatrick     case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
358409467b48Spatrick       SegmentOffset += ImmValue * PointerSize;
358509467b48Spatrick       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
358609467b48Spatrick                                                PointerSize);
358709467b48Spatrick       if (error) {
3588097a140dSpatrick         *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
358909467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
359009467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
359109467b48Spatrick         moveToEnd();
359209467b48Spatrick         return;
359309467b48Spatrick       }
359409467b48Spatrick       DEBUG_WITH_TYPE("mach-o-rebase",
359509467b48Spatrick                       dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
359609467b48Spatrick                              << format("SegmentOffset=0x%06X",
359709467b48Spatrick                                        SegmentOffset) << "\n");
359809467b48Spatrick       break;
359909467b48Spatrick     case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
360009467b48Spatrick       AdvanceAmount = PointerSize;
360109467b48Spatrick       Skip = 0;
360209467b48Spatrick       Count = ImmValue;
360309467b48Spatrick       if (ImmValue != 0)
360409467b48Spatrick         RemainingLoopCount = ImmValue - 1;
360509467b48Spatrick       else
360609467b48Spatrick         RemainingLoopCount = 0;
360709467b48Spatrick       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
360809467b48Spatrick                                                PointerSize, Count, Skip);
360909467b48Spatrick       if (error) {
361009467b48Spatrick         *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
361109467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
361209467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
361309467b48Spatrick         moveToEnd();
361409467b48Spatrick         return;
361509467b48Spatrick       }
361609467b48Spatrick       DEBUG_WITH_TYPE(
361709467b48Spatrick           "mach-o-rebase",
361809467b48Spatrick           dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
361909467b48Spatrick                  << format("SegmentOffset=0x%06X", SegmentOffset)
362009467b48Spatrick                  << ", AdvanceAmount=" << AdvanceAmount
362109467b48Spatrick                  << ", RemainingLoopCount=" << RemainingLoopCount
362209467b48Spatrick                  << "\n");
362309467b48Spatrick       return;
362409467b48Spatrick     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
362509467b48Spatrick       AdvanceAmount = PointerSize;
362609467b48Spatrick       Skip = 0;
362709467b48Spatrick       Count = readULEB128(&error);
362809467b48Spatrick       if (error) {
362909467b48Spatrick         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
363009467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
363109467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
363209467b48Spatrick         moveToEnd();
363309467b48Spatrick         return;
363409467b48Spatrick       }
363509467b48Spatrick       if (Count != 0)
363609467b48Spatrick         RemainingLoopCount = Count - 1;
363709467b48Spatrick       else
363809467b48Spatrick         RemainingLoopCount = 0;
363909467b48Spatrick       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
364009467b48Spatrick                                                PointerSize, Count, Skip);
364109467b48Spatrick       if (error) {
364209467b48Spatrick         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
364309467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
364409467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
364509467b48Spatrick         moveToEnd();
364609467b48Spatrick         return;
364709467b48Spatrick       }
364809467b48Spatrick       DEBUG_WITH_TYPE(
364909467b48Spatrick           "mach-o-rebase",
365009467b48Spatrick           dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
365109467b48Spatrick                  << format("SegmentOffset=0x%06X", SegmentOffset)
365209467b48Spatrick                  << ", AdvanceAmount=" << AdvanceAmount
365309467b48Spatrick                  << ", RemainingLoopCount=" << RemainingLoopCount
365409467b48Spatrick                  << "\n");
365509467b48Spatrick       return;
365609467b48Spatrick     case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
365709467b48Spatrick       Skip = readULEB128(&error);
365809467b48Spatrick       if (error) {
365909467b48Spatrick         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
366009467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
366109467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
366209467b48Spatrick         moveToEnd();
366309467b48Spatrick         return;
366409467b48Spatrick       }
366509467b48Spatrick       AdvanceAmount = Skip + PointerSize;
366609467b48Spatrick       Count = 1;
366709467b48Spatrick       RemainingLoopCount = 0;
366809467b48Spatrick       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
366909467b48Spatrick                                                PointerSize, Count, Skip);
367009467b48Spatrick       if (error) {
367109467b48Spatrick         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
367209467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
367309467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
367409467b48Spatrick         moveToEnd();
367509467b48Spatrick         return;
367609467b48Spatrick       }
367709467b48Spatrick       DEBUG_WITH_TYPE(
367809467b48Spatrick           "mach-o-rebase",
367909467b48Spatrick           dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
368009467b48Spatrick                  << format("SegmentOffset=0x%06X", SegmentOffset)
368109467b48Spatrick                  << ", AdvanceAmount=" << AdvanceAmount
368209467b48Spatrick                  << ", RemainingLoopCount=" << RemainingLoopCount
368309467b48Spatrick                  << "\n");
368409467b48Spatrick       return;
368509467b48Spatrick     case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
368609467b48Spatrick       Count = readULEB128(&error);
368709467b48Spatrick       if (error) {
368809467b48Spatrick         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
368909467b48Spatrick                             "ULEB " +
369009467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
369109467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
369209467b48Spatrick         moveToEnd();
369309467b48Spatrick         return;
369409467b48Spatrick       }
369509467b48Spatrick       if (Count != 0)
369609467b48Spatrick         RemainingLoopCount = Count - 1;
369709467b48Spatrick       else
369809467b48Spatrick         RemainingLoopCount = 0;
369909467b48Spatrick       Skip = readULEB128(&error);
370009467b48Spatrick       if (error) {
370109467b48Spatrick         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
370209467b48Spatrick                             "ULEB " +
370309467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
370409467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
370509467b48Spatrick         moveToEnd();
370609467b48Spatrick         return;
370709467b48Spatrick       }
370809467b48Spatrick       AdvanceAmount = Skip + PointerSize;
370909467b48Spatrick 
371009467b48Spatrick       error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
371109467b48Spatrick                                                PointerSize, Count, Skip);
371209467b48Spatrick       if (error) {
371309467b48Spatrick         *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
371409467b48Spatrick                             "ULEB " +
371509467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
371609467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
371709467b48Spatrick         moveToEnd();
371809467b48Spatrick         return;
371909467b48Spatrick       }
372009467b48Spatrick       DEBUG_WITH_TYPE(
372109467b48Spatrick           "mach-o-rebase",
372209467b48Spatrick           dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
372309467b48Spatrick                  << format("SegmentOffset=0x%06X", SegmentOffset)
372409467b48Spatrick                  << ", AdvanceAmount=" << AdvanceAmount
372509467b48Spatrick                  << ", RemainingLoopCount=" << RemainingLoopCount
372609467b48Spatrick                  << "\n");
372709467b48Spatrick       return;
372809467b48Spatrick     default:
372909467b48Spatrick       *E = malformedError("bad rebase info (bad opcode value 0x" +
373009467b48Spatrick                           Twine::utohexstr(Opcode) + " for opcode at: 0x" +
373109467b48Spatrick                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
373209467b48Spatrick       moveToEnd();
373309467b48Spatrick       return;
373409467b48Spatrick     }
373509467b48Spatrick   }
373609467b48Spatrick }
373709467b48Spatrick 
readULEB128(const char ** error)373809467b48Spatrick uint64_t MachORebaseEntry::readULEB128(const char **error) {
373909467b48Spatrick   unsigned Count;
374009467b48Spatrick   uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
374109467b48Spatrick   Ptr += Count;
374209467b48Spatrick   if (Ptr > Opcodes.end())
374309467b48Spatrick     Ptr = Opcodes.end();
374409467b48Spatrick   return Result;
374509467b48Spatrick }
374609467b48Spatrick 
segmentIndex() const374709467b48Spatrick int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
374809467b48Spatrick 
segmentOffset() const374909467b48Spatrick uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
375009467b48Spatrick 
typeName() const375109467b48Spatrick StringRef MachORebaseEntry::typeName() const {
375209467b48Spatrick   switch (RebaseType) {
375309467b48Spatrick   case MachO::REBASE_TYPE_POINTER:
375409467b48Spatrick     return "pointer";
375509467b48Spatrick   case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
375609467b48Spatrick     return "text abs32";
375709467b48Spatrick   case MachO::REBASE_TYPE_TEXT_PCREL32:
375809467b48Spatrick     return "text rel32";
375909467b48Spatrick   }
376009467b48Spatrick   return "unknown";
376109467b48Spatrick }
376209467b48Spatrick 
376309467b48Spatrick // For use with the SegIndex of a checked Mach-O Rebase entry
376409467b48Spatrick // to get the segment name.
segmentName() const376509467b48Spatrick StringRef MachORebaseEntry::segmentName() const {
376609467b48Spatrick   return O->BindRebaseSegmentName(SegmentIndex);
376709467b48Spatrick }
376809467b48Spatrick 
376909467b48Spatrick // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
377009467b48Spatrick // to get the section name.
sectionName() const377109467b48Spatrick StringRef MachORebaseEntry::sectionName() const {
377209467b48Spatrick   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
377309467b48Spatrick }
377409467b48Spatrick 
377509467b48Spatrick // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
377609467b48Spatrick // to get the address.
address() const377709467b48Spatrick uint64_t MachORebaseEntry::address() const {
377809467b48Spatrick   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
377909467b48Spatrick }
378009467b48Spatrick 
operator ==(const MachORebaseEntry & Other) const378109467b48Spatrick bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
378209467b48Spatrick #ifdef EXPENSIVE_CHECKS
378309467b48Spatrick   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
378409467b48Spatrick #else
378509467b48Spatrick   assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
378609467b48Spatrick #endif
378709467b48Spatrick   return (Ptr == Other.Ptr) &&
378809467b48Spatrick          (RemainingLoopCount == Other.RemainingLoopCount) &&
378909467b48Spatrick          (Done == Other.Done);
379009467b48Spatrick }
379109467b48Spatrick 
379209467b48Spatrick iterator_range<rebase_iterator>
rebaseTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64)379309467b48Spatrick MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
379409467b48Spatrick                              ArrayRef<uint8_t> Opcodes, bool is64) {
379509467b48Spatrick   if (O->BindRebaseSectionTable == nullptr)
379609467b48Spatrick     O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
379709467b48Spatrick   MachORebaseEntry Start(&Err, O, Opcodes, is64);
379809467b48Spatrick   Start.moveToFirst();
379909467b48Spatrick 
380009467b48Spatrick   MachORebaseEntry Finish(&Err, O, Opcodes, is64);
380109467b48Spatrick   Finish.moveToEnd();
380209467b48Spatrick 
380309467b48Spatrick   return make_range(rebase_iterator(Start), rebase_iterator(Finish));
380409467b48Spatrick }
380509467b48Spatrick 
rebaseTable(Error & Err)380609467b48Spatrick iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
380709467b48Spatrick   return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
380809467b48Spatrick }
380909467b48Spatrick 
MachOBindEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)381009467b48Spatrick MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
381109467b48Spatrick                                ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
381209467b48Spatrick     : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
381309467b48Spatrick       PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
381409467b48Spatrick 
moveToFirst()381509467b48Spatrick void MachOBindEntry::moveToFirst() {
381609467b48Spatrick   Ptr = Opcodes.begin();
381709467b48Spatrick   moveNext();
381809467b48Spatrick }
381909467b48Spatrick 
moveToEnd()382009467b48Spatrick void MachOBindEntry::moveToEnd() {
382109467b48Spatrick   Ptr = Opcodes.end();
382209467b48Spatrick   RemainingLoopCount = 0;
382309467b48Spatrick   Done = true;
382409467b48Spatrick }
382509467b48Spatrick 
moveNext()382609467b48Spatrick void MachOBindEntry::moveNext() {
382709467b48Spatrick   ErrorAsOutParameter ErrAsOutParam(E);
382809467b48Spatrick   // If in the middle of some loop, move to next binding in loop.
382909467b48Spatrick   SegmentOffset += AdvanceAmount;
383009467b48Spatrick   if (RemainingLoopCount) {
383109467b48Spatrick     --RemainingLoopCount;
383209467b48Spatrick     return;
383309467b48Spatrick   }
383409467b48Spatrick   // BIND_OPCODE_DONE is only used for padding if we are not aligned to
383509467b48Spatrick   // pointer size. Therefore it is possible to reach the end without ever having
383609467b48Spatrick   // seen BIND_OPCODE_DONE.
383709467b48Spatrick   if (Ptr == Opcodes.end()) {
383809467b48Spatrick     Done = true;
383909467b48Spatrick     return;
384009467b48Spatrick   }
384109467b48Spatrick   bool More = true;
384209467b48Spatrick   while (More) {
384309467b48Spatrick     // Parse next opcode and set up next loop.
384409467b48Spatrick     const uint8_t *OpcodeStart = Ptr;
384509467b48Spatrick     uint8_t Byte = *Ptr++;
384609467b48Spatrick     uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
384709467b48Spatrick     uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
384809467b48Spatrick     int8_t SignExtended;
384909467b48Spatrick     const uint8_t *SymStart;
385009467b48Spatrick     uint32_t Count, Skip;
385109467b48Spatrick     const char *error = nullptr;
385209467b48Spatrick     switch (Opcode) {
385309467b48Spatrick     case MachO::BIND_OPCODE_DONE:
385409467b48Spatrick       if (TableKind == Kind::Lazy) {
385509467b48Spatrick         // Lazying bindings have a DONE opcode between entries.  Need to ignore
385609467b48Spatrick         // it to advance to next entry.  But need not if this is last entry.
385709467b48Spatrick         bool NotLastEntry = false;
385809467b48Spatrick         for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
385909467b48Spatrick           if (*P) {
386009467b48Spatrick             NotLastEntry = true;
386109467b48Spatrick           }
386209467b48Spatrick         }
386309467b48Spatrick         if (NotLastEntry)
386409467b48Spatrick           break;
386509467b48Spatrick       }
386609467b48Spatrick       More = false;
386709467b48Spatrick       moveToEnd();
386809467b48Spatrick       DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
386909467b48Spatrick       break;
387009467b48Spatrick     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
387109467b48Spatrick       if (TableKind == Kind::Weak) {
387209467b48Spatrick         *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
387309467b48Spatrick                             "weak bind table for opcode at: 0x" +
387409467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
387509467b48Spatrick         moveToEnd();
387609467b48Spatrick         return;
387709467b48Spatrick       }
387809467b48Spatrick       Ordinal = ImmValue;
387909467b48Spatrick       LibraryOrdinalSet = true;
388009467b48Spatrick       if (ImmValue > O->getLibraryCount()) {
388109467b48Spatrick         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
388209467b48Spatrick                             "library ordinal: " +
388309467b48Spatrick                             Twine((int)ImmValue) + " (max " +
388409467b48Spatrick                             Twine((int)O->getLibraryCount()) +
388509467b48Spatrick                             ") for opcode at: 0x" +
388609467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
388709467b48Spatrick         moveToEnd();
388809467b48Spatrick         return;
388909467b48Spatrick       }
389009467b48Spatrick       DEBUG_WITH_TYPE(
389109467b48Spatrick           "mach-o-bind",
389209467b48Spatrick           dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
389309467b48Spatrick                  << "Ordinal=" << Ordinal << "\n");
389409467b48Spatrick       break;
389509467b48Spatrick     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
389609467b48Spatrick       if (TableKind == Kind::Weak) {
389709467b48Spatrick         *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
389809467b48Spatrick                             "weak bind table for opcode at: 0x" +
389909467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
390009467b48Spatrick         moveToEnd();
390109467b48Spatrick         return;
390209467b48Spatrick       }
390309467b48Spatrick       Ordinal = readULEB128(&error);
390409467b48Spatrick       LibraryOrdinalSet = true;
390509467b48Spatrick       if (error) {
390609467b48Spatrick         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
390709467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
390809467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
390909467b48Spatrick         moveToEnd();
391009467b48Spatrick         return;
391109467b48Spatrick       }
391209467b48Spatrick       if (Ordinal > (int)O->getLibraryCount()) {
391309467b48Spatrick         *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
391409467b48Spatrick                             "library ordinal: " +
391509467b48Spatrick                             Twine((int)Ordinal) + " (max " +
391609467b48Spatrick                             Twine((int)O->getLibraryCount()) +
391709467b48Spatrick                             ") for opcode at: 0x" +
391809467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
391909467b48Spatrick         moveToEnd();
392009467b48Spatrick         return;
392109467b48Spatrick       }
392209467b48Spatrick       DEBUG_WITH_TYPE(
392309467b48Spatrick           "mach-o-bind",
392409467b48Spatrick           dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
392509467b48Spatrick                  << "Ordinal=" << Ordinal << "\n");
392609467b48Spatrick       break;
392709467b48Spatrick     case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
392809467b48Spatrick       if (TableKind == Kind::Weak) {
392909467b48Spatrick         *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
393009467b48Spatrick                             "weak bind table for opcode at: 0x" +
393109467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
393209467b48Spatrick         moveToEnd();
393309467b48Spatrick         return;
393409467b48Spatrick       }
393509467b48Spatrick       if (ImmValue) {
393609467b48Spatrick         SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
393709467b48Spatrick         Ordinal = SignExtended;
393809467b48Spatrick         if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
393909467b48Spatrick           *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
394009467b48Spatrick                               "special ordinal: " +
394109467b48Spatrick                               Twine((int)Ordinal) + " for opcode at: 0x" +
394209467b48Spatrick                               Twine::utohexstr(OpcodeStart - Opcodes.begin()));
394309467b48Spatrick           moveToEnd();
394409467b48Spatrick           return;
394509467b48Spatrick         }
394609467b48Spatrick       } else
394709467b48Spatrick         Ordinal = 0;
394809467b48Spatrick       LibraryOrdinalSet = true;
394909467b48Spatrick       DEBUG_WITH_TYPE(
395009467b48Spatrick           "mach-o-bind",
395109467b48Spatrick           dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
395209467b48Spatrick                  << "Ordinal=" << Ordinal << "\n");
395309467b48Spatrick       break;
395409467b48Spatrick     case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
395509467b48Spatrick       Flags = ImmValue;
395609467b48Spatrick       SymStart = Ptr;
395709467b48Spatrick       while (*Ptr && (Ptr < Opcodes.end())) {
395809467b48Spatrick         ++Ptr;
395909467b48Spatrick       }
396009467b48Spatrick       if (Ptr == Opcodes.end()) {
396109467b48Spatrick         *E = malformedError(
396209467b48Spatrick             "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
396309467b48Spatrick             "symbol name extends past opcodes for opcode at: 0x" +
396409467b48Spatrick             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
396509467b48Spatrick         moveToEnd();
396609467b48Spatrick         return;
396709467b48Spatrick       }
396809467b48Spatrick       SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
396909467b48Spatrick                              Ptr-SymStart);
397009467b48Spatrick       ++Ptr;
397109467b48Spatrick       DEBUG_WITH_TYPE(
397209467b48Spatrick           "mach-o-bind",
397309467b48Spatrick           dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
397409467b48Spatrick                  << "SymbolName=" << SymbolName << "\n");
397509467b48Spatrick       if (TableKind == Kind::Weak) {
397609467b48Spatrick         if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
397709467b48Spatrick           return;
397809467b48Spatrick       }
397909467b48Spatrick       break;
398009467b48Spatrick     case MachO::BIND_OPCODE_SET_TYPE_IMM:
398109467b48Spatrick       BindType = ImmValue;
398209467b48Spatrick       if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
398309467b48Spatrick         *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
398409467b48Spatrick                             Twine((int)ImmValue) + " for opcode at: 0x" +
398509467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
398609467b48Spatrick         moveToEnd();
398709467b48Spatrick         return;
398809467b48Spatrick       }
398909467b48Spatrick       DEBUG_WITH_TYPE(
399009467b48Spatrick           "mach-o-bind",
399109467b48Spatrick           dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
399209467b48Spatrick                  << "BindType=" << (int)BindType << "\n");
399309467b48Spatrick       break;
399409467b48Spatrick     case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
399509467b48Spatrick       Addend = readSLEB128(&error);
399609467b48Spatrick       if (error) {
399709467b48Spatrick         *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
399809467b48Spatrick                             " for opcode at: 0x" +
399909467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
400009467b48Spatrick         moveToEnd();
400109467b48Spatrick         return;
400209467b48Spatrick       }
400309467b48Spatrick       DEBUG_WITH_TYPE(
400409467b48Spatrick           "mach-o-bind",
400509467b48Spatrick           dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
400609467b48Spatrick                  << "Addend=" << Addend << "\n");
400709467b48Spatrick       break;
400809467b48Spatrick     case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
400909467b48Spatrick       SegmentIndex = ImmValue;
401009467b48Spatrick       SegmentOffset = readULEB128(&error);
401109467b48Spatrick       if (error) {
401209467b48Spatrick         *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
401309467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
401409467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
401509467b48Spatrick         moveToEnd();
401609467b48Spatrick         return;
401709467b48Spatrick       }
401809467b48Spatrick       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
401909467b48Spatrick                                              PointerSize);
402009467b48Spatrick       if (error) {
402109467b48Spatrick         *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
402209467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
402309467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
402409467b48Spatrick         moveToEnd();
402509467b48Spatrick         return;
402609467b48Spatrick       }
402709467b48Spatrick       DEBUG_WITH_TYPE(
402809467b48Spatrick           "mach-o-bind",
402909467b48Spatrick           dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
403009467b48Spatrick                  << "SegmentIndex=" << SegmentIndex << ", "
403109467b48Spatrick                  << format("SegmentOffset=0x%06X", SegmentOffset)
403209467b48Spatrick                  << "\n");
403309467b48Spatrick       break;
403409467b48Spatrick     case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
403509467b48Spatrick       SegmentOffset += readULEB128(&error);
403609467b48Spatrick       if (error) {
403709467b48Spatrick         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
403809467b48Spatrick                             " for opcode at: 0x" +
403909467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
404009467b48Spatrick         moveToEnd();
404109467b48Spatrick         return;
404209467b48Spatrick       }
404309467b48Spatrick       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
404409467b48Spatrick                                              PointerSize);
404509467b48Spatrick       if (error) {
404609467b48Spatrick         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
404709467b48Spatrick                             " for opcode at: 0x" +
404809467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
404909467b48Spatrick         moveToEnd();
405009467b48Spatrick         return;
405109467b48Spatrick       }
405209467b48Spatrick       DEBUG_WITH_TYPE("mach-o-bind",
405309467b48Spatrick                       dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
405409467b48Spatrick                              << format("SegmentOffset=0x%06X",
405509467b48Spatrick                                        SegmentOffset) << "\n");
405609467b48Spatrick       break;
405709467b48Spatrick     case MachO::BIND_OPCODE_DO_BIND:
405809467b48Spatrick       AdvanceAmount = PointerSize;
405909467b48Spatrick       RemainingLoopCount = 0;
406009467b48Spatrick       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
406109467b48Spatrick                                              PointerSize);
406209467b48Spatrick       if (error) {
406309467b48Spatrick         *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
406409467b48Spatrick                             " for opcode at: 0x" +
406509467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
406609467b48Spatrick         moveToEnd();
406709467b48Spatrick         return;
406809467b48Spatrick       }
406909467b48Spatrick       if (SymbolName == StringRef()) {
407009467b48Spatrick         *E = malformedError(
407109467b48Spatrick             "for BIND_OPCODE_DO_BIND missing preceding "
407209467b48Spatrick             "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
407309467b48Spatrick             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
407409467b48Spatrick         moveToEnd();
407509467b48Spatrick         return;
407609467b48Spatrick       }
407709467b48Spatrick       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
407809467b48Spatrick         *E =
407909467b48Spatrick             malformedError("for BIND_OPCODE_DO_BIND missing preceding "
408009467b48Spatrick                            "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
408109467b48Spatrick                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
408209467b48Spatrick         moveToEnd();
408309467b48Spatrick         return;
408409467b48Spatrick       }
408509467b48Spatrick       DEBUG_WITH_TYPE("mach-o-bind",
408609467b48Spatrick                       dbgs() << "BIND_OPCODE_DO_BIND: "
408709467b48Spatrick                              << format("SegmentOffset=0x%06X",
408809467b48Spatrick                                        SegmentOffset) << "\n");
408909467b48Spatrick       return;
409009467b48Spatrick      case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
409109467b48Spatrick       if (TableKind == Kind::Lazy) {
409209467b48Spatrick         *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
409309467b48Spatrick                             "lazy bind table for opcode at: 0x" +
409409467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
409509467b48Spatrick         moveToEnd();
409609467b48Spatrick         return;
409709467b48Spatrick       }
409809467b48Spatrick       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
409909467b48Spatrick                                              PointerSize);
410009467b48Spatrick       if (error) {
410109467b48Spatrick         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
410209467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
410309467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
410409467b48Spatrick         moveToEnd();
410509467b48Spatrick         return;
410609467b48Spatrick       }
410709467b48Spatrick       if (SymbolName == StringRef()) {
410809467b48Spatrick         *E = malformedError(
410909467b48Spatrick             "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
411009467b48Spatrick             "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
411109467b48Spatrick             "at: 0x" +
411209467b48Spatrick             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
411309467b48Spatrick         moveToEnd();
411409467b48Spatrick         return;
411509467b48Spatrick       }
411609467b48Spatrick       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
411709467b48Spatrick         *E = malformedError(
411809467b48Spatrick             "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
411909467b48Spatrick             "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
412009467b48Spatrick             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
412109467b48Spatrick         moveToEnd();
412209467b48Spatrick         return;
412309467b48Spatrick       }
412409467b48Spatrick       AdvanceAmount = readULEB128(&error) + PointerSize;
412509467b48Spatrick       if (error) {
412609467b48Spatrick         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
412709467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
412809467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
412909467b48Spatrick         moveToEnd();
413009467b48Spatrick         return;
413109467b48Spatrick       }
413209467b48Spatrick       // Note, this is not really an error until the next bind but make no sense
413309467b48Spatrick       // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
413409467b48Spatrick       // bind operation.
413509467b48Spatrick       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
413609467b48Spatrick                                             AdvanceAmount, PointerSize);
413709467b48Spatrick       if (error) {
413809467b48Spatrick         *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
413909467b48Spatrick                             "ULEB) " +
414009467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
414109467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
414209467b48Spatrick         moveToEnd();
414309467b48Spatrick         return;
414409467b48Spatrick       }
414509467b48Spatrick       RemainingLoopCount = 0;
414609467b48Spatrick       DEBUG_WITH_TYPE(
414709467b48Spatrick           "mach-o-bind",
414809467b48Spatrick           dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
414909467b48Spatrick                  << format("SegmentOffset=0x%06X", SegmentOffset)
415009467b48Spatrick                  << ", AdvanceAmount=" << AdvanceAmount
415109467b48Spatrick                  << ", RemainingLoopCount=" << RemainingLoopCount
415209467b48Spatrick                  << "\n");
415309467b48Spatrick       return;
415409467b48Spatrick     case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
415509467b48Spatrick       if (TableKind == Kind::Lazy) {
415609467b48Spatrick         *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
415709467b48Spatrick                             "allowed in lazy bind table for opcode at: 0x" +
415809467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
415909467b48Spatrick         moveToEnd();
416009467b48Spatrick         return;
416109467b48Spatrick       }
416209467b48Spatrick       if (SymbolName == StringRef()) {
416309467b48Spatrick         *E = malformedError(
416409467b48Spatrick             "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
416509467b48Spatrick             "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
416609467b48Spatrick             "opcode at: 0x" +
416709467b48Spatrick             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
416809467b48Spatrick         moveToEnd();
416909467b48Spatrick         return;
417009467b48Spatrick       }
417109467b48Spatrick       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
417209467b48Spatrick         *E = malformedError(
417309467b48Spatrick             "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
417409467b48Spatrick             "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
417509467b48Spatrick             "at: 0x" +
417609467b48Spatrick             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
417709467b48Spatrick         moveToEnd();
417809467b48Spatrick         return;
417909467b48Spatrick       }
418009467b48Spatrick       AdvanceAmount = ImmValue * PointerSize + PointerSize;
418109467b48Spatrick       RemainingLoopCount = 0;
418209467b48Spatrick       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
418309467b48Spatrick                                              AdvanceAmount, PointerSize);
418409467b48Spatrick       if (error) {
4185097a140dSpatrick         *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
418609467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
418709467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
418809467b48Spatrick         moveToEnd();
418909467b48Spatrick         return;
419009467b48Spatrick       }
419109467b48Spatrick       DEBUG_WITH_TYPE("mach-o-bind",
419209467b48Spatrick                       dbgs()
419309467b48Spatrick                       << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
419409467b48Spatrick                       << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
419509467b48Spatrick       return;
419609467b48Spatrick     case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
419709467b48Spatrick       if (TableKind == Kind::Lazy) {
419809467b48Spatrick         *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
419909467b48Spatrick                             "allowed in lazy bind table for opcode at: 0x" +
420009467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
420109467b48Spatrick         moveToEnd();
420209467b48Spatrick         return;
420309467b48Spatrick       }
420409467b48Spatrick       Count = readULEB128(&error);
420509467b48Spatrick       if (Count != 0)
420609467b48Spatrick         RemainingLoopCount = Count - 1;
420709467b48Spatrick       else
420809467b48Spatrick         RemainingLoopCount = 0;
420909467b48Spatrick       if (error) {
421009467b48Spatrick         *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
421109467b48Spatrick                             " (count value) " +
421209467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
421309467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
421409467b48Spatrick         moveToEnd();
421509467b48Spatrick         return;
421609467b48Spatrick       }
421709467b48Spatrick       Skip = readULEB128(&error);
421809467b48Spatrick       AdvanceAmount = Skip + PointerSize;
421909467b48Spatrick       if (error) {
422009467b48Spatrick         *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
422109467b48Spatrick                             " (skip value) " +
422209467b48Spatrick                             Twine(error) + " for opcode at: 0x" +
422309467b48Spatrick                             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
422409467b48Spatrick         moveToEnd();
422509467b48Spatrick         return;
422609467b48Spatrick       }
422709467b48Spatrick       if (SymbolName == StringRef()) {
422809467b48Spatrick         *E = malformedError(
422909467b48Spatrick             "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
423009467b48Spatrick             "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
423109467b48Spatrick             "opcode at: 0x" +
423209467b48Spatrick             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
423309467b48Spatrick         moveToEnd();
423409467b48Spatrick         return;
423509467b48Spatrick       }
423609467b48Spatrick       if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
423709467b48Spatrick         *E = malformedError(
423809467b48Spatrick             "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
423909467b48Spatrick             "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
424009467b48Spatrick             "at: 0x" +
424109467b48Spatrick             Twine::utohexstr(OpcodeStart - Opcodes.begin()));
424209467b48Spatrick         moveToEnd();
424309467b48Spatrick         return;
424409467b48Spatrick       }
424509467b48Spatrick       error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
424609467b48Spatrick                                              PointerSize, Count, Skip);
424709467b48Spatrick       if (error) {
424809467b48Spatrick         *E =
424909467b48Spatrick             malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
425009467b48Spatrick                            Twine(error) + " for opcode at: 0x" +
425109467b48Spatrick                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
425209467b48Spatrick         moveToEnd();
425309467b48Spatrick         return;
425409467b48Spatrick       }
425509467b48Spatrick       DEBUG_WITH_TYPE(
425609467b48Spatrick           "mach-o-bind",
425709467b48Spatrick           dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
425809467b48Spatrick                  << format("SegmentOffset=0x%06X", SegmentOffset)
425909467b48Spatrick                  << ", AdvanceAmount=" << AdvanceAmount
426009467b48Spatrick                  << ", RemainingLoopCount=" << RemainingLoopCount
426109467b48Spatrick                  << "\n");
426209467b48Spatrick       return;
426309467b48Spatrick     default:
426409467b48Spatrick       *E = malformedError("bad bind info (bad opcode value 0x" +
426509467b48Spatrick                           Twine::utohexstr(Opcode) + " for opcode at: 0x" +
426609467b48Spatrick                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
426709467b48Spatrick       moveToEnd();
426809467b48Spatrick       return;
426909467b48Spatrick     }
427009467b48Spatrick   }
427109467b48Spatrick }
427209467b48Spatrick 
readULEB128(const char ** error)427309467b48Spatrick uint64_t MachOBindEntry::readULEB128(const char **error) {
427409467b48Spatrick   unsigned Count;
427509467b48Spatrick   uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
427609467b48Spatrick   Ptr += Count;
427709467b48Spatrick   if (Ptr > Opcodes.end())
427809467b48Spatrick     Ptr = Opcodes.end();
427909467b48Spatrick   return Result;
428009467b48Spatrick }
428109467b48Spatrick 
readSLEB128(const char ** error)428209467b48Spatrick int64_t MachOBindEntry::readSLEB128(const char **error) {
428309467b48Spatrick   unsigned Count;
428409467b48Spatrick   int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
428509467b48Spatrick   Ptr += Count;
428609467b48Spatrick   if (Ptr > Opcodes.end())
428709467b48Spatrick     Ptr = Opcodes.end();
428809467b48Spatrick   return Result;
428909467b48Spatrick }
429009467b48Spatrick 
segmentIndex() const429109467b48Spatrick int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
429209467b48Spatrick 
segmentOffset() const429309467b48Spatrick uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
429409467b48Spatrick 
typeName() const429509467b48Spatrick StringRef MachOBindEntry::typeName() const {
429609467b48Spatrick   switch (BindType) {
429709467b48Spatrick   case MachO::BIND_TYPE_POINTER:
429809467b48Spatrick     return "pointer";
429909467b48Spatrick   case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
430009467b48Spatrick     return "text abs32";
430109467b48Spatrick   case MachO::BIND_TYPE_TEXT_PCREL32:
430209467b48Spatrick     return "text rel32";
430309467b48Spatrick   }
430409467b48Spatrick   return "unknown";
430509467b48Spatrick }
430609467b48Spatrick 
symbolName() const430709467b48Spatrick StringRef MachOBindEntry::symbolName() const { return SymbolName; }
430809467b48Spatrick 
addend() const430909467b48Spatrick int64_t MachOBindEntry::addend() const { return Addend; }
431009467b48Spatrick 
flags() const431109467b48Spatrick uint32_t MachOBindEntry::flags() const { return Flags; }
431209467b48Spatrick 
ordinal() const431309467b48Spatrick int MachOBindEntry::ordinal() const { return Ordinal; }
431409467b48Spatrick 
431509467b48Spatrick // For use with the SegIndex of a checked Mach-O Bind entry
431609467b48Spatrick // to get the segment name.
segmentName() const431709467b48Spatrick StringRef MachOBindEntry::segmentName() const {
431809467b48Spatrick   return O->BindRebaseSegmentName(SegmentIndex);
431909467b48Spatrick }
432009467b48Spatrick 
432109467b48Spatrick // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
432209467b48Spatrick // to get the section name.
sectionName() const432309467b48Spatrick StringRef MachOBindEntry::sectionName() const {
432409467b48Spatrick   return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
432509467b48Spatrick }
432609467b48Spatrick 
432709467b48Spatrick // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
432809467b48Spatrick // to get the address.
address() const432909467b48Spatrick uint64_t MachOBindEntry::address() const {
433009467b48Spatrick   return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
433109467b48Spatrick }
433209467b48Spatrick 
operator ==(const MachOBindEntry & Other) const433309467b48Spatrick bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
433409467b48Spatrick #ifdef EXPENSIVE_CHECKS
433509467b48Spatrick   assert(Opcodes == Other.Opcodes && "compare iterators of different files");
433609467b48Spatrick #else
433709467b48Spatrick   assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
433809467b48Spatrick #endif
433909467b48Spatrick   return (Ptr == Other.Ptr) &&
434009467b48Spatrick          (RemainingLoopCount == Other.RemainingLoopCount) &&
434109467b48Spatrick          (Done == Other.Done);
434209467b48Spatrick }
434309467b48Spatrick 
434409467b48Spatrick // Build table of sections so SegIndex/SegOffset pairs can be translated.
BindRebaseSegInfo(const object::MachOObjectFile * Obj)434509467b48Spatrick BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
434609467b48Spatrick   uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
434709467b48Spatrick   StringRef CurSegName;
434809467b48Spatrick   uint64_t CurSegAddress;
434909467b48Spatrick   for (const SectionRef &Section : Obj->sections()) {
435009467b48Spatrick     SectionInfo Info;
435109467b48Spatrick     Expected<StringRef> NameOrErr = Section.getName();
435209467b48Spatrick     if (!NameOrErr)
435309467b48Spatrick       consumeError(NameOrErr.takeError());
435409467b48Spatrick     else
435509467b48Spatrick       Info.SectionName = *NameOrErr;
435609467b48Spatrick     Info.Address = Section.getAddress();
435709467b48Spatrick     Info.Size = Section.getSize();
435809467b48Spatrick     Info.SegmentName =
435909467b48Spatrick         Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
436009467b48Spatrick     if (!Info.SegmentName.equals(CurSegName)) {
436109467b48Spatrick       ++CurSegIndex;
436209467b48Spatrick       CurSegName = Info.SegmentName;
436309467b48Spatrick       CurSegAddress = Info.Address;
436409467b48Spatrick     }
436509467b48Spatrick     Info.SegmentIndex = CurSegIndex - 1;
436609467b48Spatrick     Info.OffsetInSegment = Info.Address - CurSegAddress;
436709467b48Spatrick     Info.SegmentStartAddress = CurSegAddress;
436809467b48Spatrick     Sections.push_back(Info);
436909467b48Spatrick   }
437009467b48Spatrick   MaxSegIndex = CurSegIndex;
437109467b48Spatrick }
437209467b48Spatrick 
437309467b48Spatrick // For use with a SegIndex, SegOffset, and PointerSize triple in
437409467b48Spatrick // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
437509467b48Spatrick //
437609467b48Spatrick // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
437709467b48Spatrick // that fully contains a pointer at that location. Multiple fixups in a bind
437809467b48Spatrick // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
437909467b48Spatrick // be tested via the Count and Skip parameters.
checkSegAndOffsets(int32_t SegIndex,uint64_t SegOffset,uint8_t PointerSize,uint32_t Count,uint32_t Skip)438009467b48Spatrick const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
438109467b48Spatrick                                                    uint64_t SegOffset,
438209467b48Spatrick                                                    uint8_t PointerSize,
438309467b48Spatrick                                                    uint32_t Count,
438409467b48Spatrick                                                    uint32_t Skip) {
438509467b48Spatrick   if (SegIndex == -1)
438609467b48Spatrick     return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
438709467b48Spatrick   if (SegIndex >= MaxSegIndex)
438809467b48Spatrick     return "bad segIndex (too large)";
438909467b48Spatrick   for (uint32_t i = 0; i < Count; ++i) {
439009467b48Spatrick     uint32_t Start = SegOffset + i * (PointerSize + Skip);
439109467b48Spatrick     uint32_t End = Start + PointerSize;
439209467b48Spatrick     bool Found = false;
439309467b48Spatrick     for (const SectionInfo &SI : Sections) {
439409467b48Spatrick       if (SI.SegmentIndex != SegIndex)
439509467b48Spatrick         continue;
439609467b48Spatrick       if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
439709467b48Spatrick         if (End <= SI.OffsetInSegment + SI.Size) {
439809467b48Spatrick           Found = true;
439909467b48Spatrick           break;
440009467b48Spatrick         }
440109467b48Spatrick         else
440209467b48Spatrick           return "bad offset, extends beyond section boundary";
440309467b48Spatrick       }
440409467b48Spatrick     }
440509467b48Spatrick     if (!Found)
440609467b48Spatrick       return "bad offset, not in section";
440709467b48Spatrick   }
440809467b48Spatrick   return nullptr;
440909467b48Spatrick }
441009467b48Spatrick 
441109467b48Spatrick // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
441209467b48Spatrick // to get the segment name.
segmentName(int32_t SegIndex)441309467b48Spatrick StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
441409467b48Spatrick   for (const SectionInfo &SI : Sections) {
441509467b48Spatrick     if (SI.SegmentIndex == SegIndex)
441609467b48Spatrick       return SI.SegmentName;
441709467b48Spatrick   }
441809467b48Spatrick   llvm_unreachable("invalid SegIndex");
441909467b48Spatrick }
442009467b48Spatrick 
442109467b48Spatrick // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
442209467b48Spatrick // to get the SectionInfo.
findSection(int32_t SegIndex,uint64_t SegOffset)442309467b48Spatrick const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
442409467b48Spatrick                                      int32_t SegIndex, uint64_t SegOffset) {
442509467b48Spatrick   for (const SectionInfo &SI : Sections) {
442609467b48Spatrick     if (SI.SegmentIndex != SegIndex)
442709467b48Spatrick       continue;
442809467b48Spatrick     if (SI.OffsetInSegment > SegOffset)
442909467b48Spatrick       continue;
443009467b48Spatrick     if (SegOffset >= (SI.OffsetInSegment + SI.Size))
443109467b48Spatrick       continue;
443209467b48Spatrick     return SI;
443309467b48Spatrick   }
443409467b48Spatrick   llvm_unreachable("SegIndex and SegOffset not in any section");
443509467b48Spatrick }
443609467b48Spatrick 
443709467b48Spatrick // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
443809467b48Spatrick // entry to get the section name.
sectionName(int32_t SegIndex,uint64_t SegOffset)443909467b48Spatrick StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
444009467b48Spatrick                                          uint64_t SegOffset) {
444109467b48Spatrick   return findSection(SegIndex, SegOffset).SectionName;
444209467b48Spatrick }
444309467b48Spatrick 
444409467b48Spatrick // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
444509467b48Spatrick // entry to get the address.
address(uint32_t SegIndex,uint64_t OffsetInSeg)444609467b48Spatrick uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
444709467b48Spatrick   const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
444809467b48Spatrick   return SI.SegmentStartAddress + OffsetInSeg;
444909467b48Spatrick }
445009467b48Spatrick 
445109467b48Spatrick iterator_range<bind_iterator>
bindTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)445209467b48Spatrick MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
445309467b48Spatrick                            ArrayRef<uint8_t> Opcodes, bool is64,
445409467b48Spatrick                            MachOBindEntry::Kind BKind) {
445509467b48Spatrick   if (O->BindRebaseSectionTable == nullptr)
445609467b48Spatrick     O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
445709467b48Spatrick   MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
445809467b48Spatrick   Start.moveToFirst();
445909467b48Spatrick 
446009467b48Spatrick   MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
446109467b48Spatrick   Finish.moveToEnd();
446209467b48Spatrick 
446309467b48Spatrick   return make_range(bind_iterator(Start), bind_iterator(Finish));
446409467b48Spatrick }
446509467b48Spatrick 
bindTable(Error & Err)446609467b48Spatrick iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
446709467b48Spatrick   return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
446809467b48Spatrick                    MachOBindEntry::Kind::Regular);
446909467b48Spatrick }
447009467b48Spatrick 
lazyBindTable(Error & Err)447109467b48Spatrick iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
447209467b48Spatrick   return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
447309467b48Spatrick                    MachOBindEntry::Kind::Lazy);
447409467b48Spatrick }
447509467b48Spatrick 
weakBindTable(Error & Err)447609467b48Spatrick iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
447709467b48Spatrick   return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
447809467b48Spatrick                    MachOBindEntry::Kind::Weak);
447909467b48Spatrick }
448009467b48Spatrick 
fixupTable(Error & Err)4481*d415bd75Srobert iterator_range<fixup_iterator> MachOObjectFile::fixupTable(Error &Err) {
4482*d415bd75Srobert   if (BindRebaseSectionTable == nullptr)
4483*d415bd75Srobert     BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(this);
4484*d415bd75Srobert 
4485*d415bd75Srobert   MachOChainedFixupEntry Start(&Err, this, true);
4486*d415bd75Srobert   Start.moveToFirst();
4487*d415bd75Srobert 
4488*d415bd75Srobert   MachOChainedFixupEntry Finish(&Err, this, false);
4489*d415bd75Srobert   Finish.moveToEnd();
4490*d415bd75Srobert 
4491*d415bd75Srobert   return make_range(fixup_iterator(Start), fixup_iterator(Finish));
4492*d415bd75Srobert }
4493*d415bd75Srobert 
449409467b48Spatrick MachOObjectFile::load_command_iterator
begin_load_commands() const449509467b48Spatrick MachOObjectFile::begin_load_commands() const {
449609467b48Spatrick   return LoadCommands.begin();
449709467b48Spatrick }
449809467b48Spatrick 
449909467b48Spatrick MachOObjectFile::load_command_iterator
end_load_commands() const450009467b48Spatrick MachOObjectFile::end_load_commands() const {
450109467b48Spatrick   return LoadCommands.end();
450209467b48Spatrick }
450309467b48Spatrick 
450409467b48Spatrick iterator_range<MachOObjectFile::load_command_iterator>
load_commands() const450509467b48Spatrick MachOObjectFile::load_commands() const {
450609467b48Spatrick   return make_range(begin_load_commands(), end_load_commands());
450709467b48Spatrick }
450809467b48Spatrick 
450909467b48Spatrick StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const451009467b48Spatrick MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
451109467b48Spatrick   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
451209467b48Spatrick   return parseSegmentOrSectionName(Raw.data());
451309467b48Spatrick }
451409467b48Spatrick 
451509467b48Spatrick ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const451609467b48Spatrick MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
451709467b48Spatrick   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
451809467b48Spatrick   const section_base *Base =
451909467b48Spatrick     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4520*d415bd75Srobert   return ArrayRef(Base->sectname);
452109467b48Spatrick }
452209467b48Spatrick 
452309467b48Spatrick ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const452409467b48Spatrick MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
452509467b48Spatrick   assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
452609467b48Spatrick   const section_base *Base =
452709467b48Spatrick     reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4528*d415bd75Srobert   return ArrayRef(Base->segname);
452909467b48Spatrick }
453009467b48Spatrick 
453109467b48Spatrick bool
isRelocationScattered(const MachO::any_relocation_info & RE) const453209467b48Spatrick MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
453309467b48Spatrick   const {
453409467b48Spatrick   if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
453509467b48Spatrick     return false;
453609467b48Spatrick   return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
453709467b48Spatrick }
453809467b48Spatrick 
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const453909467b48Spatrick unsigned MachOObjectFile::getPlainRelocationSymbolNum(
454009467b48Spatrick     const MachO::any_relocation_info &RE) const {
454109467b48Spatrick   if (isLittleEndian())
454209467b48Spatrick     return RE.r_word1 & 0xffffff;
454309467b48Spatrick   return RE.r_word1 >> 8;
454409467b48Spatrick }
454509467b48Spatrick 
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const454609467b48Spatrick bool MachOObjectFile::getPlainRelocationExternal(
454709467b48Spatrick     const MachO::any_relocation_info &RE) const {
454809467b48Spatrick   if (isLittleEndian())
454909467b48Spatrick     return (RE.r_word1 >> 27) & 1;
455009467b48Spatrick   return (RE.r_word1 >> 4) & 1;
455109467b48Spatrick }
455209467b48Spatrick 
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const455309467b48Spatrick bool MachOObjectFile::getScatteredRelocationScattered(
455409467b48Spatrick     const MachO::any_relocation_info &RE) const {
455509467b48Spatrick   return RE.r_word0 >> 31;
455609467b48Spatrick }
455709467b48Spatrick 
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const455809467b48Spatrick uint32_t MachOObjectFile::getScatteredRelocationValue(
455909467b48Spatrick     const MachO::any_relocation_info &RE) const {
456009467b48Spatrick   return RE.r_word1;
456109467b48Spatrick }
456209467b48Spatrick 
getScatteredRelocationType(const MachO::any_relocation_info & RE) const456309467b48Spatrick uint32_t MachOObjectFile::getScatteredRelocationType(
456409467b48Spatrick     const MachO::any_relocation_info &RE) const {
456509467b48Spatrick   return (RE.r_word0 >> 24) & 0xf;
456609467b48Spatrick }
456709467b48Spatrick 
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const456809467b48Spatrick unsigned MachOObjectFile::getAnyRelocationAddress(
456909467b48Spatrick     const MachO::any_relocation_info &RE) const {
457009467b48Spatrick   if (isRelocationScattered(RE))
457109467b48Spatrick     return getScatteredRelocationAddress(RE);
457209467b48Spatrick   return getPlainRelocationAddress(RE);
457309467b48Spatrick }
457409467b48Spatrick 
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const457509467b48Spatrick unsigned MachOObjectFile::getAnyRelocationPCRel(
457609467b48Spatrick     const MachO::any_relocation_info &RE) const {
457709467b48Spatrick   if (isRelocationScattered(RE))
457809467b48Spatrick     return getScatteredRelocationPCRel(RE);
457909467b48Spatrick   return getPlainRelocationPCRel(*this, RE);
458009467b48Spatrick }
458109467b48Spatrick 
getAnyRelocationLength(const MachO::any_relocation_info & RE) const458209467b48Spatrick unsigned MachOObjectFile::getAnyRelocationLength(
458309467b48Spatrick     const MachO::any_relocation_info &RE) const {
458409467b48Spatrick   if (isRelocationScattered(RE))
458509467b48Spatrick     return getScatteredRelocationLength(RE);
458609467b48Spatrick   return getPlainRelocationLength(*this, RE);
458709467b48Spatrick }
458809467b48Spatrick 
458909467b48Spatrick unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const459009467b48Spatrick MachOObjectFile::getAnyRelocationType(
459109467b48Spatrick                                    const MachO::any_relocation_info &RE) const {
459209467b48Spatrick   if (isRelocationScattered(RE))
459309467b48Spatrick     return getScatteredRelocationType(RE);
459409467b48Spatrick   return getPlainRelocationType(*this, RE);
459509467b48Spatrick }
459609467b48Spatrick 
459709467b48Spatrick SectionRef
getAnyRelocationSection(const MachO::any_relocation_info & RE) const459809467b48Spatrick MachOObjectFile::getAnyRelocationSection(
459909467b48Spatrick                                    const MachO::any_relocation_info &RE) const {
460009467b48Spatrick   if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
460109467b48Spatrick     return *section_end();
460209467b48Spatrick   unsigned SecNum = getPlainRelocationSymbolNum(RE);
460309467b48Spatrick   if (SecNum == MachO::R_ABS || SecNum > Sections.size())
460409467b48Spatrick     return *section_end();
460509467b48Spatrick   DataRefImpl DRI;
460609467b48Spatrick   DRI.d.a = SecNum - 1;
460709467b48Spatrick   return SectionRef(DRI, this);
460809467b48Spatrick }
460909467b48Spatrick 
getSection(DataRefImpl DRI) const461009467b48Spatrick MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
461109467b48Spatrick   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
461209467b48Spatrick   return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
461309467b48Spatrick }
461409467b48Spatrick 
getSection64(DataRefImpl DRI) const461509467b48Spatrick MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
461609467b48Spatrick   assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
461709467b48Spatrick   return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
461809467b48Spatrick }
461909467b48Spatrick 
getSection(const LoadCommandInfo & L,unsigned Index) const462009467b48Spatrick MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
462109467b48Spatrick                                            unsigned Index) const {
462209467b48Spatrick   const char *Sec = getSectionPtr(*this, L, Index);
462309467b48Spatrick   return getStruct<MachO::section>(*this, Sec);
462409467b48Spatrick }
462509467b48Spatrick 
getSection64(const LoadCommandInfo & L,unsigned Index) const462609467b48Spatrick MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
462709467b48Spatrick                                                 unsigned Index) const {
462809467b48Spatrick   const char *Sec = getSectionPtr(*this, L, Index);
462909467b48Spatrick   return getStruct<MachO::section_64>(*this, Sec);
463009467b48Spatrick }
463109467b48Spatrick 
463209467b48Spatrick MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const463309467b48Spatrick MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
463409467b48Spatrick   const char *P = reinterpret_cast<const char *>(DRI.p);
463509467b48Spatrick   return getStruct<MachO::nlist>(*this, P);
463609467b48Spatrick }
463709467b48Spatrick 
463809467b48Spatrick MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const463909467b48Spatrick MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
464009467b48Spatrick   const char *P = reinterpret_cast<const char *>(DRI.p);
464109467b48Spatrick   return getStruct<MachO::nlist_64>(*this, P);
464209467b48Spatrick }
464309467b48Spatrick 
464409467b48Spatrick MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const464509467b48Spatrick MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
464609467b48Spatrick   return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
464709467b48Spatrick }
464809467b48Spatrick 
464909467b48Spatrick MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const465009467b48Spatrick MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
465109467b48Spatrick   return getStruct<MachO::segment_command>(*this, L.Ptr);
465209467b48Spatrick }
465309467b48Spatrick 
465409467b48Spatrick MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const465509467b48Spatrick MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
465609467b48Spatrick   return getStruct<MachO::segment_command_64>(*this, L.Ptr);
465709467b48Spatrick }
465809467b48Spatrick 
465909467b48Spatrick MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const466009467b48Spatrick MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
466109467b48Spatrick   return getStruct<MachO::linker_option_command>(*this, L.Ptr);
466209467b48Spatrick }
466309467b48Spatrick 
466409467b48Spatrick MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const466509467b48Spatrick MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
466609467b48Spatrick   return getStruct<MachO::version_min_command>(*this, L.Ptr);
466709467b48Spatrick }
466809467b48Spatrick 
466909467b48Spatrick MachO::note_command
getNoteLoadCommand(const LoadCommandInfo & L) const467009467b48Spatrick MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
467109467b48Spatrick   return getStruct<MachO::note_command>(*this, L.Ptr);
467209467b48Spatrick }
467309467b48Spatrick 
467409467b48Spatrick MachO::build_version_command
getBuildVersionLoadCommand(const LoadCommandInfo & L) const467509467b48Spatrick MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
467609467b48Spatrick   return getStruct<MachO::build_version_command>(*this, L.Ptr);
467709467b48Spatrick }
467809467b48Spatrick 
467909467b48Spatrick MachO::build_tool_version
getBuildToolVersion(unsigned index) const468009467b48Spatrick MachOObjectFile::getBuildToolVersion(unsigned index) const {
468109467b48Spatrick   return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
468209467b48Spatrick }
468309467b48Spatrick 
468409467b48Spatrick MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const468509467b48Spatrick MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
468609467b48Spatrick   return getStruct<MachO::dylib_command>(*this, L.Ptr);
468709467b48Spatrick }
468809467b48Spatrick 
468909467b48Spatrick MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const469009467b48Spatrick MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
469109467b48Spatrick   return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
469209467b48Spatrick }
469309467b48Spatrick 
469409467b48Spatrick MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const469509467b48Spatrick MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
469609467b48Spatrick   return getStruct<MachO::dylinker_command>(*this, L.Ptr);
469709467b48Spatrick }
469809467b48Spatrick 
469909467b48Spatrick MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const470009467b48Spatrick MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
470109467b48Spatrick   return getStruct<MachO::uuid_command>(*this, L.Ptr);
470209467b48Spatrick }
470309467b48Spatrick 
470409467b48Spatrick MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const470509467b48Spatrick MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
470609467b48Spatrick   return getStruct<MachO::rpath_command>(*this, L.Ptr);
470709467b48Spatrick }
470809467b48Spatrick 
470909467b48Spatrick MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const471009467b48Spatrick MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
471109467b48Spatrick   return getStruct<MachO::source_version_command>(*this, L.Ptr);
471209467b48Spatrick }
471309467b48Spatrick 
471409467b48Spatrick MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const471509467b48Spatrick MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
471609467b48Spatrick   return getStruct<MachO::entry_point_command>(*this, L.Ptr);
471709467b48Spatrick }
471809467b48Spatrick 
471909467b48Spatrick MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const472009467b48Spatrick MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
472109467b48Spatrick   return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
472209467b48Spatrick }
472309467b48Spatrick 
472409467b48Spatrick MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const472509467b48Spatrick MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
472609467b48Spatrick   return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
472709467b48Spatrick }
472809467b48Spatrick 
472909467b48Spatrick MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const473009467b48Spatrick MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
473109467b48Spatrick   return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
473209467b48Spatrick }
473309467b48Spatrick 
473409467b48Spatrick MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const473509467b48Spatrick MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
473609467b48Spatrick   return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
473709467b48Spatrick }
473809467b48Spatrick 
473909467b48Spatrick MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const474009467b48Spatrick MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
474109467b48Spatrick   return getStruct<MachO::sub_library_command>(*this, L.Ptr);
474209467b48Spatrick }
474309467b48Spatrick 
474409467b48Spatrick MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const474509467b48Spatrick MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
474609467b48Spatrick   return getStruct<MachO::sub_client_command>(*this, L.Ptr);
474709467b48Spatrick }
474809467b48Spatrick 
474909467b48Spatrick MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const475009467b48Spatrick MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
475109467b48Spatrick   return getStruct<MachO::routines_command>(*this, L.Ptr);
475209467b48Spatrick }
475309467b48Spatrick 
475409467b48Spatrick MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const475509467b48Spatrick MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
475609467b48Spatrick   return getStruct<MachO::routines_command_64>(*this, L.Ptr);
475709467b48Spatrick }
475809467b48Spatrick 
475909467b48Spatrick MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const476009467b48Spatrick MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
476109467b48Spatrick   return getStruct<MachO::thread_command>(*this, L.Ptr);
476209467b48Spatrick }
476309467b48Spatrick 
476409467b48Spatrick MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const476509467b48Spatrick MachOObjectFile::getRelocation(DataRefImpl Rel) const {
476609467b48Spatrick   uint32_t Offset;
476709467b48Spatrick   if (getHeader().filetype == MachO::MH_OBJECT) {
476809467b48Spatrick     DataRefImpl Sec;
476909467b48Spatrick     Sec.d.a = Rel.d.a;
477009467b48Spatrick     if (is64Bit()) {
477109467b48Spatrick       MachO::section_64 Sect = getSection64(Sec);
477209467b48Spatrick       Offset = Sect.reloff;
477309467b48Spatrick     } else {
477409467b48Spatrick       MachO::section Sect = getSection(Sec);
477509467b48Spatrick       Offset = Sect.reloff;
477609467b48Spatrick     }
477709467b48Spatrick   } else {
477809467b48Spatrick     MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
477909467b48Spatrick     if (Rel.d.a == 0)
478009467b48Spatrick       Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
478109467b48Spatrick     else
478209467b48Spatrick       Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
478309467b48Spatrick   }
478409467b48Spatrick 
478509467b48Spatrick   auto P = reinterpret_cast<const MachO::any_relocation_info *>(
478609467b48Spatrick       getPtr(*this, Offset)) + Rel.d.b;
478709467b48Spatrick   return getStruct<MachO::any_relocation_info>(
478809467b48Spatrick       *this, reinterpret_cast<const char *>(P));
478909467b48Spatrick }
479009467b48Spatrick 
479109467b48Spatrick MachO::data_in_code_entry
getDice(DataRefImpl Rel) const479209467b48Spatrick MachOObjectFile::getDice(DataRefImpl Rel) const {
479309467b48Spatrick   const char *P = reinterpret_cast<const char *>(Rel.p);
479409467b48Spatrick   return getStruct<MachO::data_in_code_entry>(*this, P);
479509467b48Spatrick }
479609467b48Spatrick 
getHeader() const479709467b48Spatrick const MachO::mach_header &MachOObjectFile::getHeader() const {
479809467b48Spatrick   return Header;
479909467b48Spatrick }
480009467b48Spatrick 
getHeader64() const480109467b48Spatrick const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
480209467b48Spatrick   assert(is64Bit());
480309467b48Spatrick   return Header64;
480409467b48Spatrick }
480509467b48Spatrick 
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const480609467b48Spatrick uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
480709467b48Spatrick                                              const MachO::dysymtab_command &DLC,
480809467b48Spatrick                                              unsigned Index) const {
480909467b48Spatrick   uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
481009467b48Spatrick   return getStruct<uint32_t>(*this, getPtr(*this, Offset));
481109467b48Spatrick }
481209467b48Spatrick 
481309467b48Spatrick MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const481409467b48Spatrick MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
481509467b48Spatrick                                          unsigned Index) const {
481609467b48Spatrick   uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
481709467b48Spatrick   return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
481809467b48Spatrick }
481909467b48Spatrick 
getSymtabLoadCommand() const482009467b48Spatrick MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
482109467b48Spatrick   if (SymtabLoadCmd)
482209467b48Spatrick     return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
482309467b48Spatrick 
482409467b48Spatrick   // If there is no SymtabLoadCmd return a load command with zero'ed fields.
482509467b48Spatrick   MachO::symtab_command Cmd;
482609467b48Spatrick   Cmd.cmd = MachO::LC_SYMTAB;
482709467b48Spatrick   Cmd.cmdsize = sizeof(MachO::symtab_command);
482809467b48Spatrick   Cmd.symoff = 0;
482909467b48Spatrick   Cmd.nsyms = 0;
483009467b48Spatrick   Cmd.stroff = 0;
483109467b48Spatrick   Cmd.strsize = 0;
483209467b48Spatrick   return Cmd;
483309467b48Spatrick }
483409467b48Spatrick 
getDysymtabLoadCommand() const483509467b48Spatrick MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
483609467b48Spatrick   if (DysymtabLoadCmd)
483709467b48Spatrick     return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
483809467b48Spatrick 
483909467b48Spatrick   // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
484009467b48Spatrick   MachO::dysymtab_command Cmd;
484109467b48Spatrick   Cmd.cmd = MachO::LC_DYSYMTAB;
484209467b48Spatrick   Cmd.cmdsize = sizeof(MachO::dysymtab_command);
484309467b48Spatrick   Cmd.ilocalsym = 0;
484409467b48Spatrick   Cmd.nlocalsym = 0;
484509467b48Spatrick   Cmd.iextdefsym = 0;
484609467b48Spatrick   Cmd.nextdefsym = 0;
484709467b48Spatrick   Cmd.iundefsym = 0;
484809467b48Spatrick   Cmd.nundefsym = 0;
484909467b48Spatrick   Cmd.tocoff = 0;
485009467b48Spatrick   Cmd.ntoc = 0;
485109467b48Spatrick   Cmd.modtaboff = 0;
485209467b48Spatrick   Cmd.nmodtab = 0;
485309467b48Spatrick   Cmd.extrefsymoff = 0;
485409467b48Spatrick   Cmd.nextrefsyms = 0;
485509467b48Spatrick   Cmd.indirectsymoff = 0;
485609467b48Spatrick   Cmd.nindirectsyms = 0;
485709467b48Spatrick   Cmd.extreloff = 0;
485809467b48Spatrick   Cmd.nextrel = 0;
485909467b48Spatrick   Cmd.locreloff = 0;
486009467b48Spatrick   Cmd.nlocrel = 0;
486109467b48Spatrick   return Cmd;
486209467b48Spatrick }
486309467b48Spatrick 
486409467b48Spatrick MachO::linkedit_data_command
getDataInCodeLoadCommand() const486509467b48Spatrick MachOObjectFile::getDataInCodeLoadCommand() const {
486609467b48Spatrick   if (DataInCodeLoadCmd)
486709467b48Spatrick     return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
486809467b48Spatrick 
486909467b48Spatrick   // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
487009467b48Spatrick   MachO::linkedit_data_command Cmd;
487109467b48Spatrick   Cmd.cmd = MachO::LC_DATA_IN_CODE;
487209467b48Spatrick   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
487309467b48Spatrick   Cmd.dataoff = 0;
487409467b48Spatrick   Cmd.datasize = 0;
487509467b48Spatrick   return Cmd;
487609467b48Spatrick }
487709467b48Spatrick 
487809467b48Spatrick MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const487909467b48Spatrick MachOObjectFile::getLinkOptHintsLoadCommand() const {
488009467b48Spatrick   if (LinkOptHintsLoadCmd)
488109467b48Spatrick     return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
488209467b48Spatrick 
488309467b48Spatrick   // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
488409467b48Spatrick   // fields.
488509467b48Spatrick   MachO::linkedit_data_command Cmd;
488609467b48Spatrick   Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
488709467b48Spatrick   Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
488809467b48Spatrick   Cmd.dataoff = 0;
488909467b48Spatrick   Cmd.datasize = 0;
489009467b48Spatrick   return Cmd;
489109467b48Spatrick }
489209467b48Spatrick 
getDyldInfoRebaseOpcodes() const489309467b48Spatrick ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
489409467b48Spatrick   if (!DyldInfoLoadCmd)
4895*d415bd75Srobert     return std::nullopt;
489609467b48Spatrick 
489709467b48Spatrick   auto DyldInfoOrErr =
489809467b48Spatrick     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
489909467b48Spatrick   if (!DyldInfoOrErr)
4900*d415bd75Srobert     return std::nullopt;
490109467b48Spatrick   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
490209467b48Spatrick   const uint8_t *Ptr =
490309467b48Spatrick       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
4904*d415bd75Srobert   return ArrayRef(Ptr, DyldInfo.rebase_size);
490509467b48Spatrick }
490609467b48Spatrick 
getDyldInfoBindOpcodes() const490709467b48Spatrick ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
490809467b48Spatrick   if (!DyldInfoLoadCmd)
4909*d415bd75Srobert     return std::nullopt;
491009467b48Spatrick 
491109467b48Spatrick   auto DyldInfoOrErr =
491209467b48Spatrick     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
491309467b48Spatrick   if (!DyldInfoOrErr)
4914*d415bd75Srobert     return std::nullopt;
491509467b48Spatrick   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
491609467b48Spatrick   const uint8_t *Ptr =
491709467b48Spatrick       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
4918*d415bd75Srobert   return ArrayRef(Ptr, DyldInfo.bind_size);
491909467b48Spatrick }
492009467b48Spatrick 
getDyldInfoWeakBindOpcodes() const492109467b48Spatrick ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
492209467b48Spatrick   if (!DyldInfoLoadCmd)
4923*d415bd75Srobert     return std::nullopt;
492409467b48Spatrick 
492509467b48Spatrick   auto DyldInfoOrErr =
492609467b48Spatrick     getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
492709467b48Spatrick   if (!DyldInfoOrErr)
4928*d415bd75Srobert     return std::nullopt;
492909467b48Spatrick   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
493009467b48Spatrick   const uint8_t *Ptr =
493109467b48Spatrick       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
4932*d415bd75Srobert   return ArrayRef(Ptr, DyldInfo.weak_bind_size);
493309467b48Spatrick }
493409467b48Spatrick 
getDyldInfoLazyBindOpcodes() const493509467b48Spatrick ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
493609467b48Spatrick   if (!DyldInfoLoadCmd)
4937*d415bd75Srobert     return std::nullopt;
493809467b48Spatrick 
493909467b48Spatrick   auto DyldInfoOrErr =
494009467b48Spatrick       getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
494109467b48Spatrick   if (!DyldInfoOrErr)
4942*d415bd75Srobert     return std::nullopt;
494309467b48Spatrick   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
494409467b48Spatrick   const uint8_t *Ptr =
494509467b48Spatrick       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
4946*d415bd75Srobert   return ArrayRef(Ptr, DyldInfo.lazy_bind_size);
494709467b48Spatrick }
494809467b48Spatrick 
getDyldInfoExportsTrie() const494909467b48Spatrick ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
495009467b48Spatrick   if (!DyldInfoLoadCmd)
4951*d415bd75Srobert     return std::nullopt;
495209467b48Spatrick 
495309467b48Spatrick   auto DyldInfoOrErr =
495409467b48Spatrick       getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
495509467b48Spatrick   if (!DyldInfoOrErr)
4956*d415bd75Srobert     return std::nullopt;
495709467b48Spatrick   MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
495809467b48Spatrick   const uint8_t *Ptr =
495909467b48Spatrick       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
4960*d415bd75Srobert   return ArrayRef(Ptr, DyldInfo.export_size);
4961*d415bd75Srobert }
4962*d415bd75Srobert 
4963*d415bd75Srobert Expected<std::optional<MachO::linkedit_data_command>>
getChainedFixupsLoadCommand() const4964*d415bd75Srobert MachOObjectFile::getChainedFixupsLoadCommand() const {
4965*d415bd75Srobert   // Load the dyld chained fixups load command.
4966*d415bd75Srobert   if (!DyldChainedFixupsLoadCmd)
4967*d415bd75Srobert     return std::nullopt;
4968*d415bd75Srobert   auto DyldChainedFixupsOrErr = getStructOrErr<MachO::linkedit_data_command>(
4969*d415bd75Srobert       *this, DyldChainedFixupsLoadCmd);
4970*d415bd75Srobert   if (!DyldChainedFixupsOrErr)
4971*d415bd75Srobert     return DyldChainedFixupsOrErr.takeError();
4972*d415bd75Srobert   const MachO::linkedit_data_command &DyldChainedFixups =
4973*d415bd75Srobert       *DyldChainedFixupsOrErr;
4974*d415bd75Srobert 
4975*d415bd75Srobert   // If the load command is present but the data offset has been zeroed out,
4976*d415bd75Srobert   // as is the case for dylib stubs, return std::nullopt (no error).
4977*d415bd75Srobert   if (!DyldChainedFixups.dataoff)
4978*d415bd75Srobert     return std::nullopt;
4979*d415bd75Srobert   return DyldChainedFixups;
4980*d415bd75Srobert }
4981*d415bd75Srobert 
4982*d415bd75Srobert Expected<std::optional<MachO::dyld_chained_fixups_header>>
getChainedFixupsHeader() const4983*d415bd75Srobert MachOObjectFile::getChainedFixupsHeader() const {
4984*d415bd75Srobert   auto CFOrErr = getChainedFixupsLoadCommand();
4985*d415bd75Srobert   if (!CFOrErr)
4986*d415bd75Srobert     return CFOrErr.takeError();
4987*d415bd75Srobert   if (!CFOrErr->has_value())
4988*d415bd75Srobert     return std::nullopt;
4989*d415bd75Srobert 
4990*d415bd75Srobert   const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
4991*d415bd75Srobert 
4992*d415bd75Srobert   uint64_t CFHeaderOffset = DyldChainedFixups.dataoff;
4993*d415bd75Srobert   uint64_t CFSize = DyldChainedFixups.datasize;
4994*d415bd75Srobert 
4995*d415bd75Srobert   // Load the dyld chained fixups header.
4996*d415bd75Srobert   const char *CFHeaderPtr = getPtr(*this, CFHeaderOffset);
4997*d415bd75Srobert   auto CFHeaderOrErr =
4998*d415bd75Srobert       getStructOrErr<MachO::dyld_chained_fixups_header>(*this, CFHeaderPtr);
4999*d415bd75Srobert   if (!CFHeaderOrErr)
5000*d415bd75Srobert     return CFHeaderOrErr.takeError();
5001*d415bd75Srobert   MachO::dyld_chained_fixups_header CFHeader = CFHeaderOrErr.get();
5002*d415bd75Srobert 
5003*d415bd75Srobert   // Reject unknown chained fixup formats.
5004*d415bd75Srobert   if (CFHeader.fixups_version != 0)
5005*d415bd75Srobert     return malformedError(Twine("bad chained fixups: unknown version: ") +
5006*d415bd75Srobert                           Twine(CFHeader.fixups_version));
5007*d415bd75Srobert   if (CFHeader.imports_format < 1 || CFHeader.imports_format > 3)
5008*d415bd75Srobert     return malformedError(
5009*d415bd75Srobert         Twine("bad chained fixups: unknown imports format: ") +
5010*d415bd75Srobert         Twine(CFHeader.imports_format));
5011*d415bd75Srobert 
5012*d415bd75Srobert   // Validate the image format.
5013*d415bd75Srobert   //
5014*d415bd75Srobert   // Load the image starts.
5015*d415bd75Srobert   uint64_t CFImageStartsOffset = (CFHeaderOffset + CFHeader.starts_offset);
5016*d415bd75Srobert   if (CFHeader.starts_offset < sizeof(MachO::dyld_chained_fixups_header)) {
5017*d415bd75Srobert     return malformedError(Twine("bad chained fixups: image starts offset ") +
5018*d415bd75Srobert                           Twine(CFHeader.starts_offset) +
5019*d415bd75Srobert                           " overlaps with chained fixups header");
5020*d415bd75Srobert   }
5021*d415bd75Srobert   uint32_t EndOffset = CFHeaderOffset + CFSize;
5022*d415bd75Srobert   if (CFImageStartsOffset + sizeof(MachO::dyld_chained_starts_in_image) >
5023*d415bd75Srobert       EndOffset) {
5024*d415bd75Srobert     return malformedError(Twine("bad chained fixups: image starts end ") +
5025*d415bd75Srobert                           Twine(CFImageStartsOffset +
5026*d415bd75Srobert                                 sizeof(MachO::dyld_chained_starts_in_image)) +
5027*d415bd75Srobert                           " extends past end " + Twine(EndOffset));
5028*d415bd75Srobert   }
5029*d415bd75Srobert 
5030*d415bd75Srobert   return CFHeader;
5031*d415bd75Srobert }
5032*d415bd75Srobert 
5033*d415bd75Srobert Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>
getChainedFixupsSegments() const5034*d415bd75Srobert MachOObjectFile::getChainedFixupsSegments() const {
5035*d415bd75Srobert   auto CFOrErr = getChainedFixupsLoadCommand();
5036*d415bd75Srobert   if (!CFOrErr)
5037*d415bd75Srobert     return CFOrErr.takeError();
5038*d415bd75Srobert 
5039*d415bd75Srobert   std::vector<ChainedFixupsSegment> Segments;
5040*d415bd75Srobert   if (!CFOrErr->has_value())
5041*d415bd75Srobert     return std::make_pair(0, Segments);
5042*d415bd75Srobert 
5043*d415bd75Srobert   const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
5044*d415bd75Srobert 
5045*d415bd75Srobert   auto HeaderOrErr = getChainedFixupsHeader();
5046*d415bd75Srobert   if (!HeaderOrErr)
5047*d415bd75Srobert     return HeaderOrErr.takeError();
5048*d415bd75Srobert   if (!HeaderOrErr->has_value())
5049*d415bd75Srobert     return std::make_pair(0, Segments);
5050*d415bd75Srobert   const MachO::dyld_chained_fixups_header &Header = **HeaderOrErr;
5051*d415bd75Srobert 
5052*d415bd75Srobert   const char *Contents = getPtr(*this, DyldChainedFixups.dataoff);
5053*d415bd75Srobert 
5054*d415bd75Srobert   auto ImageStartsOrErr = getStructOrErr<MachO::dyld_chained_starts_in_image>(
5055*d415bd75Srobert       *this, Contents + Header.starts_offset);
5056*d415bd75Srobert   if (!ImageStartsOrErr)
5057*d415bd75Srobert     return ImageStartsOrErr.takeError();
5058*d415bd75Srobert   const MachO::dyld_chained_starts_in_image &ImageStarts = *ImageStartsOrErr;
5059*d415bd75Srobert 
5060*d415bd75Srobert   const char *SegOffsPtr =
5061*d415bd75Srobert       Contents + Header.starts_offset +
5062*d415bd75Srobert       offsetof(MachO::dyld_chained_starts_in_image, seg_info_offset);
5063*d415bd75Srobert   const char *SegOffsEnd =
5064*d415bd75Srobert       SegOffsPtr + ImageStarts.seg_count * sizeof(uint32_t);
5065*d415bd75Srobert   if (SegOffsEnd > Contents + DyldChainedFixups.datasize)
5066*d415bd75Srobert     return malformedError(
5067*d415bd75Srobert         "bad chained fixups: seg_info_offset extends past end");
5068*d415bd75Srobert 
5069*d415bd75Srobert   const char *LastSegEnd = nullptr;
5070*d415bd75Srobert   for (size_t I = 0, N = ImageStarts.seg_count; I < N; ++I) {
5071*d415bd75Srobert     auto OffOrErr =
5072*d415bd75Srobert         getStructOrErr<uint32_t>(*this, SegOffsPtr + I * sizeof(uint32_t));
5073*d415bd75Srobert     if (!OffOrErr)
5074*d415bd75Srobert       return OffOrErr.takeError();
5075*d415bd75Srobert     // seg_info_offset == 0 means there is no associated starts_in_segment
5076*d415bd75Srobert     // entry.
5077*d415bd75Srobert     if (!*OffOrErr)
5078*d415bd75Srobert       continue;
5079*d415bd75Srobert 
5080*d415bd75Srobert     auto Fail = [&](Twine Message) {
5081*d415bd75Srobert       return malformedError("bad chained fixups: segment info" + Twine(I) +
5082*d415bd75Srobert                             " at offset " + Twine(*OffOrErr) + Message);
5083*d415bd75Srobert     };
5084*d415bd75Srobert 
5085*d415bd75Srobert     const char *SegPtr = Contents + Header.starts_offset + *OffOrErr;
5086*d415bd75Srobert     if (LastSegEnd && SegPtr < LastSegEnd)
5087*d415bd75Srobert       return Fail(" overlaps with previous segment info");
5088*d415bd75Srobert 
5089*d415bd75Srobert     auto SegOrErr =
5090*d415bd75Srobert         getStructOrErr<MachO::dyld_chained_starts_in_segment>(*this, SegPtr);
5091*d415bd75Srobert     if (!SegOrErr)
5092*d415bd75Srobert       return SegOrErr.takeError();
5093*d415bd75Srobert     const MachO::dyld_chained_starts_in_segment &Seg = *SegOrErr;
5094*d415bd75Srobert 
5095*d415bd75Srobert     LastSegEnd = SegPtr + Seg.size;
5096*d415bd75Srobert     if (Seg.pointer_format < 1 || Seg.pointer_format > 12)
5097*d415bd75Srobert       return Fail(" has unknown pointer format: " + Twine(Seg.pointer_format));
5098*d415bd75Srobert 
5099*d415bd75Srobert     const char *PageStart =
5100*d415bd75Srobert         SegPtr + offsetof(MachO::dyld_chained_starts_in_segment, page_start);
5101*d415bd75Srobert     const char *PageEnd = PageStart + Seg.page_count * sizeof(uint16_t);
5102*d415bd75Srobert     if (PageEnd > SegPtr + Seg.size)
5103*d415bd75Srobert       return Fail(" : page_starts extend past seg_info size");
5104*d415bd75Srobert 
5105*d415bd75Srobert     // FIXME: This does not account for multiple offsets on a single page
5106*d415bd75Srobert     //        (DYLD_CHAINED_PTR_START_MULTI; 32-bit only).
5107*d415bd75Srobert     std::vector<uint16_t> PageStarts;
5108*d415bd75Srobert     for (size_t PageIdx = 0; PageIdx < Seg.page_count; ++PageIdx) {
5109*d415bd75Srobert       uint16_t Start;
5110*d415bd75Srobert       memcpy(&Start, PageStart + PageIdx * sizeof(uint16_t), sizeof(uint16_t));
5111*d415bd75Srobert       if (isLittleEndian() != sys::IsLittleEndianHost)
5112*d415bd75Srobert         sys::swapByteOrder(Start);
5113*d415bd75Srobert       PageStarts.push_back(Start);
5114*d415bd75Srobert     }
5115*d415bd75Srobert 
5116*d415bd75Srobert     Segments.emplace_back(I, *OffOrErr, Seg, std::move(PageStarts));
5117*d415bd75Srobert   }
5118*d415bd75Srobert 
5119*d415bd75Srobert   return std::make_pair(ImageStarts.seg_count, Segments);
5120*d415bd75Srobert }
5121*d415bd75Srobert 
5122*d415bd75Srobert // The special library ordinals have a negative value, but they are encoded in
5123*d415bd75Srobert // an unsigned bitfield, so we need to sign extend the value.
getEncodedOrdinal(T Value)5124*d415bd75Srobert template <typename T> static int getEncodedOrdinal(T Value) {
5125*d415bd75Srobert   if (Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE) ||
5126*d415bd75Srobert       Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) ||
5127*d415bd75Srobert       Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP))
5128*d415bd75Srobert     return SignExtend32<sizeof(T) * CHAR_BIT>(Value);
5129*d415bd75Srobert   return Value;
5130*d415bd75Srobert }
5131*d415bd75Srobert 
5132*d415bd75Srobert template <typename T, unsigned N>
getArray(const MachOObjectFile & O,const void * Ptr)5133*d415bd75Srobert static std::array<T, N> getArray(const MachOObjectFile &O, const void *Ptr) {
5134*d415bd75Srobert   std::array<T, N> RawValue;
5135*d415bd75Srobert   memcpy(RawValue.data(), Ptr, N * sizeof(T));
5136*d415bd75Srobert   if (O.isLittleEndian() != sys::IsLittleEndianHost)
5137*d415bd75Srobert     for (auto &Element : RawValue)
5138*d415bd75Srobert       sys::swapByteOrder(Element);
5139*d415bd75Srobert   return RawValue;
5140*d415bd75Srobert }
5141*d415bd75Srobert 
5142*d415bd75Srobert Expected<std::vector<ChainedFixupTarget>>
getDyldChainedFixupTargets() const5143*d415bd75Srobert MachOObjectFile::getDyldChainedFixupTargets() const {
5144*d415bd75Srobert   auto CFOrErr = getChainedFixupsLoadCommand();
5145*d415bd75Srobert   if (!CFOrErr)
5146*d415bd75Srobert     return CFOrErr.takeError();
5147*d415bd75Srobert 
5148*d415bd75Srobert   std::vector<ChainedFixupTarget> Targets;
5149*d415bd75Srobert   if (!CFOrErr->has_value())
5150*d415bd75Srobert     return Targets;
5151*d415bd75Srobert 
5152*d415bd75Srobert   const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
5153*d415bd75Srobert 
5154*d415bd75Srobert   auto CFHeaderOrErr = getChainedFixupsHeader();
5155*d415bd75Srobert   if (!CFHeaderOrErr)
5156*d415bd75Srobert     return CFHeaderOrErr.takeError();
5157*d415bd75Srobert   if (!(*CFHeaderOrErr))
5158*d415bd75Srobert     return Targets;
5159*d415bd75Srobert   const MachO::dyld_chained_fixups_header &Header = **CFHeaderOrErr;
5160*d415bd75Srobert 
5161*d415bd75Srobert   size_t ImportSize = 0;
5162*d415bd75Srobert   if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT)
5163*d415bd75Srobert     ImportSize = sizeof(MachO::dyld_chained_import);
5164*d415bd75Srobert   else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND)
5165*d415bd75Srobert     ImportSize = sizeof(MachO::dyld_chained_import_addend);
5166*d415bd75Srobert   else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)
5167*d415bd75Srobert     ImportSize = sizeof(MachO::dyld_chained_import_addend64);
5168*d415bd75Srobert   else
5169*d415bd75Srobert     return malformedError("bad chained fixups: unknown imports format: " +
5170*d415bd75Srobert                           Twine(Header.imports_format));
5171*d415bd75Srobert 
5172*d415bd75Srobert   const char *Contents = getPtr(*this, DyldChainedFixups.dataoff);
5173*d415bd75Srobert   const char *Imports = Contents + Header.imports_offset;
5174*d415bd75Srobert   size_t ImportsEndOffset =
5175*d415bd75Srobert       Header.imports_offset + ImportSize * Header.imports_count;
5176*d415bd75Srobert   const char *ImportsEnd = Contents + ImportsEndOffset;
5177*d415bd75Srobert   const char *Symbols = Contents + Header.symbols_offset;
5178*d415bd75Srobert   const char *SymbolsEnd = Contents + DyldChainedFixups.datasize;
5179*d415bd75Srobert 
5180*d415bd75Srobert   if (ImportsEnd > Symbols)
5181*d415bd75Srobert     return malformedError("bad chained fixups: imports end " +
5182*d415bd75Srobert                           Twine(ImportsEndOffset) + " extends past end " +
5183*d415bd75Srobert                           Twine(DyldChainedFixups.datasize));
5184*d415bd75Srobert 
5185*d415bd75Srobert   if (ImportsEnd > Symbols)
5186*d415bd75Srobert     return malformedError("bad chained fixups: imports end " +
5187*d415bd75Srobert                           Twine(ImportsEndOffset) + " overlaps with symbols");
5188*d415bd75Srobert 
5189*d415bd75Srobert   // We use bit manipulation to extract data from the bitfields. This is correct
5190*d415bd75Srobert   // for both LE and BE hosts, but we assume that the object is little-endian.
5191*d415bd75Srobert   if (!isLittleEndian())
5192*d415bd75Srobert     return createError("parsing big-endian chained fixups is not implemented");
5193*d415bd75Srobert   for (const char *ImportPtr = Imports; ImportPtr < ImportsEnd;
5194*d415bd75Srobert        ImportPtr += ImportSize) {
5195*d415bd75Srobert     int LibOrdinal;
5196*d415bd75Srobert     bool WeakImport;
5197*d415bd75Srobert     uint32_t NameOffset;
5198*d415bd75Srobert     uint64_t Addend;
5199*d415bd75Srobert     if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT) {
5200*d415bd75Srobert       static_assert(sizeof(uint32_t) == sizeof(MachO::dyld_chained_import));
5201*d415bd75Srobert       auto RawValue = getArray<uint32_t, 1>(*this, ImportPtr);
5202*d415bd75Srobert 
5203*d415bd75Srobert       LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5204*d415bd75Srobert       WeakImport = (RawValue[0] >> 8) & 1;
5205*d415bd75Srobert       NameOffset = RawValue[0] >> 9;
5206*d415bd75Srobert       Addend = 0;
5207*d415bd75Srobert     } else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND) {
5208*d415bd75Srobert       static_assert(sizeof(uint64_t) ==
5209*d415bd75Srobert                     sizeof(MachO::dyld_chained_import_addend));
5210*d415bd75Srobert       auto RawValue = getArray<uint32_t, 2>(*this, ImportPtr);
5211*d415bd75Srobert 
5212*d415bd75Srobert       LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5213*d415bd75Srobert       WeakImport = (RawValue[0] >> 8) & 1;
5214*d415bd75Srobert       NameOffset = RawValue[0] >> 9;
5215*d415bd75Srobert       Addend = bit_cast<int32_t>(RawValue[1]);
5216*d415bd75Srobert     } else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64) {
5217*d415bd75Srobert       static_assert(2 * sizeof(uint64_t) ==
5218*d415bd75Srobert                     sizeof(MachO::dyld_chained_import_addend64));
5219*d415bd75Srobert       auto RawValue = getArray<uint64_t, 2>(*this, ImportPtr);
5220*d415bd75Srobert 
5221*d415bd75Srobert       LibOrdinal = getEncodedOrdinal<uint16_t>(RawValue[0] & 0xFFFF);
5222*d415bd75Srobert       NameOffset = (RawValue[0] >> 16) & 1;
5223*d415bd75Srobert       WeakImport = RawValue[0] >> 17;
5224*d415bd75Srobert       Addend = RawValue[1];
5225*d415bd75Srobert     } else {
5226*d415bd75Srobert       llvm_unreachable("Import format should have been checked");
5227*d415bd75Srobert     }
5228*d415bd75Srobert 
5229*d415bd75Srobert     const char *Str = Symbols + NameOffset;
5230*d415bd75Srobert     if (Str >= SymbolsEnd)
5231*d415bd75Srobert       return malformedError("bad chained fixups: symbol offset " +
5232*d415bd75Srobert                             Twine(NameOffset) + " extends past end " +
5233*d415bd75Srobert                             Twine(DyldChainedFixups.datasize));
5234*d415bd75Srobert     Targets.emplace_back(LibOrdinal, NameOffset, Str, Addend, WeakImport);
5235*d415bd75Srobert   }
5236*d415bd75Srobert 
5237*d415bd75Srobert   return std::move(Targets);
5238*d415bd75Srobert }
5239*d415bd75Srobert 
getDyldExportsTrie() const5240*d415bd75Srobert ArrayRef<uint8_t> MachOObjectFile::getDyldExportsTrie() const {
5241*d415bd75Srobert   if (!DyldExportsTrieLoadCmd)
5242*d415bd75Srobert     return std::nullopt;
5243*d415bd75Srobert 
5244*d415bd75Srobert   auto DyldExportsTrieOrError = getStructOrErr<MachO::linkedit_data_command>(
5245*d415bd75Srobert       *this, DyldExportsTrieLoadCmd);
5246*d415bd75Srobert   if (!DyldExportsTrieOrError)
5247*d415bd75Srobert     return std::nullopt;
5248*d415bd75Srobert   MachO::linkedit_data_command DyldExportsTrie = DyldExportsTrieOrError.get();
5249*d415bd75Srobert   const uint8_t *Ptr =
5250*d415bd75Srobert       reinterpret_cast<const uint8_t *>(getPtr(*this, DyldExportsTrie.dataoff));
5251*d415bd75Srobert   return ArrayRef(Ptr, DyldExportsTrie.datasize);
5252*d415bd75Srobert }
5253*d415bd75Srobert 
getFunctionStarts() const5254*d415bd75Srobert SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const {
5255*d415bd75Srobert   if (!FuncStartsLoadCmd)
5256*d415bd75Srobert     return {};
5257*d415bd75Srobert 
5258*d415bd75Srobert   auto InfoOrErr =
5259*d415bd75Srobert       getStructOrErr<MachO::linkedit_data_command>(*this, FuncStartsLoadCmd);
5260*d415bd75Srobert   if (!InfoOrErr)
5261*d415bd75Srobert     return {};
5262*d415bd75Srobert 
5263*d415bd75Srobert   MachO::linkedit_data_command Info = InfoOrErr.get();
5264*d415bd75Srobert   SmallVector<uint64_t, 8> FunctionStarts;
5265*d415bd75Srobert   this->ReadULEB128s(Info.dataoff, FunctionStarts);
5266*d415bd75Srobert   return std::move(FunctionStarts);
526709467b48Spatrick }
526809467b48Spatrick 
getUuid() const526909467b48Spatrick ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
527009467b48Spatrick   if (!UuidLoadCmd)
5271*d415bd75Srobert     return std::nullopt;
527209467b48Spatrick   // Returning a pointer is fine as uuid doesn't need endian swapping.
527309467b48Spatrick   const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
5274*d415bd75Srobert   return ArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
527509467b48Spatrick }
527609467b48Spatrick 
getStringTableData() const527709467b48Spatrick StringRef MachOObjectFile::getStringTableData() const {
527809467b48Spatrick   MachO::symtab_command S = getSymtabLoadCommand();
527909467b48Spatrick   return getData().substr(S.stroff, S.strsize);
528009467b48Spatrick }
528109467b48Spatrick 
is64Bit() const528209467b48Spatrick bool MachOObjectFile::is64Bit() const {
528309467b48Spatrick   return getType() == getMachOType(false, true) ||
528409467b48Spatrick     getType() == getMachOType(true, true);
528509467b48Spatrick }
528609467b48Spatrick 
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const528709467b48Spatrick void MachOObjectFile::ReadULEB128s(uint64_t Index,
528809467b48Spatrick                                    SmallVectorImpl<uint64_t> &Out) const {
528909467b48Spatrick   DataExtractor extractor(ObjectFile::getData(), true, 0);
529009467b48Spatrick 
529109467b48Spatrick   uint64_t offset = Index;
529209467b48Spatrick   uint64_t data = 0;
529309467b48Spatrick   while (uint64_t delta = extractor.getULEB128(&offset)) {
529409467b48Spatrick     data += delta;
529509467b48Spatrick     Out.push_back(data);
529609467b48Spatrick   }
529709467b48Spatrick }
529809467b48Spatrick 
isRelocatableObject() const529909467b48Spatrick bool MachOObjectFile::isRelocatableObject() const {
530009467b48Spatrick   return getHeader().filetype == MachO::MH_OBJECT;
530109467b48Spatrick }
530209467b48Spatrick 
530309467b48Spatrick Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer,uint32_t UniversalCputype,uint32_t UniversalIndex)530409467b48Spatrick ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
530509467b48Spatrick                                   uint32_t UniversalCputype,
530609467b48Spatrick                                   uint32_t UniversalIndex) {
530709467b48Spatrick   StringRef Magic = Buffer.getBuffer().slice(0, 4);
530809467b48Spatrick   if (Magic == "\xFE\xED\xFA\xCE")
530909467b48Spatrick     return MachOObjectFile::create(Buffer, false, false,
531009467b48Spatrick                                    UniversalCputype, UniversalIndex);
531109467b48Spatrick   if (Magic == "\xCE\xFA\xED\xFE")
531209467b48Spatrick     return MachOObjectFile::create(Buffer, true, false,
531309467b48Spatrick                                    UniversalCputype, UniversalIndex);
531409467b48Spatrick   if (Magic == "\xFE\xED\xFA\xCF")
531509467b48Spatrick     return MachOObjectFile::create(Buffer, false, true,
531609467b48Spatrick                                    UniversalCputype, UniversalIndex);
531709467b48Spatrick   if (Magic == "\xCF\xFA\xED\xFE")
531809467b48Spatrick     return MachOObjectFile::create(Buffer, true, true,
531909467b48Spatrick                                    UniversalCputype, UniversalIndex);
532009467b48Spatrick   return make_error<GenericBinaryError>("Unrecognized MachO magic number",
532109467b48Spatrick                                         object_error::invalid_file_type);
532209467b48Spatrick }
532309467b48Spatrick 
mapDebugSectionName(StringRef Name) const532409467b48Spatrick StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
532509467b48Spatrick   return StringSwitch<StringRef>(Name)
532609467b48Spatrick       .Case("debug_str_offs", "debug_str_offsets")
532709467b48Spatrick       .Default(Name);
532809467b48Spatrick }
5329*d415bd75Srobert 
5330*d415bd75Srobert Expected<std::vector<std::string>>
findDsymObjectMembers(StringRef Path)5331*d415bd75Srobert MachOObjectFile::findDsymObjectMembers(StringRef Path) {
5332*d415bd75Srobert   SmallString<256> BundlePath(Path);
5333*d415bd75Srobert   // Normalize input path. This is necessary to accept `bundle.dSYM/`.
5334*d415bd75Srobert   sys::path::remove_dots(BundlePath);
5335*d415bd75Srobert   if (!sys::fs::is_directory(BundlePath) ||
5336*d415bd75Srobert       sys::path::extension(BundlePath) != ".dSYM")
5337*d415bd75Srobert     return std::vector<std::string>();
5338*d415bd75Srobert   sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
5339*d415bd75Srobert   bool IsDir;
5340*d415bd75Srobert   auto EC = sys::fs::is_directory(BundlePath, IsDir);
5341*d415bd75Srobert   if (EC == errc::no_such_file_or_directory || (!EC && !IsDir))
5342*d415bd75Srobert     return createStringError(
5343*d415bd75Srobert         EC, "%s: expected directory 'Contents/Resources/DWARF' in dSYM bundle",
5344*d415bd75Srobert         Path.str().c_str());
5345*d415bd75Srobert   if (EC)
5346*d415bd75Srobert     return createFileError(BundlePath, errorCodeToError(EC));
5347*d415bd75Srobert 
5348*d415bd75Srobert   std::vector<std::string> ObjectPaths;
5349*d415bd75Srobert   for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
5350*d415bd75Srobert        Dir != DirEnd && !EC; Dir.increment(EC)) {
5351*d415bd75Srobert     StringRef ObjectPath = Dir->path();
5352*d415bd75Srobert     sys::fs::file_status Status;
5353*d415bd75Srobert     if (auto EC = sys::fs::status(ObjectPath, Status))
5354*d415bd75Srobert       return createFileError(ObjectPath, errorCodeToError(EC));
5355*d415bd75Srobert     switch (Status.type()) {
5356*d415bd75Srobert     case sys::fs::file_type::regular_file:
5357*d415bd75Srobert     case sys::fs::file_type::symlink_file:
5358*d415bd75Srobert     case sys::fs::file_type::type_unknown:
5359*d415bd75Srobert       ObjectPaths.push_back(ObjectPath.str());
5360*d415bd75Srobert       break;
5361*d415bd75Srobert     default: /*ignore*/;
5362*d415bd75Srobert     }
5363*d415bd75Srobert   }
5364*d415bd75Srobert   if (EC)
5365*d415bd75Srobert     return createFileError(BundlePath, errorCodeToError(EC));
5366*d415bd75Srobert   if (ObjectPaths.empty())
5367*d415bd75Srobert     return createStringError(std::error_code(),
5368*d415bd75Srobert                              "%s: no objects found in dSYM bundle",
5369*d415bd75Srobert                              Path.str().c_str());
5370*d415bd75Srobert   return ObjectPaths;
5371*d415bd75Srobert }
5372*d415bd75Srobert 
5373*d415bd75Srobert llvm::binaryformat::Swift5ReflectionSectionKind
mapReflectionSectionNameToEnumValue(StringRef SectionName) const5374*d415bd75Srobert MachOObjectFile::mapReflectionSectionNameToEnumValue(
5375*d415bd75Srobert     StringRef SectionName) const {
5376*d415bd75Srobert #define HANDLE_SWIFT_SECTION(KIND, MACHO, ELF, COFF)                           \
5377*d415bd75Srobert   .Case(MACHO, llvm::binaryformat::Swift5ReflectionSectionKind::KIND)
5378*d415bd75Srobert   return StringSwitch<llvm::binaryformat::Swift5ReflectionSectionKind>(
5379*d415bd75Srobert              SectionName)
5380*d415bd75Srobert #include "llvm/BinaryFormat/Swift.def"
5381*d415bd75Srobert       .Default(llvm::binaryformat::Swift5ReflectionSectionKind::unknown);
5382*d415bd75Srobert #undef HANDLE_SWIFT_SECTION
5383*d415bd75Srobert }
5384*d415bd75Srobert 
isMachOPairedReloc(uint64_t RelocType,uint64_t Arch)5385*d415bd75Srobert bool MachOObjectFile::isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {
5386*d415bd75Srobert   switch (Arch) {
5387*d415bd75Srobert   case Triple::x86:
5388*d415bd75Srobert     return RelocType == MachO::GENERIC_RELOC_SECTDIFF ||
5389*d415bd75Srobert            RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
5390*d415bd75Srobert   case Triple::x86_64:
5391*d415bd75Srobert     return RelocType == MachO::X86_64_RELOC_SUBTRACTOR;
5392*d415bd75Srobert   case Triple::arm:
5393*d415bd75Srobert   case Triple::thumb:
5394*d415bd75Srobert     return RelocType == MachO::ARM_RELOC_SECTDIFF ||
5395*d415bd75Srobert            RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
5396*d415bd75Srobert            RelocType == MachO::ARM_RELOC_HALF ||
5397*d415bd75Srobert            RelocType == MachO::ARM_RELOC_HALF_SECTDIFF;
5398*d415bd75Srobert   case Triple::aarch64:
5399*d415bd75Srobert     return RelocType == MachO::ARM64_RELOC_SUBTRACTOR;
5400*d415bd75Srobert   default:
5401*d415bd75Srobert     return false;
5402*d415bd75Srobert   }
5403*d415bd75Srobert }
5404