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