151690af2SDimitry Andric //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
23b0f4066SDimitry Andric //
33b0f4066SDimitry Andric // The LLVM Compiler Infrastructure
43b0f4066SDimitry Andric //
53b0f4066SDimitry Andric // This file is distributed under the University of Illinois Open Source
63b0f4066SDimitry Andric // License. See LICENSE.TXT for details.
73b0f4066SDimitry Andric //
83b0f4066SDimitry Andric //===----------------------------------------------------------------------===//
93b0f4066SDimitry Andric //
103b0f4066SDimitry Andric // This file defines the MachOObjectFile class, which binds the MachOObject
113b0f4066SDimitry Andric // class to the generic ObjectFile wrapper.
123b0f4066SDimitry Andric //
133b0f4066SDimitry Andric //===----------------------------------------------------------------------===//
143b0f4066SDimitry Andric
1551690af2SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1651690af2SDimitry Andric #include "llvm/ADT/None.h"
1791bc56edSDimitry Andric #include "llvm/ADT/STLExtras.h"
18db17bf38SDimitry Andric #include "llvm/ADT/SmallVector.h"
1951690af2SDimitry Andric #include "llvm/ADT/StringRef.h"
2039d628a0SDimitry Andric #include "llvm/ADT/StringSwitch.h"
21139f7f9bSDimitry Andric #include "llvm/ADT/Triple.h"
2251690af2SDimitry Andric #include "llvm/ADT/Twine.h"
23db17bf38SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
2451690af2SDimitry Andric #include "llvm/Object/Error.h"
2551690af2SDimitry Andric #include "llvm/Object/MachO.h"
2651690af2SDimitry Andric #include "llvm/Object/ObjectFile.h"
2751690af2SDimitry Andric #include "llvm/Object/SymbolicFile.h"
28284c1978SDimitry Andric #include "llvm/Support/DataExtractor.h"
2939d628a0SDimitry Andric #include "llvm/Support/Debug.h"
3051690af2SDimitry Andric #include "llvm/Support/Error.h"
3151690af2SDimitry Andric #include "llvm/Support/ErrorHandling.h"
32dff0c46cSDimitry Andric #include "llvm/Support/Format.h"
33284c1978SDimitry Andric #include "llvm/Support/Host.h"
3439d628a0SDimitry Andric #include "llvm/Support/LEB128.h"
353b0f4066SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
3651690af2SDimitry Andric #include "llvm/Support/SwapByteOrder.h"
37db17bf38SDimitry Andric #include "llvm/Support/raw_ostream.h"
3851690af2SDimitry Andric #include <algorithm>
3951690af2SDimitry Andric #include <cassert>
4051690af2SDimitry Andric #include <cstddef>
4151690af2SDimitry Andric #include <cstdint>
423b0f4066SDimitry Andric #include <cstring>
433b0f4066SDimitry Andric #include <limits>
44d88c1a5aSDimitry Andric #include <list>
4551690af2SDimitry Andric #include <memory>
4651690af2SDimitry Andric #include <string>
4751690af2SDimitry Andric #include <system_error>
483b0f4066SDimitry Andric
493b0f4066SDimitry Andric using namespace llvm;
503b0f4066SDimitry Andric using namespace object;
513b0f4066SDimitry Andric
5291bc56edSDimitry Andric namespace {
5351690af2SDimitry Andric
54f785676fSDimitry Andric struct section_base {
55f785676fSDimitry Andric char sectname[16];
56f785676fSDimitry Andric char segname[16];
57284c1978SDimitry Andric };
5851690af2SDimitry Andric
5951690af2SDimitry Andric } // end anonymous namespace
603b0f4066SDimitry Andric
malformedError(const Twine & Msg)612cab237bSDimitry Andric static Error malformedError(const Twine &Msg) {
622cab237bSDimitry Andric return make_error<GenericBinaryError>("truncated or malformed object (" +
632cab237bSDimitry Andric Msg + ")",
643ca95b02SDimitry Andric object_error::parse_failed);
653ca95b02SDimitry Andric }
663ca95b02SDimitry Andric
6797bc6c73SDimitry Andric // FIXME: Replace all uses of this function with getStructOrErr.
68284c1978SDimitry Andric template <typename T>
getStruct(const MachOObjectFile & O,const char * P)69d88c1a5aSDimitry Andric static T getStruct(const MachOObjectFile &O, const char *P) {
70ff0cc061SDimitry Andric // Don't read before the beginning or past the end of the file
71d88c1a5aSDimitry Andric if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
72ff0cc061SDimitry Andric report_fatal_error("Malformed MachO file.");
73ff0cc061SDimitry Andric
74284c1978SDimitry Andric T Cmd;
75284c1978SDimitry Andric memcpy(&Cmd, P, sizeof(T));
76d88c1a5aSDimitry Andric if (O.isLittleEndian() != sys::IsLittleEndianHost)
7791bc56edSDimitry Andric MachO::swapStruct(Cmd);
78284c1978SDimitry Andric return Cmd;
79284c1978SDimitry Andric }
80284c1978SDimitry Andric
8197bc6c73SDimitry Andric template <typename T>
getStructOrErr(const MachOObjectFile & O,const char * P)82d88c1a5aSDimitry Andric static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
8397bc6c73SDimitry Andric // Don't read before the beginning or past the end of the file
84d88c1a5aSDimitry Andric if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
853ca95b02SDimitry Andric return malformedError("Structure read out-of-range");
86ff0cc061SDimitry Andric
8797bc6c73SDimitry Andric T Cmd;
8897bc6c73SDimitry Andric memcpy(&Cmd, P, sizeof(T));
89d88c1a5aSDimitry Andric if (O.isLittleEndian() != sys::IsLittleEndianHost)
9097bc6c73SDimitry Andric MachO::swapStruct(Cmd);
9197bc6c73SDimitry Andric return Cmd;
92284c1978SDimitry Andric }
93284c1978SDimitry Andric
94284c1978SDimitry Andric static const char *
getSectionPtr(const MachOObjectFile & O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)95d88c1a5aSDimitry Andric getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
96284c1978SDimitry Andric unsigned Sec) {
97284c1978SDimitry Andric uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
98284c1978SDimitry Andric
99d88c1a5aSDimitry Andric bool Is64 = O.is64Bit();
100f785676fSDimitry Andric unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
101f785676fSDimitry Andric sizeof(MachO::segment_command);
102f785676fSDimitry Andric unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
103f785676fSDimitry Andric sizeof(MachO::section);
104284c1978SDimitry Andric
105284c1978SDimitry Andric uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
106284c1978SDimitry Andric return reinterpret_cast<const char*>(SectionAddr);
107284c1978SDimitry Andric }
108284c1978SDimitry Andric
getPtr(const MachOObjectFile & O,size_t Offset)109d88c1a5aSDimitry Andric static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
1104ba319b5SDimitry Andric assert(Offset <= O.getData().size());
1114ba319b5SDimitry Andric return O.getData().data() + Offset;
112284c1978SDimitry Andric }
113284c1978SDimitry Andric
11491bc56edSDimitry Andric static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile & O,DataRefImpl DRI)115d88c1a5aSDimitry Andric getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
116284c1978SDimitry Andric const char *P = reinterpret_cast<const char *>(DRI.p);
11791bc56edSDimitry Andric return getStruct<MachO::nlist_base>(O, P);
118284c1978SDimitry Andric }
119284c1978SDimitry Andric
parseSegmentOrSectionName(const char * P)120284c1978SDimitry Andric static StringRef parseSegmentOrSectionName(const char *P) {
121284c1978SDimitry Andric if (P[15] == 0)
122284c1978SDimitry Andric // Null terminated.
123284c1978SDimitry Andric return P;
124284c1978SDimitry Andric // Not null terminated, so this is a 16 char string.
125284c1978SDimitry Andric return StringRef(P, 16);
126284c1978SDimitry Andric }
127284c1978SDimitry Andric
getCPUType(const MachOObjectFile & O)128d88c1a5aSDimitry Andric static unsigned getCPUType(const MachOObjectFile &O) {
129d88c1a5aSDimitry Andric return O.getHeader().cputype;
130284c1978SDimitry Andric }
131284c1978SDimitry Andric
132f785676fSDimitry Andric static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)133f785676fSDimitry Andric getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
134f785676fSDimitry Andric return RE.r_word0;
135284c1978SDimitry Andric }
136284c1978SDimitry Andric
137284c1978SDimitry Andric static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)138f785676fSDimitry Andric getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
139f785676fSDimitry Andric return RE.r_word0 & 0xffffff;
140284c1978SDimitry Andric }
141284c1978SDimitry Andric
getPlainRelocationPCRel(const MachOObjectFile & O,const MachO::any_relocation_info & RE)142d88c1a5aSDimitry Andric static bool getPlainRelocationPCRel(const MachOObjectFile &O,
143f785676fSDimitry Andric const MachO::any_relocation_info &RE) {
144d88c1a5aSDimitry Andric if (O.isLittleEndian())
145f785676fSDimitry Andric return (RE.r_word1 >> 24) & 1;
146f785676fSDimitry Andric return (RE.r_word1 >> 7) & 1;
147284c1978SDimitry Andric }
148284c1978SDimitry Andric
149284c1978SDimitry Andric static bool
getScatteredRelocationPCRel(const MachO::any_relocation_info & RE)150d88c1a5aSDimitry Andric getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
151f785676fSDimitry Andric return (RE.r_word0 >> 30) & 1;
152284c1978SDimitry Andric }
153284c1978SDimitry Andric
getPlainRelocationLength(const MachOObjectFile & O,const MachO::any_relocation_info & RE)154d88c1a5aSDimitry Andric static unsigned getPlainRelocationLength(const MachOObjectFile &O,
155f785676fSDimitry Andric const MachO::any_relocation_info &RE) {
156d88c1a5aSDimitry Andric if (O.isLittleEndian())
157f785676fSDimitry Andric return (RE.r_word1 >> 25) & 3;
158f785676fSDimitry Andric return (RE.r_word1 >> 5) & 3;
159284c1978SDimitry Andric }
160284c1978SDimitry Andric
161284c1978SDimitry Andric static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)162f785676fSDimitry Andric getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
163f785676fSDimitry Andric return (RE.r_word0 >> 28) & 3;
164284c1978SDimitry Andric }
165284c1978SDimitry Andric
getPlainRelocationType(const MachOObjectFile & O,const MachO::any_relocation_info & RE)166d88c1a5aSDimitry Andric static unsigned getPlainRelocationType(const MachOObjectFile &O,
167f785676fSDimitry Andric const MachO::any_relocation_info &RE) {
168d88c1a5aSDimitry Andric if (O.isLittleEndian())
169f785676fSDimitry Andric return RE.r_word1 >> 28;
170f785676fSDimitry Andric return RE.r_word1 & 0xf;
171284c1978SDimitry Andric }
172284c1978SDimitry Andric
getSectionFlags(const MachOObjectFile & O,DataRefImpl Sec)173d88c1a5aSDimitry Andric static uint32_t getSectionFlags(const MachOObjectFile &O,
174284c1978SDimitry Andric DataRefImpl Sec) {
175d88c1a5aSDimitry Andric if (O.is64Bit()) {
176d88c1a5aSDimitry Andric MachO::section_64 Sect = O.getSection64(Sec);
177f785676fSDimitry Andric return Sect.flags;
178284c1978SDimitry Andric }
179d88c1a5aSDimitry Andric MachO::section Sect = O.getSection(Sec);
180f785676fSDimitry Andric return Sect.flags;
181284c1978SDimitry Andric }
182284c1978SDimitry Andric
1833ca95b02SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile & Obj,const char * Ptr,uint32_t LoadCommandIndex)184d88c1a5aSDimitry Andric getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
1853ca95b02SDimitry Andric uint32_t LoadCommandIndex) {
1863ca95b02SDimitry Andric if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
1872cab237bSDimitry Andric if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
1882cab237bSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1892cab237bSDimitry Andric " extends past end of file");
19097bc6c73SDimitry Andric if (CmdOrErr->cmdsize < 8)
1913ca95b02SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1923ca95b02SDimitry Andric " with size less than 8 bytes");
1933ca95b02SDimitry Andric return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
1943ca95b02SDimitry Andric } else
1953ca95b02SDimitry Andric return CmdOrErr.takeError();
19697bc6c73SDimitry Andric }
19797bc6c73SDimitry Andric
1983ca95b02SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getFirstLoadCommandInfo(const MachOObjectFile & Obj)199d88c1a5aSDimitry Andric getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
200d88c1a5aSDimitry Andric unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
20197bc6c73SDimitry Andric : sizeof(MachO::mach_header);
202d88c1a5aSDimitry Andric if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
2033ca95b02SDimitry Andric return malformedError("load command 0 extends past the end all load "
2043ca95b02SDimitry Andric "commands in the file");
2053ca95b02SDimitry Andric return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
20697bc6c73SDimitry Andric }
20797bc6c73SDimitry Andric
2083ca95b02SDimitry Andric static Expected<MachOObjectFile::LoadCommandInfo>
getNextLoadCommandInfo(const MachOObjectFile & Obj,uint32_t LoadCommandIndex,const MachOObjectFile::LoadCommandInfo & L)209d88c1a5aSDimitry Andric getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
21097bc6c73SDimitry Andric const MachOObjectFile::LoadCommandInfo &L) {
211d88c1a5aSDimitry Andric unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
2123ca95b02SDimitry Andric : sizeof(MachO::mach_header);
213d88c1a5aSDimitry Andric if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
214d88c1a5aSDimitry Andric Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
2153ca95b02SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex + 1) +
2163ca95b02SDimitry Andric " extends past the end all load commands in the file");
2173ca95b02SDimitry Andric return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
21897bc6c73SDimitry Andric }
21997bc6c73SDimitry Andric
22097bc6c73SDimitry Andric template <typename T>
parseHeader(const MachOObjectFile & Obj,T & Header,Error & Err)221d88c1a5aSDimitry Andric static void parseHeader(const MachOObjectFile &Obj, T &Header,
2223ca95b02SDimitry Andric Error &Err) {
223d88c1a5aSDimitry Andric if (sizeof(T) > Obj.getData().size()) {
2243ca95b02SDimitry Andric Err = malformedError("the mach header extends past the end of the "
2253ca95b02SDimitry Andric "file");
2263ca95b02SDimitry Andric return;
2273ca95b02SDimitry Andric }
2283ca95b02SDimitry Andric if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
2293ca95b02SDimitry Andric Header = *HeaderOrErr;
23097bc6c73SDimitry Andric else
2313ca95b02SDimitry Andric Err = HeaderOrErr.takeError();
23297bc6c73SDimitry Andric }
23397bc6c73SDimitry Andric
234d88c1a5aSDimitry Andric // This is used to check for overlapping of Mach-O elements.
235d88c1a5aSDimitry Andric struct MachOElement {
236d88c1a5aSDimitry Andric uint64_t Offset;
237d88c1a5aSDimitry Andric uint64_t Size;
238d88c1a5aSDimitry Andric const char *Name;
239d88c1a5aSDimitry Andric };
240d88c1a5aSDimitry Andric
checkOverlappingElement(std::list<MachOElement> & Elements,uint64_t Offset,uint64_t Size,const char * Name)241d88c1a5aSDimitry Andric static Error checkOverlappingElement(std::list<MachOElement> &Elements,
242d88c1a5aSDimitry Andric uint64_t Offset, uint64_t Size,
243d88c1a5aSDimitry Andric const char *Name) {
244d88c1a5aSDimitry Andric if (Size == 0)
245d88c1a5aSDimitry Andric return Error::success();
246d88c1a5aSDimitry Andric
247d88c1a5aSDimitry Andric for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
248d88c1a5aSDimitry Andric auto E = *it;
249d88c1a5aSDimitry Andric if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
250d88c1a5aSDimitry Andric (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
251d88c1a5aSDimitry Andric (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
252d88c1a5aSDimitry Andric return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
253d88c1a5aSDimitry Andric " with a size of " + Twine(Size) + ", overlaps " +
254d88c1a5aSDimitry Andric E.Name + " at offset " + Twine(E.Offset) + " with "
255d88c1a5aSDimitry Andric "a size of " + Twine(E.Size));
256d88c1a5aSDimitry Andric auto nt = it;
257d88c1a5aSDimitry Andric nt++;
258d88c1a5aSDimitry Andric if (nt != Elements.end()) {
259d88c1a5aSDimitry Andric auto N = *nt;
260d88c1a5aSDimitry Andric if (Offset + Size <= N.Offset) {
261d88c1a5aSDimitry Andric Elements.insert(nt, {Offset, Size, Name});
262d88c1a5aSDimitry Andric return Error::success();
263d88c1a5aSDimitry Andric }
264d88c1a5aSDimitry Andric }
265d88c1a5aSDimitry Andric }
266d88c1a5aSDimitry Andric Elements.push_back({Offset, Size, Name});
267d88c1a5aSDimitry Andric return Error::success();
268d88c1a5aSDimitry Andric }
269d88c1a5aSDimitry Andric
27097bc6c73SDimitry Andric // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
27197bc6c73SDimitry Andric // sections to \param Sections, and optionally sets
27297bc6c73SDimitry Andric // \param IsPageZeroSegment to true.
273d88c1a5aSDimitry Andric template <typename Segment, typename Section>
parseSegmentLoadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & Sections,bool & IsPageZeroSegment,uint32_t LoadCommandIndex,const char * CmdName,uint64_t SizeOfHeaders,std::list<MachOElement> & Elements)2743ca95b02SDimitry Andric static Error parseSegmentLoadCommand(
275d88c1a5aSDimitry Andric const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
2763ca95b02SDimitry Andric SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
277d88c1a5aSDimitry Andric uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
278d88c1a5aSDimitry Andric std::list<MachOElement> &Elements) {
279d88c1a5aSDimitry Andric const unsigned SegmentLoadSize = sizeof(Segment);
28097bc6c73SDimitry Andric if (Load.C.cmdsize < SegmentLoadSize)
2813ca95b02SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
2823ca95b02SDimitry Andric " " + CmdName + " cmdsize too small");
283d88c1a5aSDimitry Andric if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
284d88c1a5aSDimitry Andric Segment S = SegOrErr.get();
285d88c1a5aSDimitry Andric const unsigned SectionSize = sizeof(Section);
286d88c1a5aSDimitry Andric uint64_t FileSize = Obj.getData().size();
28797bc6c73SDimitry Andric if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
28897bc6c73SDimitry Andric S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
2893ca95b02SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
2903ca95b02SDimitry Andric " inconsistent cmdsize in " + CmdName +
2913ca95b02SDimitry Andric " for the number of sections");
29297bc6c73SDimitry Andric for (unsigned J = 0; J < S.nsects; ++J) {
29397bc6c73SDimitry Andric const char *Sec = getSectionPtr(Obj, Load, J);
29497bc6c73SDimitry Andric Sections.push_back(Sec);
295d88c1a5aSDimitry Andric Section s = getStruct<Section>(Obj, Sec);
296d88c1a5aSDimitry Andric if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
297d88c1a5aSDimitry Andric Obj.getHeader().filetype != MachO::MH_DSYM &&
298d88c1a5aSDimitry Andric s.flags != MachO::S_ZEROFILL &&
299d88c1a5aSDimitry Andric s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
300d88c1a5aSDimitry Andric s.offset > FileSize)
301d88c1a5aSDimitry Andric return malformedError("offset field of section " + Twine(J) + " in " +
302d88c1a5aSDimitry Andric CmdName + " command " + Twine(LoadCommandIndex) +
303d88c1a5aSDimitry Andric " extends past the end of the file");
304d88c1a5aSDimitry Andric if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
305d88c1a5aSDimitry Andric Obj.getHeader().filetype != MachO::MH_DSYM &&
306d88c1a5aSDimitry Andric s.flags != MachO::S_ZEROFILL &&
307d88c1a5aSDimitry Andric s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
308d88c1a5aSDimitry Andric s.offset < SizeOfHeaders && s.size != 0)
309d88c1a5aSDimitry Andric return malformedError("offset field of section " + Twine(J) + " in " +
310d88c1a5aSDimitry Andric CmdName + " command " + Twine(LoadCommandIndex) +
311d88c1a5aSDimitry Andric " not past the headers of the file");
312d88c1a5aSDimitry Andric uint64_t BigSize = s.offset;
313d88c1a5aSDimitry Andric BigSize += s.size;
314d88c1a5aSDimitry Andric if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
315d88c1a5aSDimitry Andric Obj.getHeader().filetype != MachO::MH_DSYM &&
316d88c1a5aSDimitry Andric s.flags != MachO::S_ZEROFILL &&
317d88c1a5aSDimitry Andric s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
318d88c1a5aSDimitry Andric BigSize > FileSize)
319d88c1a5aSDimitry Andric return malformedError("offset field plus size field of section " +
320d88c1a5aSDimitry Andric Twine(J) + " in " + CmdName + " command " +
321d88c1a5aSDimitry Andric Twine(LoadCommandIndex) +
322d88c1a5aSDimitry Andric " extends past the end of the file");
323d88c1a5aSDimitry Andric if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
324d88c1a5aSDimitry Andric Obj.getHeader().filetype != MachO::MH_DSYM &&
325d88c1a5aSDimitry Andric s.flags != MachO::S_ZEROFILL &&
326d88c1a5aSDimitry Andric s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
327d88c1a5aSDimitry Andric s.size > S.filesize)
328d88c1a5aSDimitry Andric return malformedError("size field of section " +
329d88c1a5aSDimitry Andric Twine(J) + " in " + CmdName + " command " +
330d88c1a5aSDimitry Andric Twine(LoadCommandIndex) +
331d88c1a5aSDimitry Andric " greater than the segment");
332d88c1a5aSDimitry Andric if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
333d88c1a5aSDimitry Andric Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
334d88c1a5aSDimitry Andric s.addr < S.vmaddr)
335d88c1a5aSDimitry Andric return malformedError("addr field of section " + Twine(J) + " in " +
336d88c1a5aSDimitry Andric CmdName + " command " + Twine(LoadCommandIndex) +
337d88c1a5aSDimitry Andric " less than the segment's vmaddr");
338d88c1a5aSDimitry Andric BigSize = s.addr;
339d88c1a5aSDimitry Andric BigSize += s.size;
340d88c1a5aSDimitry Andric uint64_t BigEnd = S.vmaddr;
341d88c1a5aSDimitry Andric BigEnd += S.vmsize;
342d88c1a5aSDimitry Andric if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
343d88c1a5aSDimitry Andric return malformedError("addr field plus size of section " + Twine(J) +
344d88c1a5aSDimitry Andric " in " + CmdName + " command " +
345d88c1a5aSDimitry Andric Twine(LoadCommandIndex) +
346d88c1a5aSDimitry Andric " greater than than "
347d88c1a5aSDimitry Andric "the segment's vmaddr plus vmsize");
348d88c1a5aSDimitry Andric if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
349d88c1a5aSDimitry Andric Obj.getHeader().filetype != MachO::MH_DSYM &&
350d88c1a5aSDimitry Andric s.flags != MachO::S_ZEROFILL &&
351d88c1a5aSDimitry Andric s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
352d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
353d88c1a5aSDimitry Andric "section contents"))
354d88c1a5aSDimitry Andric return Err;
355d88c1a5aSDimitry Andric if (s.reloff > FileSize)
356d88c1a5aSDimitry Andric return malformedError("reloff field of section " + Twine(J) + " in " +
357d88c1a5aSDimitry Andric CmdName + " command " + Twine(LoadCommandIndex) +
358d88c1a5aSDimitry Andric " extends past the end of the file");
359d88c1a5aSDimitry Andric BigSize = s.nreloc;
360d88c1a5aSDimitry Andric BigSize *= sizeof(struct MachO::relocation_info);
361d88c1a5aSDimitry Andric BigSize += s.reloff;
362d88c1a5aSDimitry Andric if (BigSize > FileSize)
363d88c1a5aSDimitry Andric return malformedError("reloff field plus nreloc field times sizeof("
364d88c1a5aSDimitry Andric "struct relocation_info) of section " +
365d88c1a5aSDimitry Andric Twine(J) + " in " + CmdName + " command " +
366d88c1a5aSDimitry Andric Twine(LoadCommandIndex) +
367d88c1a5aSDimitry Andric " extends past the end of the file");
368d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
369d88c1a5aSDimitry Andric sizeof(struct
370d88c1a5aSDimitry Andric MachO::relocation_info),
371d88c1a5aSDimitry Andric "section relocation entries"))
372d88c1a5aSDimitry Andric return Err;
37397bc6c73SDimitry Andric }
374d88c1a5aSDimitry Andric if (S.fileoff > FileSize)
375d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
376d88c1a5aSDimitry Andric " fileoff field in " + CmdName +
377d88c1a5aSDimitry Andric " extends past the end of the file");
378d88c1a5aSDimitry Andric uint64_t BigSize = S.fileoff;
379d88c1a5aSDimitry Andric BigSize += S.filesize;
380d88c1a5aSDimitry Andric if (BigSize > FileSize)
381d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
382d88c1a5aSDimitry Andric " fileoff field plus filesize field in " +
383d88c1a5aSDimitry Andric CmdName + " extends past the end of the file");
384d88c1a5aSDimitry Andric if (S.vmsize != 0 && S.filesize > S.vmsize)
385d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
3867a7e6055SDimitry Andric " filesize field in " + CmdName +
387d88c1a5aSDimitry Andric " greater than vmsize field");
38897bc6c73SDimitry Andric IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
3893ca95b02SDimitry Andric } else
3903ca95b02SDimitry Andric return SegOrErr.takeError();
3913ca95b02SDimitry Andric
3923ca95b02SDimitry Andric return Error::success();
3933ca95b02SDimitry Andric }
3943ca95b02SDimitry Andric
checkSymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** SymtabLoadCmd,std::list<MachOElement> & Elements)395d88c1a5aSDimitry Andric static Error checkSymtabCommand(const MachOObjectFile &Obj,
396d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
397d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
398d88c1a5aSDimitry Andric const char **SymtabLoadCmd,
399d88c1a5aSDimitry Andric std::list<MachOElement> &Elements) {
400d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::symtab_command))
401d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
402d88c1a5aSDimitry Andric " LC_SYMTAB cmdsize too small");
403d88c1a5aSDimitry Andric if (*SymtabLoadCmd != nullptr)
404d88c1a5aSDimitry Andric return malformedError("more than one LC_SYMTAB command");
405d88c1a5aSDimitry Andric MachO::symtab_command Symtab =
406d88c1a5aSDimitry Andric getStruct<MachO::symtab_command>(Obj, Load.Ptr);
407d88c1a5aSDimitry Andric if (Symtab.cmdsize != sizeof(MachO::symtab_command))
408d88c1a5aSDimitry Andric return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
409d88c1a5aSDimitry Andric " has incorrect cmdsize");
410d88c1a5aSDimitry Andric uint64_t FileSize = Obj.getData().size();
411d88c1a5aSDimitry Andric if (Symtab.symoff > FileSize)
412d88c1a5aSDimitry Andric return malformedError("symoff field of LC_SYMTAB command " +
413d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end "
414d88c1a5aSDimitry Andric "of the file");
415d88c1a5aSDimitry Andric uint64_t SymtabSize = Symtab.nsyms;
416d88c1a5aSDimitry Andric const char *struct_nlist_name;
417d88c1a5aSDimitry Andric if (Obj.is64Bit()) {
418d88c1a5aSDimitry Andric SymtabSize *= sizeof(MachO::nlist_64);
419d88c1a5aSDimitry Andric struct_nlist_name = "struct nlist_64";
420d88c1a5aSDimitry Andric } else {
421d88c1a5aSDimitry Andric SymtabSize *= sizeof(MachO::nlist);
422d88c1a5aSDimitry Andric struct_nlist_name = "struct nlist";
423d88c1a5aSDimitry Andric }
424d88c1a5aSDimitry Andric uint64_t BigSize = SymtabSize;
425d88c1a5aSDimitry Andric BigSize += Symtab.symoff;
426d88c1a5aSDimitry Andric if (BigSize > FileSize)
427d88c1a5aSDimitry Andric return malformedError("symoff field plus nsyms field times sizeof(" +
428d88c1a5aSDimitry Andric Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
429d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end "
430d88c1a5aSDimitry Andric "of the file");
431d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
432d88c1a5aSDimitry Andric "symbol table"))
433d88c1a5aSDimitry Andric return Err;
434d88c1a5aSDimitry Andric if (Symtab.stroff > FileSize)
435d88c1a5aSDimitry Andric return malformedError("stroff field of LC_SYMTAB command " +
436d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end "
437d88c1a5aSDimitry Andric "of the file");
438d88c1a5aSDimitry Andric BigSize = Symtab.stroff;
439d88c1a5aSDimitry Andric BigSize += Symtab.strsize;
440d88c1a5aSDimitry Andric if (BigSize > FileSize)
441d88c1a5aSDimitry Andric return malformedError("stroff field plus strsize field of LC_SYMTAB "
442d88c1a5aSDimitry Andric "command " + Twine(LoadCommandIndex) + " extends "
443d88c1a5aSDimitry Andric "past the end of the file");
444d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
445d88c1a5aSDimitry Andric Symtab.strsize, "string table"))
446d88c1a5aSDimitry Andric return Err;
447d88c1a5aSDimitry Andric *SymtabLoadCmd = Load.Ptr;
448d88c1a5aSDimitry Andric return Error::success();
449d88c1a5aSDimitry Andric }
450d88c1a5aSDimitry Andric
checkDysymtabCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** DysymtabLoadCmd,std::list<MachOElement> & Elements)451d88c1a5aSDimitry Andric static Error checkDysymtabCommand(const MachOObjectFile &Obj,
452d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
453d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
454d88c1a5aSDimitry Andric const char **DysymtabLoadCmd,
455d88c1a5aSDimitry Andric std::list<MachOElement> &Elements) {
456d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
457d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
458d88c1a5aSDimitry Andric " LC_DYSYMTAB cmdsize too small");
459d88c1a5aSDimitry Andric if (*DysymtabLoadCmd != nullptr)
460d88c1a5aSDimitry Andric return malformedError("more than one LC_DYSYMTAB command");
461d88c1a5aSDimitry Andric MachO::dysymtab_command Dysymtab =
462d88c1a5aSDimitry Andric getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
463d88c1a5aSDimitry Andric if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
464d88c1a5aSDimitry Andric return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
465d88c1a5aSDimitry Andric " has incorrect cmdsize");
466d88c1a5aSDimitry Andric uint64_t FileSize = Obj.getData().size();
467d88c1a5aSDimitry Andric if (Dysymtab.tocoff > FileSize)
468d88c1a5aSDimitry Andric return malformedError("tocoff field of LC_DYSYMTAB command " +
469d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
470d88c1a5aSDimitry Andric "the file");
471d88c1a5aSDimitry Andric uint64_t BigSize = Dysymtab.ntoc;
472d88c1a5aSDimitry Andric BigSize *= sizeof(MachO::dylib_table_of_contents);
473d88c1a5aSDimitry Andric BigSize += Dysymtab.tocoff;
474d88c1a5aSDimitry Andric if (BigSize > FileSize)
475d88c1a5aSDimitry Andric return malformedError("tocoff field plus ntoc field times sizeof(struct "
476d88c1a5aSDimitry Andric "dylib_table_of_contents) of LC_DYSYMTAB command " +
477d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
478d88c1a5aSDimitry Andric "the file");
479d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
480d88c1a5aSDimitry Andric Dysymtab.ntoc * sizeof(struct
481d88c1a5aSDimitry Andric MachO::dylib_table_of_contents),
482d88c1a5aSDimitry Andric "table of contents"))
483d88c1a5aSDimitry Andric return Err;
484d88c1a5aSDimitry Andric if (Dysymtab.modtaboff > FileSize)
485d88c1a5aSDimitry Andric return malformedError("modtaboff field of LC_DYSYMTAB command " +
486d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
487d88c1a5aSDimitry Andric "the file");
488d88c1a5aSDimitry Andric BigSize = Dysymtab.nmodtab;
489d88c1a5aSDimitry Andric const char *struct_dylib_module_name;
490d88c1a5aSDimitry Andric uint64_t sizeof_modtab;
491d88c1a5aSDimitry Andric if (Obj.is64Bit()) {
492d88c1a5aSDimitry Andric sizeof_modtab = sizeof(MachO::dylib_module_64);
493d88c1a5aSDimitry Andric struct_dylib_module_name = "struct dylib_module_64";
494d88c1a5aSDimitry Andric } else {
495d88c1a5aSDimitry Andric sizeof_modtab = sizeof(MachO::dylib_module);
496d88c1a5aSDimitry Andric struct_dylib_module_name = "struct dylib_module";
497d88c1a5aSDimitry Andric }
498d88c1a5aSDimitry Andric BigSize *= sizeof_modtab;
499d88c1a5aSDimitry Andric BigSize += Dysymtab.modtaboff;
500d88c1a5aSDimitry Andric if (BigSize > FileSize)
501d88c1a5aSDimitry Andric return malformedError("modtaboff field plus nmodtab field times sizeof(" +
502d88c1a5aSDimitry Andric Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
503d88c1a5aSDimitry Andric "command " + Twine(LoadCommandIndex) + " extends "
504d88c1a5aSDimitry Andric "past the end of the file");
505d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
506d88c1a5aSDimitry Andric Dysymtab.nmodtab * sizeof_modtab,
507d88c1a5aSDimitry Andric "module table"))
508d88c1a5aSDimitry Andric return Err;
509d88c1a5aSDimitry Andric if (Dysymtab.extrefsymoff > FileSize)
510d88c1a5aSDimitry Andric return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
511d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
512d88c1a5aSDimitry Andric "the file");
513d88c1a5aSDimitry Andric BigSize = Dysymtab.nextrefsyms;
514d88c1a5aSDimitry Andric BigSize *= sizeof(MachO::dylib_reference);
515d88c1a5aSDimitry Andric BigSize += Dysymtab.extrefsymoff;
516d88c1a5aSDimitry Andric if (BigSize > FileSize)
517d88c1a5aSDimitry Andric return malformedError("extrefsymoff field plus nextrefsyms field times "
518d88c1a5aSDimitry Andric "sizeof(struct dylib_reference) of LC_DYSYMTAB "
519d88c1a5aSDimitry Andric "command " + Twine(LoadCommandIndex) + " extends "
520d88c1a5aSDimitry Andric "past the end of the file");
521d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
522d88c1a5aSDimitry Andric Dysymtab.nextrefsyms *
523d88c1a5aSDimitry Andric sizeof(MachO::dylib_reference),
524d88c1a5aSDimitry Andric "reference table"))
525d88c1a5aSDimitry Andric return Err;
526d88c1a5aSDimitry Andric if (Dysymtab.indirectsymoff > FileSize)
527d88c1a5aSDimitry Andric return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
528d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
529d88c1a5aSDimitry Andric "the file");
530d88c1a5aSDimitry Andric BigSize = Dysymtab.nindirectsyms;
531d88c1a5aSDimitry Andric BigSize *= sizeof(uint32_t);
532d88c1a5aSDimitry Andric BigSize += Dysymtab.indirectsymoff;
533d88c1a5aSDimitry Andric if (BigSize > FileSize)
534d88c1a5aSDimitry Andric return malformedError("indirectsymoff field plus nindirectsyms field times "
535d88c1a5aSDimitry Andric "sizeof(uint32_t) of LC_DYSYMTAB command " +
536d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
537d88c1a5aSDimitry Andric "the file");
538d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
539d88c1a5aSDimitry Andric Dysymtab.nindirectsyms *
540d88c1a5aSDimitry Andric sizeof(uint32_t),
541d88c1a5aSDimitry Andric "indirect table"))
542d88c1a5aSDimitry Andric return Err;
543d88c1a5aSDimitry Andric if (Dysymtab.extreloff > FileSize)
544d88c1a5aSDimitry Andric return malformedError("extreloff field of LC_DYSYMTAB command " +
545d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
546d88c1a5aSDimitry Andric "the file");
547d88c1a5aSDimitry Andric BigSize = Dysymtab.nextrel;
548d88c1a5aSDimitry Andric BigSize *= sizeof(MachO::relocation_info);
549d88c1a5aSDimitry Andric BigSize += Dysymtab.extreloff;
550d88c1a5aSDimitry Andric if (BigSize > FileSize)
551d88c1a5aSDimitry Andric return malformedError("extreloff field plus nextrel field times sizeof"
552d88c1a5aSDimitry Andric "(struct relocation_info) of LC_DYSYMTAB command " +
553d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
554d88c1a5aSDimitry Andric "the file");
555d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
556d88c1a5aSDimitry Andric Dysymtab.nextrel *
557d88c1a5aSDimitry Andric sizeof(MachO::relocation_info),
558d88c1a5aSDimitry Andric "external relocation table"))
559d88c1a5aSDimitry Andric return Err;
560d88c1a5aSDimitry Andric if (Dysymtab.locreloff > FileSize)
561d88c1a5aSDimitry Andric return malformedError("locreloff field of LC_DYSYMTAB command " +
562d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
563d88c1a5aSDimitry Andric "the file");
564d88c1a5aSDimitry Andric BigSize = Dysymtab.nlocrel;
565d88c1a5aSDimitry Andric BigSize *= sizeof(MachO::relocation_info);
566d88c1a5aSDimitry Andric BigSize += Dysymtab.locreloff;
567d88c1a5aSDimitry Andric if (BigSize > FileSize)
568d88c1a5aSDimitry Andric return malformedError("locreloff field plus nlocrel field times sizeof"
569d88c1a5aSDimitry Andric "(struct relocation_info) of LC_DYSYMTAB command " +
570d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
571d88c1a5aSDimitry Andric "the file");
572d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
573d88c1a5aSDimitry Andric Dysymtab.nlocrel *
574d88c1a5aSDimitry Andric sizeof(MachO::relocation_info),
575d88c1a5aSDimitry Andric "local relocation table"))
576d88c1a5aSDimitry Andric return Err;
577d88c1a5aSDimitry Andric *DysymtabLoadCmd = Load.Ptr;
578d88c1a5aSDimitry Andric return Error::success();
579d88c1a5aSDimitry Andric }
580d88c1a5aSDimitry Andric
checkLinkeditDataCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements,const char * ElementName)581d88c1a5aSDimitry Andric static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
582d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
583d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
584d88c1a5aSDimitry Andric const char **LoadCmd, const char *CmdName,
585d88c1a5aSDimitry Andric std::list<MachOElement> &Elements,
586d88c1a5aSDimitry Andric const char *ElementName) {
587d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
588d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
589d88c1a5aSDimitry Andric CmdName + " cmdsize too small");
590d88c1a5aSDimitry Andric if (*LoadCmd != nullptr)
591d88c1a5aSDimitry Andric return malformedError("more than one " + Twine(CmdName) + " command");
592d88c1a5aSDimitry Andric MachO::linkedit_data_command LinkData =
593d88c1a5aSDimitry Andric getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
594d88c1a5aSDimitry Andric if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
595d88c1a5aSDimitry Andric return malformedError(Twine(CmdName) + " command " +
596d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " has incorrect cmdsize");
597d88c1a5aSDimitry Andric uint64_t FileSize = Obj.getData().size();
598d88c1a5aSDimitry Andric if (LinkData.dataoff > FileSize)
599d88c1a5aSDimitry Andric return malformedError("dataoff field of " + Twine(CmdName) + " command " +
600d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
601d88c1a5aSDimitry Andric "the file");
602d88c1a5aSDimitry Andric uint64_t BigSize = LinkData.dataoff;
603d88c1a5aSDimitry Andric BigSize += LinkData.datasize;
604d88c1a5aSDimitry Andric if (BigSize > FileSize)
605d88c1a5aSDimitry Andric return malformedError("dataoff field plus datasize field of " +
606d88c1a5aSDimitry Andric Twine(CmdName) + " command " +
607d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
608d88c1a5aSDimitry Andric "the file");
609d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
610d88c1a5aSDimitry Andric LinkData.datasize, ElementName))
611d88c1a5aSDimitry Andric return Err;
612d88c1a5aSDimitry Andric *LoadCmd = Load.Ptr;
613d88c1a5aSDimitry Andric return Error::success();
614d88c1a5aSDimitry Andric }
615d88c1a5aSDimitry Andric
checkDyldInfoCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName,std::list<MachOElement> & Elements)616d88c1a5aSDimitry Andric static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
617d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
618d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
619d88c1a5aSDimitry Andric const char **LoadCmd, const char *CmdName,
620d88c1a5aSDimitry Andric std::list<MachOElement> &Elements) {
621d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
622d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
623d88c1a5aSDimitry Andric CmdName + " cmdsize too small");
624d88c1a5aSDimitry Andric if (*LoadCmd != nullptr)
625d88c1a5aSDimitry Andric return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
626d88c1a5aSDimitry Andric "command");
627d88c1a5aSDimitry Andric MachO::dyld_info_command DyldInfo =
628d88c1a5aSDimitry Andric getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
629d88c1a5aSDimitry Andric if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
630d88c1a5aSDimitry Andric return malformedError(Twine(CmdName) + " command " +
631d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " has incorrect cmdsize");
632d88c1a5aSDimitry Andric uint64_t FileSize = Obj.getData().size();
633d88c1a5aSDimitry Andric if (DyldInfo.rebase_off > FileSize)
634d88c1a5aSDimitry Andric return malformedError("rebase_off field of " + Twine(CmdName) +
635d88c1a5aSDimitry Andric " command " + Twine(LoadCommandIndex) + " extends "
636d88c1a5aSDimitry Andric "past the end of the file");
637d88c1a5aSDimitry Andric uint64_t BigSize = DyldInfo.rebase_off;
638d88c1a5aSDimitry Andric BigSize += DyldInfo.rebase_size;
639d88c1a5aSDimitry Andric if (BigSize > FileSize)
640d88c1a5aSDimitry Andric return malformedError("rebase_off field plus rebase_size field of " +
641d88c1a5aSDimitry Andric Twine(CmdName) + " command " +
642d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
643d88c1a5aSDimitry Andric "the file");
644d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
645d88c1a5aSDimitry Andric DyldInfo.rebase_size,
646d88c1a5aSDimitry Andric "dyld rebase info"))
647d88c1a5aSDimitry Andric return Err;
648d88c1a5aSDimitry Andric if (DyldInfo.bind_off > FileSize)
649d88c1a5aSDimitry Andric return malformedError("bind_off field of " + Twine(CmdName) +
650d88c1a5aSDimitry Andric " command " + Twine(LoadCommandIndex) + " extends "
651d88c1a5aSDimitry Andric "past the end of the file");
652d88c1a5aSDimitry Andric BigSize = DyldInfo.bind_off;
653d88c1a5aSDimitry Andric BigSize += DyldInfo.bind_size;
654d88c1a5aSDimitry Andric if (BigSize > FileSize)
655d88c1a5aSDimitry Andric return malformedError("bind_off field plus bind_size field of " +
656d88c1a5aSDimitry Andric Twine(CmdName) + " command " +
657d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
658d88c1a5aSDimitry Andric "the file");
659d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
660d88c1a5aSDimitry Andric DyldInfo.bind_size,
661d88c1a5aSDimitry Andric "dyld bind info"))
662d88c1a5aSDimitry Andric return Err;
663d88c1a5aSDimitry Andric if (DyldInfo.weak_bind_off > FileSize)
664d88c1a5aSDimitry Andric return malformedError("weak_bind_off field of " + Twine(CmdName) +
665d88c1a5aSDimitry Andric " command " + Twine(LoadCommandIndex) + " extends "
666d88c1a5aSDimitry Andric "past the end of the file");
667d88c1a5aSDimitry Andric BigSize = DyldInfo.weak_bind_off;
668d88c1a5aSDimitry Andric BigSize += DyldInfo.weak_bind_size;
669d88c1a5aSDimitry Andric if (BigSize > FileSize)
670d88c1a5aSDimitry Andric return malformedError("weak_bind_off field plus weak_bind_size field of " +
671d88c1a5aSDimitry Andric Twine(CmdName) + " command " +
672d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
673d88c1a5aSDimitry Andric "the file");
674d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
675d88c1a5aSDimitry Andric DyldInfo.weak_bind_size,
676d88c1a5aSDimitry Andric "dyld weak bind info"))
677d88c1a5aSDimitry Andric return Err;
678d88c1a5aSDimitry Andric if (DyldInfo.lazy_bind_off > FileSize)
679d88c1a5aSDimitry Andric return malformedError("lazy_bind_off field of " + Twine(CmdName) +
680d88c1a5aSDimitry Andric " command " + Twine(LoadCommandIndex) + " extends "
681d88c1a5aSDimitry Andric "past the end of the file");
682d88c1a5aSDimitry Andric BigSize = DyldInfo.lazy_bind_off;
683d88c1a5aSDimitry Andric BigSize += DyldInfo.lazy_bind_size;
684d88c1a5aSDimitry Andric if (BigSize > FileSize)
685d88c1a5aSDimitry Andric return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
686d88c1a5aSDimitry Andric Twine(CmdName) + " command " +
687d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
688d88c1a5aSDimitry Andric "the file");
689d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
690d88c1a5aSDimitry Andric DyldInfo.lazy_bind_size,
691d88c1a5aSDimitry Andric "dyld lazy bind info"))
692d88c1a5aSDimitry Andric return Err;
693d88c1a5aSDimitry Andric if (DyldInfo.export_off > FileSize)
694d88c1a5aSDimitry Andric return malformedError("export_off field of " + Twine(CmdName) +
695d88c1a5aSDimitry Andric " command " + Twine(LoadCommandIndex) + " extends "
696d88c1a5aSDimitry Andric "past the end of the file");
697d88c1a5aSDimitry Andric BigSize = DyldInfo.export_off;
698d88c1a5aSDimitry Andric BigSize += DyldInfo.export_size;
699d88c1a5aSDimitry Andric if (BigSize > FileSize)
700d88c1a5aSDimitry Andric return malformedError("export_off field plus export_size field of " +
701d88c1a5aSDimitry Andric Twine(CmdName) + " command " +
702d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
703d88c1a5aSDimitry Andric "the file");
704d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
705d88c1a5aSDimitry Andric DyldInfo.export_size,
706d88c1a5aSDimitry Andric "dyld export info"))
707d88c1a5aSDimitry Andric return Err;
708d88c1a5aSDimitry Andric *LoadCmd = Load.Ptr;
709d88c1a5aSDimitry Andric return Error::success();
710d88c1a5aSDimitry Andric }
711d88c1a5aSDimitry Andric
checkDylibCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)712d88c1a5aSDimitry Andric static Error checkDylibCommand(const MachOObjectFile &Obj,
713d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
714d88c1a5aSDimitry Andric uint32_t LoadCommandIndex, const char *CmdName) {
715d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::dylib_command))
716d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
717d88c1a5aSDimitry Andric CmdName + " cmdsize too small");
718d88c1a5aSDimitry Andric MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
719d88c1a5aSDimitry Andric if (D.dylib.name < sizeof(MachO::dylib_command))
720d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
721d88c1a5aSDimitry Andric CmdName + " name.offset field too small, not past "
722d88c1a5aSDimitry Andric "the end of the dylib_command struct");
723d88c1a5aSDimitry Andric if (D.dylib.name >= D.cmdsize)
724d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
725d88c1a5aSDimitry Andric CmdName + " name.offset field extends past the end "
726d88c1a5aSDimitry Andric "of the load command");
727d88c1a5aSDimitry Andric // Make sure there is a null between the starting offset of the name and
728d88c1a5aSDimitry Andric // the end of the load command.
729d88c1a5aSDimitry Andric uint32_t i;
730d88c1a5aSDimitry Andric const char *P = (const char *)Load.Ptr;
731d88c1a5aSDimitry Andric for (i = D.dylib.name; i < D.cmdsize; i++)
732d88c1a5aSDimitry Andric if (P[i] == '\0')
733d88c1a5aSDimitry Andric break;
734d88c1a5aSDimitry Andric if (i >= D.cmdsize)
735d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
736d88c1a5aSDimitry Andric CmdName + " library name extends past the end of the "
737d88c1a5aSDimitry Andric "load command");
738d88c1a5aSDimitry Andric return Error::success();
739d88c1a5aSDimitry Andric }
740d88c1a5aSDimitry Andric
checkDylibIdCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd)741d88c1a5aSDimitry Andric static Error checkDylibIdCommand(const MachOObjectFile &Obj,
742d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
743d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
744d88c1a5aSDimitry Andric const char **LoadCmd) {
745d88c1a5aSDimitry Andric if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
746d88c1a5aSDimitry Andric "LC_ID_DYLIB"))
747d88c1a5aSDimitry Andric return Err;
748d88c1a5aSDimitry Andric if (*LoadCmd != nullptr)
749d88c1a5aSDimitry Andric return malformedError("more than one LC_ID_DYLIB command");
750d88c1a5aSDimitry Andric if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
751d88c1a5aSDimitry Andric Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
752d88c1a5aSDimitry Andric return malformedError("LC_ID_DYLIB load command in non-dynamic library "
753d88c1a5aSDimitry Andric "file type");
754d88c1a5aSDimitry Andric *LoadCmd = Load.Ptr;
755d88c1a5aSDimitry Andric return Error::success();
756d88c1a5aSDimitry Andric }
757d88c1a5aSDimitry Andric
checkDyldCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)758d88c1a5aSDimitry Andric static Error checkDyldCommand(const MachOObjectFile &Obj,
759d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
760d88c1a5aSDimitry Andric uint32_t LoadCommandIndex, const char *CmdName) {
761d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
762d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
763d88c1a5aSDimitry Andric CmdName + " cmdsize too small");
764d88c1a5aSDimitry Andric MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
765d88c1a5aSDimitry Andric if (D.name < sizeof(MachO::dylinker_command))
766d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
767d88c1a5aSDimitry Andric CmdName + " name.offset field too small, not past "
768d88c1a5aSDimitry Andric "the end of the dylinker_command struct");
769d88c1a5aSDimitry Andric if (D.name >= D.cmdsize)
770d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
771d88c1a5aSDimitry Andric CmdName + " name.offset field extends past the end "
772d88c1a5aSDimitry Andric "of the load command");
773d88c1a5aSDimitry Andric // Make sure there is a null between the starting offset of the name and
774d88c1a5aSDimitry Andric // the end of the load command.
775d88c1a5aSDimitry Andric uint32_t i;
776d88c1a5aSDimitry Andric const char *P = (const char *)Load.Ptr;
777d88c1a5aSDimitry Andric for (i = D.name; i < D.cmdsize; i++)
778d88c1a5aSDimitry Andric if (P[i] == '\0')
779d88c1a5aSDimitry Andric break;
780d88c1a5aSDimitry Andric if (i >= D.cmdsize)
781d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
782d88c1a5aSDimitry Andric CmdName + " dyld name extends past the end of the "
783d88c1a5aSDimitry Andric "load command");
784d88c1a5aSDimitry Andric return Error::success();
785d88c1a5aSDimitry Andric }
786d88c1a5aSDimitry Andric
checkVersCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,const char * CmdName)787d88c1a5aSDimitry Andric static Error checkVersCommand(const MachOObjectFile &Obj,
788d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
789d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
790d88c1a5aSDimitry Andric const char **LoadCmd, const char *CmdName) {
791d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::version_min_command))
792d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
793d88c1a5aSDimitry Andric CmdName + " has incorrect cmdsize");
794d88c1a5aSDimitry Andric if (*LoadCmd != nullptr)
795d88c1a5aSDimitry Andric return malformedError("more than one LC_VERSION_MIN_MACOSX, "
796d88c1a5aSDimitry Andric "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
797d88c1a5aSDimitry Andric "LC_VERSION_MIN_WATCHOS command");
798d88c1a5aSDimitry Andric *LoadCmd = Load.Ptr;
799d88c1a5aSDimitry Andric return Error::success();
800d88c1a5aSDimitry Andric }
801d88c1a5aSDimitry Andric
checkNoteCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,std::list<MachOElement> & Elements)8027a7e6055SDimitry Andric static Error checkNoteCommand(const MachOObjectFile &Obj,
8037a7e6055SDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
8047a7e6055SDimitry Andric uint32_t LoadCommandIndex,
8057a7e6055SDimitry Andric std::list<MachOElement> &Elements) {
8067a7e6055SDimitry Andric if (Load.C.cmdsize != sizeof(MachO::note_command))
8077a7e6055SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
8087a7e6055SDimitry Andric " LC_NOTE has incorrect cmdsize");
8097a7e6055SDimitry Andric MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
8107a7e6055SDimitry Andric uint64_t FileSize = Obj.getData().size();
8117a7e6055SDimitry Andric if (Nt.offset > FileSize)
8127a7e6055SDimitry Andric return malformedError("offset field of LC_NOTE command " +
8137a7e6055SDimitry Andric Twine(LoadCommandIndex) + " extends "
8147a7e6055SDimitry Andric "past the end of the file");
8157a7e6055SDimitry Andric uint64_t BigSize = Nt.offset;
8167a7e6055SDimitry Andric BigSize += Nt.size;
8177a7e6055SDimitry Andric if (BigSize > FileSize)
8187a7e6055SDimitry Andric return malformedError("size field plus offset field of LC_NOTE command " +
8197a7e6055SDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
8207a7e6055SDimitry Andric "the file");
8217a7e6055SDimitry Andric if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
8227a7e6055SDimitry Andric "LC_NOTE data"))
8237a7e6055SDimitry Andric return Err;
8247a7e6055SDimitry Andric return Error::success();
8257a7e6055SDimitry Andric }
8267a7e6055SDimitry Andric
8277a7e6055SDimitry Andric static Error
parseBuildVersionCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & BuildTools,uint32_t LoadCommandIndex)8287a7e6055SDimitry Andric parseBuildVersionCommand(const MachOObjectFile &Obj,
8297a7e6055SDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
8307a7e6055SDimitry Andric SmallVectorImpl<const char*> &BuildTools,
8317a7e6055SDimitry Andric uint32_t LoadCommandIndex) {
8327a7e6055SDimitry Andric MachO::build_version_command BVC =
8337a7e6055SDimitry Andric getStruct<MachO::build_version_command>(Obj, Load.Ptr);
8347a7e6055SDimitry Andric if (Load.C.cmdsize !=
8357a7e6055SDimitry Andric sizeof(MachO::build_version_command) +
8367a7e6055SDimitry Andric BVC.ntools * sizeof(MachO::build_tool_version))
8377a7e6055SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
8387a7e6055SDimitry Andric " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
8397a7e6055SDimitry Andric
8407a7e6055SDimitry Andric auto Start = Load.Ptr + sizeof(MachO::build_version_command);
8417a7e6055SDimitry Andric BuildTools.resize(BVC.ntools);
8427a7e6055SDimitry Andric for (unsigned i = 0; i < BVC.ntools; ++i)
8437a7e6055SDimitry Andric BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
8447a7e6055SDimitry Andric
8457a7e6055SDimitry Andric return Error::success();
8467a7e6055SDimitry Andric }
8477a7e6055SDimitry Andric
checkRpathCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)848d88c1a5aSDimitry Andric static Error checkRpathCommand(const MachOObjectFile &Obj,
849d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
850d88c1a5aSDimitry Andric uint32_t LoadCommandIndex) {
851d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::rpath_command))
852d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
853d88c1a5aSDimitry Andric " LC_RPATH cmdsize too small");
854d88c1a5aSDimitry Andric MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
855d88c1a5aSDimitry Andric if (R.path < sizeof(MachO::rpath_command))
856d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
857d88c1a5aSDimitry Andric " LC_RPATH path.offset field too small, not past "
858d88c1a5aSDimitry Andric "the end of the rpath_command struct");
859d88c1a5aSDimitry Andric if (R.path >= R.cmdsize)
860d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
861d88c1a5aSDimitry Andric " LC_RPATH path.offset field extends past the end "
862d88c1a5aSDimitry Andric "of the load command");
863d88c1a5aSDimitry Andric // Make sure there is a null between the starting offset of the path and
864d88c1a5aSDimitry Andric // the end of the load command.
865d88c1a5aSDimitry Andric uint32_t i;
866d88c1a5aSDimitry Andric const char *P = (const char *)Load.Ptr;
867d88c1a5aSDimitry Andric for (i = R.path; i < R.cmdsize; i++)
868d88c1a5aSDimitry Andric if (P[i] == '\0')
869d88c1a5aSDimitry Andric break;
870d88c1a5aSDimitry Andric if (i >= R.cmdsize)
871d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
872d88c1a5aSDimitry Andric " LC_RPATH library name extends past the end of the "
873d88c1a5aSDimitry Andric "load command");
874d88c1a5aSDimitry Andric return Error::success();
875d88c1a5aSDimitry Andric }
876d88c1a5aSDimitry Andric
checkEncryptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,uint64_t cryptoff,uint64_t cryptsize,const char ** LoadCmd,const char * CmdName)877d88c1a5aSDimitry Andric static Error checkEncryptCommand(const MachOObjectFile &Obj,
878d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
879d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
880d88c1a5aSDimitry Andric uint64_t cryptoff, uint64_t cryptsize,
881d88c1a5aSDimitry Andric const char **LoadCmd, const char *CmdName) {
882d88c1a5aSDimitry Andric if (*LoadCmd != nullptr)
883d88c1a5aSDimitry Andric return malformedError("more than one LC_ENCRYPTION_INFO and or "
884d88c1a5aSDimitry Andric "LC_ENCRYPTION_INFO_64 command");
885d88c1a5aSDimitry Andric uint64_t FileSize = Obj.getData().size();
886d88c1a5aSDimitry Andric if (cryptoff > FileSize)
887d88c1a5aSDimitry Andric return malformedError("cryptoff field of " + Twine(CmdName) +
888d88c1a5aSDimitry Andric " command " + Twine(LoadCommandIndex) + " extends "
889d88c1a5aSDimitry Andric "past the end of the file");
890d88c1a5aSDimitry Andric uint64_t BigSize = cryptoff;
891d88c1a5aSDimitry Andric BigSize += cryptsize;
892d88c1a5aSDimitry Andric if (BigSize > FileSize)
893d88c1a5aSDimitry Andric return malformedError("cryptoff field plus cryptsize field of " +
894d88c1a5aSDimitry Andric Twine(CmdName) + " command " +
895d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
896d88c1a5aSDimitry Andric "the file");
897d88c1a5aSDimitry Andric *LoadCmd = Load.Ptr;
898d88c1a5aSDimitry Andric return Error::success();
899d88c1a5aSDimitry Andric }
900d88c1a5aSDimitry Andric
checkLinkerOptCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex)901d88c1a5aSDimitry Andric static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
902d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
903d88c1a5aSDimitry Andric uint32_t LoadCommandIndex) {
904d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
905d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
906d88c1a5aSDimitry Andric " LC_LINKER_OPTION cmdsize too small");
907d88c1a5aSDimitry Andric MachO::linker_option_command L =
908d88c1a5aSDimitry Andric getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
909d88c1a5aSDimitry Andric // Make sure the count of strings is correct.
910d88c1a5aSDimitry Andric const char *string = (const char *)Load.Ptr +
911d88c1a5aSDimitry Andric sizeof(struct MachO::linker_option_command);
912d88c1a5aSDimitry Andric uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
913d88c1a5aSDimitry Andric uint32_t i = 0;
914d88c1a5aSDimitry Andric while (left > 0) {
915d88c1a5aSDimitry Andric while (*string == '\0' && left > 0) {
916d88c1a5aSDimitry Andric string++;
917d88c1a5aSDimitry Andric left--;
918d88c1a5aSDimitry Andric }
919d88c1a5aSDimitry Andric if (left > 0) {
920d88c1a5aSDimitry Andric i++;
921d88c1a5aSDimitry Andric uint32_t NullPos = StringRef(string, left).find('\0');
922d88c1a5aSDimitry Andric uint32_t len = std::min(NullPos, left) + 1;
923d88c1a5aSDimitry Andric string += len;
924d88c1a5aSDimitry Andric left -= len;
925d88c1a5aSDimitry Andric }
926d88c1a5aSDimitry Andric }
927d88c1a5aSDimitry Andric if (L.count != i)
928d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
929d88c1a5aSDimitry Andric " LC_LINKER_OPTION string count " + Twine(L.count) +
930d88c1a5aSDimitry Andric " does not match number of strings");
931d88c1a5aSDimitry Andric return Error::success();
932d88c1a5aSDimitry Andric }
933d88c1a5aSDimitry Andric
checkSubCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName,size_t SizeOfCmd,const char * CmdStructName,uint32_t PathOffset,const char * PathFieldName)934d88c1a5aSDimitry Andric static Error checkSubCommand(const MachOObjectFile &Obj,
935d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
936d88c1a5aSDimitry Andric uint32_t LoadCommandIndex, const char *CmdName,
937d88c1a5aSDimitry Andric size_t SizeOfCmd, const char *CmdStructName,
938d88c1a5aSDimitry Andric uint32_t PathOffset, const char *PathFieldName) {
939d88c1a5aSDimitry Andric if (PathOffset < SizeOfCmd)
940d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
941d88c1a5aSDimitry Andric CmdName + " " + PathFieldName + ".offset field too "
942d88c1a5aSDimitry Andric "small, not past the end of the " + CmdStructName);
943d88c1a5aSDimitry Andric if (PathOffset >= Load.C.cmdsize)
944d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
945d88c1a5aSDimitry Andric CmdName + " " + PathFieldName + ".offset field "
946d88c1a5aSDimitry Andric "extends past the end of the load command");
947d88c1a5aSDimitry Andric // Make sure there is a null between the starting offset of the path and
948d88c1a5aSDimitry Andric // the end of the load command.
949d88c1a5aSDimitry Andric uint32_t i;
950d88c1a5aSDimitry Andric const char *P = (const char *)Load.Ptr;
951d88c1a5aSDimitry Andric for (i = PathOffset; i < Load.C.cmdsize; i++)
952d88c1a5aSDimitry Andric if (P[i] == '\0')
953d88c1a5aSDimitry Andric break;
954d88c1a5aSDimitry Andric if (i >= Load.C.cmdsize)
955d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) + " " +
956d88c1a5aSDimitry Andric CmdName + " " + PathFieldName + " name extends past "
957d88c1a5aSDimitry Andric "the end of the load command");
958d88c1a5aSDimitry Andric return Error::success();
959d88c1a5aSDimitry Andric }
960d88c1a5aSDimitry Andric
checkThreadCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char * CmdName)961d88c1a5aSDimitry Andric static Error checkThreadCommand(const MachOObjectFile &Obj,
962d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo &Load,
963d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
964d88c1a5aSDimitry Andric const char *CmdName) {
965d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::thread_command))
966d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
967d88c1a5aSDimitry Andric CmdName + " cmdsize too small");
968d88c1a5aSDimitry Andric MachO::thread_command T =
969d88c1a5aSDimitry Andric getStruct<MachO::thread_command>(Obj, Load.Ptr);
970d88c1a5aSDimitry Andric const char *state = Load.Ptr + sizeof(MachO::thread_command);
971d88c1a5aSDimitry Andric const char *end = Load.Ptr + T.cmdsize;
972d88c1a5aSDimitry Andric uint32_t nflavor = 0;
973d88c1a5aSDimitry Andric uint32_t cputype = getCPUType(Obj);
974d88c1a5aSDimitry Andric while (state < end) {
975d88c1a5aSDimitry Andric if(state + sizeof(uint32_t) > end)
976d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
977d88c1a5aSDimitry Andric "flavor in " + CmdName + " extends past end of "
978d88c1a5aSDimitry Andric "command");
979d88c1a5aSDimitry Andric uint32_t flavor;
980d88c1a5aSDimitry Andric memcpy(&flavor, state, sizeof(uint32_t));
981d88c1a5aSDimitry Andric if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
982d88c1a5aSDimitry Andric sys::swapByteOrder(flavor);
983d88c1a5aSDimitry Andric state += sizeof(uint32_t);
984d88c1a5aSDimitry Andric
985d88c1a5aSDimitry Andric if(state + sizeof(uint32_t) > end)
986d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
987d88c1a5aSDimitry Andric " count in " + CmdName + " extends past end of "
988d88c1a5aSDimitry Andric "command");
989d88c1a5aSDimitry Andric uint32_t count;
990d88c1a5aSDimitry Andric memcpy(&count, state, sizeof(uint32_t));
991d88c1a5aSDimitry Andric if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
992d88c1a5aSDimitry Andric sys::swapByteOrder(count);
993d88c1a5aSDimitry Andric state += sizeof(uint32_t);
994d88c1a5aSDimitry Andric
9957a7e6055SDimitry Andric if (cputype == MachO::CPU_TYPE_I386) {
9967a7e6055SDimitry Andric if (flavor == MachO::x86_THREAD_STATE32) {
9977a7e6055SDimitry Andric if (count != MachO::x86_THREAD_STATE32_COUNT)
9987a7e6055SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
9997a7e6055SDimitry Andric " count not x86_THREAD_STATE32_COUNT for "
10007a7e6055SDimitry Andric "flavor number " + Twine(nflavor) + " which is "
10017a7e6055SDimitry Andric "a x86_THREAD_STATE32 flavor in " + CmdName +
10027a7e6055SDimitry Andric " command");
10037a7e6055SDimitry Andric if (state + sizeof(MachO::x86_thread_state32_t) > end)
10047a7e6055SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10057a7e6055SDimitry Andric " x86_THREAD_STATE32 extends past end of "
10067a7e6055SDimitry Andric "command in " + CmdName + " command");
10077a7e6055SDimitry Andric state += sizeof(MachO::x86_thread_state32_t);
10087a7e6055SDimitry Andric } else {
10097a7e6055SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10107a7e6055SDimitry Andric " unknown flavor (" + Twine(flavor) + ") for "
10117a7e6055SDimitry Andric "flavor number " + Twine(nflavor) + " in " +
10127a7e6055SDimitry Andric CmdName + " command");
10137a7e6055SDimitry Andric }
10147a7e6055SDimitry Andric } else if (cputype == MachO::CPU_TYPE_X86_64) {
10154ba319b5SDimitry Andric if (flavor == MachO::x86_THREAD_STATE) {
10164ba319b5SDimitry Andric if (count != MachO::x86_THREAD_STATE_COUNT)
10174ba319b5SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10184ba319b5SDimitry Andric " count not x86_THREAD_STATE_COUNT for "
10194ba319b5SDimitry Andric "flavor number " + Twine(nflavor) + " which is "
10204ba319b5SDimitry Andric "a x86_THREAD_STATE flavor in " + CmdName +
10214ba319b5SDimitry Andric " command");
10224ba319b5SDimitry Andric if (state + sizeof(MachO::x86_thread_state_t) > end)
10234ba319b5SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10244ba319b5SDimitry Andric " x86_THREAD_STATE extends past end of "
10254ba319b5SDimitry Andric "command in " + CmdName + " command");
10264ba319b5SDimitry Andric state += sizeof(MachO::x86_thread_state_t);
10274ba319b5SDimitry Andric } else if (flavor == MachO::x86_FLOAT_STATE) {
10284ba319b5SDimitry Andric if (count != MachO::x86_FLOAT_STATE_COUNT)
10294ba319b5SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10304ba319b5SDimitry Andric " count not x86_FLOAT_STATE_COUNT for "
10314ba319b5SDimitry Andric "flavor number " + Twine(nflavor) + " which is "
10324ba319b5SDimitry Andric "a x86_FLOAT_STATE flavor in " + CmdName +
10334ba319b5SDimitry Andric " command");
10344ba319b5SDimitry Andric if (state + sizeof(MachO::x86_float_state_t) > end)
10354ba319b5SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10364ba319b5SDimitry Andric " x86_FLOAT_STATE extends past end of "
10374ba319b5SDimitry Andric "command in " + CmdName + " command");
10384ba319b5SDimitry Andric state += sizeof(MachO::x86_float_state_t);
10394ba319b5SDimitry Andric } else if (flavor == MachO::x86_EXCEPTION_STATE) {
10404ba319b5SDimitry Andric if (count != MachO::x86_EXCEPTION_STATE_COUNT)
10414ba319b5SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10424ba319b5SDimitry Andric " count not x86_EXCEPTION_STATE_COUNT for "
10434ba319b5SDimitry Andric "flavor number " + Twine(nflavor) + " which is "
10444ba319b5SDimitry Andric "a x86_EXCEPTION_STATE flavor in " + CmdName +
10454ba319b5SDimitry Andric " command");
10464ba319b5SDimitry Andric if (state + sizeof(MachO::x86_exception_state_t) > end)
10474ba319b5SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10484ba319b5SDimitry Andric " x86_EXCEPTION_STATE extends past end of "
10494ba319b5SDimitry Andric "command in " + CmdName + " command");
10504ba319b5SDimitry Andric state += sizeof(MachO::x86_exception_state_t);
10514ba319b5SDimitry Andric } else if (flavor == MachO::x86_THREAD_STATE64) {
1052d88c1a5aSDimitry Andric if (count != MachO::x86_THREAD_STATE64_COUNT)
1053d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1054d88c1a5aSDimitry Andric " count not x86_THREAD_STATE64_COUNT for "
1055d88c1a5aSDimitry Andric "flavor number " + Twine(nflavor) + " which is "
1056d88c1a5aSDimitry Andric "a x86_THREAD_STATE64 flavor in " + CmdName +
1057d88c1a5aSDimitry Andric " command");
1058d88c1a5aSDimitry Andric if (state + sizeof(MachO::x86_thread_state64_t) > end)
1059d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1060d88c1a5aSDimitry Andric " x86_THREAD_STATE64 extends past end of "
1061d88c1a5aSDimitry Andric "command in " + CmdName + " command");
1062d88c1a5aSDimitry Andric state += sizeof(MachO::x86_thread_state64_t);
10634ba319b5SDimitry Andric } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
10644ba319b5SDimitry Andric if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
10654ba319b5SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10664ba319b5SDimitry Andric " count not x86_EXCEPTION_STATE64_COUNT for "
10674ba319b5SDimitry Andric "flavor number " + Twine(nflavor) + " which is "
10684ba319b5SDimitry Andric "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
10694ba319b5SDimitry Andric " command");
10704ba319b5SDimitry Andric if (state + sizeof(MachO::x86_exception_state64_t) > end)
10714ba319b5SDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
10724ba319b5SDimitry Andric " x86_EXCEPTION_STATE64 extends past end of "
10734ba319b5SDimitry Andric "command in " + CmdName + " command");
10744ba319b5SDimitry Andric state += sizeof(MachO::x86_exception_state64_t);
1075d88c1a5aSDimitry Andric } else {
1076d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1077d88c1a5aSDimitry Andric " unknown flavor (" + Twine(flavor) + ") for "
1078d88c1a5aSDimitry Andric "flavor number " + Twine(nflavor) + " in " +
1079d88c1a5aSDimitry Andric CmdName + " command");
1080d88c1a5aSDimitry Andric }
1081d88c1a5aSDimitry Andric } else if (cputype == MachO::CPU_TYPE_ARM) {
1082d88c1a5aSDimitry Andric if (flavor == MachO::ARM_THREAD_STATE) {
1083d88c1a5aSDimitry Andric if (count != MachO::ARM_THREAD_STATE_COUNT)
1084d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1085d88c1a5aSDimitry Andric " count not ARM_THREAD_STATE_COUNT for "
1086d88c1a5aSDimitry Andric "flavor number " + Twine(nflavor) + " which is "
1087d88c1a5aSDimitry Andric "a ARM_THREAD_STATE flavor in " + CmdName +
1088d88c1a5aSDimitry Andric " command");
1089d88c1a5aSDimitry Andric if (state + sizeof(MachO::arm_thread_state32_t) > end)
1090d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1091d88c1a5aSDimitry Andric " ARM_THREAD_STATE extends past end of "
1092d88c1a5aSDimitry Andric "command in " + CmdName + " command");
1093d88c1a5aSDimitry Andric state += sizeof(MachO::arm_thread_state32_t);
1094d88c1a5aSDimitry Andric } else {
1095d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1096d88c1a5aSDimitry Andric " unknown flavor (" + Twine(flavor) + ") for "
1097d88c1a5aSDimitry Andric "flavor number " + Twine(nflavor) + " in " +
1098d88c1a5aSDimitry Andric CmdName + " command");
1099d88c1a5aSDimitry Andric }
1100d88c1a5aSDimitry Andric } else if (cputype == MachO::CPU_TYPE_ARM64) {
1101d88c1a5aSDimitry Andric if (flavor == MachO::ARM_THREAD_STATE64) {
1102d88c1a5aSDimitry Andric if (count != MachO::ARM_THREAD_STATE64_COUNT)
1103d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1104d88c1a5aSDimitry Andric " count not ARM_THREAD_STATE64_COUNT for "
1105d88c1a5aSDimitry Andric "flavor number " + Twine(nflavor) + " which is "
1106d88c1a5aSDimitry Andric "a ARM_THREAD_STATE64 flavor in " + CmdName +
1107d88c1a5aSDimitry Andric " command");
1108d88c1a5aSDimitry Andric if (state + sizeof(MachO::arm_thread_state64_t) > end)
1109d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1110d88c1a5aSDimitry Andric " ARM_THREAD_STATE64 extends past end of "
1111d88c1a5aSDimitry Andric "command in " + CmdName + " command");
1112d88c1a5aSDimitry Andric state += sizeof(MachO::arm_thread_state64_t);
1113d88c1a5aSDimitry Andric } else {
1114d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1115d88c1a5aSDimitry Andric " unknown flavor (" + Twine(flavor) + ") for "
1116d88c1a5aSDimitry Andric "flavor number " + Twine(nflavor) + " in " +
1117d88c1a5aSDimitry Andric CmdName + " command");
1118d88c1a5aSDimitry Andric }
1119d88c1a5aSDimitry Andric } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1120d88c1a5aSDimitry Andric if (flavor == MachO::PPC_THREAD_STATE) {
1121d88c1a5aSDimitry Andric if (count != MachO::PPC_THREAD_STATE_COUNT)
1122d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1123d88c1a5aSDimitry Andric " count not PPC_THREAD_STATE_COUNT for "
1124d88c1a5aSDimitry Andric "flavor number " + Twine(nflavor) + " which is "
1125d88c1a5aSDimitry Andric "a PPC_THREAD_STATE flavor in " + CmdName +
1126d88c1a5aSDimitry Andric " command");
1127d88c1a5aSDimitry Andric if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1128d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1129d88c1a5aSDimitry Andric " PPC_THREAD_STATE extends past end of "
1130d88c1a5aSDimitry Andric "command in " + CmdName + " command");
1131d88c1a5aSDimitry Andric state += sizeof(MachO::ppc_thread_state32_t);
1132d88c1a5aSDimitry Andric } else {
1133d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1134d88c1a5aSDimitry Andric " unknown flavor (" + Twine(flavor) + ") for "
1135d88c1a5aSDimitry Andric "flavor number " + Twine(nflavor) + " in " +
1136d88c1a5aSDimitry Andric CmdName + " command");
1137d88c1a5aSDimitry Andric }
1138d88c1a5aSDimitry Andric } else {
1139d88c1a5aSDimitry Andric return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1140d88c1a5aSDimitry Andric "command " + Twine(LoadCommandIndex) + " for " +
1141d88c1a5aSDimitry Andric CmdName + " command can't be checked");
1142d88c1a5aSDimitry Andric }
1143d88c1a5aSDimitry Andric nflavor++;
1144d88c1a5aSDimitry Andric }
1145d88c1a5aSDimitry Andric return Error::success();
1146d88c1a5aSDimitry Andric }
1147d88c1a5aSDimitry Andric
checkTwoLevelHintsCommand(const MachOObjectFile & Obj,const MachOObjectFile::LoadCommandInfo & Load,uint32_t LoadCommandIndex,const char ** LoadCmd,std::list<MachOElement> & Elements)1148d88c1a5aSDimitry Andric static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1149d88c1a5aSDimitry Andric const MachOObjectFile::LoadCommandInfo
1150d88c1a5aSDimitry Andric &Load,
1151d88c1a5aSDimitry Andric uint32_t LoadCommandIndex,
1152d88c1a5aSDimitry Andric const char **LoadCmd,
1153d88c1a5aSDimitry Andric std::list<MachOElement> &Elements) {
1154d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1155d88c1a5aSDimitry Andric return malformedError("load command " + Twine(LoadCommandIndex) +
1156d88c1a5aSDimitry Andric " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1157d88c1a5aSDimitry Andric if (*LoadCmd != nullptr)
1158d88c1a5aSDimitry Andric return malformedError("more than one LC_TWOLEVEL_HINTS command");
1159d88c1a5aSDimitry Andric MachO::twolevel_hints_command Hints =
1160d88c1a5aSDimitry Andric getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1161d88c1a5aSDimitry Andric uint64_t FileSize = Obj.getData().size();
1162d88c1a5aSDimitry Andric if (Hints.offset > FileSize)
1163d88c1a5aSDimitry Andric return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1164d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
1165d88c1a5aSDimitry Andric "the file");
1166d88c1a5aSDimitry Andric uint64_t BigSize = Hints.nhints;
11672cab237bSDimitry Andric BigSize *= sizeof(MachO::twolevel_hint);
1168d88c1a5aSDimitry Andric BigSize += Hints.offset;
1169d88c1a5aSDimitry Andric if (BigSize > FileSize)
1170d88c1a5aSDimitry Andric return malformedError("offset field plus nhints times sizeof(struct "
1171d88c1a5aSDimitry Andric "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1172d88c1a5aSDimitry Andric Twine(LoadCommandIndex) + " extends past the end of "
1173d88c1a5aSDimitry Andric "the file");
1174d88c1a5aSDimitry Andric if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1175d88c1a5aSDimitry Andric sizeof(MachO::twolevel_hint),
1176d88c1a5aSDimitry Andric "two level hints"))
1177d88c1a5aSDimitry Andric return Err;
1178d88c1a5aSDimitry Andric *LoadCmd = Load.Ptr;
1179d88c1a5aSDimitry Andric return Error::success();
1180d88c1a5aSDimitry Andric }
1181d88c1a5aSDimitry Andric
1182d88c1a5aSDimitry Andric // Returns true if the libObject code does not support the load command and its
1183d88c1a5aSDimitry Andric // contents. The cmd value it is treated as an unknown load command but with
1184d88c1a5aSDimitry Andric // an error message that says the cmd value is obsolete.
isLoadCommandObsolete(uint32_t cmd)1185d88c1a5aSDimitry Andric static bool isLoadCommandObsolete(uint32_t cmd) {
1186d88c1a5aSDimitry Andric if (cmd == MachO::LC_SYMSEG ||
1187d88c1a5aSDimitry Andric cmd == MachO::LC_LOADFVMLIB ||
1188d88c1a5aSDimitry Andric cmd == MachO::LC_IDFVMLIB ||
1189d88c1a5aSDimitry Andric cmd == MachO::LC_IDENT ||
1190d88c1a5aSDimitry Andric cmd == MachO::LC_FVMFILE ||
1191d88c1a5aSDimitry Andric cmd == MachO::LC_PREPAGE ||
1192d88c1a5aSDimitry Andric cmd == MachO::LC_PREBOUND_DYLIB ||
1193d88c1a5aSDimitry Andric cmd == MachO::LC_TWOLEVEL_HINTS ||
1194d88c1a5aSDimitry Andric cmd == MachO::LC_PREBIND_CKSUM)
1195d88c1a5aSDimitry Andric return true;
1196d88c1a5aSDimitry Andric return false;
1197d88c1a5aSDimitry Andric }
1198d88c1a5aSDimitry Andric
11993ca95b02SDimitry Andric Expected<std::unique_ptr<MachOObjectFile>>
create(MemoryBufferRef Object,bool IsLittleEndian,bool Is64Bits,uint32_t UniversalCputype,uint32_t UniversalIndex)12003ca95b02SDimitry Andric MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1201d88c1a5aSDimitry Andric bool Is64Bits, uint32_t UniversalCputype,
1202d88c1a5aSDimitry Andric uint32_t UniversalIndex) {
1203d88c1a5aSDimitry Andric Error Err = Error::success();
12043ca95b02SDimitry Andric std::unique_ptr<MachOObjectFile> Obj(
12053ca95b02SDimitry Andric new MachOObjectFile(std::move(Object), IsLittleEndian,
1206d88c1a5aSDimitry Andric Is64Bits, Err, UniversalCputype,
1207d88c1a5aSDimitry Andric UniversalIndex));
12083ca95b02SDimitry Andric if (Err)
12093ca95b02SDimitry Andric return std::move(Err);
12103ca95b02SDimitry Andric return std::move(Obj);
121197bc6c73SDimitry Andric }
121297bc6c73SDimitry Andric
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,Error & Err,uint32_t UniversalCputype,uint32_t UniversalIndex)121339d628a0SDimitry Andric MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1214d88c1a5aSDimitry Andric bool Is64bits, Error &Err,
1215d88c1a5aSDimitry Andric uint32_t UniversalCputype,
1216d88c1a5aSDimitry Andric uint32_t UniversalIndex)
121751690af2SDimitry Andric : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
1218d88c1a5aSDimitry Andric ErrorAsOutParameter ErrAsOutParam(&Err);
1219d88c1a5aSDimitry Andric uint64_t SizeOfHeaders;
1220d88c1a5aSDimitry Andric uint32_t cputype;
12213ca95b02SDimitry Andric if (is64Bit()) {
1222d88c1a5aSDimitry Andric parseHeader(*this, Header64, Err);
1223d88c1a5aSDimitry Andric SizeOfHeaders = sizeof(MachO::mach_header_64);
1224d88c1a5aSDimitry Andric cputype = Header64.cputype;
12253ca95b02SDimitry Andric } else {
1226d88c1a5aSDimitry Andric parseHeader(*this, Header, Err);
1227d88c1a5aSDimitry Andric SizeOfHeaders = sizeof(MachO::mach_header);
1228d88c1a5aSDimitry Andric cputype = Header.cputype;
12293ca95b02SDimitry Andric }
12303ca95b02SDimitry Andric if (Err)
123197bc6c73SDimitry Andric return;
1232d88c1a5aSDimitry Andric SizeOfHeaders += getHeader().sizeofcmds;
1233d88c1a5aSDimitry Andric if (getData().data() + SizeOfHeaders > getData().end()) {
12343ca95b02SDimitry Andric Err = malformedError("load commands extend past the end of the file");
12353ca95b02SDimitry Andric return;
12363ca95b02SDimitry Andric }
1237d88c1a5aSDimitry Andric if (UniversalCputype != 0 && cputype != UniversalCputype) {
1238d88c1a5aSDimitry Andric Err = malformedError("universal header architecture: " +
1239d88c1a5aSDimitry Andric Twine(UniversalIndex) + "'s cputype does not match "
1240d88c1a5aSDimitry Andric "object file's mach header");
1241d88c1a5aSDimitry Andric return;
1242d88c1a5aSDimitry Andric }
1243d88c1a5aSDimitry Andric std::list<MachOElement> Elements;
1244d88c1a5aSDimitry Andric Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
124597bc6c73SDimitry Andric
124697bc6c73SDimitry Andric uint32_t LoadCommandCount = getHeader().ncmds;
12473ca95b02SDimitry Andric LoadCommandInfo Load;
1248d88c1a5aSDimitry Andric if (LoadCommandCount != 0) {
1249d88c1a5aSDimitry Andric if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
12503ca95b02SDimitry Andric Load = *LoadOrErr;
12513ca95b02SDimitry Andric else {
12523ca95b02SDimitry Andric Err = LoadOrErr.takeError();
125397bc6c73SDimitry Andric return;
125497bc6c73SDimitry Andric }
1255d88c1a5aSDimitry Andric }
12563ca95b02SDimitry Andric
1257d88c1a5aSDimitry Andric const char *DyldIdLoadCmd = nullptr;
1258d88c1a5aSDimitry Andric const char *FuncStartsLoadCmd = nullptr;
1259d88c1a5aSDimitry Andric const char *SplitInfoLoadCmd = nullptr;
1260d88c1a5aSDimitry Andric const char *CodeSignDrsLoadCmd = nullptr;
1261d88c1a5aSDimitry Andric const char *CodeSignLoadCmd = nullptr;
1262d88c1a5aSDimitry Andric const char *VersLoadCmd = nullptr;
1263d88c1a5aSDimitry Andric const char *SourceLoadCmd = nullptr;
1264d88c1a5aSDimitry Andric const char *EntryPointLoadCmd = nullptr;
1265d88c1a5aSDimitry Andric const char *EncryptLoadCmd = nullptr;
1266d88c1a5aSDimitry Andric const char *RoutinesLoadCmd = nullptr;
1267d88c1a5aSDimitry Andric const char *UnixThreadLoadCmd = nullptr;
1268d88c1a5aSDimitry Andric const char *TwoLevelHintsLoadCmd = nullptr;
126997bc6c73SDimitry Andric for (unsigned I = 0; I < LoadCommandCount; ++I) {
12703ca95b02SDimitry Andric if (is64Bit()) {
12713ca95b02SDimitry Andric if (Load.C.cmdsize % 8 != 0) {
12723ca95b02SDimitry Andric // We have a hack here to allow 64-bit Mach-O core files to have
12733ca95b02SDimitry Andric // LC_THREAD commands that are only a multiple of 4 and not 8 to be
12743ca95b02SDimitry Andric // allowed since the macOS kernel produces them.
12753ca95b02SDimitry Andric if (getHeader().filetype != MachO::MH_CORE ||
12763ca95b02SDimitry Andric Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
12773ca95b02SDimitry Andric Err = malformedError("load command " + Twine(I) + " cmdsize not a "
12783ca95b02SDimitry Andric "multiple of 8");
12793ca95b02SDimitry Andric return;
12803ca95b02SDimitry Andric }
12813ca95b02SDimitry Andric }
12823ca95b02SDimitry Andric } else {
12833ca95b02SDimitry Andric if (Load.C.cmdsize % 4 != 0) {
12843ca95b02SDimitry Andric Err = malformedError("load command " + Twine(I) + " cmdsize not a "
12853ca95b02SDimitry Andric "multiple of 4");
12863ca95b02SDimitry Andric return;
12873ca95b02SDimitry Andric }
12883ca95b02SDimitry Andric }
128997bc6c73SDimitry Andric LoadCommands.push_back(Load);
1290f785676fSDimitry Andric if (Load.C.cmd == MachO::LC_SYMTAB) {
1291d88c1a5aSDimitry Andric if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
129239d628a0SDimitry Andric return;
1293f785676fSDimitry Andric } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1294d88c1a5aSDimitry Andric if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1295d88c1a5aSDimitry Andric Elements)))
129639d628a0SDimitry Andric return;
1297f785676fSDimitry Andric } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1298d88c1a5aSDimitry Andric if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1299d88c1a5aSDimitry Andric "LC_DATA_IN_CODE", Elements,
1300d88c1a5aSDimitry Andric "data in code info")))
130139d628a0SDimitry Andric return;
1302ff0cc061SDimitry Andric } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1303d88c1a5aSDimitry Andric if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1304d88c1a5aSDimitry Andric "LC_LINKER_OPTIMIZATION_HINT",
1305d88c1a5aSDimitry Andric Elements, "linker optimization "
1306d88c1a5aSDimitry Andric "hints")))
1307ff0cc061SDimitry Andric return;
1308d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1309d88c1a5aSDimitry Andric if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1310d88c1a5aSDimitry Andric "LC_FUNCTION_STARTS", Elements,
1311d88c1a5aSDimitry Andric "function starts data")))
131239d628a0SDimitry Andric return;
1313d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1314d88c1a5aSDimitry Andric if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1315d88c1a5aSDimitry Andric "LC_SEGMENT_SPLIT_INFO", Elements,
1316d88c1a5aSDimitry Andric "split info data")))
1317d88c1a5aSDimitry Andric return;
1318d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1319d88c1a5aSDimitry Andric if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1320d88c1a5aSDimitry Andric "LC_DYLIB_CODE_SIGN_DRS", Elements,
1321d88c1a5aSDimitry Andric "code signing RDs data")))
1322d88c1a5aSDimitry Andric return;
1323d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1324d88c1a5aSDimitry Andric if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1325d88c1a5aSDimitry Andric "LC_CODE_SIGNATURE", Elements,
1326d88c1a5aSDimitry Andric "code signature data")))
1327d88c1a5aSDimitry Andric return;
1328d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1329d88c1a5aSDimitry Andric if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1330d88c1a5aSDimitry Andric "LC_DYLD_INFO", Elements)))
1331d88c1a5aSDimitry Andric return;
1332d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1333d88c1a5aSDimitry Andric if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1334d88c1a5aSDimitry Andric "LC_DYLD_INFO_ONLY", Elements)))
1335d88c1a5aSDimitry Andric return;
133639d628a0SDimitry Andric } else if (Load.C.cmd == MachO::LC_UUID) {
1337d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1338d88c1a5aSDimitry Andric Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1339d88c1a5aSDimitry Andric "cmdsize");
1340d88c1a5aSDimitry Andric return;
1341d88c1a5aSDimitry Andric }
134239d628a0SDimitry Andric if (UuidLoadCmd) {
1343d88c1a5aSDimitry Andric Err = malformedError("more than one LC_UUID command");
134439d628a0SDimitry Andric return;
134539d628a0SDimitry Andric }
134639d628a0SDimitry Andric UuidLoadCmd = Load.Ptr;
134797bc6c73SDimitry Andric } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1348d88c1a5aSDimitry Andric if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1349d88c1a5aSDimitry Andric MachO::section_64>(
1350d88c1a5aSDimitry Andric *this, Load, Sections, HasPageZeroSegment, I,
1351d88c1a5aSDimitry Andric "LC_SEGMENT_64", SizeOfHeaders, Elements)))
135297bc6c73SDimitry Andric return;
135397bc6c73SDimitry Andric } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1354d88c1a5aSDimitry Andric if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1355d88c1a5aSDimitry Andric MachO::section>(
1356d88c1a5aSDimitry Andric *this, Load, Sections, HasPageZeroSegment, I,
1357d88c1a5aSDimitry Andric "LC_SEGMENT", SizeOfHeaders, Elements)))
135897bc6c73SDimitry Andric return;
1359d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1360d88c1a5aSDimitry Andric if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1361d88c1a5aSDimitry Andric return;
1362d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1363d88c1a5aSDimitry Andric if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1364d88c1a5aSDimitry Andric return;
136591bc56edSDimitry Andric Libraries.push_back(Load.Ptr);
1366d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1367d88c1a5aSDimitry Andric if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1368d88c1a5aSDimitry Andric return;
1369d88c1a5aSDimitry Andric Libraries.push_back(Load.Ptr);
1370d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1371d88c1a5aSDimitry Andric if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1372d88c1a5aSDimitry Andric return;
1373d88c1a5aSDimitry Andric Libraries.push_back(Load.Ptr);
1374d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1375d88c1a5aSDimitry Andric if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1376d88c1a5aSDimitry Andric return;
1377d88c1a5aSDimitry Andric Libraries.push_back(Load.Ptr);
1378d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1379d88c1a5aSDimitry Andric if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1380d88c1a5aSDimitry Andric return;
1381d88c1a5aSDimitry Andric Libraries.push_back(Load.Ptr);
1382d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1383d88c1a5aSDimitry Andric if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1384d88c1a5aSDimitry Andric return;
1385d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1386d88c1a5aSDimitry Andric if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1387d88c1a5aSDimitry Andric return;
1388d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1389d88c1a5aSDimitry Andric if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1390d88c1a5aSDimitry Andric return;
1391d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1392d88c1a5aSDimitry Andric if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1393d88c1a5aSDimitry Andric "LC_VERSION_MIN_MACOSX")))
1394d88c1a5aSDimitry Andric return;
1395d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1396d88c1a5aSDimitry Andric if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1397d88c1a5aSDimitry Andric "LC_VERSION_MIN_IPHONEOS")))
1398d88c1a5aSDimitry Andric return;
1399d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1400d88c1a5aSDimitry Andric if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1401d88c1a5aSDimitry Andric "LC_VERSION_MIN_TVOS")))
1402d88c1a5aSDimitry Andric return;
1403d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1404d88c1a5aSDimitry Andric if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1405d88c1a5aSDimitry Andric "LC_VERSION_MIN_WATCHOS")))
1406d88c1a5aSDimitry Andric return;
14077a7e6055SDimitry Andric } else if (Load.C.cmd == MachO::LC_NOTE) {
14087a7e6055SDimitry Andric if ((Err = checkNoteCommand(*this, Load, I, Elements)))
14097a7e6055SDimitry Andric return;
14107a7e6055SDimitry Andric } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
14117a7e6055SDimitry Andric if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
14127a7e6055SDimitry Andric return;
1413d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_RPATH) {
1414d88c1a5aSDimitry Andric if ((Err = checkRpathCommand(*this, Load, I)))
1415d88c1a5aSDimitry Andric return;
1416d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1417d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1418d88c1a5aSDimitry Andric Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1419d88c1a5aSDimitry Andric " has incorrect cmdsize");
1420d88c1a5aSDimitry Andric return;
14213b0f4066SDimitry Andric }
1422d88c1a5aSDimitry Andric if (SourceLoadCmd) {
1423d88c1a5aSDimitry Andric Err = malformedError("more than one LC_SOURCE_VERSION command");
1424d88c1a5aSDimitry Andric return;
1425d88c1a5aSDimitry Andric }
1426d88c1a5aSDimitry Andric SourceLoadCmd = Load.Ptr;
1427d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_MAIN) {
1428d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1429d88c1a5aSDimitry Andric Err = malformedError("LC_MAIN command " + Twine(I) +
1430d88c1a5aSDimitry Andric " has incorrect cmdsize");
1431d88c1a5aSDimitry Andric return;
1432d88c1a5aSDimitry Andric }
1433d88c1a5aSDimitry Andric if (EntryPointLoadCmd) {
1434d88c1a5aSDimitry Andric Err = malformedError("more than one LC_MAIN command");
1435d88c1a5aSDimitry Andric return;
1436d88c1a5aSDimitry Andric }
1437d88c1a5aSDimitry Andric EntryPointLoadCmd = Load.Ptr;
1438d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1439d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1440d88c1a5aSDimitry Andric Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1441d88c1a5aSDimitry Andric " has incorrect cmdsize");
1442d88c1a5aSDimitry Andric return;
1443d88c1a5aSDimitry Andric }
1444d88c1a5aSDimitry Andric MachO::encryption_info_command E =
1445d88c1a5aSDimitry Andric getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1446d88c1a5aSDimitry Andric if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1447d88c1a5aSDimitry Andric &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1448d88c1a5aSDimitry Andric return;
1449d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1450d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1451d88c1a5aSDimitry Andric Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1452d88c1a5aSDimitry Andric " has incorrect cmdsize");
1453d88c1a5aSDimitry Andric return;
1454d88c1a5aSDimitry Andric }
1455d88c1a5aSDimitry Andric MachO::encryption_info_command_64 E =
1456d88c1a5aSDimitry Andric getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1457d88c1a5aSDimitry Andric if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1458d88c1a5aSDimitry Andric &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1459d88c1a5aSDimitry Andric return;
1460d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1461d88c1a5aSDimitry Andric if ((Err = checkLinkerOptCommand(*this, Load, I)))
1462d88c1a5aSDimitry Andric return;
1463d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1464d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1465d88c1a5aSDimitry Andric Err = malformedError("load command " + Twine(I) +
1466d88c1a5aSDimitry Andric " LC_SUB_FRAMEWORK cmdsize too small");
1467d88c1a5aSDimitry Andric return;
1468d88c1a5aSDimitry Andric }
1469d88c1a5aSDimitry Andric MachO::sub_framework_command S =
1470d88c1a5aSDimitry Andric getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1471d88c1a5aSDimitry Andric if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1472d88c1a5aSDimitry Andric sizeof(MachO::sub_framework_command),
1473d88c1a5aSDimitry Andric "sub_framework_command", S.umbrella,
1474d88c1a5aSDimitry Andric "umbrella")))
1475d88c1a5aSDimitry Andric return;
1476d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1477d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1478d88c1a5aSDimitry Andric Err = malformedError("load command " + Twine(I) +
1479d88c1a5aSDimitry Andric " LC_SUB_UMBRELLA cmdsize too small");
1480d88c1a5aSDimitry Andric return;
1481d88c1a5aSDimitry Andric }
1482d88c1a5aSDimitry Andric MachO::sub_umbrella_command S =
1483d88c1a5aSDimitry Andric getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1484d88c1a5aSDimitry Andric if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1485d88c1a5aSDimitry Andric sizeof(MachO::sub_umbrella_command),
1486d88c1a5aSDimitry Andric "sub_umbrella_command", S.sub_umbrella,
1487d88c1a5aSDimitry Andric "sub_umbrella")))
1488d88c1a5aSDimitry Andric return;
1489d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1490d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1491d88c1a5aSDimitry Andric Err = malformedError("load command " + Twine(I) +
1492d88c1a5aSDimitry Andric " LC_SUB_LIBRARY cmdsize too small");
1493d88c1a5aSDimitry Andric return;
1494d88c1a5aSDimitry Andric }
1495d88c1a5aSDimitry Andric MachO::sub_library_command S =
1496d88c1a5aSDimitry Andric getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1497d88c1a5aSDimitry Andric if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1498d88c1a5aSDimitry Andric sizeof(MachO::sub_library_command),
1499d88c1a5aSDimitry Andric "sub_library_command", S.sub_library,
1500d88c1a5aSDimitry Andric "sub_library")))
1501d88c1a5aSDimitry Andric return;
1502d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1503d88c1a5aSDimitry Andric if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1504d88c1a5aSDimitry Andric Err = malformedError("load command " + Twine(I) +
1505d88c1a5aSDimitry Andric " LC_SUB_CLIENT cmdsize too small");
1506d88c1a5aSDimitry Andric return;
1507d88c1a5aSDimitry Andric }
1508d88c1a5aSDimitry Andric MachO::sub_client_command S =
1509d88c1a5aSDimitry Andric getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1510d88c1a5aSDimitry Andric if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1511d88c1a5aSDimitry Andric sizeof(MachO::sub_client_command),
1512d88c1a5aSDimitry Andric "sub_client_command", S.client, "client")))
1513d88c1a5aSDimitry Andric return;
1514d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1515d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1516d88c1a5aSDimitry Andric Err = malformedError("LC_ROUTINES command " + Twine(I) +
1517d88c1a5aSDimitry Andric " has incorrect cmdsize");
1518d88c1a5aSDimitry Andric return;
1519d88c1a5aSDimitry Andric }
1520d88c1a5aSDimitry Andric if (RoutinesLoadCmd) {
1521d88c1a5aSDimitry Andric Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1522d88c1a5aSDimitry Andric "command");
1523d88c1a5aSDimitry Andric return;
1524d88c1a5aSDimitry Andric }
1525d88c1a5aSDimitry Andric RoutinesLoadCmd = Load.Ptr;
1526d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1527d88c1a5aSDimitry Andric if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1528d88c1a5aSDimitry Andric Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1529d88c1a5aSDimitry Andric " has incorrect cmdsize");
1530d88c1a5aSDimitry Andric return;
1531d88c1a5aSDimitry Andric }
1532d88c1a5aSDimitry Andric if (RoutinesLoadCmd) {
1533d88c1a5aSDimitry Andric Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1534d88c1a5aSDimitry Andric "command");
1535d88c1a5aSDimitry Andric return;
1536d88c1a5aSDimitry Andric }
1537d88c1a5aSDimitry Andric RoutinesLoadCmd = Load.Ptr;
1538d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1539d88c1a5aSDimitry Andric if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1540d88c1a5aSDimitry Andric return;
1541d88c1a5aSDimitry Andric if (UnixThreadLoadCmd) {
1542d88c1a5aSDimitry Andric Err = malformedError("more than one LC_UNIXTHREAD command");
1543d88c1a5aSDimitry Andric return;
1544d88c1a5aSDimitry Andric }
1545d88c1a5aSDimitry Andric UnixThreadLoadCmd = Load.Ptr;
1546d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_THREAD) {
1547d88c1a5aSDimitry Andric if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1548d88c1a5aSDimitry Andric return;
1549d88c1a5aSDimitry Andric // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1550d88c1a5aSDimitry Andric } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1551d88c1a5aSDimitry Andric if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1552d88c1a5aSDimitry Andric &TwoLevelHintsLoadCmd, Elements)))
1553d88c1a5aSDimitry Andric return;
1554d88c1a5aSDimitry Andric } else if (isLoadCommandObsolete(Load.C.cmd)) {
1555d88c1a5aSDimitry Andric Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1556d88c1a5aSDimitry Andric Twine(Load.C.cmd) + " is obsolete and not "
1557d88c1a5aSDimitry Andric "supported");
1558d88c1a5aSDimitry Andric return;
1559d88c1a5aSDimitry Andric }
1560d88c1a5aSDimitry Andric // TODO: generate a error for unknown load commands by default. But still
1561d88c1a5aSDimitry Andric // need work out an approach to allow or not allow unknown values like this
1562d88c1a5aSDimitry Andric // as an option for some uses like lldb.
156397bc6c73SDimitry Andric if (I < LoadCommandCount - 1) {
1564d88c1a5aSDimitry Andric if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
15653ca95b02SDimitry Andric Load = *LoadOrErr;
15663ca95b02SDimitry Andric else {
15673ca95b02SDimitry Andric Err = LoadOrErr.takeError();
156897bc6c73SDimitry Andric return;
1569284c1978SDimitry Andric }
15703ca95b02SDimitry Andric }
15713ca95b02SDimitry Andric }
15723ca95b02SDimitry Andric if (!SymtabLoadCmd) {
15733ca95b02SDimitry Andric if (DysymtabLoadCmd) {
15743ca95b02SDimitry Andric Err = malformedError("contains LC_DYSYMTAB load command without a "
15753ca95b02SDimitry Andric "LC_SYMTAB load command");
15763ca95b02SDimitry Andric return;
15773ca95b02SDimitry Andric }
15783ca95b02SDimitry Andric } else if (DysymtabLoadCmd) {
15793ca95b02SDimitry Andric MachO::symtab_command Symtab =
1580d88c1a5aSDimitry Andric getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
15813ca95b02SDimitry Andric MachO::dysymtab_command Dysymtab =
1582d88c1a5aSDimitry Andric getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
15833ca95b02SDimitry Andric if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
15843ca95b02SDimitry Andric Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
15853ca95b02SDimitry Andric "extends past the end of the symbol table");
15863ca95b02SDimitry Andric return;
15873ca95b02SDimitry Andric }
15883ca95b02SDimitry Andric uint64_t BigSize = Dysymtab.ilocalsym;
15893ca95b02SDimitry Andric BigSize += Dysymtab.nlocalsym;
15903ca95b02SDimitry Andric if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
15913ca95b02SDimitry Andric Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
15923ca95b02SDimitry Andric "command extends past the end of the symbol table");
15933ca95b02SDimitry Andric return;
15943ca95b02SDimitry Andric }
1595*b5893f02SDimitry Andric if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
1596*b5893f02SDimitry Andric Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
15973ca95b02SDimitry Andric "extends past the end of the symbol table");
15983ca95b02SDimitry Andric return;
15993ca95b02SDimitry Andric }
16003ca95b02SDimitry Andric BigSize = Dysymtab.iextdefsym;
16013ca95b02SDimitry Andric BigSize += Dysymtab.nextdefsym;
16023ca95b02SDimitry Andric if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
16033ca95b02SDimitry Andric Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
16043ca95b02SDimitry Andric "load command extends past the end of the symbol "
16053ca95b02SDimitry Andric "table");
16063ca95b02SDimitry Andric return;
16073ca95b02SDimitry Andric }
16083ca95b02SDimitry Andric if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
1609*b5893f02SDimitry Andric Err = malformedError("iundefsym in LC_DYSYMTAB load command "
16103ca95b02SDimitry Andric "extends past the end of the symbol table");
16113ca95b02SDimitry Andric return;
16123ca95b02SDimitry Andric }
16133ca95b02SDimitry Andric BigSize = Dysymtab.iundefsym;
16143ca95b02SDimitry Andric BigSize += Dysymtab.nundefsym;
16153ca95b02SDimitry Andric if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
16163ca95b02SDimitry Andric Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
16173ca95b02SDimitry Andric " command extends past the end of the symbol table");
16183ca95b02SDimitry Andric return;
161997bc6c73SDimitry Andric }
162097bc6c73SDimitry Andric }
1621d88c1a5aSDimitry Andric if ((getHeader().filetype == MachO::MH_DYLIB ||
1622d88c1a5aSDimitry Andric getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1623d88c1a5aSDimitry Andric DyldIdLoadCmd == nullptr) {
1624d88c1a5aSDimitry Andric Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1625d88c1a5aSDimitry Andric "filetype");
1626d88c1a5aSDimitry Andric return;
1627d88c1a5aSDimitry Andric }
162897bc6c73SDimitry Andric assert(LoadCommands.size() == LoadCommandCount);
16293ca95b02SDimitry Andric
16303ca95b02SDimitry Andric Err = Error::success();
16313b0f4066SDimitry Andric }
16323b0f4066SDimitry Andric
checkSymbolTable() const1633d88c1a5aSDimitry Andric Error MachOObjectFile::checkSymbolTable() const {
1634d88c1a5aSDimitry Andric uint32_t Flags = 0;
1635d88c1a5aSDimitry Andric if (is64Bit()) {
1636d88c1a5aSDimitry Andric MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1637d88c1a5aSDimitry Andric Flags = H_64.flags;
1638d88c1a5aSDimitry Andric } else {
1639d88c1a5aSDimitry Andric MachO::mach_header H = MachOObjectFile::getHeader();
1640d88c1a5aSDimitry Andric Flags = H.flags;
1641d88c1a5aSDimitry Andric }
1642d88c1a5aSDimitry Andric uint8_t NType = 0;
1643d88c1a5aSDimitry Andric uint8_t NSect = 0;
1644d88c1a5aSDimitry Andric uint16_t NDesc = 0;
1645d88c1a5aSDimitry Andric uint32_t NStrx = 0;
1646d88c1a5aSDimitry Andric uint64_t NValue = 0;
1647d88c1a5aSDimitry Andric uint32_t SymbolIndex = 0;
1648d88c1a5aSDimitry Andric MachO::symtab_command S = getSymtabLoadCommand();
1649d88c1a5aSDimitry Andric for (const SymbolRef &Symbol : symbols()) {
1650d88c1a5aSDimitry Andric DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1651d88c1a5aSDimitry Andric if (is64Bit()) {
1652d88c1a5aSDimitry Andric MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1653d88c1a5aSDimitry Andric NType = STE_64.n_type;
1654d88c1a5aSDimitry Andric NSect = STE_64.n_sect;
1655d88c1a5aSDimitry Andric NDesc = STE_64.n_desc;
1656d88c1a5aSDimitry Andric NStrx = STE_64.n_strx;
1657d88c1a5aSDimitry Andric NValue = STE_64.n_value;
1658d88c1a5aSDimitry Andric } else {
1659d88c1a5aSDimitry Andric MachO::nlist STE = getSymbolTableEntry(SymDRI);
1660d88c1a5aSDimitry Andric NType = STE.n_type;
1661d88c1a5aSDimitry Andric NType = STE.n_type;
1662d88c1a5aSDimitry Andric NSect = STE.n_sect;
1663d88c1a5aSDimitry Andric NDesc = STE.n_desc;
1664d88c1a5aSDimitry Andric NStrx = STE.n_strx;
1665d88c1a5aSDimitry Andric NValue = STE.n_value;
1666d88c1a5aSDimitry Andric }
1667d88c1a5aSDimitry Andric if ((NType & MachO::N_STAB) == 0 &&
1668d88c1a5aSDimitry Andric (NType & MachO::N_TYPE) == MachO::N_SECT) {
1669d88c1a5aSDimitry Andric if (NSect == 0 || NSect > Sections.size())
1670d88c1a5aSDimitry Andric return malformedError("bad section index: " + Twine((int)NSect) +
1671d88c1a5aSDimitry Andric " for symbol at index " + Twine(SymbolIndex));
1672d88c1a5aSDimitry Andric }
1673d88c1a5aSDimitry Andric if ((NType & MachO::N_STAB) == 0 &&
1674d88c1a5aSDimitry Andric (NType & MachO::N_TYPE) == MachO::N_INDR) {
1675d88c1a5aSDimitry Andric if (NValue >= S.strsize)
1676d88c1a5aSDimitry Andric return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1677d88c1a5aSDimitry Andric "the end of string table, for N_INDR symbol at "
1678d88c1a5aSDimitry Andric "index " + Twine(SymbolIndex));
1679d88c1a5aSDimitry Andric }
1680d88c1a5aSDimitry Andric if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1681d88c1a5aSDimitry Andric (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1682d88c1a5aSDimitry Andric (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1683d88c1a5aSDimitry Andric uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1684d88c1a5aSDimitry Andric if (LibraryOrdinal != 0 &&
1685d88c1a5aSDimitry Andric LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1686d88c1a5aSDimitry Andric LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1687d88c1a5aSDimitry Andric LibraryOrdinal - 1 >= Libraries.size() ) {
1688d88c1a5aSDimitry Andric return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1689d88c1a5aSDimitry Andric " for symbol at index " + Twine(SymbolIndex));
1690d88c1a5aSDimitry Andric }
1691d88c1a5aSDimitry Andric }
1692d88c1a5aSDimitry Andric if (NStrx >= S.strsize)
1693d88c1a5aSDimitry Andric return malformedError("bad string table index: " + Twine((int)NStrx) +
1694d88c1a5aSDimitry Andric " past the end of string table, for symbol at "
1695d88c1a5aSDimitry Andric "index " + Twine(SymbolIndex));
1696d88c1a5aSDimitry Andric SymbolIndex++;
1697d88c1a5aSDimitry Andric }
1698d88c1a5aSDimitry Andric return Error::success();
1699d88c1a5aSDimitry Andric }
1700d88c1a5aSDimitry Andric
moveSymbolNext(DataRefImpl & Symb) const170191bc56edSDimitry Andric void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1702284c1978SDimitry Andric unsigned SymbolTableEntrySize = is64Bit() ?
1703f785676fSDimitry Andric sizeof(MachO::nlist_64) :
1704f785676fSDimitry Andric sizeof(MachO::nlist);
1705284c1978SDimitry Andric Symb.p += SymbolTableEntrySize;
17063b0f4066SDimitry Andric }
17073b0f4066SDimitry Andric
getSymbolName(DataRefImpl Symb) const17083ca95b02SDimitry Andric Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1709284c1978SDimitry Andric StringRef StringTable = getStringTableData();
1710d88c1a5aSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
17114ba319b5SDimitry Andric if (Entry.n_strx == 0)
17124ba319b5SDimitry Andric // A n_strx value of 0 indicates that no name is associated with a
17134ba319b5SDimitry Andric // particular symbol table entry.
17144ba319b5SDimitry Andric return StringRef();
1715f785676fSDimitry Andric const char *Start = &StringTable.data()[Entry.n_strx];
17163ca95b02SDimitry Andric if (Start < getData().begin() || Start >= getData().end()) {
17173ca95b02SDimitry Andric return malformedError("bad string index: " + Twine(Entry.n_strx) +
17183ca95b02SDimitry Andric " for symbol at index " + Twine(getSymbolIndex(Symb)));
17193ca95b02SDimitry Andric }
17203dac3a9bSDimitry Andric return StringRef(Start);
1721284c1978SDimitry Andric }
1722284c1978SDimitry Andric
getSectionType(SectionRef Sec) const172339d628a0SDimitry Andric unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
172439d628a0SDimitry Andric DataRefImpl DRI = Sec.getRawDataRefImpl();
1725d88c1a5aSDimitry Andric uint32_t Flags = getSectionFlags(*this, DRI);
172639d628a0SDimitry Andric return Flags & MachO::SECTION_TYPE;
172739d628a0SDimitry Andric }
172839d628a0SDimitry Andric
getNValue(DataRefImpl Sym) const17293dac3a9bSDimitry Andric uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
17303dac3a9bSDimitry Andric if (is64Bit()) {
17313dac3a9bSDimitry Andric MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
17323dac3a9bSDimitry Andric return Entry.n_value;
17333dac3a9bSDimitry Andric }
17343dac3a9bSDimitry Andric MachO::nlist Entry = getSymbolTableEntry(Sym);
17353dac3a9bSDimitry Andric return Entry.n_value;
17363dac3a9bSDimitry Andric }
17373dac3a9bSDimitry Andric
173891bc56edSDimitry Andric // getIndirectName() returns the name of the alias'ed symbol who's string table
173991bc56edSDimitry Andric // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const174091bc56edSDimitry Andric std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
174191bc56edSDimitry Andric StringRef &Res) const {
174291bc56edSDimitry Andric StringRef StringTable = getStringTableData();
1743d88c1a5aSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
174491bc56edSDimitry Andric if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
174591bc56edSDimitry Andric return object_error::parse_failed;
17463dac3a9bSDimitry Andric uint64_t NValue = getNValue(Symb);
174791bc56edSDimitry Andric if (NValue >= StringTable.size())
174891bc56edSDimitry Andric return object_error::parse_failed;
174991bc56edSDimitry Andric const char *Start = &StringTable.data()[NValue];
175091bc56edSDimitry Andric Res = StringRef(Start);
175197bc6c73SDimitry Andric return std::error_code();
175291bc56edSDimitry Andric }
175391bc56edSDimitry Andric
getSymbolValueImpl(DataRefImpl Sym) const1754875ed548SDimitry Andric uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1755875ed548SDimitry Andric return getNValue(Sym);
175617a519f9SDimitry Andric }
17573dac3a9bSDimitry Andric
getSymbolAddress(DataRefImpl Sym) const17583ca95b02SDimitry Andric Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1759875ed548SDimitry Andric return getSymbolValue(Sym);
17603b0f4066SDimitry Andric }
17613b0f4066SDimitry Andric
getSymbolAlignment(DataRefImpl DRI) const176297bc6c73SDimitry Andric uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
176391bc56edSDimitry Andric uint32_t flags = getSymbolFlags(DRI);
1764284c1978SDimitry Andric if (flags & SymbolRef::SF_Common) {
1765d88c1a5aSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
176697bc6c73SDimitry Andric return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
176717a519f9SDimitry Andric }
176897bc6c73SDimitry Andric return 0;
17693b0f4066SDimitry Andric }
17703b0f4066SDimitry Andric
getCommonSymbolSizeImpl(DataRefImpl DRI) const17713dac3a9bSDimitry Andric uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1772875ed548SDimitry Andric return getNValue(DRI);
17733b0f4066SDimitry Andric }
17743b0f4066SDimitry Andric
17753ca95b02SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const17763ca95b02SDimitry Andric MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1777d88c1a5aSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1778f785676fSDimitry Andric uint8_t n_type = Entry.n_type;
1779284c1978SDimitry Andric
17806122f3e6SDimitry Andric // If this is a STAB debugging symbol, we can do nothing more.
17813dac3a9bSDimitry Andric if (n_type & MachO::N_STAB)
17823dac3a9bSDimitry Andric return SymbolRef::ST_Debug;
17836122f3e6SDimitry Andric
1784f785676fSDimitry Andric switch (n_type & MachO::N_TYPE) {
1785f785676fSDimitry Andric case MachO::N_UNDF :
17863dac3a9bSDimitry Andric return SymbolRef::ST_Unknown;
1787f785676fSDimitry Andric case MachO::N_SECT :
17883ca95b02SDimitry Andric Expected<section_iterator> SecOrError = getSymbolSection(Symb);
17893ca95b02SDimitry Andric if (!SecOrError)
17903ca95b02SDimitry Andric return SecOrError.takeError();
17913ca95b02SDimitry Andric section_iterator Sec = *SecOrError;
17927d523365SDimitry Andric if (Sec->isData() || Sec->isBSS())
17937d523365SDimitry Andric return SymbolRef::ST_Data;
17943dac3a9bSDimitry Andric return SymbolRef::ST_Function;
17956122f3e6SDimitry Andric }
17963dac3a9bSDimitry Andric return SymbolRef::ST_Other;
17976122f3e6SDimitry Andric }
17986122f3e6SDimitry Andric
getSymbolFlags(DataRefImpl DRI) const179991bc56edSDimitry Andric uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1800d88c1a5aSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1801284c1978SDimitry Andric
1802f785676fSDimitry Andric uint8_t MachOType = Entry.n_type;
1803f785676fSDimitry Andric uint16_t MachOFlags = Entry.n_desc;
1804284c1978SDimitry Andric
180591bc56edSDimitry Andric uint32_t Result = SymbolRef::SF_None;
1806284c1978SDimitry Andric
180791bc56edSDimitry Andric if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
180891bc56edSDimitry Andric Result |= SymbolRef::SF_Indirect;
180991bc56edSDimitry Andric
1810f785676fSDimitry Andric if (MachOType & MachO::N_STAB)
1811284c1978SDimitry Andric Result |= SymbolRef::SF_FormatSpecific;
1812284c1978SDimitry Andric
1813f785676fSDimitry Andric if (MachOType & MachO::N_EXT) {
1814284c1978SDimitry Andric Result |= SymbolRef::SF_Global;
1815f785676fSDimitry Andric if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1816875ed548SDimitry Andric if (getNValue(DRI))
1817284c1978SDimitry Andric Result |= SymbolRef::SF_Common;
1818875ed548SDimitry Andric else
1819875ed548SDimitry Andric Result |= SymbolRef::SF_Undefined;
1820284c1978SDimitry Andric }
1821ff0cc061SDimitry Andric
1822ff0cc061SDimitry Andric if (!(MachOType & MachO::N_PEXT))
1823ff0cc061SDimitry Andric Result |= SymbolRef::SF_Exported;
1824284c1978SDimitry Andric }
1825284c1978SDimitry Andric
1826f785676fSDimitry Andric if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1827284c1978SDimitry Andric Result |= SymbolRef::SF_Weak;
1828284c1978SDimitry Andric
182939d628a0SDimitry Andric if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
183039d628a0SDimitry Andric Result |= SymbolRef::SF_Thumb;
183139d628a0SDimitry Andric
1832f785676fSDimitry Andric if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1833284c1978SDimitry Andric Result |= SymbolRef::SF_Absolute;
1834284c1978SDimitry Andric
183591bc56edSDimitry Andric return Result;
1836284c1978SDimitry Andric }
1837284c1978SDimitry Andric
18383ca95b02SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const18397d523365SDimitry Andric MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1840d88c1a5aSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1841f785676fSDimitry Andric uint8_t index = Entry.n_sect;
1842284c1978SDimitry Andric
18437d523365SDimitry Andric if (index == 0)
18447d523365SDimitry Andric return section_end();
1845284c1978SDimitry Andric DataRefImpl DRI;
1846284c1978SDimitry Andric DRI.d.a = index - 1;
18473ca95b02SDimitry Andric if (DRI.d.a >= Sections.size()){
18483ca95b02SDimitry Andric return malformedError("bad section index: " + Twine((int)index) +
18493ca95b02SDimitry Andric " for symbol at index " + Twine(getSymbolIndex(Symb)));
18503ca95b02SDimitry Andric }
18517d523365SDimitry Andric return section_iterator(SectionRef(DRI, this));
1852284c1978SDimitry Andric }
1853284c1978SDimitry Andric
getSymbolSectionID(SymbolRef Sym) const18543dac3a9bSDimitry Andric unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
18553dac3a9bSDimitry Andric MachO::nlist_base Entry =
1856d88c1a5aSDimitry Andric getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
18573dac3a9bSDimitry Andric return Entry.n_sect - 1;
18583dac3a9bSDimitry Andric }
18593dac3a9bSDimitry Andric
moveSectionNext(DataRefImpl & Sec) const186091bc56edSDimitry Andric void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1861284c1978SDimitry Andric Sec.d.a++;
18623b0f4066SDimitry Andric }
18633b0f4066SDimitry Andric
getSectionName(DataRefImpl Sec,StringRef & Result) const186491bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
186591bc56edSDimitry Andric StringRef &Result) const {
1866284c1978SDimitry Andric ArrayRef<char> Raw = getSectionRawName(Sec);
1867284c1978SDimitry Andric Result = parseSegmentOrSectionName(Raw.data());
186897bc6c73SDimitry Andric return std::error_code();
18693b0f4066SDimitry Andric }
18703b0f4066SDimitry Andric
getSectionAddress(DataRefImpl Sec) const187139d628a0SDimitry Andric uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
187239d628a0SDimitry Andric if (is64Bit())
187339d628a0SDimitry Andric return getSection64(Sec).addr;
187439d628a0SDimitry Andric return getSection(Sec).addr;
1875139f7f9bSDimitry Andric }
1876139f7f9bSDimitry Andric
getSectionIndex(DataRefImpl Sec) const1877302affcbSDimitry Andric uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1878302affcbSDimitry Andric return Sec.d.a;
1879302affcbSDimitry Andric }
1880302affcbSDimitry Andric
getSectionSize(DataRefImpl Sec) const188139d628a0SDimitry Andric uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
18827d523365SDimitry Andric // In the case if a malformed Mach-O file where the section offset is past
18837d523365SDimitry Andric // the end of the file or some part of the section size is past the end of
18847d523365SDimitry Andric // the file return a size of zero or a size that covers the rest of the file
18857d523365SDimitry Andric // but does not extend past the end of the file.
18867d523365SDimitry Andric uint32_t SectOffset, SectType;
18877d523365SDimitry Andric uint64_t SectSize;
18887d523365SDimitry Andric
18897d523365SDimitry Andric if (is64Bit()) {
18907d523365SDimitry Andric MachO::section_64 Sect = getSection64(Sec);
18917d523365SDimitry Andric SectOffset = Sect.offset;
18927d523365SDimitry Andric SectSize = Sect.size;
18937d523365SDimitry Andric SectType = Sect.flags & MachO::SECTION_TYPE;
18947d523365SDimitry Andric } else {
18957d523365SDimitry Andric MachO::section Sect = getSection(Sec);
18967d523365SDimitry Andric SectOffset = Sect.offset;
18977d523365SDimitry Andric SectSize = Sect.size;
18987d523365SDimitry Andric SectType = Sect.flags & MachO::SECTION_TYPE;
18997d523365SDimitry Andric }
19007d523365SDimitry Andric if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
19017d523365SDimitry Andric return SectSize;
19027d523365SDimitry Andric uint64_t FileSize = getData().size();
19037d523365SDimitry Andric if (SectOffset > FileSize)
19047d523365SDimitry Andric return 0;
19057d523365SDimitry Andric if (FileSize - SectOffset < SectSize)
19067d523365SDimitry Andric return FileSize - SectOffset;
19077d523365SDimitry Andric return SectSize;
19083b0f4066SDimitry Andric }
19093b0f4066SDimitry Andric
getSectionContents(DataRefImpl Sec,StringRef & Res) const191091bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
191191bc56edSDimitry Andric StringRef &Res) const {
1912284c1978SDimitry Andric uint32_t Offset;
1913284c1978SDimitry Andric uint64_t Size;
1914284c1978SDimitry Andric
1915284c1978SDimitry Andric if (is64Bit()) {
1916f785676fSDimitry Andric MachO::section_64 Sect = getSection64(Sec);
1917f785676fSDimitry Andric Offset = Sect.offset;
1918f785676fSDimitry Andric Size = Sect.size;
191917a519f9SDimitry Andric } else {
1920f785676fSDimitry Andric MachO::section Sect = getSection(Sec);
1921f785676fSDimitry Andric Offset = Sect.offset;
1922f785676fSDimitry Andric Size = Sect.size;
192317a519f9SDimitry Andric }
1924284c1978SDimitry Andric
1925284c1978SDimitry Andric Res = this->getData().substr(Offset, Size);
192697bc6c73SDimitry Andric return std::error_code();
19273b0f4066SDimitry Andric }
19283b0f4066SDimitry Andric
getSectionAlignment(DataRefImpl Sec) const192939d628a0SDimitry Andric uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1930284c1978SDimitry Andric uint32_t Align;
1931284c1978SDimitry Andric if (is64Bit()) {
1932f785676fSDimitry Andric MachO::section_64 Sect = getSection64(Sec);
1933f785676fSDimitry Andric Align = Sect.align;
193417a519f9SDimitry Andric } else {
1935f785676fSDimitry Andric MachO::section Sect = getSection(Sec);
1936f785676fSDimitry Andric Align = Sect.align;
193717a519f9SDimitry Andric }
1938284c1978SDimitry Andric
193939d628a0SDimitry Andric return uint64_t(1) << Align;
19403b0f4066SDimitry Andric }
19413b0f4066SDimitry Andric
getSection(unsigned SectionIndex) const19424ba319b5SDimitry Andric Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
19434ba319b5SDimitry Andric if (SectionIndex < 1 || SectionIndex > Sections.size())
19444ba319b5SDimitry Andric return malformedError("bad section index: " + Twine((int)SectionIndex));
19454ba319b5SDimitry Andric
19464ba319b5SDimitry Andric DataRefImpl DRI;
19474ba319b5SDimitry Andric DRI.d.a = SectionIndex - 1;
19484ba319b5SDimitry Andric return SectionRef(DRI, this);
19494ba319b5SDimitry Andric }
19504ba319b5SDimitry Andric
getSection(StringRef SectionName) const19514ba319b5SDimitry Andric Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
19524ba319b5SDimitry Andric StringRef SecName;
19534ba319b5SDimitry Andric for (const SectionRef &Section : sections()) {
19544ba319b5SDimitry Andric if (std::error_code E = Section.getName(SecName))
19554ba319b5SDimitry Andric return errorCodeToError(E);
19564ba319b5SDimitry Andric if (SecName == SectionName) {
19574ba319b5SDimitry Andric return Section;
19584ba319b5SDimitry Andric }
19594ba319b5SDimitry Andric }
19604ba319b5SDimitry Andric return errorCodeToError(object_error::parse_failed);
19614ba319b5SDimitry Andric }
19624ba319b5SDimitry Andric
isSectionCompressed(DataRefImpl Sec) const19633ca95b02SDimitry Andric bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
19643ca95b02SDimitry Andric return false;
19653ca95b02SDimitry Andric }
19663ca95b02SDimitry Andric
isSectionText(DataRefImpl Sec) const196739d628a0SDimitry Andric bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
1968d88c1a5aSDimitry Andric uint32_t Flags = getSectionFlags(*this, Sec);
196939d628a0SDimitry Andric return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
19703b0f4066SDimitry Andric }
19713b0f4066SDimitry Andric
isSectionData(DataRefImpl Sec) const197239d628a0SDimitry Andric bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
1973d88c1a5aSDimitry Andric uint32_t Flags = getSectionFlags(*this, Sec);
197491bc56edSDimitry Andric unsigned SectionType = Flags & MachO::SECTION_TYPE;
197539d628a0SDimitry Andric return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
197691bc56edSDimitry Andric !(SectionType == MachO::S_ZEROFILL ||
197791bc56edSDimitry Andric SectionType == MachO::S_GB_ZEROFILL);
19783b0f4066SDimitry Andric }
19793b0f4066SDimitry Andric
isSectionBSS(DataRefImpl Sec) const198039d628a0SDimitry Andric bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
1981d88c1a5aSDimitry Andric uint32_t Flags = getSectionFlags(*this, Sec);
198291bc56edSDimitry Andric unsigned SectionType = Flags & MachO::SECTION_TYPE;
198339d628a0SDimitry Andric return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
198491bc56edSDimitry Andric (SectionType == MachO::S_ZEROFILL ||
198591bc56edSDimitry Andric SectionType == MachO::S_GB_ZEROFILL);
19866122f3e6SDimitry Andric }
19876122f3e6SDimitry Andric
getSectionID(SectionRef Sec) const19883dac3a9bSDimitry Andric unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
19893dac3a9bSDimitry Andric return Sec.getRawDataRefImpl().d.a;
19903dac3a9bSDimitry Andric }
19913dac3a9bSDimitry Andric
isSectionVirtual(DataRefImpl Sec) const199239d628a0SDimitry Andric bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
19934ba319b5SDimitry Andric uint32_t Flags = getSectionFlags(*this, Sec);
19944ba319b5SDimitry Andric unsigned SectionType = Flags & MachO::SECTION_TYPE;
19954ba319b5SDimitry Andric return SectionType == MachO::S_ZEROFILL ||
19964ba319b5SDimitry Andric SectionType == MachO::S_GB_ZEROFILL;
1997dff0c46cSDimitry Andric }
1998dff0c46cSDimitry Andric
isSectionBitcode(DataRefImpl Sec) const19993ca95b02SDimitry Andric bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
20003ca95b02SDimitry Andric StringRef SegmentName = getSectionFinalSegmentName(Sec);
20013ca95b02SDimitry Andric StringRef SectName;
20023ca95b02SDimitry Andric if (!getSectionName(Sec, SectName))
20033ca95b02SDimitry Andric return (SegmentName == "__LLVM" && SectName == "__bitcode");
20043ca95b02SDimitry Andric return false;
20053ca95b02SDimitry Andric }
20063ca95b02SDimitry Andric
isSectionStripped(DataRefImpl Sec) const20072cab237bSDimitry Andric bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
20082cab237bSDimitry Andric if (is64Bit())
20092cab237bSDimitry Andric return getSection64(Sec).offset == 0;
20102cab237bSDimitry Andric return getSection(Sec).offset == 0;
20112cab237bSDimitry Andric }
20122cab237bSDimitry Andric
section_rel_begin(DataRefImpl Sec) const2013f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
2014284c1978SDimitry Andric DataRefImpl Ret;
201591bc56edSDimitry Andric Ret.d.a = Sec.d.a;
201691bc56edSDimitry Andric Ret.d.b = 0;
2017284c1978SDimitry Andric return relocation_iterator(RelocationRef(Ret, this));
20183b0f4066SDimitry Andric }
20193b0f4066SDimitry Andric
2020284c1978SDimitry Andric relocation_iterator
section_rel_end(DataRefImpl Sec) const2021f785676fSDimitry Andric MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
2022284c1978SDimitry Andric uint32_t Num;
2023284c1978SDimitry Andric if (is64Bit()) {
2024f785676fSDimitry Andric MachO::section_64 Sect = getSection64(Sec);
2025f785676fSDimitry Andric Num = Sect.nreloc;
20266122f3e6SDimitry Andric } else {
2027f785676fSDimitry Andric MachO::section Sect = getSection(Sec);
2028f785676fSDimitry Andric Num = Sect.nreloc;
20296122f3e6SDimitry Andric }
2030284c1978SDimitry Andric
2031284c1978SDimitry Andric DataRefImpl Ret;
203291bc56edSDimitry Andric Ret.d.a = Sec.d.a;
203391bc56edSDimitry Andric Ret.d.b = Num;
2034284c1978SDimitry Andric return relocation_iterator(RelocationRef(Ret, this));
20356122f3e6SDimitry Andric }
2036284c1978SDimitry Andric
extrel_begin() const2037edd7eaddSDimitry Andric relocation_iterator MachOObjectFile::extrel_begin() const {
2038edd7eaddSDimitry Andric DataRefImpl Ret;
20392cab237bSDimitry Andric // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2040edd7eaddSDimitry Andric Ret.d.a = 0; // Would normally be a section index.
2041edd7eaddSDimitry Andric Ret.d.b = 0; // Index into the external relocations
2042edd7eaddSDimitry Andric return relocation_iterator(RelocationRef(Ret, this));
2043edd7eaddSDimitry Andric }
2044edd7eaddSDimitry Andric
extrel_end() const2045edd7eaddSDimitry Andric relocation_iterator MachOObjectFile::extrel_end() const {
2046edd7eaddSDimitry Andric MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2047edd7eaddSDimitry Andric DataRefImpl Ret;
20482cab237bSDimitry Andric // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2049edd7eaddSDimitry Andric Ret.d.a = 0; // Would normally be a section index.
2050edd7eaddSDimitry Andric Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2051edd7eaddSDimitry Andric return relocation_iterator(RelocationRef(Ret, this));
2052edd7eaddSDimitry Andric }
2053edd7eaddSDimitry Andric
locrel_begin() const20542cab237bSDimitry Andric relocation_iterator MachOObjectFile::locrel_begin() const {
20552cab237bSDimitry Andric DataRefImpl Ret;
20562cab237bSDimitry Andric // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
20572cab237bSDimitry Andric Ret.d.a = 1; // Would normally be a section index.
20582cab237bSDimitry Andric Ret.d.b = 0; // Index into the local relocations
20592cab237bSDimitry Andric return relocation_iterator(RelocationRef(Ret, this));
20602cab237bSDimitry Andric }
20612cab237bSDimitry Andric
locrel_end() const20622cab237bSDimitry Andric relocation_iterator MachOObjectFile::locrel_end() const {
20632cab237bSDimitry Andric MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
20642cab237bSDimitry Andric DataRefImpl Ret;
20652cab237bSDimitry Andric // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
20662cab237bSDimitry Andric Ret.d.a = 1; // Would normally be a section index.
20672cab237bSDimitry Andric Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
20682cab237bSDimitry Andric return relocation_iterator(RelocationRef(Ret, this));
20692cab237bSDimitry Andric }
20702cab237bSDimitry Andric
moveRelocationNext(DataRefImpl & Rel) const207191bc56edSDimitry Andric void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
207291bc56edSDimitry Andric ++Rel.d.b;
207391bc56edSDimitry Andric }
207491bc56edSDimitry Andric
getRelocationOffset(DataRefImpl Rel) const20753dac3a9bSDimitry Andric uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
2076edd7eaddSDimitry Andric assert((getHeader().filetype == MachO::MH_OBJECT ||
2077edd7eaddSDimitry Andric getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2078edd7eaddSDimitry Andric "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2079f785676fSDimitry Andric MachO::any_relocation_info RE = getRelocation(Rel);
20803dac3a9bSDimitry Andric return getAnyRelocationAddress(RE);
20816122f3e6SDimitry Andric }
20826122f3e6SDimitry Andric
2083f785676fSDimitry Andric symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const2084f785676fSDimitry Andric MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
2085f785676fSDimitry Andric MachO::any_relocation_info RE = getRelocation(Rel);
208691bc56edSDimitry Andric if (isRelocationScattered(RE))
208791bc56edSDimitry Andric return symbol_end();
208891bc56edSDimitry Andric
2089284c1978SDimitry Andric uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2090284c1978SDimitry Andric bool isExtern = getPlainRelocationExternal(RE);
2091f785676fSDimitry Andric if (!isExtern)
209291bc56edSDimitry Andric return symbol_end();
2093284c1978SDimitry Andric
2094f785676fSDimitry Andric MachO::symtab_command S = getSymtabLoadCommand();
2095284c1978SDimitry Andric unsigned SymbolTableEntrySize = is64Bit() ?
2096f785676fSDimitry Andric sizeof(MachO::nlist_64) :
2097f785676fSDimitry Andric sizeof(MachO::nlist);
2098f785676fSDimitry Andric uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
20996122f3e6SDimitry Andric DataRefImpl Sym;
2100d88c1a5aSDimitry Andric Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2101f785676fSDimitry Andric return symbol_iterator(SymbolRef(Sym, this));
21026122f3e6SDimitry Andric }
2103284c1978SDimitry Andric
2104ff0cc061SDimitry Andric section_iterator
getRelocationSection(DataRefImpl Rel) const2105ff0cc061SDimitry Andric MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2106ff0cc061SDimitry Andric return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2107ff0cc061SDimitry Andric }
2108ff0cc061SDimitry Andric
getRelocationType(DataRefImpl Rel) const21093dac3a9bSDimitry Andric uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
2110f785676fSDimitry Andric MachO::any_relocation_info RE = getRelocation(Rel);
21113dac3a9bSDimitry Andric return getAnyRelocationType(RE);
21126122f3e6SDimitry Andric }
2113284c1978SDimitry Andric
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const21143dac3a9bSDimitry Andric void MachOObjectFile::getRelocationTypeName(
21153dac3a9bSDimitry Andric DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
2116dff0c46cSDimitry Andric StringRef res;
21173dac3a9bSDimitry Andric uint64_t RType = getRelocationType(Rel);
2118dff0c46cSDimitry Andric
2119284c1978SDimitry Andric unsigned Arch = this->getArch();
2120dff0c46cSDimitry Andric
2121dff0c46cSDimitry Andric switch (Arch) {
2122dff0c46cSDimitry Andric case Triple::x86: {
21237ae0e2c9SDimitry Andric static const char *const Table[] = {
2124dff0c46cSDimitry Andric "GENERIC_RELOC_VANILLA",
2125dff0c46cSDimitry Andric "GENERIC_RELOC_PAIR",
2126dff0c46cSDimitry Andric "GENERIC_RELOC_SECTDIFF",
2127dff0c46cSDimitry Andric "GENERIC_RELOC_PB_LA_PTR",
2128dff0c46cSDimitry Andric "GENERIC_RELOC_LOCAL_SECTDIFF",
2129dff0c46cSDimitry Andric "GENERIC_RELOC_TLV" };
2130dff0c46cSDimitry Andric
213191bc56edSDimitry Andric if (RType > 5)
2132dff0c46cSDimitry Andric res = "Unknown";
2133dff0c46cSDimitry Andric else
2134284c1978SDimitry Andric res = Table[RType];
2135dff0c46cSDimitry Andric break;
2136dff0c46cSDimitry Andric }
2137dff0c46cSDimitry Andric case Triple::x86_64: {
21387ae0e2c9SDimitry Andric static const char *const Table[] = {
2139dff0c46cSDimitry Andric "X86_64_RELOC_UNSIGNED",
2140dff0c46cSDimitry Andric "X86_64_RELOC_SIGNED",
2141dff0c46cSDimitry Andric "X86_64_RELOC_BRANCH",
2142dff0c46cSDimitry Andric "X86_64_RELOC_GOT_LOAD",
2143dff0c46cSDimitry Andric "X86_64_RELOC_GOT",
2144dff0c46cSDimitry Andric "X86_64_RELOC_SUBTRACTOR",
2145dff0c46cSDimitry Andric "X86_64_RELOC_SIGNED_1",
2146dff0c46cSDimitry Andric "X86_64_RELOC_SIGNED_2",
2147dff0c46cSDimitry Andric "X86_64_RELOC_SIGNED_4",
2148dff0c46cSDimitry Andric "X86_64_RELOC_TLV" };
2149dff0c46cSDimitry Andric
2150284c1978SDimitry Andric if (RType > 9)
2151dff0c46cSDimitry Andric res = "Unknown";
2152dff0c46cSDimitry Andric else
2153284c1978SDimitry Andric res = Table[RType];
2154dff0c46cSDimitry Andric break;
2155dff0c46cSDimitry Andric }
2156dff0c46cSDimitry Andric case Triple::arm: {
21577ae0e2c9SDimitry Andric static const char *const Table[] = {
2158dff0c46cSDimitry Andric "ARM_RELOC_VANILLA",
2159dff0c46cSDimitry Andric "ARM_RELOC_PAIR",
2160dff0c46cSDimitry Andric "ARM_RELOC_SECTDIFF",
2161dff0c46cSDimitry Andric "ARM_RELOC_LOCAL_SECTDIFF",
2162dff0c46cSDimitry Andric "ARM_RELOC_PB_LA_PTR",
2163dff0c46cSDimitry Andric "ARM_RELOC_BR24",
2164dff0c46cSDimitry Andric "ARM_THUMB_RELOC_BR22",
2165dff0c46cSDimitry Andric "ARM_THUMB_32BIT_BRANCH",
2166dff0c46cSDimitry Andric "ARM_RELOC_HALF",
2167dff0c46cSDimitry Andric "ARM_RELOC_HALF_SECTDIFF" };
2168dff0c46cSDimitry Andric
2169284c1978SDimitry Andric if (RType > 9)
2170dff0c46cSDimitry Andric res = "Unknown";
2171dff0c46cSDimitry Andric else
2172284c1978SDimitry Andric res = Table[RType];
2173dff0c46cSDimitry Andric break;
2174dff0c46cSDimitry Andric }
217591bc56edSDimitry Andric case Triple::aarch64: {
217691bc56edSDimitry Andric static const char *const Table[] = {
217791bc56edSDimitry Andric "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
217891bc56edSDimitry Andric "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
217991bc56edSDimitry Andric "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
218091bc56edSDimitry Andric "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
218191bc56edSDimitry Andric "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
218291bc56edSDimitry Andric "ARM64_RELOC_ADDEND"
218391bc56edSDimitry Andric };
218491bc56edSDimitry Andric
218591bc56edSDimitry Andric if (RType >= array_lengthof(Table))
218691bc56edSDimitry Andric res = "Unknown";
218791bc56edSDimitry Andric else
218891bc56edSDimitry Andric res = Table[RType];
218991bc56edSDimitry Andric break;
219091bc56edSDimitry Andric }
2191dff0c46cSDimitry Andric case Triple::ppc: {
21927ae0e2c9SDimitry Andric static const char *const Table[] = {
2193dff0c46cSDimitry Andric "PPC_RELOC_VANILLA",
2194dff0c46cSDimitry Andric "PPC_RELOC_PAIR",
2195dff0c46cSDimitry Andric "PPC_RELOC_BR14",
2196dff0c46cSDimitry Andric "PPC_RELOC_BR24",
2197dff0c46cSDimitry Andric "PPC_RELOC_HI16",
2198dff0c46cSDimitry Andric "PPC_RELOC_LO16",
2199dff0c46cSDimitry Andric "PPC_RELOC_HA16",
2200dff0c46cSDimitry Andric "PPC_RELOC_LO14",
2201dff0c46cSDimitry Andric "PPC_RELOC_SECTDIFF",
2202dff0c46cSDimitry Andric "PPC_RELOC_PB_LA_PTR",
2203dff0c46cSDimitry Andric "PPC_RELOC_HI16_SECTDIFF",
2204dff0c46cSDimitry Andric "PPC_RELOC_LO16_SECTDIFF",
2205dff0c46cSDimitry Andric "PPC_RELOC_HA16_SECTDIFF",
2206dff0c46cSDimitry Andric "PPC_RELOC_JBSR",
2207dff0c46cSDimitry Andric "PPC_RELOC_LO14_SECTDIFF",
2208dff0c46cSDimitry Andric "PPC_RELOC_LOCAL_SECTDIFF" };
2209dff0c46cSDimitry Andric
221091bc56edSDimitry Andric if (RType > 15)
221191bc56edSDimitry Andric res = "Unknown";
221291bc56edSDimitry Andric else
2213284c1978SDimitry Andric res = Table[RType];
2214dff0c46cSDimitry Andric break;
2215dff0c46cSDimitry Andric }
2216dff0c46cSDimitry Andric case Triple::UnknownArch:
2217dff0c46cSDimitry Andric res = "Unknown";
2218dff0c46cSDimitry Andric break;
2219dff0c46cSDimitry Andric }
2220dff0c46cSDimitry Andric Result.append(res.begin(), res.end());
222197bc6c73SDimitry Andric }
222297bc6c73SDimitry Andric
getRelocationLength(DataRefImpl Rel) const222397bc6c73SDimitry Andric uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
222497bc6c73SDimitry Andric MachO::any_relocation_info RE = getRelocation(Rel);
222597bc6c73SDimitry Andric return getAnyRelocationLength(RE);
2226dff0c46cSDimitry Andric }
2227dff0c46cSDimitry Andric
222891bc56edSDimitry Andric //
222991bc56edSDimitry Andric // guessLibraryShortName() is passed a name of a dynamic library and returns a
223091bc56edSDimitry Andric // guess on what the short name is. Then name is returned as a substring of the
223191bc56edSDimitry Andric // StringRef Name passed in. The name of the dynamic library is recognized as
223291bc56edSDimitry Andric // a framework if it has one of the two following forms:
223391bc56edSDimitry Andric // Foo.framework/Versions/A/Foo
223491bc56edSDimitry Andric // Foo.framework/Foo
223591bc56edSDimitry Andric // Where A and Foo can be any string. And may contain a trailing suffix
223691bc56edSDimitry Andric // starting with an underbar. If the Name is recognized as a framework then
223791bc56edSDimitry Andric // isFramework is set to true else it is set to false. If the Name has a
223891bc56edSDimitry Andric // suffix then Suffix is set to the substring in Name that contains the suffix
223991bc56edSDimitry Andric // else it is set to a NULL StringRef.
224091bc56edSDimitry Andric //
224191bc56edSDimitry Andric // The Name of the dynamic library is recognized as a library name if it has
224291bc56edSDimitry Andric // one of the two following forms:
224391bc56edSDimitry Andric // libFoo.A.dylib
224491bc56edSDimitry Andric // libFoo.dylib
224591bc56edSDimitry Andric // The library may have a suffix trailing the name Foo of the form:
224691bc56edSDimitry Andric // libFoo_profile.A.dylib
224791bc56edSDimitry Andric // libFoo_profile.dylib
224891bc56edSDimitry Andric //
224991bc56edSDimitry Andric // The Name of the dynamic library is also recognized as a library name if it
225091bc56edSDimitry Andric // has the following form:
225191bc56edSDimitry Andric // Foo.qtx
225291bc56edSDimitry Andric //
225391bc56edSDimitry Andric // If the Name of the dynamic library is none of the forms above then a NULL
225491bc56edSDimitry Andric // StringRef is returned.
225591bc56edSDimitry Andric //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)225691bc56edSDimitry Andric StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
225791bc56edSDimitry Andric bool &isFramework,
225891bc56edSDimitry Andric StringRef &Suffix) {
225991bc56edSDimitry Andric StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
226091bc56edSDimitry Andric size_t a, b, c, d, Idx;
2261dff0c46cSDimitry Andric
226291bc56edSDimitry Andric isFramework = false;
226391bc56edSDimitry Andric Suffix = StringRef();
226491bc56edSDimitry Andric
226591bc56edSDimitry Andric // Pull off the last component and make Foo point to it
226691bc56edSDimitry Andric a = Name.rfind('/');
226791bc56edSDimitry Andric if (a == Name.npos || a == 0)
226891bc56edSDimitry Andric goto guess_library;
226991bc56edSDimitry Andric Foo = Name.slice(a+1, Name.npos);
227091bc56edSDimitry Andric
227191bc56edSDimitry Andric // Look for a suffix starting with a '_'
227291bc56edSDimitry Andric Idx = Foo.rfind('_');
227391bc56edSDimitry Andric if (Idx != Foo.npos && Foo.size() >= 2) {
227491bc56edSDimitry Andric Suffix = Foo.slice(Idx, Foo.npos);
227591bc56edSDimitry Andric Foo = Foo.slice(0, Idx);
2276284c1978SDimitry Andric }
2277284c1978SDimitry Andric
227891bc56edSDimitry Andric // First look for the form Foo.framework/Foo
227991bc56edSDimitry Andric b = Name.rfind('/', a);
228091bc56edSDimitry Andric if (b == Name.npos)
228191bc56edSDimitry Andric Idx = 0;
228291bc56edSDimitry Andric else
228391bc56edSDimitry Andric Idx = b+1;
228491bc56edSDimitry Andric F = Name.slice(Idx, Idx + Foo.size());
228591bc56edSDimitry Andric DotFramework = Name.slice(Idx + Foo.size(),
228691bc56edSDimitry Andric Idx + Foo.size() + sizeof(".framework/")-1);
228791bc56edSDimitry Andric if (F == Foo && DotFramework == ".framework/") {
228891bc56edSDimitry Andric isFramework = true;
228991bc56edSDimitry Andric return Foo;
229091bc56edSDimitry Andric }
229191bc56edSDimitry Andric
229291bc56edSDimitry Andric // Next look for the form Foo.framework/Versions/A/Foo
229391bc56edSDimitry Andric if (b == Name.npos)
229491bc56edSDimitry Andric goto guess_library;
229591bc56edSDimitry Andric c = Name.rfind('/', b);
229691bc56edSDimitry Andric if (c == Name.npos || c == 0)
229791bc56edSDimitry Andric goto guess_library;
229891bc56edSDimitry Andric V = Name.slice(c+1, Name.npos);
229991bc56edSDimitry Andric if (!V.startswith("Versions/"))
230091bc56edSDimitry Andric goto guess_library;
230191bc56edSDimitry Andric d = Name.rfind('/', c);
230291bc56edSDimitry Andric if (d == Name.npos)
230391bc56edSDimitry Andric Idx = 0;
230491bc56edSDimitry Andric else
230591bc56edSDimitry Andric Idx = d+1;
230691bc56edSDimitry Andric F = Name.slice(Idx, Idx + Foo.size());
230791bc56edSDimitry Andric DotFramework = Name.slice(Idx + Foo.size(),
230891bc56edSDimitry Andric Idx + Foo.size() + sizeof(".framework/")-1);
230991bc56edSDimitry Andric if (F == Foo && DotFramework == ".framework/") {
231091bc56edSDimitry Andric isFramework = true;
231191bc56edSDimitry Andric return Foo;
231291bc56edSDimitry Andric }
231391bc56edSDimitry Andric
231491bc56edSDimitry Andric guess_library:
231591bc56edSDimitry Andric // pull off the suffix after the "." and make a point to it
231691bc56edSDimitry Andric a = Name.rfind('.');
231791bc56edSDimitry Andric if (a == Name.npos || a == 0)
231891bc56edSDimitry Andric return StringRef();
231991bc56edSDimitry Andric Dylib = Name.slice(a, Name.npos);
232091bc56edSDimitry Andric if (Dylib != ".dylib")
232191bc56edSDimitry Andric goto guess_qtx;
232291bc56edSDimitry Andric
232391bc56edSDimitry Andric // First pull off the version letter for the form Foo.A.dylib if any.
232491bc56edSDimitry Andric if (a >= 3) {
232591bc56edSDimitry Andric Dot = Name.slice(a-2, a-1);
232691bc56edSDimitry Andric if (Dot == ".")
232791bc56edSDimitry Andric a = a - 2;
232891bc56edSDimitry Andric }
232991bc56edSDimitry Andric
233091bc56edSDimitry Andric b = Name.rfind('/', a);
233191bc56edSDimitry Andric if (b == Name.npos)
233291bc56edSDimitry Andric b = 0;
233391bc56edSDimitry Andric else
233491bc56edSDimitry Andric b = b+1;
233591bc56edSDimitry Andric // ignore any suffix after an underbar like Foo_profile.A.dylib
233691bc56edSDimitry Andric Idx = Name.find('_', b);
233791bc56edSDimitry Andric if (Idx != Name.npos && Idx != b) {
233891bc56edSDimitry Andric Lib = Name.slice(b, Idx);
233991bc56edSDimitry Andric Suffix = Name.slice(Idx, a);
234091bc56edSDimitry Andric }
234191bc56edSDimitry Andric else
234291bc56edSDimitry Andric Lib = Name.slice(b, a);
234391bc56edSDimitry Andric // There are incorrect library names of the form:
234491bc56edSDimitry Andric // libATS.A_profile.dylib so check for these.
234591bc56edSDimitry Andric if (Lib.size() >= 3) {
234691bc56edSDimitry Andric Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
234791bc56edSDimitry Andric if (Dot == ".")
234891bc56edSDimitry Andric Lib = Lib.slice(0, Lib.size()-2);
234991bc56edSDimitry Andric }
235091bc56edSDimitry Andric return Lib;
235191bc56edSDimitry Andric
235291bc56edSDimitry Andric guess_qtx:
235391bc56edSDimitry Andric Qtx = Name.slice(a, Name.npos);
235491bc56edSDimitry Andric if (Qtx != ".qtx")
235591bc56edSDimitry Andric return StringRef();
235691bc56edSDimitry Andric b = Name.rfind('/', a);
235791bc56edSDimitry Andric if (b == Name.npos)
235891bc56edSDimitry Andric Lib = Name.slice(0, a);
235991bc56edSDimitry Andric else
236091bc56edSDimitry Andric Lib = Name.slice(b+1, a);
236191bc56edSDimitry Andric // There are library names of the form: QT.A.qtx so check for these.
236291bc56edSDimitry Andric if (Lib.size() >= 3) {
236391bc56edSDimitry Andric Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
236491bc56edSDimitry Andric if (Dot == ".")
236591bc56edSDimitry Andric Lib = Lib.slice(0, Lib.size()-2);
236691bc56edSDimitry Andric }
236791bc56edSDimitry Andric return Lib;
236891bc56edSDimitry Andric }
236991bc56edSDimitry Andric
237091bc56edSDimitry Andric // getLibraryShortNameByIndex() is used to get the short name of the library
237191bc56edSDimitry Andric // for an undefined symbol in a linked Mach-O binary that was linked with the
237291bc56edSDimitry Andric // normal two-level namespace default (that is MH_TWOLEVEL in the header).
237391bc56edSDimitry Andric // It is passed the index (0 - based) of the library as translated from
237491bc56edSDimitry Andric // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const237591bc56edSDimitry Andric std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
237639d628a0SDimitry Andric StringRef &Res) const {
237791bc56edSDimitry Andric if (Index >= Libraries.size())
237891bc56edSDimitry Andric return object_error::parse_failed;
237991bc56edSDimitry Andric
238091bc56edSDimitry Andric // If the cache of LibrariesShortNames is not built up do that first for
238191bc56edSDimitry Andric // all the Libraries.
238291bc56edSDimitry Andric if (LibrariesShortNames.size() == 0) {
238391bc56edSDimitry Andric for (unsigned i = 0; i < Libraries.size(); i++) {
238491bc56edSDimitry Andric MachO::dylib_command D =
2385d88c1a5aSDimitry Andric getStruct<MachO::dylib_command>(*this, Libraries[i]);
238639d628a0SDimitry Andric if (D.dylib.name >= D.cmdsize)
238739d628a0SDimitry Andric return object_error::parse_failed;
238891bc56edSDimitry Andric const char *P = (const char *)(Libraries[i]) + D.dylib.name;
238991bc56edSDimitry Andric StringRef Name = StringRef(P);
239039d628a0SDimitry Andric if (D.dylib.name+Name.size() >= D.cmdsize)
239139d628a0SDimitry Andric return object_error::parse_failed;
239291bc56edSDimitry Andric StringRef Suffix;
239391bc56edSDimitry Andric bool isFramework;
239491bc56edSDimitry Andric StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
239539d628a0SDimitry Andric if (shortName.empty())
239691bc56edSDimitry Andric LibrariesShortNames.push_back(Name);
239791bc56edSDimitry Andric else
239891bc56edSDimitry Andric LibrariesShortNames.push_back(shortName);
239991bc56edSDimitry Andric }
240091bc56edSDimitry Andric }
240191bc56edSDimitry Andric
240291bc56edSDimitry Andric Res = LibrariesShortNames[Index];
240397bc6c73SDimitry Andric return std::error_code();
240491bc56edSDimitry Andric }
240591bc56edSDimitry Andric
getLibraryCount() const24067a7e6055SDimitry Andric uint32_t MachOObjectFile::getLibraryCount() const {
24077a7e6055SDimitry Andric return Libraries.size();
24087a7e6055SDimitry Andric }
24097a7e6055SDimitry Andric
2410875ed548SDimitry Andric section_iterator
getRelocationRelocatedSection(relocation_iterator Rel) const2411875ed548SDimitry Andric MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2412875ed548SDimitry Andric DataRefImpl Sec;
2413875ed548SDimitry Andric Sec.d.a = Rel->getRawDataRefImpl().d.a;
2414875ed548SDimitry Andric return section_iterator(SectionRef(Sec, this));
2415875ed548SDimitry Andric }
2416875ed548SDimitry Andric
symbol_begin() const2417d88c1a5aSDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_begin() const {
24183ca95b02SDimitry Andric DataRefImpl DRI;
24193ca95b02SDimitry Andric MachO::symtab_command Symtab = getSymtabLoadCommand();
24203ca95b02SDimitry Andric if (!SymtabLoadCmd || Symtab.nsyms == 0)
24213ca95b02SDimitry Andric return basic_symbol_iterator(SymbolRef(DRI, this));
24223ca95b02SDimitry Andric
242391bc56edSDimitry Andric return getSymbolByIndex(0);
242491bc56edSDimitry Andric }
242591bc56edSDimitry Andric
symbol_end() const2426d88c1a5aSDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_end() const {
2427284c1978SDimitry Andric DataRefImpl DRI;
24283ca95b02SDimitry Andric MachO::symtab_command Symtab = getSymtabLoadCommand();
24293ca95b02SDimitry Andric if (!SymtabLoadCmd || Symtab.nsyms == 0)
243091bc56edSDimitry Andric return basic_symbol_iterator(SymbolRef(DRI, this));
2431284c1978SDimitry Andric
2432284c1978SDimitry Andric unsigned SymbolTableEntrySize = is64Bit() ?
2433f785676fSDimitry Andric sizeof(MachO::nlist_64) :
2434f785676fSDimitry Andric sizeof(MachO::nlist);
2435f785676fSDimitry Andric unsigned Offset = Symtab.symoff +
2436f785676fSDimitry Andric Symtab.nsyms * SymbolTableEntrySize;
2437d88c1a5aSDimitry Andric DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
243891bc56edSDimitry Andric return basic_symbol_iterator(SymbolRef(DRI, this));
2439284c1978SDimitry Andric }
2440284c1978SDimitry Andric
getSymbolByIndex(unsigned Index) const2441*b5893f02SDimitry Andric symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
244291bc56edSDimitry Andric MachO::symtab_command Symtab = getSymtabLoadCommand();
24433ca95b02SDimitry Andric if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2444ff0cc061SDimitry Andric report_fatal_error("Requested symbol index is out of range.");
244591bc56edSDimitry Andric unsigned SymbolTableEntrySize =
244691bc56edSDimitry Andric is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
24473ca95b02SDimitry Andric DataRefImpl DRI;
2448d88c1a5aSDimitry Andric DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
244991bc56edSDimitry Andric DRI.p += Index * SymbolTableEntrySize;
245091bc56edSDimitry Andric return basic_symbol_iterator(SymbolRef(DRI, this));
2451284c1978SDimitry Andric }
2452284c1978SDimitry Andric
getSymbolIndex(DataRefImpl Symb) const24533ca95b02SDimitry Andric uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
24543ca95b02SDimitry Andric MachO::symtab_command Symtab = getSymtabLoadCommand();
24553ca95b02SDimitry Andric if (!SymtabLoadCmd)
24563ca95b02SDimitry Andric report_fatal_error("getSymbolIndex() called with no symbol table symbol");
24573ca95b02SDimitry Andric unsigned SymbolTableEntrySize =
24583ca95b02SDimitry Andric is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
24593ca95b02SDimitry Andric DataRefImpl DRIstart;
2460d88c1a5aSDimitry Andric DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
24613ca95b02SDimitry Andric uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
24623ca95b02SDimitry Andric return Index;
24633ca95b02SDimitry Andric }
24643ca95b02SDimitry Andric
section_begin() const246591bc56edSDimitry Andric section_iterator MachOObjectFile::section_begin() const {
2466284c1978SDimitry Andric DataRefImpl DRI;
2467284c1978SDimitry Andric return section_iterator(SectionRef(DRI, this));
2468284c1978SDimitry Andric }
2469284c1978SDimitry Andric
section_end() const247091bc56edSDimitry Andric section_iterator MachOObjectFile::section_end() const {
2471284c1978SDimitry Andric DataRefImpl DRI;
2472284c1978SDimitry Andric DRI.d.a = Sections.size();
2473284c1978SDimitry Andric return section_iterator(SectionRef(DRI, this));
2474284c1978SDimitry Andric }
2475284c1978SDimitry Andric
getBytesInAddress() const24763b0f4066SDimitry Andric uint8_t MachOObjectFile::getBytesInAddress() const {
2477284c1978SDimitry Andric return is64Bit() ? 8 : 4;
24783b0f4066SDimitry Andric }
24793b0f4066SDimitry Andric
getFileFormatName() const24803b0f4066SDimitry Andric StringRef MachOObjectFile::getFileFormatName() const {
2481d88c1a5aSDimitry Andric unsigned CPUType = getCPUType(*this);
2482284c1978SDimitry Andric if (!is64Bit()) {
2483284c1978SDimitry Andric switch (CPUType) {
248451690af2SDimitry Andric case MachO::CPU_TYPE_I386:
24853b0f4066SDimitry Andric return "Mach-O 32-bit i386";
248651690af2SDimitry Andric case MachO::CPU_TYPE_ARM:
24873b0f4066SDimitry Andric return "Mach-O arm";
248851690af2SDimitry Andric case MachO::CPU_TYPE_POWERPC:
24893b0f4066SDimitry Andric return "Mach-O 32-bit ppc";
24903b0f4066SDimitry Andric default:
24913b0f4066SDimitry Andric return "Mach-O 32-bit unknown";
24923b0f4066SDimitry Andric }
24933b0f4066SDimitry Andric }
24943b0f4066SDimitry Andric
2495284c1978SDimitry Andric switch (CPUType) {
249651690af2SDimitry Andric case MachO::CPU_TYPE_X86_64:
24973b0f4066SDimitry Andric return "Mach-O 64-bit x86-64";
249851690af2SDimitry Andric case MachO::CPU_TYPE_ARM64:
249991bc56edSDimitry Andric return "Mach-O arm64";
250051690af2SDimitry Andric case MachO::CPU_TYPE_POWERPC64:
25013b0f4066SDimitry Andric return "Mach-O 64-bit ppc64";
25023b0f4066SDimitry Andric default:
25033b0f4066SDimitry Andric return "Mach-O 64-bit unknown";
25043b0f4066SDimitry Andric }
25053b0f4066SDimitry Andric }
25063b0f4066SDimitry Andric
getArch(uint32_t CPUType)2507f785676fSDimitry Andric Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2508f785676fSDimitry Andric switch (CPUType) {
250951690af2SDimitry Andric case MachO::CPU_TYPE_I386:
25103b0f4066SDimitry Andric return Triple::x86;
251151690af2SDimitry Andric case MachO::CPU_TYPE_X86_64:
25123b0f4066SDimitry Andric return Triple::x86_64;
251351690af2SDimitry Andric case MachO::CPU_TYPE_ARM:
25143b0f4066SDimitry Andric return Triple::arm;
251551690af2SDimitry Andric case MachO::CPU_TYPE_ARM64:
251639d628a0SDimitry Andric return Triple::aarch64;
251751690af2SDimitry Andric case MachO::CPU_TYPE_POWERPC:
25183b0f4066SDimitry Andric return Triple::ppc;
251951690af2SDimitry Andric case MachO::CPU_TYPE_POWERPC64:
25203b0f4066SDimitry Andric return Triple::ppc64;
25213b0f4066SDimitry Andric default:
25223b0f4066SDimitry Andric return Triple::UnknownArch;
25233b0f4066SDimitry Andric }
25243b0f4066SDimitry Andric }
25253b0f4066SDimitry Andric
getArchTriple(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,const char ** ArchFlag)25263ca95b02SDimitry Andric Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2527d88c1a5aSDimitry Andric const char **McpuDefault,
2528d88c1a5aSDimitry Andric const char **ArchFlag) {
252939d628a0SDimitry Andric if (McpuDefault)
253039d628a0SDimitry Andric *McpuDefault = nullptr;
2531d88c1a5aSDimitry Andric if (ArchFlag)
2532d88c1a5aSDimitry Andric *ArchFlag = nullptr;
253339d628a0SDimitry Andric
253491bc56edSDimitry Andric switch (CPUType) {
253591bc56edSDimitry Andric case MachO::CPU_TYPE_I386:
253691bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
253791bc56edSDimitry Andric case MachO::CPU_SUBTYPE_I386_ALL:
2538d88c1a5aSDimitry Andric if (ArchFlag)
2539d88c1a5aSDimitry Andric *ArchFlag = "i386";
254091bc56edSDimitry Andric return Triple("i386-apple-darwin");
254191bc56edSDimitry Andric default:
254291bc56edSDimitry Andric return Triple();
254391bc56edSDimitry Andric }
254491bc56edSDimitry Andric case MachO::CPU_TYPE_X86_64:
254591bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
254691bc56edSDimitry Andric case MachO::CPU_SUBTYPE_X86_64_ALL:
2547d88c1a5aSDimitry Andric if (ArchFlag)
2548d88c1a5aSDimitry Andric *ArchFlag = "x86_64";
254991bc56edSDimitry Andric return Triple("x86_64-apple-darwin");
255091bc56edSDimitry Andric case MachO::CPU_SUBTYPE_X86_64_H:
2551d88c1a5aSDimitry Andric if (ArchFlag)
2552d88c1a5aSDimitry Andric *ArchFlag = "x86_64h";
255391bc56edSDimitry Andric return Triple("x86_64h-apple-darwin");
255491bc56edSDimitry Andric default:
255591bc56edSDimitry Andric return Triple();
255691bc56edSDimitry Andric }
255791bc56edSDimitry Andric case MachO::CPU_TYPE_ARM:
255891bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
255991bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V4T:
2560d88c1a5aSDimitry Andric if (ArchFlag)
2561d88c1a5aSDimitry Andric *ArchFlag = "armv4t";
256291bc56edSDimitry Andric return Triple("armv4t-apple-darwin");
256391bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2564d88c1a5aSDimitry Andric if (ArchFlag)
2565d88c1a5aSDimitry Andric *ArchFlag = "armv5e";
256691bc56edSDimitry Andric return Triple("armv5e-apple-darwin");
256739d628a0SDimitry Andric case MachO::CPU_SUBTYPE_ARM_XSCALE:
2568d88c1a5aSDimitry Andric if (ArchFlag)
2569d88c1a5aSDimitry Andric *ArchFlag = "xscale";
257039d628a0SDimitry Andric return Triple("xscale-apple-darwin");
257191bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V6:
2572d88c1a5aSDimitry Andric if (ArchFlag)
2573d88c1a5aSDimitry Andric *ArchFlag = "armv6";
257491bc56edSDimitry Andric return Triple("armv6-apple-darwin");
257591bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V6M:
257639d628a0SDimitry Andric if (McpuDefault)
257739d628a0SDimitry Andric *McpuDefault = "cortex-m0";
2578d88c1a5aSDimitry Andric if (ArchFlag)
2579d88c1a5aSDimitry Andric *ArchFlag = "armv6m";
258091bc56edSDimitry Andric return Triple("armv6m-apple-darwin");
258139d628a0SDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7:
2582d88c1a5aSDimitry Andric if (ArchFlag)
2583d88c1a5aSDimitry Andric *ArchFlag = "armv7";
258439d628a0SDimitry Andric return Triple("armv7-apple-darwin");
258591bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7EM:
258639d628a0SDimitry Andric if (McpuDefault)
258739d628a0SDimitry Andric *McpuDefault = "cortex-m4";
2588d88c1a5aSDimitry Andric if (ArchFlag)
2589d88c1a5aSDimitry Andric *ArchFlag = "armv7em";
25903ca95b02SDimitry Andric return Triple("thumbv7em-apple-darwin");
259191bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7K:
25927a7e6055SDimitry Andric if (McpuDefault)
25937a7e6055SDimitry Andric *McpuDefault = "cortex-a7";
2594d88c1a5aSDimitry Andric if (ArchFlag)
2595d88c1a5aSDimitry Andric *ArchFlag = "armv7k";
259691bc56edSDimitry Andric return Triple("armv7k-apple-darwin");
259791bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7M:
259839d628a0SDimitry Andric if (McpuDefault)
259939d628a0SDimitry Andric *McpuDefault = "cortex-m3";
2600d88c1a5aSDimitry Andric if (ArchFlag)
2601d88c1a5aSDimitry Andric *ArchFlag = "armv7m";
26023ca95b02SDimitry Andric return Triple("thumbv7m-apple-darwin");
260391bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7S:
26047a7e6055SDimitry Andric if (McpuDefault)
26057a7e6055SDimitry Andric *McpuDefault = "cortex-a7";
2606d88c1a5aSDimitry Andric if (ArchFlag)
2607d88c1a5aSDimitry Andric *ArchFlag = "armv7s";
260891bc56edSDimitry Andric return Triple("armv7s-apple-darwin");
260991bc56edSDimitry Andric default:
261091bc56edSDimitry Andric return Triple();
261191bc56edSDimitry Andric }
261291bc56edSDimitry Andric case MachO::CPU_TYPE_ARM64:
261391bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
261491bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM64_ALL:
26157a7e6055SDimitry Andric if (McpuDefault)
26167a7e6055SDimitry Andric *McpuDefault = "cyclone";
2617d88c1a5aSDimitry Andric if (ArchFlag)
2618d88c1a5aSDimitry Andric *ArchFlag = "arm64";
261991bc56edSDimitry Andric return Triple("arm64-apple-darwin");
262091bc56edSDimitry Andric default:
262191bc56edSDimitry Andric return Triple();
262291bc56edSDimitry Andric }
262391bc56edSDimitry Andric case MachO::CPU_TYPE_POWERPC:
262491bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
262591bc56edSDimitry Andric case MachO::CPU_SUBTYPE_POWERPC_ALL:
2626d88c1a5aSDimitry Andric if (ArchFlag)
2627d88c1a5aSDimitry Andric *ArchFlag = "ppc";
262891bc56edSDimitry Andric return Triple("ppc-apple-darwin");
262991bc56edSDimitry Andric default:
263091bc56edSDimitry Andric return Triple();
263191bc56edSDimitry Andric }
263291bc56edSDimitry Andric case MachO::CPU_TYPE_POWERPC64:
263391bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
263491bc56edSDimitry Andric case MachO::CPU_SUBTYPE_POWERPC_ALL:
2635d88c1a5aSDimitry Andric if (ArchFlag)
2636d88c1a5aSDimitry Andric *ArchFlag = "ppc64";
263791bc56edSDimitry Andric return Triple("ppc64-apple-darwin");
263891bc56edSDimitry Andric default:
263991bc56edSDimitry Andric return Triple();
264091bc56edSDimitry Andric }
264191bc56edSDimitry Andric default:
264291bc56edSDimitry Andric return Triple();
264391bc56edSDimitry Andric }
264491bc56edSDimitry Andric }
264591bc56edSDimitry Andric
getHostArch()264691bc56edSDimitry Andric Triple MachOObjectFile::getHostArch() {
264791bc56edSDimitry Andric return Triple(sys::getDefaultTargetTriple());
264891bc56edSDimitry Andric }
264991bc56edSDimitry Andric
isValidArch(StringRef ArchFlag)265039d628a0SDimitry Andric bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
265139d628a0SDimitry Andric return StringSwitch<bool>(ArchFlag)
265239d628a0SDimitry Andric .Case("i386", true)
265339d628a0SDimitry Andric .Case("x86_64", true)
265439d628a0SDimitry Andric .Case("x86_64h", true)
265539d628a0SDimitry Andric .Case("armv4t", true)
265639d628a0SDimitry Andric .Case("arm", true)
265739d628a0SDimitry Andric .Case("armv5e", true)
265839d628a0SDimitry Andric .Case("armv6", true)
265939d628a0SDimitry Andric .Case("armv6m", true)
26608f0fd8f6SDimitry Andric .Case("armv7", true)
266139d628a0SDimitry Andric .Case("armv7em", true)
266239d628a0SDimitry Andric .Case("armv7k", true)
266339d628a0SDimitry Andric .Case("armv7m", true)
266439d628a0SDimitry Andric .Case("armv7s", true)
266539d628a0SDimitry Andric .Case("arm64", true)
266639d628a0SDimitry Andric .Case("ppc", true)
266739d628a0SDimitry Andric .Case("ppc64", true)
266839d628a0SDimitry Andric .Default(false);
266991bc56edSDimitry Andric }
267091bc56edSDimitry Andric
getArch() const26712cab237bSDimitry Andric Triple::ArchType MachOObjectFile::getArch() const {
2672d88c1a5aSDimitry Andric return getArch(getCPUType(*this));
2673f785676fSDimitry Andric }
2674f785676fSDimitry Andric
getArchTriple(const char ** McpuDefault) const26753ca95b02SDimitry Andric Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
26763ca95b02SDimitry Andric return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2677284c1978SDimitry Andric }
2678284c1978SDimitry Andric
section_rel_begin(unsigned Index) const2679f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2680284c1978SDimitry Andric DataRefImpl DRI;
2681284c1978SDimitry Andric DRI.d.a = Index;
2682f785676fSDimitry Andric return section_rel_begin(DRI);
2683284c1978SDimitry Andric }
2684284c1978SDimitry Andric
section_rel_end(unsigned Index) const2685f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2686284c1978SDimitry Andric DataRefImpl DRI;
2687284c1978SDimitry Andric DRI.d.a = Index;
2688f785676fSDimitry Andric return section_rel_end(DRI);
2689f785676fSDimitry Andric }
2690f785676fSDimitry Andric
begin_dices() const2691f785676fSDimitry Andric dice_iterator MachOObjectFile::begin_dices() const {
2692f785676fSDimitry Andric DataRefImpl DRI;
2693f785676fSDimitry Andric if (!DataInCodeLoadCmd)
2694f785676fSDimitry Andric return dice_iterator(DiceRef(DRI, this));
2695f785676fSDimitry Andric
2696f785676fSDimitry Andric MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2697d88c1a5aSDimitry Andric DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2698f785676fSDimitry Andric return dice_iterator(DiceRef(DRI, this));
2699f785676fSDimitry Andric }
2700f785676fSDimitry Andric
end_dices() const2701f785676fSDimitry Andric dice_iterator MachOObjectFile::end_dices() const {
2702f785676fSDimitry Andric DataRefImpl DRI;
2703f785676fSDimitry Andric if (!DataInCodeLoadCmd)
2704f785676fSDimitry Andric return dice_iterator(DiceRef(DRI, this));
2705f785676fSDimitry Andric
2706f785676fSDimitry Andric MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2707f785676fSDimitry Andric unsigned Offset = DicLC.dataoff + DicLC.datasize;
2708d88c1a5aSDimitry Andric DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2709f785676fSDimitry Andric return dice_iterator(DiceRef(DRI, this));
2710284c1978SDimitry Andric }
2711284c1978SDimitry Andric
ExportEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> T)27122cab237bSDimitry Andric ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
27132cab237bSDimitry Andric ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
271439d628a0SDimitry Andric
moveToFirst()271539d628a0SDimitry Andric void ExportEntry::moveToFirst() {
27162cab237bSDimitry Andric ErrorAsOutParameter ErrAsOutParam(E);
271739d628a0SDimitry Andric pushNode(0);
27182cab237bSDimitry Andric if (*E)
27192cab237bSDimitry Andric return;
272039d628a0SDimitry Andric pushDownUntilBottom();
272139d628a0SDimitry Andric }
272239d628a0SDimitry Andric
moveToEnd()272339d628a0SDimitry Andric void ExportEntry::moveToEnd() {
272439d628a0SDimitry Andric Stack.clear();
272539d628a0SDimitry Andric Done = true;
272639d628a0SDimitry Andric }
272739d628a0SDimitry Andric
operator ==(const ExportEntry & Other) const272839d628a0SDimitry Andric bool ExportEntry::operator==(const ExportEntry &Other) const {
272939d628a0SDimitry Andric // Common case, one at end, other iterating from begin.
273039d628a0SDimitry Andric if (Done || Other.Done)
273139d628a0SDimitry Andric return (Done == Other.Done);
273239d628a0SDimitry Andric // Not equal if different stack sizes.
273339d628a0SDimitry Andric if (Stack.size() != Other.Stack.size())
273439d628a0SDimitry Andric return false;
273539d628a0SDimitry Andric // Not equal if different cumulative strings.
2736ff0cc061SDimitry Andric if (!CumulativeString.equals(Other.CumulativeString))
273739d628a0SDimitry Andric return false;
273839d628a0SDimitry Andric // Equal if all nodes in both stacks match.
273939d628a0SDimitry Andric for (unsigned i=0; i < Stack.size(); ++i) {
274039d628a0SDimitry Andric if (Stack[i].Start != Other.Stack[i].Start)
274139d628a0SDimitry Andric return false;
274239d628a0SDimitry Andric }
274339d628a0SDimitry Andric return true;
274439d628a0SDimitry Andric }
274539d628a0SDimitry Andric
readULEB128(const uint8_t * & Ptr,const char ** error)27462cab237bSDimitry Andric uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
274739d628a0SDimitry Andric unsigned Count;
27482cab237bSDimitry Andric uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
274939d628a0SDimitry Andric Ptr += Count;
27502cab237bSDimitry Andric if (Ptr > Trie.end())
275139d628a0SDimitry Andric Ptr = Trie.end();
275239d628a0SDimitry Andric return Result;
275339d628a0SDimitry Andric }
275439d628a0SDimitry Andric
name() const275539d628a0SDimitry Andric StringRef ExportEntry::name() const {
2756ff0cc061SDimitry Andric return CumulativeString;
275739d628a0SDimitry Andric }
275839d628a0SDimitry Andric
flags() const275939d628a0SDimitry Andric uint64_t ExportEntry::flags() const {
276039d628a0SDimitry Andric return Stack.back().Flags;
276139d628a0SDimitry Andric }
276239d628a0SDimitry Andric
address() const276339d628a0SDimitry Andric uint64_t ExportEntry::address() const {
276439d628a0SDimitry Andric return Stack.back().Address;
276539d628a0SDimitry Andric }
276639d628a0SDimitry Andric
other() const276739d628a0SDimitry Andric uint64_t ExportEntry::other() const {
276839d628a0SDimitry Andric return Stack.back().Other;
276939d628a0SDimitry Andric }
277039d628a0SDimitry Andric
otherName() const277139d628a0SDimitry Andric StringRef ExportEntry::otherName() const {
277239d628a0SDimitry Andric const char* ImportName = Stack.back().ImportName;
277339d628a0SDimitry Andric if (ImportName)
277439d628a0SDimitry Andric return StringRef(ImportName);
277539d628a0SDimitry Andric return StringRef();
277639d628a0SDimitry Andric }
277739d628a0SDimitry Andric
nodeOffset() const277839d628a0SDimitry Andric uint32_t ExportEntry::nodeOffset() const {
277939d628a0SDimitry Andric return Stack.back().Start - Trie.begin();
278039d628a0SDimitry Andric }
278139d628a0SDimitry Andric
NodeState(const uint8_t * Ptr)278239d628a0SDimitry Andric ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
278351690af2SDimitry Andric : Start(Ptr), Current(Ptr) {}
278439d628a0SDimitry Andric
pushNode(uint64_t offset)278539d628a0SDimitry Andric void ExportEntry::pushNode(uint64_t offset) {
27862cab237bSDimitry Andric ErrorAsOutParameter ErrAsOutParam(E);
278739d628a0SDimitry Andric const uint8_t *Ptr = Trie.begin() + offset;
278839d628a0SDimitry Andric NodeState State(Ptr);
27892cab237bSDimitry Andric const char *error;
27902cab237bSDimitry Andric uint64_t ExportInfoSize = readULEB128(State.Current, &error);
27912cab237bSDimitry Andric if (error) {
27922cab237bSDimitry Andric *E = malformedError("export info size " + Twine(error) +
27932cab237bSDimitry Andric " in export trie data at node: 0x" +
27942cab237bSDimitry Andric Twine::utohexstr(offset));
27952cab237bSDimitry Andric moveToEnd();
27962cab237bSDimitry Andric return;
27972cab237bSDimitry Andric }
279839d628a0SDimitry Andric State.IsExportNode = (ExportInfoSize != 0);
279939d628a0SDimitry Andric const uint8_t* Children = State.Current + ExportInfoSize;
28002cab237bSDimitry Andric if (Children > Trie.end()) {
28012cab237bSDimitry Andric *E = malformedError(
28022cab237bSDimitry Andric "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
28032cab237bSDimitry Andric " in export trie data at node: 0x" + Twine::utohexstr(offset) +
28042cab237bSDimitry Andric " too big and extends past end of trie data");
28052cab237bSDimitry Andric moveToEnd();
28062cab237bSDimitry Andric return;
28072cab237bSDimitry Andric }
280839d628a0SDimitry Andric if (State.IsExportNode) {
28092cab237bSDimitry Andric const uint8_t *ExportStart = State.Current;
28102cab237bSDimitry Andric State.Flags = readULEB128(State.Current, &error);
28112cab237bSDimitry Andric if (error) {
28122cab237bSDimitry Andric *E = malformedError("flags " + Twine(error) +
28132cab237bSDimitry Andric " in export trie data at node: 0x" +
28142cab237bSDimitry Andric Twine::utohexstr(offset));
28152cab237bSDimitry Andric moveToEnd();
28162cab237bSDimitry Andric return;
28172cab237bSDimitry Andric }
28182cab237bSDimitry Andric uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
28192cab237bSDimitry Andric if (State.Flags != 0 &&
28202cab237bSDimitry Andric (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
28212cab237bSDimitry Andric Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
28222cab237bSDimitry Andric Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
28232cab237bSDimitry Andric *E = malformedError(
28242cab237bSDimitry Andric "unsupported exported symbol kind: " + Twine((int)Kind) +
28252cab237bSDimitry Andric " in flags: 0x" + Twine::utohexstr(State.Flags) +
28262cab237bSDimitry Andric " in export trie data at node: 0x" + Twine::utohexstr(offset));
28272cab237bSDimitry Andric moveToEnd();
28282cab237bSDimitry Andric return;
28292cab237bSDimitry Andric }
283039d628a0SDimitry Andric if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
283139d628a0SDimitry Andric State.Address = 0;
28322cab237bSDimitry Andric State.Other = readULEB128(State.Current, &error); // dylib ordinal
28332cab237bSDimitry Andric if (error) {
28342cab237bSDimitry Andric *E = malformedError("dylib ordinal of re-export " + Twine(error) +
28352cab237bSDimitry Andric " in export trie data at node: 0x" +
28362cab237bSDimitry Andric Twine::utohexstr(offset));
28372cab237bSDimitry Andric moveToEnd();
28382cab237bSDimitry Andric return;
28392cab237bSDimitry Andric }
28402cab237bSDimitry Andric if (O != nullptr) {
28412cab237bSDimitry Andric if (State.Other > O->getLibraryCount()) {
28422cab237bSDimitry Andric *E = malformedError(
28432cab237bSDimitry Andric "bad library ordinal: " + Twine((int)State.Other) + " (max " +
28442cab237bSDimitry Andric Twine((int)O->getLibraryCount()) +
28452cab237bSDimitry Andric ") in export trie data at node: 0x" + Twine::utohexstr(offset));
28462cab237bSDimitry Andric moveToEnd();
28472cab237bSDimitry Andric return;
28482cab237bSDimitry Andric }
28492cab237bSDimitry Andric }
285039d628a0SDimitry Andric State.ImportName = reinterpret_cast<const char*>(State.Current);
28512cab237bSDimitry Andric if (*State.ImportName == '\0') {
28522cab237bSDimitry Andric State.Current++;
285339d628a0SDimitry Andric } else {
28542cab237bSDimitry Andric const uint8_t *End = State.Current + 1;
28552cab237bSDimitry Andric if (End >= Trie.end()) {
28562cab237bSDimitry Andric *E = malformedError("import name of re-export in export trie data at "
28572cab237bSDimitry Andric "node: 0x" +
28582cab237bSDimitry Andric Twine::utohexstr(offset) +
28592cab237bSDimitry Andric " starts past end of trie data");
28602cab237bSDimitry Andric moveToEnd();
28612cab237bSDimitry Andric return;
28622cab237bSDimitry Andric }
28632cab237bSDimitry Andric while(*End != '\0' && End < Trie.end())
28642cab237bSDimitry Andric End++;
28652cab237bSDimitry Andric if (*End != '\0') {
28662cab237bSDimitry Andric *E = malformedError("import name of re-export in export trie data at "
28672cab237bSDimitry Andric "node: 0x" +
28682cab237bSDimitry Andric Twine::utohexstr(offset) +
28692cab237bSDimitry Andric " extends past end of trie data");
28702cab237bSDimitry Andric moveToEnd();
28712cab237bSDimitry Andric return;
28722cab237bSDimitry Andric }
28732cab237bSDimitry Andric State.Current = End + 1;
28742cab237bSDimitry Andric }
28752cab237bSDimitry Andric } else {
28762cab237bSDimitry Andric State.Address = readULEB128(State.Current, &error);
28772cab237bSDimitry Andric if (error) {
28782cab237bSDimitry Andric *E = malformedError("address " + Twine(error) +
28792cab237bSDimitry Andric " in export trie data at node: 0x" +
28802cab237bSDimitry Andric Twine::utohexstr(offset));
28812cab237bSDimitry Andric moveToEnd();
28822cab237bSDimitry Andric return;
28832cab237bSDimitry Andric }
28842cab237bSDimitry Andric if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
28852cab237bSDimitry Andric State.Other = readULEB128(State.Current, &error);
28862cab237bSDimitry Andric if (error) {
28872cab237bSDimitry Andric *E = malformedError("resolver of stub and resolver " + Twine(error) +
28882cab237bSDimitry Andric " in export trie data at node: 0x" +
28892cab237bSDimitry Andric Twine::utohexstr(offset));
28902cab237bSDimitry Andric moveToEnd();
28912cab237bSDimitry Andric return;
28922cab237bSDimitry Andric }
28932cab237bSDimitry Andric }
28942cab237bSDimitry Andric }
28952cab237bSDimitry Andric if(ExportStart + ExportInfoSize != State.Current) {
28962cab237bSDimitry Andric *E = malformedError(
28972cab237bSDimitry Andric "inconsistant export info size: 0x" +
28982cab237bSDimitry Andric Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
28992cab237bSDimitry Andric Twine::utohexstr(State.Current - ExportStart) +
29002cab237bSDimitry Andric " in export trie data at node: 0x" + Twine::utohexstr(offset));
29012cab237bSDimitry Andric moveToEnd();
29022cab237bSDimitry Andric return;
290339d628a0SDimitry Andric }
290439d628a0SDimitry Andric }
290539d628a0SDimitry Andric State.ChildCount = *Children;
29062cab237bSDimitry Andric if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
29072cab237bSDimitry Andric *E = malformedError("byte for count of childern in export trie data at "
29082cab237bSDimitry Andric "node: 0x" +
29092cab237bSDimitry Andric Twine::utohexstr(offset) +
29102cab237bSDimitry Andric " extends past end of trie data");
29112cab237bSDimitry Andric moveToEnd();
29122cab237bSDimitry Andric return;
29132cab237bSDimitry Andric }
291439d628a0SDimitry Andric State.Current = Children + 1;
291539d628a0SDimitry Andric State.NextChildIndex = 0;
291639d628a0SDimitry Andric State.ParentStringLength = CumulativeString.size();
291739d628a0SDimitry Andric Stack.push_back(State);
291839d628a0SDimitry Andric }
291939d628a0SDimitry Andric
pushDownUntilBottom()292039d628a0SDimitry Andric void ExportEntry::pushDownUntilBottom() {
29212cab237bSDimitry Andric ErrorAsOutParameter ErrAsOutParam(E);
29222cab237bSDimitry Andric const char *error;
292339d628a0SDimitry Andric while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
292439d628a0SDimitry Andric NodeState &Top = Stack.back();
292539d628a0SDimitry Andric CumulativeString.resize(Top.ParentStringLength);
29262cab237bSDimitry Andric for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
292739d628a0SDimitry Andric char C = *Top.Current;
292839d628a0SDimitry Andric CumulativeString.push_back(C);
292939d628a0SDimitry Andric }
29302cab237bSDimitry Andric if (Top.Current >= Trie.end()) {
29312cab237bSDimitry Andric *E = malformedError("edge sub-string in export trie data at node: 0x" +
29322cab237bSDimitry Andric Twine::utohexstr(Top.Start - Trie.begin()) +
29332cab237bSDimitry Andric " for child #" + Twine((int)Top.NextChildIndex) +
29342cab237bSDimitry Andric " extends past end of trie data");
29352cab237bSDimitry Andric moveToEnd();
29362cab237bSDimitry Andric return;
29372cab237bSDimitry Andric }
293839d628a0SDimitry Andric Top.Current += 1;
29392cab237bSDimitry Andric uint64_t childNodeIndex = readULEB128(Top.Current, &error);
29402cab237bSDimitry Andric if (error) {
29412cab237bSDimitry Andric *E = malformedError("child node offset " + Twine(error) +
29422cab237bSDimitry Andric " in export trie data at node: 0x" +
29432cab237bSDimitry Andric Twine::utohexstr(Top.Start - Trie.begin()));
29442cab237bSDimitry Andric moveToEnd();
29452cab237bSDimitry Andric return;
29462cab237bSDimitry Andric }
29472cab237bSDimitry Andric for (const NodeState &node : nodes()) {
29482cab237bSDimitry Andric if (node.Start == Trie.begin() + childNodeIndex){
29492cab237bSDimitry Andric *E = malformedError("loop in childern in export trie data at node: 0x" +
29502cab237bSDimitry Andric Twine::utohexstr(Top.Start - Trie.begin()) +
29512cab237bSDimitry Andric " back to node: 0x" +
29522cab237bSDimitry Andric Twine::utohexstr(childNodeIndex));
29532cab237bSDimitry Andric moveToEnd();
29542cab237bSDimitry Andric return;
29552cab237bSDimitry Andric }
29562cab237bSDimitry Andric }
295739d628a0SDimitry Andric Top.NextChildIndex += 1;
295839d628a0SDimitry Andric pushNode(childNodeIndex);
29592cab237bSDimitry Andric if (*E)
29602cab237bSDimitry Andric return;
296139d628a0SDimitry Andric }
296239d628a0SDimitry Andric if (!Stack.back().IsExportNode) {
29632cab237bSDimitry Andric *E = malformedError("node is not an export node in export trie data at "
29642cab237bSDimitry Andric "node: 0x" +
29652cab237bSDimitry Andric Twine::utohexstr(Stack.back().Start - Trie.begin()));
296639d628a0SDimitry Andric moveToEnd();
29672cab237bSDimitry Andric return;
296839d628a0SDimitry Andric }
296939d628a0SDimitry Andric }
297039d628a0SDimitry Andric
297139d628a0SDimitry Andric // We have a trie data structure and need a way to walk it that is compatible
297239d628a0SDimitry Andric // with the C++ iterator model. The solution is a non-recursive depth first
297339d628a0SDimitry Andric // traversal where the iterator contains a stack of parent nodes along with a
297439d628a0SDimitry Andric // string that is the accumulation of all edge strings along the parent chain
297539d628a0SDimitry Andric // to this point.
297639d628a0SDimitry Andric //
297739d628a0SDimitry Andric // There is one "export" node for each exported symbol. But because some
297839d628a0SDimitry Andric // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
297939d628a0SDimitry Andric // node may have child nodes too.
298039d628a0SDimitry Andric //
298139d628a0SDimitry Andric // The algorithm for moveNext() is to keep moving down the leftmost unvisited
298239d628a0SDimitry Andric // child until hitting a node with no children (which is an export node or
298339d628a0SDimitry Andric // else the trie is malformed). On the way down, each node is pushed on the
298439d628a0SDimitry Andric // stack ivar. If there is no more ways down, it pops up one and tries to go
298539d628a0SDimitry Andric // down a sibling path until a childless node is reached.
moveNext()298639d628a0SDimitry Andric void ExportEntry::moveNext() {
29872cab237bSDimitry Andric assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
29882cab237bSDimitry Andric if (!Stack.back().IsExportNode) {
29892cab237bSDimitry Andric *E = malformedError("node is not an export node in export trie data at "
29902cab237bSDimitry Andric "node: 0x" +
29912cab237bSDimitry Andric Twine::utohexstr(Stack.back().Start - Trie.begin()));
299239d628a0SDimitry Andric moveToEnd();
299339d628a0SDimitry Andric return;
299439d628a0SDimitry Andric }
299539d628a0SDimitry Andric
299639d628a0SDimitry Andric Stack.pop_back();
299739d628a0SDimitry Andric while (!Stack.empty()) {
299839d628a0SDimitry Andric NodeState &Top = Stack.back();
299939d628a0SDimitry Andric if (Top.NextChildIndex < Top.ChildCount) {
300039d628a0SDimitry Andric pushDownUntilBottom();
300139d628a0SDimitry Andric // Now at the next export node.
300239d628a0SDimitry Andric return;
300339d628a0SDimitry Andric } else {
300439d628a0SDimitry Andric if (Top.IsExportNode) {
300539d628a0SDimitry Andric // This node has no children but is itself an export node.
300639d628a0SDimitry Andric CumulativeString.resize(Top.ParentStringLength);
300739d628a0SDimitry Andric return;
300839d628a0SDimitry Andric }
300939d628a0SDimitry Andric Stack.pop_back();
301039d628a0SDimitry Andric }
301139d628a0SDimitry Andric }
301239d628a0SDimitry Andric Done = true;
301339d628a0SDimitry Andric }
301439d628a0SDimitry Andric
301539d628a0SDimitry Andric iterator_range<export_iterator>
exports(Error & E,ArrayRef<uint8_t> Trie,const MachOObjectFile * O)30162cab237bSDimitry Andric MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
30172cab237bSDimitry Andric const MachOObjectFile *O) {
30182cab237bSDimitry Andric ExportEntry Start(&E, O, Trie);
301951690af2SDimitry Andric if (Trie.empty())
302039d628a0SDimitry Andric Start.moveToEnd();
302139d628a0SDimitry Andric else
302239d628a0SDimitry Andric Start.moveToFirst();
302339d628a0SDimitry Andric
30242cab237bSDimitry Andric ExportEntry Finish(&E, O, Trie);
302539d628a0SDimitry Andric Finish.moveToEnd();
302639d628a0SDimitry Andric
30277d523365SDimitry Andric return make_range(export_iterator(Start), export_iterator(Finish));
302839d628a0SDimitry Andric }
302939d628a0SDimitry Andric
exports(Error & Err) const30302cab237bSDimitry Andric iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
30312cab237bSDimitry Andric return exports(Err, getDyldInfoExportsTrie(), this);
303239d628a0SDimitry Andric }
303339d628a0SDimitry Andric
MachORebaseEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit)30347a7e6055SDimitry Andric MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
30357a7e6055SDimitry Andric ArrayRef<uint8_t> Bytes, bool is64Bit)
303651690af2SDimitry Andric : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
303751690af2SDimitry Andric PointerSize(is64Bit ? 8 : 4) {}
303839d628a0SDimitry Andric
moveToFirst()303939d628a0SDimitry Andric void MachORebaseEntry::moveToFirst() {
304039d628a0SDimitry Andric Ptr = Opcodes.begin();
304139d628a0SDimitry Andric moveNext();
304239d628a0SDimitry Andric }
304339d628a0SDimitry Andric
moveToEnd()304439d628a0SDimitry Andric void MachORebaseEntry::moveToEnd() {
304539d628a0SDimitry Andric Ptr = Opcodes.end();
304639d628a0SDimitry Andric RemainingLoopCount = 0;
304739d628a0SDimitry Andric Done = true;
304839d628a0SDimitry Andric }
304939d628a0SDimitry Andric
moveNext()305039d628a0SDimitry Andric void MachORebaseEntry::moveNext() {
30517a7e6055SDimitry Andric ErrorAsOutParameter ErrAsOutParam(E);
305239d628a0SDimitry Andric // If in the middle of some loop, move to next rebasing in loop.
305339d628a0SDimitry Andric SegmentOffset += AdvanceAmount;
305439d628a0SDimitry Andric if (RemainingLoopCount) {
305539d628a0SDimitry Andric --RemainingLoopCount;
305639d628a0SDimitry Andric return;
305739d628a0SDimitry Andric }
30587a7e6055SDimitry Andric // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
30597a7e6055SDimitry Andric // pointer size. Therefore it is possible to reach the end without ever having
30607a7e6055SDimitry Andric // seen REBASE_OPCODE_DONE.
306139d628a0SDimitry Andric if (Ptr == Opcodes.end()) {
306239d628a0SDimitry Andric Done = true;
306339d628a0SDimitry Andric return;
306439d628a0SDimitry Andric }
306539d628a0SDimitry Andric bool More = true;
30667a7e6055SDimitry Andric while (More) {
306739d628a0SDimitry Andric // Parse next opcode and set up next loop.
30687a7e6055SDimitry Andric const uint8_t *OpcodeStart = Ptr;
306939d628a0SDimitry Andric uint8_t Byte = *Ptr++;
307039d628a0SDimitry Andric uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
307139d628a0SDimitry Andric uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
30727a7e6055SDimitry Andric uint32_t Count, Skip;
30737a7e6055SDimitry Andric const char *error = nullptr;
307439d628a0SDimitry Andric switch (Opcode) {
307539d628a0SDimitry Andric case MachO::REBASE_OPCODE_DONE:
307639d628a0SDimitry Andric More = false;
307739d628a0SDimitry Andric Done = true;
307839d628a0SDimitry Andric moveToEnd();
307951690af2SDimitry Andric DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
308039d628a0SDimitry Andric break;
308139d628a0SDimitry Andric case MachO::REBASE_OPCODE_SET_TYPE_IMM:
308239d628a0SDimitry Andric RebaseType = ImmValue;
30837a7e6055SDimitry Andric if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
30847a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
30857a7e6055SDimitry Andric Twine((int)RebaseType) + " for opcode at: 0x" +
30862cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
30877a7e6055SDimitry Andric moveToEnd();
30887a7e6055SDimitry Andric return;
30897a7e6055SDimitry Andric }
309039d628a0SDimitry Andric DEBUG_WITH_TYPE(
309139d628a0SDimitry Andric "mach-o-rebase",
309251690af2SDimitry Andric dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
309339d628a0SDimitry Andric << "RebaseType=" << (int) RebaseType << "\n");
309439d628a0SDimitry Andric break;
309539d628a0SDimitry Andric case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
309639d628a0SDimitry Andric SegmentIndex = ImmValue;
30977a7e6055SDimitry Andric SegmentOffset = readULEB128(&error);
30987a7e6055SDimitry Andric if (error) {
30997a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
31007a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
31012cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31027a7e6055SDimitry Andric moveToEnd();
31037a7e6055SDimitry Andric return;
31047a7e6055SDimitry Andric }
31057a7e6055SDimitry Andric error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31067a7e6055SDimitry Andric true);
31077a7e6055SDimitry Andric if (error) {
31087a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
31097a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
31102cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31117a7e6055SDimitry Andric moveToEnd();
31127a7e6055SDimitry Andric return;
31137a7e6055SDimitry Andric }
311439d628a0SDimitry Andric DEBUG_WITH_TYPE(
311539d628a0SDimitry Andric "mach-o-rebase",
311651690af2SDimitry Andric dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
311739d628a0SDimitry Andric << "SegmentIndex=" << SegmentIndex << ", "
311839d628a0SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset)
311939d628a0SDimitry Andric << "\n");
312039d628a0SDimitry Andric break;
312139d628a0SDimitry Andric case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
31227a7e6055SDimitry Andric SegmentOffset += readULEB128(&error);
31237a7e6055SDimitry Andric if (error) {
31242cab237bSDimitry Andric *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
31252cab237bSDimitry Andric " for opcode at: 0x" +
31262cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31277a7e6055SDimitry Andric moveToEnd();
31287a7e6055SDimitry Andric return;
31297a7e6055SDimitry Andric }
31307a7e6055SDimitry Andric error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31317a7e6055SDimitry Andric true);
31327a7e6055SDimitry Andric if (error) {
31332cab237bSDimitry Andric *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
31342cab237bSDimitry Andric " for opcode at: 0x" +
31352cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31367a7e6055SDimitry Andric moveToEnd();
31377a7e6055SDimitry Andric return;
31387a7e6055SDimitry Andric }
313939d628a0SDimitry Andric DEBUG_WITH_TYPE("mach-o-rebase",
314051690af2SDimitry Andric dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
314139d628a0SDimitry Andric << format("SegmentOffset=0x%06X",
314239d628a0SDimitry Andric SegmentOffset) << "\n");
314339d628a0SDimitry Andric break;
314439d628a0SDimitry Andric case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
31457a7e6055SDimitry Andric error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31467a7e6055SDimitry Andric true);
31477a7e6055SDimitry Andric if (error) {
31487a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
31497a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
31502cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31517a7e6055SDimitry Andric moveToEnd();
31527a7e6055SDimitry Andric return;
31537a7e6055SDimitry Andric }
315439d628a0SDimitry Andric SegmentOffset += ImmValue * PointerSize;
31557a7e6055SDimitry Andric error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31567a7e6055SDimitry Andric false);
31577a7e6055SDimitry Andric if (error) {
31582cab237bSDimitry Andric *E =
31592cab237bSDimitry Andric malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
31607a7e6055SDimitry Andric " (after adding immediate times the pointer size) " +
31617a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
31622cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31637a7e6055SDimitry Andric moveToEnd();
31647a7e6055SDimitry Andric return;
31657a7e6055SDimitry Andric }
316639d628a0SDimitry Andric DEBUG_WITH_TYPE("mach-o-rebase",
316751690af2SDimitry Andric dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
316839d628a0SDimitry Andric << format("SegmentOffset=0x%06X",
316939d628a0SDimitry Andric SegmentOffset) << "\n");
317039d628a0SDimitry Andric break;
317139d628a0SDimitry Andric case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
31727a7e6055SDimitry Andric error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
31737a7e6055SDimitry Andric true);
31747a7e6055SDimitry Andric if (error) {
31757a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
31767a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
31772cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31787a7e6055SDimitry Andric moveToEnd();
31797a7e6055SDimitry Andric return;
31807a7e6055SDimitry Andric }
318139d628a0SDimitry Andric AdvanceAmount = PointerSize;
31827a7e6055SDimitry Andric Skip = 0;
31837a7e6055SDimitry Andric Count = ImmValue;
31847a7e6055SDimitry Andric if (ImmValue != 0)
318539d628a0SDimitry Andric RemainingLoopCount = ImmValue - 1;
31867a7e6055SDimitry Andric else
31877a7e6055SDimitry Andric RemainingLoopCount = 0;
31887a7e6055SDimitry Andric error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
31897a7e6055SDimitry Andric SegmentIndex, SegmentOffset);
31907a7e6055SDimitry Andric if (error) {
31912cab237bSDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
31922cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
31932cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
31947a7e6055SDimitry Andric moveToEnd();
31957a7e6055SDimitry Andric return;
31967a7e6055SDimitry Andric }
319739d628a0SDimitry Andric DEBUG_WITH_TYPE(
319839d628a0SDimitry Andric "mach-o-rebase",
319951690af2SDimitry Andric dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
320039d628a0SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset)
320139d628a0SDimitry Andric << ", AdvanceAmount=" << AdvanceAmount
320239d628a0SDimitry Andric << ", RemainingLoopCount=" << RemainingLoopCount
320339d628a0SDimitry Andric << "\n");
320439d628a0SDimitry Andric return;
320539d628a0SDimitry Andric case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
32067a7e6055SDimitry Andric error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
32077a7e6055SDimitry Andric true);
32087a7e6055SDimitry Andric if (error) {
32097a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
32107a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
32112cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32127a7e6055SDimitry Andric moveToEnd();
32137a7e6055SDimitry Andric return;
32147a7e6055SDimitry Andric }
321539d628a0SDimitry Andric AdvanceAmount = PointerSize;
32167a7e6055SDimitry Andric Skip = 0;
32177a7e6055SDimitry Andric Count = readULEB128(&error);
32187a7e6055SDimitry Andric if (error) {
32197a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
32207a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
32212cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32227a7e6055SDimitry Andric moveToEnd();
32237a7e6055SDimitry Andric return;
32247a7e6055SDimitry Andric }
32257a7e6055SDimitry Andric if (Count != 0)
32267a7e6055SDimitry Andric RemainingLoopCount = Count - 1;
32277a7e6055SDimitry Andric else
32287a7e6055SDimitry Andric RemainingLoopCount = 0;
32297a7e6055SDimitry Andric error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
32307a7e6055SDimitry Andric SegmentIndex, SegmentOffset);
32317a7e6055SDimitry Andric if (error) {
32322cab237bSDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
32332cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
32342cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32357a7e6055SDimitry Andric moveToEnd();
32367a7e6055SDimitry Andric return;
32377a7e6055SDimitry Andric }
323839d628a0SDimitry Andric DEBUG_WITH_TYPE(
323939d628a0SDimitry Andric "mach-o-rebase",
324051690af2SDimitry Andric dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
324139d628a0SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset)
324239d628a0SDimitry Andric << ", AdvanceAmount=" << AdvanceAmount
324339d628a0SDimitry Andric << ", RemainingLoopCount=" << RemainingLoopCount
324439d628a0SDimitry Andric << "\n");
324539d628a0SDimitry Andric return;
324639d628a0SDimitry Andric case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
32477a7e6055SDimitry Andric error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
32487a7e6055SDimitry Andric true);
32497a7e6055SDimitry Andric if (error) {
32507a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
32517a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
32522cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32537a7e6055SDimitry Andric moveToEnd();
32547a7e6055SDimitry Andric return;
32557a7e6055SDimitry Andric }
32567a7e6055SDimitry Andric Skip = readULEB128(&error);
32577a7e6055SDimitry Andric if (error) {
32587a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
32597a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
32602cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32617a7e6055SDimitry Andric moveToEnd();
32627a7e6055SDimitry Andric return;
32637a7e6055SDimitry Andric }
32647a7e6055SDimitry Andric AdvanceAmount = Skip + PointerSize;
32657a7e6055SDimitry Andric Count = 1;
326639d628a0SDimitry Andric RemainingLoopCount = 0;
32677a7e6055SDimitry Andric error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
32687a7e6055SDimitry Andric SegmentIndex, SegmentOffset);
32697a7e6055SDimitry Andric if (error) {
32702cab237bSDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
32712cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
32722cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32737a7e6055SDimitry Andric moveToEnd();
32747a7e6055SDimitry Andric return;
32757a7e6055SDimitry Andric }
327639d628a0SDimitry Andric DEBUG_WITH_TYPE(
327739d628a0SDimitry Andric "mach-o-rebase",
327851690af2SDimitry Andric dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
327939d628a0SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset)
328039d628a0SDimitry Andric << ", AdvanceAmount=" << AdvanceAmount
328139d628a0SDimitry Andric << ", RemainingLoopCount=" << RemainingLoopCount
328239d628a0SDimitry Andric << "\n");
328339d628a0SDimitry Andric return;
328439d628a0SDimitry Andric case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
32857a7e6055SDimitry Andric error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
32867a7e6055SDimitry Andric true);
32877a7e6055SDimitry Andric if (error) {
32887a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
32892cab237bSDimitry Andric "ULEB " +
32902cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
32912cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
32927a7e6055SDimitry Andric moveToEnd();
32937a7e6055SDimitry Andric return;
32947a7e6055SDimitry Andric }
32957a7e6055SDimitry Andric Count = readULEB128(&error);
32967a7e6055SDimitry Andric if (error) {
32977a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
32982cab237bSDimitry Andric "ULEB " +
32992cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
33002cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33017a7e6055SDimitry Andric moveToEnd();
33027a7e6055SDimitry Andric return;
33037a7e6055SDimitry Andric }
33047a7e6055SDimitry Andric if (Count != 0)
33057a7e6055SDimitry Andric RemainingLoopCount = Count - 1;
33067a7e6055SDimitry Andric else
33077a7e6055SDimitry Andric RemainingLoopCount = 0;
33087a7e6055SDimitry Andric Skip = readULEB128(&error);
33097a7e6055SDimitry Andric if (error) {
33107a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
33112cab237bSDimitry Andric "ULEB " +
33122cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
33132cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33147a7e6055SDimitry Andric moveToEnd();
33157a7e6055SDimitry Andric return;
33167a7e6055SDimitry Andric }
33177a7e6055SDimitry Andric AdvanceAmount = Skip + PointerSize;
33187a7e6055SDimitry Andric
33197a7e6055SDimitry Andric error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
33207a7e6055SDimitry Andric SegmentIndex, SegmentOffset);
33217a7e6055SDimitry Andric if (error) {
33227a7e6055SDimitry Andric *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
33232cab237bSDimitry Andric "ULEB " +
33242cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
33252cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33267a7e6055SDimitry Andric moveToEnd();
33277a7e6055SDimitry Andric return;
33287a7e6055SDimitry Andric }
332939d628a0SDimitry Andric DEBUG_WITH_TYPE(
333039d628a0SDimitry Andric "mach-o-rebase",
333151690af2SDimitry Andric dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
333239d628a0SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset)
333339d628a0SDimitry Andric << ", AdvanceAmount=" << AdvanceAmount
333439d628a0SDimitry Andric << ", RemainingLoopCount=" << RemainingLoopCount
333539d628a0SDimitry Andric << "\n");
333639d628a0SDimitry Andric return;
333739d628a0SDimitry Andric default:
33387a7e6055SDimitry Andric *E = malformedError("bad rebase info (bad opcode value 0x" +
33392cab237bSDimitry Andric Twine::utohexstr(Opcode) + " for opcode at: 0x" +
33402cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
33417a7e6055SDimitry Andric moveToEnd();
33427a7e6055SDimitry Andric return;
334339d628a0SDimitry Andric }
334439d628a0SDimitry Andric }
334539d628a0SDimitry Andric }
334639d628a0SDimitry Andric
readULEB128(const char ** error)33477a7e6055SDimitry Andric uint64_t MachORebaseEntry::readULEB128(const char **error) {
334839d628a0SDimitry Andric unsigned Count;
33497a7e6055SDimitry Andric uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
335039d628a0SDimitry Andric Ptr += Count;
33517a7e6055SDimitry Andric if (Ptr > Opcodes.end())
335239d628a0SDimitry Andric Ptr = Opcodes.end();
335339d628a0SDimitry Andric return Result;
335439d628a0SDimitry Andric }
335539d628a0SDimitry Andric
segmentIndex() const33567a7e6055SDimitry Andric int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
335739d628a0SDimitry Andric
segmentOffset() const335839d628a0SDimitry Andric uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
335939d628a0SDimitry Andric
typeName() const336039d628a0SDimitry Andric StringRef MachORebaseEntry::typeName() const {
336139d628a0SDimitry Andric switch (RebaseType) {
336239d628a0SDimitry Andric case MachO::REBASE_TYPE_POINTER:
336339d628a0SDimitry Andric return "pointer";
336439d628a0SDimitry Andric case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
336539d628a0SDimitry Andric return "text abs32";
336639d628a0SDimitry Andric case MachO::REBASE_TYPE_TEXT_PCREL32:
336739d628a0SDimitry Andric return "text rel32";
336839d628a0SDimitry Andric }
336939d628a0SDimitry Andric return "unknown";
337039d628a0SDimitry Andric }
337139d628a0SDimitry Andric
33727a7e6055SDimitry Andric // For use with the SegIndex of a checked Mach-O Rebase entry
33737a7e6055SDimitry Andric // to get the segment name.
segmentName() const33747a7e6055SDimitry Andric StringRef MachORebaseEntry::segmentName() const {
33757a7e6055SDimitry Andric return O->BindRebaseSegmentName(SegmentIndex);
33767a7e6055SDimitry Andric }
33777a7e6055SDimitry Andric
33787a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
33797a7e6055SDimitry Andric // to get the section name.
sectionName() const33807a7e6055SDimitry Andric StringRef MachORebaseEntry::sectionName() const {
33817a7e6055SDimitry Andric return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
33827a7e6055SDimitry Andric }
33837a7e6055SDimitry Andric
33847a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
33857a7e6055SDimitry Andric // to get the address.
address() const33867a7e6055SDimitry Andric uint64_t MachORebaseEntry::address() const {
33877a7e6055SDimitry Andric return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
33887a7e6055SDimitry Andric }
33897a7e6055SDimitry Andric
operator ==(const MachORebaseEntry & Other) const339039d628a0SDimitry Andric bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
339124e2fe98SDimitry Andric #ifdef EXPENSIVE_CHECKS
339239d628a0SDimitry Andric assert(Opcodes == Other.Opcodes && "compare iterators of different files");
339324e2fe98SDimitry Andric #else
339424e2fe98SDimitry Andric assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
339524e2fe98SDimitry Andric #endif
339639d628a0SDimitry Andric return (Ptr == Other.Ptr) &&
339739d628a0SDimitry Andric (RemainingLoopCount == Other.RemainingLoopCount) &&
339839d628a0SDimitry Andric (Done == Other.Done);
339939d628a0SDimitry Andric }
340039d628a0SDimitry Andric
340139d628a0SDimitry Andric iterator_range<rebase_iterator>
rebaseTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64)34027a7e6055SDimitry Andric MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
34037a7e6055SDimitry Andric ArrayRef<uint8_t> Opcodes, bool is64) {
34047a7e6055SDimitry Andric if (O->BindRebaseSectionTable == nullptr)
34057a7e6055SDimitry Andric O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
34067a7e6055SDimitry Andric MachORebaseEntry Start(&Err, O, Opcodes, is64);
340739d628a0SDimitry Andric Start.moveToFirst();
340839d628a0SDimitry Andric
34097a7e6055SDimitry Andric MachORebaseEntry Finish(&Err, O, Opcodes, is64);
341039d628a0SDimitry Andric Finish.moveToEnd();
341139d628a0SDimitry Andric
34127d523365SDimitry Andric return make_range(rebase_iterator(Start), rebase_iterator(Finish));
341339d628a0SDimitry Andric }
341439d628a0SDimitry Andric
rebaseTable(Error & Err)34157a7e6055SDimitry Andric iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
34167a7e6055SDimitry Andric return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
341739d628a0SDimitry Andric }
341839d628a0SDimitry Andric
MachOBindEntry(Error * E,const MachOObjectFile * O,ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)34197a7e6055SDimitry Andric MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
34207a7e6055SDimitry Andric ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
342151690af2SDimitry Andric : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
342251690af2SDimitry Andric PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
342339d628a0SDimitry Andric
moveToFirst()342439d628a0SDimitry Andric void MachOBindEntry::moveToFirst() {
342539d628a0SDimitry Andric Ptr = Opcodes.begin();
342639d628a0SDimitry Andric moveNext();
342739d628a0SDimitry Andric }
342839d628a0SDimitry Andric
moveToEnd()342939d628a0SDimitry Andric void MachOBindEntry::moveToEnd() {
343039d628a0SDimitry Andric Ptr = Opcodes.end();
343139d628a0SDimitry Andric RemainingLoopCount = 0;
343239d628a0SDimitry Andric Done = true;
343339d628a0SDimitry Andric }
343439d628a0SDimitry Andric
moveNext()343539d628a0SDimitry Andric void MachOBindEntry::moveNext() {
34367a7e6055SDimitry Andric ErrorAsOutParameter ErrAsOutParam(E);
343739d628a0SDimitry Andric // If in the middle of some loop, move to next binding in loop.
343839d628a0SDimitry Andric SegmentOffset += AdvanceAmount;
343939d628a0SDimitry Andric if (RemainingLoopCount) {
344039d628a0SDimitry Andric --RemainingLoopCount;
344139d628a0SDimitry Andric return;
344239d628a0SDimitry Andric }
34437a7e6055SDimitry Andric // BIND_OPCODE_DONE is only used for padding if we are not aligned to
34447a7e6055SDimitry Andric // pointer size. Therefore it is possible to reach the end without ever having
34457a7e6055SDimitry Andric // seen BIND_OPCODE_DONE.
344639d628a0SDimitry Andric if (Ptr == Opcodes.end()) {
344739d628a0SDimitry Andric Done = true;
344839d628a0SDimitry Andric return;
344939d628a0SDimitry Andric }
345039d628a0SDimitry Andric bool More = true;
34517a7e6055SDimitry Andric while (More) {
345239d628a0SDimitry Andric // Parse next opcode and set up next loop.
34537a7e6055SDimitry Andric const uint8_t *OpcodeStart = Ptr;
345439d628a0SDimitry Andric uint8_t Byte = *Ptr++;
345539d628a0SDimitry Andric uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
345639d628a0SDimitry Andric uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
345739d628a0SDimitry Andric int8_t SignExtended;
345839d628a0SDimitry Andric const uint8_t *SymStart;
34597a7e6055SDimitry Andric uint32_t Count, Skip;
34607a7e6055SDimitry Andric const char *error = nullptr;
346139d628a0SDimitry Andric switch (Opcode) {
346239d628a0SDimitry Andric case MachO::BIND_OPCODE_DONE:
346339d628a0SDimitry Andric if (TableKind == Kind::Lazy) {
346439d628a0SDimitry Andric // Lazying bindings have a DONE opcode between entries. Need to ignore
346539d628a0SDimitry Andric // it to advance to next entry. But need not if this is last entry.
346639d628a0SDimitry Andric bool NotLastEntry = false;
346739d628a0SDimitry Andric for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
346839d628a0SDimitry Andric if (*P) {
346939d628a0SDimitry Andric NotLastEntry = true;
347039d628a0SDimitry Andric }
347139d628a0SDimitry Andric }
347239d628a0SDimitry Andric if (NotLastEntry)
347339d628a0SDimitry Andric break;
347439d628a0SDimitry Andric }
347539d628a0SDimitry Andric More = false;
347639d628a0SDimitry Andric moveToEnd();
347751690af2SDimitry Andric DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
347839d628a0SDimitry Andric break;
347939d628a0SDimitry Andric case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
34807a7e6055SDimitry Andric if (TableKind == Kind::Weak) {
34817a7e6055SDimitry Andric *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
34827a7e6055SDimitry Andric "weak bind table for opcode at: 0x" +
34832cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
34847a7e6055SDimitry Andric moveToEnd();
34857a7e6055SDimitry Andric return;
34867a7e6055SDimitry Andric }
348739d628a0SDimitry Andric Ordinal = ImmValue;
34887a7e6055SDimitry Andric LibraryOrdinalSet = true;
34897a7e6055SDimitry Andric if (ImmValue > O->getLibraryCount()) {
34907a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
34912cab237bSDimitry Andric "library ordinal: " +
34922cab237bSDimitry Andric Twine((int)ImmValue) + " (max " +
34932cab237bSDimitry Andric Twine((int)O->getLibraryCount()) +
34942cab237bSDimitry Andric ") for opcode at: 0x" +
34952cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
34967a7e6055SDimitry Andric moveToEnd();
34977a7e6055SDimitry Andric return;
34987a7e6055SDimitry Andric }
349939d628a0SDimitry Andric DEBUG_WITH_TYPE(
350039d628a0SDimitry Andric "mach-o-bind",
350151690af2SDimitry Andric dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
350239d628a0SDimitry Andric << "Ordinal=" << Ordinal << "\n");
350339d628a0SDimitry Andric break;
350439d628a0SDimitry Andric case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
35057a7e6055SDimitry Andric if (TableKind == Kind::Weak) {
35067a7e6055SDimitry Andric *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
35077a7e6055SDimitry Andric "weak bind table for opcode at: 0x" +
35082cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35097a7e6055SDimitry Andric moveToEnd();
35107a7e6055SDimitry Andric return;
35117a7e6055SDimitry Andric }
35127a7e6055SDimitry Andric Ordinal = readULEB128(&error);
35137a7e6055SDimitry Andric LibraryOrdinalSet = true;
35147a7e6055SDimitry Andric if (error) {
35157a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
35167a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
35172cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35187a7e6055SDimitry Andric moveToEnd();
35197a7e6055SDimitry Andric return;
35207a7e6055SDimitry Andric }
35217a7e6055SDimitry Andric if (Ordinal > (int)O->getLibraryCount()) {
35227a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
35232cab237bSDimitry Andric "library ordinal: " +
35242cab237bSDimitry Andric Twine((int)Ordinal) + " (max " +
35252cab237bSDimitry Andric Twine((int)O->getLibraryCount()) +
35262cab237bSDimitry Andric ") for opcode at: 0x" +
35272cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35287a7e6055SDimitry Andric moveToEnd();
35297a7e6055SDimitry Andric return;
35307a7e6055SDimitry Andric }
353139d628a0SDimitry Andric DEBUG_WITH_TYPE(
353239d628a0SDimitry Andric "mach-o-bind",
353351690af2SDimitry Andric dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
353439d628a0SDimitry Andric << "Ordinal=" << Ordinal << "\n");
353539d628a0SDimitry Andric break;
353639d628a0SDimitry Andric case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
35377a7e6055SDimitry Andric if (TableKind == Kind::Weak) {
35387a7e6055SDimitry Andric *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
35397a7e6055SDimitry Andric "weak bind table for opcode at: 0x" +
35402cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35417a7e6055SDimitry Andric moveToEnd();
35427a7e6055SDimitry Andric return;
35437a7e6055SDimitry Andric }
354439d628a0SDimitry Andric if (ImmValue) {
354539d628a0SDimitry Andric SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
354639d628a0SDimitry Andric Ordinal = SignExtended;
35477a7e6055SDimitry Andric if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
35487a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
35492cab237bSDimitry Andric "special ordinal: " +
35502cab237bSDimitry Andric Twine((int)Ordinal) + " for opcode at: 0x" +
35512cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35527a7e6055SDimitry Andric moveToEnd();
35537a7e6055SDimitry Andric return;
35547a7e6055SDimitry Andric }
355539d628a0SDimitry Andric } else
355639d628a0SDimitry Andric Ordinal = 0;
3557f9448bf3SDimitry Andric LibraryOrdinalSet = true;
355839d628a0SDimitry Andric DEBUG_WITH_TYPE(
355939d628a0SDimitry Andric "mach-o-bind",
356051690af2SDimitry Andric dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
356139d628a0SDimitry Andric << "Ordinal=" << Ordinal << "\n");
356239d628a0SDimitry Andric break;
356339d628a0SDimitry Andric case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
356439d628a0SDimitry Andric Flags = ImmValue;
356539d628a0SDimitry Andric SymStart = Ptr;
35667a7e6055SDimitry Andric while (*Ptr && (Ptr < Opcodes.end())) {
356739d628a0SDimitry Andric ++Ptr;
356839d628a0SDimitry Andric }
35697a7e6055SDimitry Andric if (Ptr == Opcodes.end()) {
35702cab237bSDimitry Andric *E = malformedError(
35712cab237bSDimitry Andric "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
35727a7e6055SDimitry Andric "symbol name extends past opcodes for opcode at: 0x" +
35732cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35747a7e6055SDimitry Andric moveToEnd();
35757a7e6055SDimitry Andric return;
35767a7e6055SDimitry Andric }
357739d628a0SDimitry Andric SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
357839d628a0SDimitry Andric Ptr-SymStart);
357939d628a0SDimitry Andric ++Ptr;
358039d628a0SDimitry Andric DEBUG_WITH_TYPE(
358139d628a0SDimitry Andric "mach-o-bind",
358251690af2SDimitry Andric dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
358339d628a0SDimitry Andric << "SymbolName=" << SymbolName << "\n");
358439d628a0SDimitry Andric if (TableKind == Kind::Weak) {
358539d628a0SDimitry Andric if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
358639d628a0SDimitry Andric return;
358739d628a0SDimitry Andric }
358839d628a0SDimitry Andric break;
358939d628a0SDimitry Andric case MachO::BIND_OPCODE_SET_TYPE_IMM:
359039d628a0SDimitry Andric BindType = ImmValue;
35917a7e6055SDimitry Andric if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
35927a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
35937a7e6055SDimitry Andric Twine((int)ImmValue) + " for opcode at: 0x" +
35942cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
35957a7e6055SDimitry Andric moveToEnd();
35967a7e6055SDimitry Andric return;
35977a7e6055SDimitry Andric }
359839d628a0SDimitry Andric DEBUG_WITH_TYPE(
359939d628a0SDimitry Andric "mach-o-bind",
360051690af2SDimitry Andric dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
360139d628a0SDimitry Andric << "BindType=" << (int)BindType << "\n");
360239d628a0SDimitry Andric break;
360339d628a0SDimitry Andric case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
36047a7e6055SDimitry Andric Addend = readSLEB128(&error);
36057a7e6055SDimitry Andric if (error) {
36062cab237bSDimitry Andric *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
36072cab237bSDimitry Andric " for opcode at: 0x" +
36082cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36097a7e6055SDimitry Andric moveToEnd();
36107a7e6055SDimitry Andric return;
36117a7e6055SDimitry Andric }
361239d628a0SDimitry Andric DEBUG_WITH_TYPE(
361339d628a0SDimitry Andric "mach-o-bind",
361451690af2SDimitry Andric dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
361539d628a0SDimitry Andric << "Addend=" << Addend << "\n");
361639d628a0SDimitry Andric break;
361739d628a0SDimitry Andric case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
361839d628a0SDimitry Andric SegmentIndex = ImmValue;
36197a7e6055SDimitry Andric SegmentOffset = readULEB128(&error);
36207a7e6055SDimitry Andric if (error) {
36217a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
36227a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
36232cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36247a7e6055SDimitry Andric moveToEnd();
36257a7e6055SDimitry Andric return;
36267a7e6055SDimitry Andric }
36277a7e6055SDimitry Andric error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
36287a7e6055SDimitry Andric if (error) {
36297a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
36307a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
36312cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36327a7e6055SDimitry Andric moveToEnd();
36337a7e6055SDimitry Andric return;
36347a7e6055SDimitry Andric }
363539d628a0SDimitry Andric DEBUG_WITH_TYPE(
363639d628a0SDimitry Andric "mach-o-bind",
363751690af2SDimitry Andric dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
363839d628a0SDimitry Andric << "SegmentIndex=" << SegmentIndex << ", "
363939d628a0SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset)
364039d628a0SDimitry Andric << "\n");
364139d628a0SDimitry Andric break;
364239d628a0SDimitry Andric case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
36437a7e6055SDimitry Andric SegmentOffset += readULEB128(&error);
36447a7e6055SDimitry Andric if (error) {
36452cab237bSDimitry Andric *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
36462cab237bSDimitry Andric " for opcode at: 0x" +
36472cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36487a7e6055SDimitry Andric moveToEnd();
36497a7e6055SDimitry Andric return;
36507a7e6055SDimitry Andric }
36517a7e6055SDimitry Andric error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
36527a7e6055SDimitry Andric if (error) {
36532cab237bSDimitry Andric *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
36542cab237bSDimitry Andric " for opcode at: 0x" +
36552cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36567a7e6055SDimitry Andric moveToEnd();
36577a7e6055SDimitry Andric return;
36587a7e6055SDimitry Andric }
365939d628a0SDimitry Andric DEBUG_WITH_TYPE("mach-o-bind",
366051690af2SDimitry Andric dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
366139d628a0SDimitry Andric << format("SegmentOffset=0x%06X",
366239d628a0SDimitry Andric SegmentOffset) << "\n");
366339d628a0SDimitry Andric break;
366439d628a0SDimitry Andric case MachO::BIND_OPCODE_DO_BIND:
366539d628a0SDimitry Andric AdvanceAmount = PointerSize;
366639d628a0SDimitry Andric RemainingLoopCount = 0;
36677a7e6055SDimitry Andric error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
36687a7e6055SDimitry Andric if (error) {
36697a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
36702cab237bSDimitry Andric " for opcode at: 0x" +
36712cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36727a7e6055SDimitry Andric moveToEnd();
36737a7e6055SDimitry Andric return;
36747a7e6055SDimitry Andric }
36757a7e6055SDimitry Andric if (SymbolName == StringRef()) {
36762cab237bSDimitry Andric *E = malformedError(
36772cab237bSDimitry Andric "for BIND_OPCODE_DO_BIND missing preceding "
36787a7e6055SDimitry Andric "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
36792cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36807a7e6055SDimitry Andric moveToEnd();
36817a7e6055SDimitry Andric return;
36827a7e6055SDimitry Andric }
36837a7e6055SDimitry Andric if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
36842cab237bSDimitry Andric *E =
36852cab237bSDimitry Andric malformedError("for BIND_OPCODE_DO_BIND missing preceding "
36867a7e6055SDimitry Andric "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
36872cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
36887a7e6055SDimitry Andric moveToEnd();
36897a7e6055SDimitry Andric return;
36907a7e6055SDimitry Andric }
369139d628a0SDimitry Andric DEBUG_WITH_TYPE("mach-o-bind",
369251690af2SDimitry Andric dbgs() << "BIND_OPCODE_DO_BIND: "
369339d628a0SDimitry Andric << format("SegmentOffset=0x%06X",
369439d628a0SDimitry Andric SegmentOffset) << "\n");
369539d628a0SDimitry Andric return;
369639d628a0SDimitry Andric case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
36977a7e6055SDimitry Andric if (TableKind == Kind::Lazy) {
36987a7e6055SDimitry Andric *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
36997a7e6055SDimitry Andric "lazy bind table for opcode at: 0x" +
37002cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37017a7e6055SDimitry Andric moveToEnd();
37027a7e6055SDimitry Andric return;
37037a7e6055SDimitry Andric }
37047a7e6055SDimitry Andric error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
37057a7e6055SDimitry Andric if (error) {
37067a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
37077a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
37082cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37097a7e6055SDimitry Andric moveToEnd();
37107a7e6055SDimitry Andric return;
37117a7e6055SDimitry Andric }
37127a7e6055SDimitry Andric if (SymbolName == StringRef()) {
37132cab237bSDimitry Andric *E = malformedError(
37142cab237bSDimitry Andric "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
37157a7e6055SDimitry Andric "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
37162cab237bSDimitry Andric "at: 0x" +
37172cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37187a7e6055SDimitry Andric moveToEnd();
37197a7e6055SDimitry Andric return;
37207a7e6055SDimitry Andric }
37217a7e6055SDimitry Andric if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
37222cab237bSDimitry Andric *E = malformedError(
37232cab237bSDimitry Andric "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
37247a7e6055SDimitry Andric "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
37252cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37267a7e6055SDimitry Andric moveToEnd();
37277a7e6055SDimitry Andric return;
37287a7e6055SDimitry Andric }
37297a7e6055SDimitry Andric AdvanceAmount = readULEB128(&error) + PointerSize;
37307a7e6055SDimitry Andric if (error) {
37317a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
37327a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
37332cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37347a7e6055SDimitry Andric moveToEnd();
37357a7e6055SDimitry Andric return;
37367a7e6055SDimitry Andric }
37377a7e6055SDimitry Andric // Note, this is not really an error until the next bind but make no sense
37387a7e6055SDimitry Andric // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
37397a7e6055SDimitry Andric // bind operation.
37407a7e6055SDimitry Andric error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
37417a7e6055SDimitry Andric AdvanceAmount, false);
37427a7e6055SDimitry Andric if (error) {
37437a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
37442cab237bSDimitry Andric "ULEB) " +
37452cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
37462cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37477a7e6055SDimitry Andric moveToEnd();
37487a7e6055SDimitry Andric return;
37497a7e6055SDimitry Andric }
375039d628a0SDimitry Andric RemainingLoopCount = 0;
375139d628a0SDimitry Andric DEBUG_WITH_TYPE(
375239d628a0SDimitry Andric "mach-o-bind",
375351690af2SDimitry Andric dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
375439d628a0SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset)
375539d628a0SDimitry Andric << ", AdvanceAmount=" << AdvanceAmount
375639d628a0SDimitry Andric << ", RemainingLoopCount=" << RemainingLoopCount
375739d628a0SDimitry Andric << "\n");
375839d628a0SDimitry Andric return;
375939d628a0SDimitry Andric case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
37607a7e6055SDimitry Andric if (TableKind == Kind::Lazy) {
37617a7e6055SDimitry Andric *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
37627a7e6055SDimitry Andric "allowed in lazy bind table for opcode at: 0x" +
37632cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37647a7e6055SDimitry Andric moveToEnd();
37657a7e6055SDimitry Andric return;
37667a7e6055SDimitry Andric }
37677a7e6055SDimitry Andric error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
37687a7e6055SDimitry Andric if (error) {
37697a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
37707a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
37712cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37727a7e6055SDimitry Andric moveToEnd();
37737a7e6055SDimitry Andric return;
37747a7e6055SDimitry Andric }
37757a7e6055SDimitry Andric if (SymbolName == StringRef()) {
37762cab237bSDimitry Andric *E = malformedError(
37772cab237bSDimitry Andric "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
37787a7e6055SDimitry Andric "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
37792cab237bSDimitry Andric "opcode at: 0x" +
37802cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37817a7e6055SDimitry Andric moveToEnd();
37827a7e6055SDimitry Andric return;
37837a7e6055SDimitry Andric }
37847a7e6055SDimitry Andric if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
37852cab237bSDimitry Andric *E = malformedError(
37862cab237bSDimitry Andric "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
37877a7e6055SDimitry Andric "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
37882cab237bSDimitry Andric "at: 0x" +
37892cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
37907a7e6055SDimitry Andric moveToEnd();
37917a7e6055SDimitry Andric return;
37927a7e6055SDimitry Andric }
379339d628a0SDimitry Andric AdvanceAmount = ImmValue * PointerSize + PointerSize;
379439d628a0SDimitry Andric RemainingLoopCount = 0;
37957a7e6055SDimitry Andric error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
37967a7e6055SDimitry Andric AdvanceAmount, false);
37977a7e6055SDimitry Andric if (error) {
37982cab237bSDimitry Andric *E =
37992cab237bSDimitry Andric malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
38007a7e6055SDimitry Andric " (after adding immediate times the pointer size) " +
38017a7e6055SDimitry Andric Twine(error) + " for opcode at: 0x" +
38022cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38037a7e6055SDimitry Andric moveToEnd();
38047a7e6055SDimitry Andric return;
38057a7e6055SDimitry Andric }
380639d628a0SDimitry Andric DEBUG_WITH_TYPE("mach-o-bind",
380751690af2SDimitry Andric dbgs()
380839d628a0SDimitry Andric << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
380951690af2SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
381039d628a0SDimitry Andric return;
381139d628a0SDimitry Andric case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
38127a7e6055SDimitry Andric if (TableKind == Kind::Lazy) {
38137a7e6055SDimitry Andric *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
38147a7e6055SDimitry Andric "allowed in lazy bind table for opcode at: 0x" +
38152cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38167a7e6055SDimitry Andric moveToEnd();
38177a7e6055SDimitry Andric return;
38187a7e6055SDimitry Andric }
38197a7e6055SDimitry Andric Count = readULEB128(&error);
38207a7e6055SDimitry Andric if (Count != 0)
38217a7e6055SDimitry Andric RemainingLoopCount = Count - 1;
38227a7e6055SDimitry Andric else
38237a7e6055SDimitry Andric RemainingLoopCount = 0;
38247a7e6055SDimitry Andric if (error) {
38257a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38262cab237bSDimitry Andric " (count value) " +
38272cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
38282cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38297a7e6055SDimitry Andric moveToEnd();
38307a7e6055SDimitry Andric return;
38317a7e6055SDimitry Andric }
38327a7e6055SDimitry Andric Skip = readULEB128(&error);
38337a7e6055SDimitry Andric AdvanceAmount = Skip + PointerSize;
38347a7e6055SDimitry Andric if (error) {
38357a7e6055SDimitry Andric *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38362cab237bSDimitry Andric " (skip value) " +
38372cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
38382cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38397a7e6055SDimitry Andric moveToEnd();
38407a7e6055SDimitry Andric return;
38417a7e6055SDimitry Andric }
38427a7e6055SDimitry Andric error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
38437a7e6055SDimitry Andric if (error) {
38442cab237bSDimitry Andric *E =
38452cab237bSDimitry Andric malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
38462cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
38472cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38487a7e6055SDimitry Andric moveToEnd();
38497a7e6055SDimitry Andric return;
38507a7e6055SDimitry Andric }
38517a7e6055SDimitry Andric if (SymbolName == StringRef()) {
38522cab237bSDimitry Andric *E = malformedError(
38532cab237bSDimitry Andric "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38547a7e6055SDimitry Andric "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
38552cab237bSDimitry Andric "opcode at: 0x" +
38562cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38577a7e6055SDimitry Andric moveToEnd();
38587a7e6055SDimitry Andric return;
38597a7e6055SDimitry Andric }
38607a7e6055SDimitry Andric if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
38612cab237bSDimitry Andric *E = malformedError(
38622cab237bSDimitry Andric "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
38637a7e6055SDimitry Andric "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
38642cab237bSDimitry Andric "at: 0x" +
38652cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38667a7e6055SDimitry Andric moveToEnd();
38677a7e6055SDimitry Andric return;
38687a7e6055SDimitry Andric }
38697a7e6055SDimitry Andric error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
38707a7e6055SDimitry Andric SegmentIndex, SegmentOffset);
38717a7e6055SDimitry Andric if (error) {
38722cab237bSDimitry Andric *E =
38732cab237bSDimitry Andric malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
38742cab237bSDimitry Andric Twine(error) + " for opcode at: 0x" +
38752cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38767a7e6055SDimitry Andric moveToEnd();
38777a7e6055SDimitry Andric return;
38787a7e6055SDimitry Andric }
387939d628a0SDimitry Andric DEBUG_WITH_TYPE(
388039d628a0SDimitry Andric "mach-o-bind",
388151690af2SDimitry Andric dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
388239d628a0SDimitry Andric << format("SegmentOffset=0x%06X", SegmentOffset)
388339d628a0SDimitry Andric << ", AdvanceAmount=" << AdvanceAmount
388439d628a0SDimitry Andric << ", RemainingLoopCount=" << RemainingLoopCount
388539d628a0SDimitry Andric << "\n");
388639d628a0SDimitry Andric return;
388739d628a0SDimitry Andric default:
38887a7e6055SDimitry Andric *E = malformedError("bad bind info (bad opcode value 0x" +
38892cab237bSDimitry Andric Twine::utohexstr(Opcode) + " for opcode at: 0x" +
38902cab237bSDimitry Andric Twine::utohexstr(OpcodeStart - Opcodes.begin()));
38917a7e6055SDimitry Andric moveToEnd();
38927a7e6055SDimitry Andric return;
389339d628a0SDimitry Andric }
389439d628a0SDimitry Andric }
389539d628a0SDimitry Andric }
389639d628a0SDimitry Andric
readULEB128(const char ** error)38977a7e6055SDimitry Andric uint64_t MachOBindEntry::readULEB128(const char **error) {
389839d628a0SDimitry Andric unsigned Count;
38997a7e6055SDimitry Andric uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
390039d628a0SDimitry Andric Ptr += Count;
39017a7e6055SDimitry Andric if (Ptr > Opcodes.end())
390239d628a0SDimitry Andric Ptr = Opcodes.end();
390339d628a0SDimitry Andric return Result;
390439d628a0SDimitry Andric }
390539d628a0SDimitry Andric
readSLEB128(const char ** error)39067a7e6055SDimitry Andric int64_t MachOBindEntry::readSLEB128(const char **error) {
390739d628a0SDimitry Andric unsigned Count;
39087a7e6055SDimitry Andric int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
390939d628a0SDimitry Andric Ptr += Count;
39107a7e6055SDimitry Andric if (Ptr > Opcodes.end())
391139d628a0SDimitry Andric Ptr = Opcodes.end();
391239d628a0SDimitry Andric return Result;
391339d628a0SDimitry Andric }
391439d628a0SDimitry Andric
segmentIndex() const39157a7e6055SDimitry Andric int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
391639d628a0SDimitry Andric
segmentOffset() const391739d628a0SDimitry Andric uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
391839d628a0SDimitry Andric
typeName() const391939d628a0SDimitry Andric StringRef MachOBindEntry::typeName() const {
392039d628a0SDimitry Andric switch (BindType) {
392139d628a0SDimitry Andric case MachO::BIND_TYPE_POINTER:
392239d628a0SDimitry Andric return "pointer";
392339d628a0SDimitry Andric case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
392439d628a0SDimitry Andric return "text abs32";
392539d628a0SDimitry Andric case MachO::BIND_TYPE_TEXT_PCREL32:
392639d628a0SDimitry Andric return "text rel32";
392739d628a0SDimitry Andric }
392839d628a0SDimitry Andric return "unknown";
392939d628a0SDimitry Andric }
393039d628a0SDimitry Andric
symbolName() const393139d628a0SDimitry Andric StringRef MachOBindEntry::symbolName() const { return SymbolName; }
393239d628a0SDimitry Andric
addend() const393339d628a0SDimitry Andric int64_t MachOBindEntry::addend() const { return Addend; }
393439d628a0SDimitry Andric
flags() const393539d628a0SDimitry Andric uint32_t MachOBindEntry::flags() const { return Flags; }
393639d628a0SDimitry Andric
ordinal() const393739d628a0SDimitry Andric int MachOBindEntry::ordinal() const { return Ordinal; }
393839d628a0SDimitry Andric
39397a7e6055SDimitry Andric // For use with the SegIndex of a checked Mach-O Bind entry
39407a7e6055SDimitry Andric // to get the segment name.
segmentName() const39417a7e6055SDimitry Andric StringRef MachOBindEntry::segmentName() const {
39427a7e6055SDimitry Andric return O->BindRebaseSegmentName(SegmentIndex);
39437a7e6055SDimitry Andric }
39447a7e6055SDimitry Andric
39457a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
39467a7e6055SDimitry Andric // to get the section name.
sectionName() const39477a7e6055SDimitry Andric StringRef MachOBindEntry::sectionName() const {
39487a7e6055SDimitry Andric return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
39497a7e6055SDimitry Andric }
39507a7e6055SDimitry Andric
39517a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
39527a7e6055SDimitry Andric // to get the address.
address() const39537a7e6055SDimitry Andric uint64_t MachOBindEntry::address() const {
39547a7e6055SDimitry Andric return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
39557a7e6055SDimitry Andric }
39567a7e6055SDimitry Andric
operator ==(const MachOBindEntry & Other) const395739d628a0SDimitry Andric bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
395824e2fe98SDimitry Andric #ifdef EXPENSIVE_CHECKS
395939d628a0SDimitry Andric assert(Opcodes == Other.Opcodes && "compare iterators of different files");
396024e2fe98SDimitry Andric #else
396124e2fe98SDimitry Andric assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
396224e2fe98SDimitry Andric #endif
396339d628a0SDimitry Andric return (Ptr == Other.Ptr) &&
396439d628a0SDimitry Andric (RemainingLoopCount == Other.RemainingLoopCount) &&
396539d628a0SDimitry Andric (Done == Other.Done);
396639d628a0SDimitry Andric }
396739d628a0SDimitry Andric
39687a7e6055SDimitry Andric // Build table of sections so SegIndex/SegOffset pairs can be translated.
BindRebaseSegInfo(const object::MachOObjectFile * Obj)39697a7e6055SDimitry Andric BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
39707a7e6055SDimitry Andric uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
39717a7e6055SDimitry Andric StringRef CurSegName;
39727a7e6055SDimitry Andric uint64_t CurSegAddress;
39737a7e6055SDimitry Andric for (const SectionRef &Section : Obj->sections()) {
39747a7e6055SDimitry Andric SectionInfo Info;
39757a7e6055SDimitry Andric Section.getName(Info.SectionName);
39767a7e6055SDimitry Andric Info.Address = Section.getAddress();
39777a7e6055SDimitry Andric Info.Size = Section.getSize();
39787a7e6055SDimitry Andric Info.SegmentName =
39797a7e6055SDimitry Andric Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
39807a7e6055SDimitry Andric if (!Info.SegmentName.equals(CurSegName)) {
39817a7e6055SDimitry Andric ++CurSegIndex;
39827a7e6055SDimitry Andric CurSegName = Info.SegmentName;
39837a7e6055SDimitry Andric CurSegAddress = Info.Address;
39847a7e6055SDimitry Andric }
39857a7e6055SDimitry Andric Info.SegmentIndex = CurSegIndex - 1;
39867a7e6055SDimitry Andric Info.OffsetInSegment = Info.Address - CurSegAddress;
39877a7e6055SDimitry Andric Info.SegmentStartAddress = CurSegAddress;
39887a7e6055SDimitry Andric Sections.push_back(Info);
39897a7e6055SDimitry Andric }
39907a7e6055SDimitry Andric MaxSegIndex = CurSegIndex;
39917a7e6055SDimitry Andric }
39927a7e6055SDimitry Andric
39937a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
39947a7e6055SDimitry Andric // validate a MachOBindEntry or MachORebaseEntry.
checkSegAndOffset(int32_t SegIndex,uint64_t SegOffset,bool endInvalid)39957a7e6055SDimitry Andric const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
39967a7e6055SDimitry Andric uint64_t SegOffset,
39977a7e6055SDimitry Andric bool endInvalid) {
39987a7e6055SDimitry Andric if (SegIndex == -1)
39997a7e6055SDimitry Andric return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
40007a7e6055SDimitry Andric if (SegIndex >= MaxSegIndex)
40017a7e6055SDimitry Andric return "bad segIndex (too large)";
40027a7e6055SDimitry Andric for (const SectionInfo &SI : Sections) {
40037a7e6055SDimitry Andric if (SI.SegmentIndex != SegIndex)
40047a7e6055SDimitry Andric continue;
40057a7e6055SDimitry Andric if (SI.OffsetInSegment > SegOffset)
40067a7e6055SDimitry Andric continue;
40077a7e6055SDimitry Andric if (SegOffset > (SI.OffsetInSegment + SI.Size))
40087a7e6055SDimitry Andric continue;
40097a7e6055SDimitry Andric if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
40107a7e6055SDimitry Andric continue;
40117a7e6055SDimitry Andric return nullptr;
40127a7e6055SDimitry Andric }
40137a7e6055SDimitry Andric return "bad segOffset, too large";
40147a7e6055SDimitry Andric }
40157a7e6055SDimitry Andric
40167a7e6055SDimitry Andric // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
40177a7e6055SDimitry Andric // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
40187a7e6055SDimitry Andric // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
40197a7e6055SDimitry Andric // REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
40207a7e6055SDimitry Andric // been already checked.
checkCountAndSkip(uint32_t Count,uint32_t Skip,uint8_t PointerSize,int32_t SegIndex,uint64_t SegOffset)40217a7e6055SDimitry Andric const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
40227a7e6055SDimitry Andric uint8_t PointerSize,
40237a7e6055SDimitry Andric int32_t SegIndex,
40247a7e6055SDimitry Andric uint64_t SegOffset) {
40257a7e6055SDimitry Andric const SectionInfo &SI = findSection(SegIndex, SegOffset);
40267a7e6055SDimitry Andric uint64_t addr = SI.SegmentStartAddress + SegOffset;
40277a7e6055SDimitry Andric if (addr >= SI.Address + SI.Size)
40287a7e6055SDimitry Andric return "bad segOffset, too large";
40297a7e6055SDimitry Andric uint64_t i = 0;
40307a7e6055SDimitry Andric if (Count > 1)
40317a7e6055SDimitry Andric i = (Skip + PointerSize) * (Count - 1);
40327a7e6055SDimitry Andric else if (Count == 1)
40337a7e6055SDimitry Andric i = Skip + PointerSize;
40347a7e6055SDimitry Andric if (addr + i >= SI.Address + SI.Size) {
40357a7e6055SDimitry Andric // For rebase opcodes they can step from one section to another.
40367a7e6055SDimitry Andric uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
40377a7e6055SDimitry Andric const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
40387a7e6055SDimitry Andric if (error)
40397a7e6055SDimitry Andric return "bad count and skip, too large";
40407a7e6055SDimitry Andric }
40417a7e6055SDimitry Andric return nullptr;
40427a7e6055SDimitry Andric }
40437a7e6055SDimitry Andric
40447a7e6055SDimitry Andric // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
40457a7e6055SDimitry Andric // to get the segment name.
segmentName(int32_t SegIndex)40467a7e6055SDimitry Andric StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
40477a7e6055SDimitry Andric for (const SectionInfo &SI : Sections) {
40487a7e6055SDimitry Andric if (SI.SegmentIndex == SegIndex)
40497a7e6055SDimitry Andric return SI.SegmentName;
40507a7e6055SDimitry Andric }
40517a7e6055SDimitry Andric llvm_unreachable("invalid SegIndex");
40527a7e6055SDimitry Andric }
40537a7e6055SDimitry Andric
40547a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
40557a7e6055SDimitry Andric // to get the SectionInfo.
findSection(int32_t SegIndex,uint64_t SegOffset)40567a7e6055SDimitry Andric const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
40577a7e6055SDimitry Andric int32_t SegIndex, uint64_t SegOffset) {
40587a7e6055SDimitry Andric for (const SectionInfo &SI : Sections) {
40597a7e6055SDimitry Andric if (SI.SegmentIndex != SegIndex)
40607a7e6055SDimitry Andric continue;
40617a7e6055SDimitry Andric if (SI.OffsetInSegment > SegOffset)
40627a7e6055SDimitry Andric continue;
40637a7e6055SDimitry Andric if (SegOffset >= (SI.OffsetInSegment + SI.Size))
40647a7e6055SDimitry Andric continue;
40657a7e6055SDimitry Andric return SI;
40667a7e6055SDimitry Andric }
40677a7e6055SDimitry Andric llvm_unreachable("SegIndex and SegOffset not in any section");
40687a7e6055SDimitry Andric }
40697a7e6055SDimitry Andric
40707a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
40717a7e6055SDimitry Andric // entry to get the section name.
sectionName(int32_t SegIndex,uint64_t SegOffset)40727a7e6055SDimitry Andric StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
40737a7e6055SDimitry Andric uint64_t SegOffset) {
40747a7e6055SDimitry Andric return findSection(SegIndex, SegOffset).SectionName;
40757a7e6055SDimitry Andric }
40767a7e6055SDimitry Andric
40777a7e6055SDimitry Andric // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
40787a7e6055SDimitry Andric // entry to get the address.
address(uint32_t SegIndex,uint64_t OffsetInSeg)40797a7e6055SDimitry Andric uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
40807a7e6055SDimitry Andric const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
40817a7e6055SDimitry Andric return SI.SegmentStartAddress + OffsetInSeg;
40827a7e6055SDimitry Andric }
40837a7e6055SDimitry Andric
408439d628a0SDimitry Andric iterator_range<bind_iterator>
bindTable(Error & Err,MachOObjectFile * O,ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)40857a7e6055SDimitry Andric MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
40867a7e6055SDimitry Andric ArrayRef<uint8_t> Opcodes, bool is64,
408739d628a0SDimitry Andric MachOBindEntry::Kind BKind) {
40887a7e6055SDimitry Andric if (O->BindRebaseSectionTable == nullptr)
40897a7e6055SDimitry Andric O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
40907a7e6055SDimitry Andric MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
409139d628a0SDimitry Andric Start.moveToFirst();
409239d628a0SDimitry Andric
40937a7e6055SDimitry Andric MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
409439d628a0SDimitry Andric Finish.moveToEnd();
409539d628a0SDimitry Andric
40967d523365SDimitry Andric return make_range(bind_iterator(Start), bind_iterator(Finish));
409739d628a0SDimitry Andric }
409839d628a0SDimitry Andric
bindTable(Error & Err)40997a7e6055SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
41007a7e6055SDimitry Andric return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
410139d628a0SDimitry Andric MachOBindEntry::Kind::Regular);
410239d628a0SDimitry Andric }
410339d628a0SDimitry Andric
lazyBindTable(Error & Err)41047a7e6055SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
41057a7e6055SDimitry Andric return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
410639d628a0SDimitry Andric MachOBindEntry::Kind::Lazy);
410739d628a0SDimitry Andric }
410839d628a0SDimitry Andric
weakBindTable(Error & Err)41097a7e6055SDimitry Andric iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
41107a7e6055SDimitry Andric return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
411139d628a0SDimitry Andric MachOBindEntry::Kind::Weak);
411239d628a0SDimitry Andric }
411339d628a0SDimitry Andric
411497bc6c73SDimitry Andric MachOObjectFile::load_command_iterator
begin_load_commands() const411597bc6c73SDimitry Andric MachOObjectFile::begin_load_commands() const {
411697bc6c73SDimitry Andric return LoadCommands.begin();
411797bc6c73SDimitry Andric }
411897bc6c73SDimitry Andric
411997bc6c73SDimitry Andric MachOObjectFile::load_command_iterator
end_load_commands() const412097bc6c73SDimitry Andric MachOObjectFile::end_load_commands() const {
412197bc6c73SDimitry Andric return LoadCommands.end();
412297bc6c73SDimitry Andric }
412397bc6c73SDimitry Andric
412497bc6c73SDimitry Andric iterator_range<MachOObjectFile::load_command_iterator>
load_commands() const412597bc6c73SDimitry Andric MachOObjectFile::load_commands() const {
41267d523365SDimitry Andric return make_range(begin_load_commands(), end_load_commands());
412797bc6c73SDimitry Andric }
412897bc6c73SDimitry Andric
4129284c1978SDimitry Andric StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const4130284c1978SDimitry Andric MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4131284c1978SDimitry Andric ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4132284c1978SDimitry Andric return parseSegmentOrSectionName(Raw.data());
4133284c1978SDimitry Andric }
4134284c1978SDimitry Andric
4135284c1978SDimitry Andric ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const4136284c1978SDimitry Andric MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
4137ff0cc061SDimitry Andric assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4138f785676fSDimitry Andric const section_base *Base =
4139f785676fSDimitry Andric reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
414039d628a0SDimitry Andric return makeArrayRef(Base->sectname);
4141284c1978SDimitry Andric }
4142284c1978SDimitry Andric
4143284c1978SDimitry Andric ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const4144284c1978SDimitry Andric MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
4145ff0cc061SDimitry Andric assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4146f785676fSDimitry Andric const section_base *Base =
4147f785676fSDimitry Andric reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
414839d628a0SDimitry Andric return makeArrayRef(Base->segname);
4149284c1978SDimitry Andric }
4150284c1978SDimitry Andric
4151284c1978SDimitry Andric bool
isRelocationScattered(const MachO::any_relocation_info & RE) const4152f785676fSDimitry Andric MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
4153284c1978SDimitry Andric const {
4154d88c1a5aSDimitry Andric if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
4155284c1978SDimitry Andric return false;
4156f785676fSDimitry Andric return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
4157284c1978SDimitry Andric }
4158284c1978SDimitry Andric
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const4159f785676fSDimitry Andric unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4160f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4161284c1978SDimitry Andric if (isLittleEndian())
4162f785676fSDimitry Andric return RE.r_word1 & 0xffffff;
4163f785676fSDimitry Andric return RE.r_word1 >> 8;
4164284c1978SDimitry Andric }
4165284c1978SDimitry Andric
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const4166f785676fSDimitry Andric bool MachOObjectFile::getPlainRelocationExternal(
4167f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4168284c1978SDimitry Andric if (isLittleEndian())
4169f785676fSDimitry Andric return (RE.r_word1 >> 27) & 1;
4170f785676fSDimitry Andric return (RE.r_word1 >> 4) & 1;
4171284c1978SDimitry Andric }
4172284c1978SDimitry Andric
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const4173f785676fSDimitry Andric bool MachOObjectFile::getScatteredRelocationScattered(
4174f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4175f785676fSDimitry Andric return RE.r_word0 >> 31;
4176284c1978SDimitry Andric }
4177284c1978SDimitry Andric
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const4178f785676fSDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationValue(
4179f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4180f785676fSDimitry Andric return RE.r_word1;
4181284c1978SDimitry Andric }
4182284c1978SDimitry Andric
getScatteredRelocationType(const MachO::any_relocation_info & RE) const418339d628a0SDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationType(
418439d628a0SDimitry Andric const MachO::any_relocation_info &RE) const {
418539d628a0SDimitry Andric return (RE.r_word0 >> 24) & 0xf;
418639d628a0SDimitry Andric }
418739d628a0SDimitry Andric
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const4188f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationAddress(
4189f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4190284c1978SDimitry Andric if (isRelocationScattered(RE))
4191284c1978SDimitry Andric return getScatteredRelocationAddress(RE);
4192284c1978SDimitry Andric return getPlainRelocationAddress(RE);
4193284c1978SDimitry Andric }
4194284c1978SDimitry Andric
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const4195f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationPCRel(
4196f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4197284c1978SDimitry Andric if (isRelocationScattered(RE))
4198d88c1a5aSDimitry Andric return getScatteredRelocationPCRel(RE);
4199d88c1a5aSDimitry Andric return getPlainRelocationPCRel(*this, RE);
4200284c1978SDimitry Andric }
4201284c1978SDimitry Andric
getAnyRelocationLength(const MachO::any_relocation_info & RE) const4202f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationLength(
4203f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4204284c1978SDimitry Andric if (isRelocationScattered(RE))
4205284c1978SDimitry Andric return getScatteredRelocationLength(RE);
4206d88c1a5aSDimitry Andric return getPlainRelocationLength(*this, RE);
4207284c1978SDimitry Andric }
4208284c1978SDimitry Andric
4209284c1978SDimitry Andric unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const4210f785676fSDimitry Andric MachOObjectFile::getAnyRelocationType(
4211f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4212284c1978SDimitry Andric if (isRelocationScattered(RE))
4213284c1978SDimitry Andric return getScatteredRelocationType(RE);
4214d88c1a5aSDimitry Andric return getPlainRelocationType(*this, RE);
4215284c1978SDimitry Andric }
4216284c1978SDimitry Andric
4217284c1978SDimitry Andric SectionRef
getAnyRelocationSection(const MachO::any_relocation_info & RE) const4218ff0cc061SDimitry Andric MachOObjectFile::getAnyRelocationSection(
4219f785676fSDimitry Andric const MachO::any_relocation_info &RE) const {
4220284c1978SDimitry Andric if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
422191bc56edSDimitry Andric return *section_end();
42228f0fd8f6SDimitry Andric unsigned SecNum = getPlainRelocationSymbolNum(RE);
42238f0fd8f6SDimitry Andric if (SecNum == MachO::R_ABS || SecNum > Sections.size())
42248f0fd8f6SDimitry Andric return *section_end();
4225284c1978SDimitry Andric DataRefImpl DRI;
42268f0fd8f6SDimitry Andric DRI.d.a = SecNum - 1;
4227284c1978SDimitry Andric return SectionRef(DRI, this);
4228284c1978SDimitry Andric }
4229284c1978SDimitry Andric
getSection(DataRefImpl DRI) const4230f785676fSDimitry Andric MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
4231ff0cc061SDimitry Andric assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4232d88c1a5aSDimitry Andric return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
4233284c1978SDimitry Andric }
4234284c1978SDimitry Andric
getSection64(DataRefImpl DRI) const4235f785676fSDimitry Andric MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
4236ff0cc061SDimitry Andric assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4237d88c1a5aSDimitry Andric return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
4238284c1978SDimitry Andric }
4239284c1978SDimitry Andric
getSection(const LoadCommandInfo & L,unsigned Index) const4240f785676fSDimitry Andric MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
4241284c1978SDimitry Andric unsigned Index) const {
4242d88c1a5aSDimitry Andric const char *Sec = getSectionPtr(*this, L, Index);
4243d88c1a5aSDimitry Andric return getStruct<MachO::section>(*this, Sec);
4244284c1978SDimitry Andric }
4245284c1978SDimitry Andric
getSection64(const LoadCommandInfo & L,unsigned Index) const4246f785676fSDimitry Andric MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4247284c1978SDimitry Andric unsigned Index) const {
4248d88c1a5aSDimitry Andric const char *Sec = getSectionPtr(*this, L, Index);
4249d88c1a5aSDimitry Andric return getStruct<MachO::section_64>(*this, Sec);
4250284c1978SDimitry Andric }
4251284c1978SDimitry Andric
4252f785676fSDimitry Andric MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const4253284c1978SDimitry Andric MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
4254284c1978SDimitry Andric const char *P = reinterpret_cast<const char *>(DRI.p);
4255d88c1a5aSDimitry Andric return getStruct<MachO::nlist>(*this, P);
4256284c1978SDimitry Andric }
4257284c1978SDimitry Andric
4258f785676fSDimitry Andric MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const4259284c1978SDimitry Andric MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
4260284c1978SDimitry Andric const char *P = reinterpret_cast<const char *>(DRI.p);
4261d88c1a5aSDimitry Andric return getStruct<MachO::nlist_64>(*this, P);
4262284c1978SDimitry Andric }
4263284c1978SDimitry Andric
4264f785676fSDimitry Andric MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const4265f785676fSDimitry Andric MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
4266d88c1a5aSDimitry Andric return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
4267284c1978SDimitry Andric }
4268284c1978SDimitry Andric
4269f785676fSDimitry Andric MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const4270284c1978SDimitry Andric MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
4271d88c1a5aSDimitry Andric return getStruct<MachO::segment_command>(*this, L.Ptr);
4272284c1978SDimitry Andric }
4273284c1978SDimitry Andric
4274f785676fSDimitry Andric MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const4275284c1978SDimitry Andric MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
4276d88c1a5aSDimitry Andric return getStruct<MachO::segment_command_64>(*this, L.Ptr);
4277284c1978SDimitry Andric }
4278284c1978SDimitry Andric
427939d628a0SDimitry Andric MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const428039d628a0SDimitry Andric MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
4281d88c1a5aSDimitry Andric return getStruct<MachO::linker_option_command>(*this, L.Ptr);
4282284c1978SDimitry Andric }
4283284c1978SDimitry Andric
428491bc56edSDimitry Andric MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const428591bc56edSDimitry Andric MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
4286d88c1a5aSDimitry Andric return getStruct<MachO::version_min_command>(*this, L.Ptr);
428791bc56edSDimitry Andric }
428891bc56edSDimitry Andric
42897a7e6055SDimitry Andric MachO::note_command
getNoteLoadCommand(const LoadCommandInfo & L) const42907a7e6055SDimitry Andric MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
42917a7e6055SDimitry Andric return getStruct<MachO::note_command>(*this, L.Ptr);
42927a7e6055SDimitry Andric }
42937a7e6055SDimitry Andric
42947a7e6055SDimitry Andric MachO::build_version_command
getBuildVersionLoadCommand(const LoadCommandInfo & L) const42957a7e6055SDimitry Andric MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
42967a7e6055SDimitry Andric return getStruct<MachO::build_version_command>(*this, L.Ptr);
42977a7e6055SDimitry Andric }
42987a7e6055SDimitry Andric
42997a7e6055SDimitry Andric MachO::build_tool_version
getBuildToolVersion(unsigned index) const43007a7e6055SDimitry Andric MachOObjectFile::getBuildToolVersion(unsigned index) const {
43017a7e6055SDimitry Andric return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
43027a7e6055SDimitry Andric }
43037a7e6055SDimitry Andric
430491bc56edSDimitry Andric MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const430591bc56edSDimitry Andric MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
4306d88c1a5aSDimitry Andric return getStruct<MachO::dylib_command>(*this, L.Ptr);
430791bc56edSDimitry Andric }
430891bc56edSDimitry Andric
430939d628a0SDimitry Andric MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const431039d628a0SDimitry Andric MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
4311d88c1a5aSDimitry Andric return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
431239d628a0SDimitry Andric }
431339d628a0SDimitry Andric
431439d628a0SDimitry Andric MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const431539d628a0SDimitry Andric MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
4316d88c1a5aSDimitry Andric return getStruct<MachO::dylinker_command>(*this, L.Ptr);
431739d628a0SDimitry Andric }
431839d628a0SDimitry Andric
431939d628a0SDimitry Andric MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const432039d628a0SDimitry Andric MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
4321d88c1a5aSDimitry Andric return getStruct<MachO::uuid_command>(*this, L.Ptr);
432239d628a0SDimitry Andric }
432339d628a0SDimitry Andric
432439d628a0SDimitry Andric MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const432539d628a0SDimitry Andric MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
4326d88c1a5aSDimitry Andric return getStruct<MachO::rpath_command>(*this, L.Ptr);
432739d628a0SDimitry Andric }
432839d628a0SDimitry Andric
432939d628a0SDimitry Andric MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const433039d628a0SDimitry Andric MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
4331d88c1a5aSDimitry Andric return getStruct<MachO::source_version_command>(*this, L.Ptr);
433239d628a0SDimitry Andric }
433339d628a0SDimitry Andric
433439d628a0SDimitry Andric MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const433539d628a0SDimitry Andric MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
4336d88c1a5aSDimitry Andric return getStruct<MachO::entry_point_command>(*this, L.Ptr);
433739d628a0SDimitry Andric }
433839d628a0SDimitry Andric
433939d628a0SDimitry Andric MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const434039d628a0SDimitry Andric MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
4341d88c1a5aSDimitry Andric return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
434239d628a0SDimitry Andric }
434339d628a0SDimitry Andric
434439d628a0SDimitry Andric MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const434539d628a0SDimitry Andric MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
4346d88c1a5aSDimitry Andric return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
434739d628a0SDimitry Andric }
434839d628a0SDimitry Andric
434939d628a0SDimitry Andric MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const435039d628a0SDimitry Andric MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
4351d88c1a5aSDimitry Andric return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
435239d628a0SDimitry Andric }
435339d628a0SDimitry Andric
435439d628a0SDimitry Andric MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const435539d628a0SDimitry Andric MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
4356d88c1a5aSDimitry Andric return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
435739d628a0SDimitry Andric }
435839d628a0SDimitry Andric
435939d628a0SDimitry Andric MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const436039d628a0SDimitry Andric MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
4361d88c1a5aSDimitry Andric return getStruct<MachO::sub_library_command>(*this, L.Ptr);
436239d628a0SDimitry Andric }
436339d628a0SDimitry Andric
436439d628a0SDimitry Andric MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const436539d628a0SDimitry Andric MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
4366d88c1a5aSDimitry Andric return getStruct<MachO::sub_client_command>(*this, L.Ptr);
436739d628a0SDimitry Andric }
436839d628a0SDimitry Andric
436939d628a0SDimitry Andric MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const437039d628a0SDimitry Andric MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
4371d88c1a5aSDimitry Andric return getStruct<MachO::routines_command>(*this, L.Ptr);
437239d628a0SDimitry Andric }
437339d628a0SDimitry Andric
437439d628a0SDimitry Andric MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const437539d628a0SDimitry Andric MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
4376d88c1a5aSDimitry Andric return getStruct<MachO::routines_command_64>(*this, L.Ptr);
437739d628a0SDimitry Andric }
437839d628a0SDimitry Andric
437939d628a0SDimitry Andric MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const438039d628a0SDimitry Andric MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
4381d88c1a5aSDimitry Andric return getStruct<MachO::thread_command>(*this, L.Ptr);
438239d628a0SDimitry Andric }
438391bc56edSDimitry Andric
4384f785676fSDimitry Andric MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const4385284c1978SDimitry Andric MachOObjectFile::getRelocation(DataRefImpl Rel) const {
4386edd7eaddSDimitry Andric uint32_t Offset;
4387edd7eaddSDimitry Andric if (getHeader().filetype == MachO::MH_OBJECT) {
438891bc56edSDimitry Andric DataRefImpl Sec;
438991bc56edSDimitry Andric Sec.d.a = Rel.d.a;
439091bc56edSDimitry Andric if (is64Bit()) {
439191bc56edSDimitry Andric MachO::section_64 Sect = getSection64(Sec);
439291bc56edSDimitry Andric Offset = Sect.reloff;
439391bc56edSDimitry Andric } else {
439491bc56edSDimitry Andric MachO::section Sect = getSection(Sec);
439591bc56edSDimitry Andric Offset = Sect.reloff;
439691bc56edSDimitry Andric }
4397edd7eaddSDimitry Andric } else {
4398edd7eaddSDimitry Andric MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
43992cab237bSDimitry Andric if (Rel.d.a == 0)
4400edd7eaddSDimitry Andric Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
44012cab237bSDimitry Andric else
44022cab237bSDimitry Andric Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
4403edd7eaddSDimitry Andric }
440491bc56edSDimitry Andric
440591bc56edSDimitry Andric auto P = reinterpret_cast<const MachO::any_relocation_info *>(
4406d88c1a5aSDimitry Andric getPtr(*this, Offset)) + Rel.d.b;
440791bc56edSDimitry Andric return getStruct<MachO::any_relocation_info>(
4408d88c1a5aSDimitry Andric *this, reinterpret_cast<const char *>(P));
4409284c1978SDimitry Andric }
4410284c1978SDimitry Andric
4411f785676fSDimitry Andric MachO::data_in_code_entry
getDice(DataRefImpl Rel) const4412f785676fSDimitry Andric MachOObjectFile::getDice(DataRefImpl Rel) const {
4413f785676fSDimitry Andric const char *P = reinterpret_cast<const char *>(Rel.p);
4414d88c1a5aSDimitry Andric return getStruct<MachO::data_in_code_entry>(*this, P);
4415284c1978SDimitry Andric }
4416284c1978SDimitry Andric
getHeader() const441797bc6c73SDimitry Andric const MachO::mach_header &MachOObjectFile::getHeader() const {
441897bc6c73SDimitry Andric return Header;
4419284c1978SDimitry Andric }
4420284c1978SDimitry Andric
getHeader64() const442197bc6c73SDimitry Andric const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
442297bc6c73SDimitry Andric assert(is64Bit());
442397bc6c73SDimitry Andric return Header64;
4424f785676fSDimitry Andric }
4425f785676fSDimitry Andric
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const4426f785676fSDimitry Andric uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4427f785676fSDimitry Andric const MachO::dysymtab_command &DLC,
4428284c1978SDimitry Andric unsigned Index) const {
4429f785676fSDimitry Andric uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
4430d88c1a5aSDimitry Andric return getStruct<uint32_t>(*this, getPtr(*this, Offset));
4431284c1978SDimitry Andric }
4432284c1978SDimitry Andric
4433f785676fSDimitry Andric MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const4434284c1978SDimitry Andric MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4435284c1978SDimitry Andric unsigned Index) const {
4436f785676fSDimitry Andric uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
4437d88c1a5aSDimitry Andric return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
4438284c1978SDimitry Andric }
4439284c1978SDimitry Andric
getSymtabLoadCommand() const4440f785676fSDimitry Andric MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
444139d628a0SDimitry Andric if (SymtabLoadCmd)
4442d88c1a5aSDimitry Andric return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
444339d628a0SDimitry Andric
444439d628a0SDimitry Andric // If there is no SymtabLoadCmd return a load command with zero'ed fields.
444539d628a0SDimitry Andric MachO::symtab_command Cmd;
444639d628a0SDimitry Andric Cmd.cmd = MachO::LC_SYMTAB;
444739d628a0SDimitry Andric Cmd.cmdsize = sizeof(MachO::symtab_command);
444839d628a0SDimitry Andric Cmd.symoff = 0;
444939d628a0SDimitry Andric Cmd.nsyms = 0;
445039d628a0SDimitry Andric Cmd.stroff = 0;
445139d628a0SDimitry Andric Cmd.strsize = 0;
445239d628a0SDimitry Andric return Cmd;
4453284c1978SDimitry Andric }
4454284c1978SDimitry Andric
getDysymtabLoadCommand() const4455f785676fSDimitry Andric MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
445639d628a0SDimitry Andric if (DysymtabLoadCmd)
4457d88c1a5aSDimitry Andric return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
445839d628a0SDimitry Andric
445939d628a0SDimitry Andric // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
446039d628a0SDimitry Andric MachO::dysymtab_command Cmd;
446139d628a0SDimitry Andric Cmd.cmd = MachO::LC_DYSYMTAB;
446239d628a0SDimitry Andric Cmd.cmdsize = sizeof(MachO::dysymtab_command);
446339d628a0SDimitry Andric Cmd.ilocalsym = 0;
446439d628a0SDimitry Andric Cmd.nlocalsym = 0;
446539d628a0SDimitry Andric Cmd.iextdefsym = 0;
446639d628a0SDimitry Andric Cmd.nextdefsym = 0;
446739d628a0SDimitry Andric Cmd.iundefsym = 0;
446839d628a0SDimitry Andric Cmd.nundefsym = 0;
446939d628a0SDimitry Andric Cmd.tocoff = 0;
447039d628a0SDimitry Andric Cmd.ntoc = 0;
447139d628a0SDimitry Andric Cmd.modtaboff = 0;
447239d628a0SDimitry Andric Cmd.nmodtab = 0;
447339d628a0SDimitry Andric Cmd.extrefsymoff = 0;
447439d628a0SDimitry Andric Cmd.nextrefsyms = 0;
447539d628a0SDimitry Andric Cmd.indirectsymoff = 0;
447639d628a0SDimitry Andric Cmd.nindirectsyms = 0;
447739d628a0SDimitry Andric Cmd.extreloff = 0;
447839d628a0SDimitry Andric Cmd.nextrel = 0;
447939d628a0SDimitry Andric Cmd.locreloff = 0;
448039d628a0SDimitry Andric Cmd.nlocrel = 0;
448139d628a0SDimitry Andric return Cmd;
4482f785676fSDimitry Andric }
4483f785676fSDimitry Andric
4484f785676fSDimitry Andric MachO::linkedit_data_command
getDataInCodeLoadCommand() const4485f785676fSDimitry Andric MachOObjectFile::getDataInCodeLoadCommand() const {
4486f785676fSDimitry Andric if (DataInCodeLoadCmd)
4487d88c1a5aSDimitry Andric return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
4488f785676fSDimitry Andric
4489f785676fSDimitry Andric // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4490f785676fSDimitry Andric MachO::linkedit_data_command Cmd;
4491f785676fSDimitry Andric Cmd.cmd = MachO::LC_DATA_IN_CODE;
4492f785676fSDimitry Andric Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4493f785676fSDimitry Andric Cmd.dataoff = 0;
4494f785676fSDimitry Andric Cmd.datasize = 0;
4495f785676fSDimitry Andric return Cmd;
4496284c1978SDimitry Andric }
4497284c1978SDimitry Andric
4498ff0cc061SDimitry Andric MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const4499ff0cc061SDimitry Andric MachOObjectFile::getLinkOptHintsLoadCommand() const {
4500ff0cc061SDimitry Andric if (LinkOptHintsLoadCmd)
4501d88c1a5aSDimitry Andric return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
4502ff0cc061SDimitry Andric
4503ff0cc061SDimitry Andric // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4504ff0cc061SDimitry Andric // fields.
4505ff0cc061SDimitry Andric MachO::linkedit_data_command Cmd;
4506ff0cc061SDimitry Andric Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4507ff0cc061SDimitry Andric Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4508ff0cc061SDimitry Andric Cmd.dataoff = 0;
4509ff0cc061SDimitry Andric Cmd.datasize = 0;
4510ff0cc061SDimitry Andric return Cmd;
4511ff0cc061SDimitry Andric }
4512ff0cc061SDimitry Andric
getDyldInfoRebaseOpcodes() const451339d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
451439d628a0SDimitry Andric if (!DyldInfoLoadCmd)
45157d523365SDimitry Andric return None;
451639d628a0SDimitry Andric
45177d523365SDimitry Andric MachO::dyld_info_command DyldInfo =
4518d88c1a5aSDimitry Andric getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45197d523365SDimitry Andric const uint8_t *Ptr =
4520d88c1a5aSDimitry Andric reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
45217d523365SDimitry Andric return makeArrayRef(Ptr, DyldInfo.rebase_size);
452239d628a0SDimitry Andric }
452339d628a0SDimitry Andric
getDyldInfoBindOpcodes() const452439d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
452539d628a0SDimitry Andric if (!DyldInfoLoadCmd)
45267d523365SDimitry Andric return None;
452739d628a0SDimitry Andric
45287d523365SDimitry Andric MachO::dyld_info_command DyldInfo =
4529d88c1a5aSDimitry Andric getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45307d523365SDimitry Andric const uint8_t *Ptr =
4531d88c1a5aSDimitry Andric reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
45327d523365SDimitry Andric return makeArrayRef(Ptr, DyldInfo.bind_size);
453339d628a0SDimitry Andric }
453439d628a0SDimitry Andric
getDyldInfoWeakBindOpcodes() const453539d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
453639d628a0SDimitry Andric if (!DyldInfoLoadCmd)
45377d523365SDimitry Andric return None;
453839d628a0SDimitry Andric
45397d523365SDimitry Andric MachO::dyld_info_command DyldInfo =
4540d88c1a5aSDimitry Andric getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45417d523365SDimitry Andric const uint8_t *Ptr =
4542d88c1a5aSDimitry Andric reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
45437d523365SDimitry Andric return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
454439d628a0SDimitry Andric }
454539d628a0SDimitry Andric
getDyldInfoLazyBindOpcodes() const454639d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
454739d628a0SDimitry Andric if (!DyldInfoLoadCmd)
45487d523365SDimitry Andric return None;
454939d628a0SDimitry Andric
45507d523365SDimitry Andric MachO::dyld_info_command DyldInfo =
4551d88c1a5aSDimitry Andric getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45527d523365SDimitry Andric const uint8_t *Ptr =
4553d88c1a5aSDimitry Andric reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
45547d523365SDimitry Andric return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
455539d628a0SDimitry Andric }
455639d628a0SDimitry Andric
getDyldInfoExportsTrie() const455739d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
455839d628a0SDimitry Andric if (!DyldInfoLoadCmd)
45597d523365SDimitry Andric return None;
456039d628a0SDimitry Andric
45617d523365SDimitry Andric MachO::dyld_info_command DyldInfo =
4562d88c1a5aSDimitry Andric getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
45637d523365SDimitry Andric const uint8_t *Ptr =
4564d88c1a5aSDimitry Andric reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
45657d523365SDimitry Andric return makeArrayRef(Ptr, DyldInfo.export_size);
456639d628a0SDimitry Andric }
456739d628a0SDimitry Andric
getUuid() const456839d628a0SDimitry Andric ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
456939d628a0SDimitry Andric if (!UuidLoadCmd)
45707d523365SDimitry Andric return None;
457139d628a0SDimitry Andric // Returning a pointer is fine as uuid doesn't need endian swapping.
457239d628a0SDimitry Andric const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
45737d523365SDimitry Andric return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
457439d628a0SDimitry Andric }
457539d628a0SDimitry Andric
getStringTableData() const4576284c1978SDimitry Andric StringRef MachOObjectFile::getStringTableData() const {
4577f785676fSDimitry Andric MachO::symtab_command S = getSymtabLoadCommand();
4578f785676fSDimitry Andric return getData().substr(S.stroff, S.strsize);
4579284c1978SDimitry Andric }
4580284c1978SDimitry Andric
is64Bit() const4581284c1978SDimitry Andric bool MachOObjectFile::is64Bit() const {
4582284c1978SDimitry Andric return getType() == getMachOType(false, true) ||
4583284c1978SDimitry Andric getType() == getMachOType(true, true);
4584284c1978SDimitry Andric }
4585284c1978SDimitry Andric
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const4586284c1978SDimitry Andric void MachOObjectFile::ReadULEB128s(uint64_t Index,
4587284c1978SDimitry Andric SmallVectorImpl<uint64_t> &Out) const {
4588284c1978SDimitry Andric DataExtractor extractor(ObjectFile::getData(), true, 0);
4589284c1978SDimitry Andric
4590284c1978SDimitry Andric uint32_t offset = Index;
4591284c1978SDimitry Andric uint64_t data = 0;
4592284c1978SDimitry Andric while (uint64_t delta = extractor.getULEB128(&offset)) {
4593284c1978SDimitry Andric data += delta;
4594284c1978SDimitry Andric Out.push_back(data);
4595284c1978SDimitry Andric }
4596284c1978SDimitry Andric }
4597284c1978SDimitry Andric
isRelocatableObject() const459839d628a0SDimitry Andric bool MachOObjectFile::isRelocatableObject() const {
459939d628a0SDimitry Andric return getHeader().filetype == MachO::MH_OBJECT;
460039d628a0SDimitry Andric }
460139d628a0SDimitry Andric
46023ca95b02SDimitry Andric Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer,uint32_t UniversalCputype,uint32_t UniversalIndex)4603d88c1a5aSDimitry Andric ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4604d88c1a5aSDimitry Andric uint32_t UniversalCputype,
4605d88c1a5aSDimitry Andric uint32_t UniversalIndex) {
460639d628a0SDimitry Andric StringRef Magic = Buffer.getBuffer().slice(0, 4);
4607284c1978SDimitry Andric if (Magic == "\xFE\xED\xFA\xCE")
4608d88c1a5aSDimitry Andric return MachOObjectFile::create(Buffer, false, false,
4609d88c1a5aSDimitry Andric UniversalCputype, UniversalIndex);
46103ca95b02SDimitry Andric if (Magic == "\xCE\xFA\xED\xFE")
4611d88c1a5aSDimitry Andric return MachOObjectFile::create(Buffer, true, false,
4612d88c1a5aSDimitry Andric UniversalCputype, UniversalIndex);
46133ca95b02SDimitry Andric if (Magic == "\xFE\xED\xFA\xCF")
4614d88c1a5aSDimitry Andric return MachOObjectFile::create(Buffer, false, true,
4615d88c1a5aSDimitry Andric UniversalCputype, UniversalIndex);
46163ca95b02SDimitry Andric if (Magic == "\xCF\xFA\xED\xFE")
4617d88c1a5aSDimitry Andric return MachOObjectFile::create(Buffer, true, true,
4618d88c1a5aSDimitry Andric UniversalCputype, UniversalIndex);
46193ca95b02SDimitry Andric return make_error<GenericBinaryError>("Unrecognized MachO magic number",
46203ca95b02SDimitry Andric object_error::invalid_file_type);
4621f785676fSDimitry Andric }
4622db17bf38SDimitry Andric
mapDebugSectionName(StringRef Name) const4623db17bf38SDimitry Andric StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4624db17bf38SDimitry Andric return StringSwitch<StringRef>(Name)
4625db17bf38SDimitry Andric .Case("debug_str_offs", "debug_str_offsets")
4626db17bf38SDimitry Andric .Default(Name);
4627db17bf38SDimitry Andric }
4628