blob: 8124c18f30e97467dd252076819c5a53b4336c6b [file] [log] [blame]
Eric Christopher7b015c72011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Anderson27c579d2011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Tim Northover00ed9962014-03-29 10:18:08 +000016#include "llvm/ADT/STLExtras.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000017#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "llvm/ADT/Triple.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000019#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000020#include "llvm/Support/Debug.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000021#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000022#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000023#include "llvm/Support/LEB128.h"
24#include "llvm/Support/MachO.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000025#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000026#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000027#include <cctype>
28#include <cstring>
29#include <limits>
Kevin Enderbyd5039402016-10-31 20:29:48 +000030#include <list>
Eric Christopher7b015c72011-04-22 03:19:48 +000031
32using namespace llvm;
33using namespace object;
34
Artyom Skrobov7d602f72014-07-20 12:08:28 +000035namespace {
36 struct section_base {
37 char sectname[16];
38 char segname[16];
39 };
40}
Rafael Espindola56f976f2013-04-18 18:08:55 +000041
Lang Hames9e964f32016-03-25 17:25:34 +000042static Error
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000043malformedError(Twine Msg) {
Kevin Enderby89134962016-05-05 23:41:05 +000044 std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")";
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000045 return make_error<GenericBinaryError>(std::move(StringMsg),
Kevin Enderby89134962016-05-05 23:41:05 +000046 object_error::parse_failed);
Lang Hames9e964f32016-03-25 17:25:34 +000047}
48
Alexey Samsonov9f336632015-06-04 19:45:22 +000049// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000050template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000051static T getStruct(const MachOObjectFile &O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000052 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000053 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Filipe Cabecinhas40139502015-01-15 22:52:38 +000054 report_fatal_error("Malformed MachO file.");
55
Rafael Espindola3cdeb172013-04-19 13:45:05 +000056 T Cmd;
57 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000058 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000059 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000060 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000061}
62
Alexey Samsonov9f336632015-06-04 19:45:22 +000063template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000064static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000065 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000066 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000067 return malformedError("Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000068
69 T Cmd;
70 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000071 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Alexey Samsonov9f336632015-06-04 19:45:22 +000072 MachO::swapStruct(Cmd);
73 return Cmd;
74}
75
Rafael Espindola6e040c02013-04-26 20:07:33 +000076static const char *
Lang Hames697e7cd2016-12-04 01:56:10 +000077getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
Rafael Espindola6e040c02013-04-26 20:07:33 +000078 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000079 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
80
Lang Hames697e7cd2016-12-04 01:56:10 +000081 bool Is64 = O.is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000082 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
83 sizeof(MachO::segment_command);
84 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
85 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000086
87 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000088 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000089}
90
Lang Hames697e7cd2016-12-04 01:56:10 +000091static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
92 return O.getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000093}
94
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000095static MachO::nlist_base
Lang Hames697e7cd2016-12-04 01:56:10 +000096getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000097 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000098 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000099}
100
Rafael Espindola56f976f2013-04-18 18:08:55 +0000101static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000102 if (P[15] == 0)
103 // Null terminated.
104 return P;
105 // Not null terminated, so this is a 16 char string.
106 return StringRef(P, 16);
107}
108
Rafael Espindola56f976f2013-04-18 18:08:55 +0000109// Helper to advance a section or symbol iterator multiple increments at a time.
110template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000111static void advance(T &it, size_t Val) {
112 while (Val--)
113 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000114}
115
Lang Hames697e7cd2016-12-04 01:56:10 +0000116static unsigned getCPUType(const MachOObjectFile &O) {
117 return O.getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000118}
119
Charles Davis8bdfafd2013-09-01 04:28:48 +0000120static uint32_t
121getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
122 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000123}
124
125static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000126getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
127 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000128}
129
Lang Hames697e7cd2016-12-04 01:56:10 +0000130static bool getPlainRelocationPCRel(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000132 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000133 return (RE.r_word1 >> 24) & 1;
134 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000135}
136
137static bool
Lang Hames697e7cd2016-12-04 01:56:10 +0000138getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000139 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140}
141
Lang Hames697e7cd2016-12-04 01:56:10 +0000142static unsigned getPlainRelocationLength(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000143 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000144 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000145 return (RE.r_word1 >> 25) & 3;
146 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000147}
148
149static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
151 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152}
153
Lang Hames697e7cd2016-12-04 01:56:10 +0000154static unsigned getPlainRelocationType(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000155 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000156 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000157 return RE.r_word1 >> 28;
158 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159}
160
Lang Hames697e7cd2016-12-04 01:56:10 +0000161static uint32_t getSectionFlags(const MachOObjectFile &O,
Rafael Espindola56f976f2013-04-18 18:08:55 +0000162 DataRefImpl Sec) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000163 if (O.is64Bit()) {
164 MachO::section_64 Sect = O.getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000165 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000166 }
Lang Hames697e7cd2016-12-04 01:56:10 +0000167 MachO::section Sect = O.getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000168 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000169}
170
Lang Hames9e964f32016-03-25 17:25:34 +0000171static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000172getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000173 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000174 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
175 if (CmdOrErr->cmdsize < 8)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000176 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000177 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000178 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
179 } else
180 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000181}
182
Lang Hames9e964f32016-03-25 17:25:34 +0000183static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000184getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
185 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
186 : sizeof(MachO::mach_header);
187 if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000188 return malformedError("load command 0 extends past the end all load "
Kevin Enderby89134962016-05-05 23:41:05 +0000189 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000190 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000191}
192
Lang Hames9e964f32016-03-25 17:25:34 +0000193static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000194getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000195 const MachOObjectFile::LoadCommandInfo &L) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000196 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
197 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000198 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
Lang Hames697e7cd2016-12-04 01:56:10 +0000199 Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000200 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
Kevin Enderby89134962016-05-05 23:41:05 +0000201 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000202 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000203}
204
Alexey Samsonov9f336632015-06-04 19:45:22 +0000205template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +0000206static void parseHeader(const MachOObjectFile &Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000207 Error &Err) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000208 if (sizeof(T) > Obj.getData().size()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000209 Err = malformedError("the mach header extends past the end of the "
Kevin Enderby89134962016-05-05 23:41:05 +0000210 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000211 return;
212 }
Lang Hames9e964f32016-03-25 17:25:34 +0000213 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
214 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000215 else
Lang Hames9e964f32016-03-25 17:25:34 +0000216 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000217}
218
Kevin Enderbyd5039402016-10-31 20:29:48 +0000219// This is used to check for overlapping of Mach-O elements.
220struct MachOElement {
221 uint64_t Offset;
222 uint64_t Size;
223 const char *Name;
224};
225
226static Error checkOverlappingElement(std::list<MachOElement> &Elements,
227 uint64_t Offset, uint64_t Size,
228 const char *Name) {
229 if (Size == 0)
230 return Error::success();
231
232 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
233 auto E = *it;
234 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
235 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
236 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
237 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
238 " with a size of " + Twine(Size) + ", overlaps " +
239 E.Name + " at offset " + Twine(E.Offset) + " with "
240 "a size of " + Twine(E.Size));
241 auto nt = it;
242 nt++;
243 if (nt != Elements.end()) {
244 auto N = *nt;
245 if (Offset + Size <= N.Offset) {
246 Elements.insert(nt, {Offset, Size, Name});
247 return Error::success();
248 }
249 }
250 }
251 Elements.push_back({Offset, Size, Name});
252 return Error::success();
253}
254
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000255// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
256// sections to \param Sections, and optionally sets
257// \param IsPageZeroSegment to true.
Kevin Enderbyc614d282016-08-12 20:10:25 +0000258template <typename Segment, typename Section>
Lang Hames9e964f32016-03-25 17:25:34 +0000259static Error parseSegmentLoadCommand(
Lang Hames697e7cd2016-12-04 01:56:10 +0000260 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000261 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000262 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
263 std::list<MachOElement> &Elements) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000264 const unsigned SegmentLoadSize = sizeof(Segment);
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000265 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000266 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000267 " " + CmdName + " cmdsize too small");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000268 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
269 Segment S = SegOrErr.get();
270 const unsigned SectionSize = sizeof(Section);
Lang Hames697e7cd2016-12-04 01:56:10 +0000271 uint64_t FileSize = Obj.getData().size();
Lang Hames9e964f32016-03-25 17:25:34 +0000272 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
273 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000274 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000275 " inconsistent cmdsize in " + CmdName +
Kevin Enderby89134962016-05-05 23:41:05 +0000276 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000277 for (unsigned J = 0; J < S.nsects; ++J) {
278 const char *Sec = getSectionPtr(Obj, Load, J);
279 Sections.push_back(Sec);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000280 Section s = getStruct<Section>(Obj, Sec);
Lang Hames697e7cd2016-12-04 01:56:10 +0000281 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
282 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000283 s.flags != MachO::S_ZEROFILL &&
284 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
285 s.offset > FileSize)
286 return malformedError("offset field of section " + Twine(J) + " in " +
287 CmdName + " command " + Twine(LoadCommandIndex) +
288 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000289 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
290 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000291 s.flags != MachO::S_ZEROFILL &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000292 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
293 s.offset < SizeOfHeaders && s.size != 0)
Kevin Enderbyc614d282016-08-12 20:10:25 +0000294 return malformedError("offset field of section " + Twine(J) + " in " +
295 CmdName + " command " + Twine(LoadCommandIndex) +
296 " not past the headers of the file");
297 uint64_t BigSize = s.offset;
298 BigSize += s.size;
Lang Hames697e7cd2016-12-04 01:56:10 +0000299 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
300 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000301 s.flags != MachO::S_ZEROFILL &&
302 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
303 BigSize > FileSize)
304 return malformedError("offset field plus size field of section " +
305 Twine(J) + " in " + CmdName + " command " +
306 Twine(LoadCommandIndex) +
307 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000308 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
309 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000310 s.flags != MachO::S_ZEROFILL &&
311 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
312 s.size > S.filesize)
313 return malformedError("size field of section " +
314 Twine(J) + " in " + CmdName + " command " +
315 Twine(LoadCommandIndex) +
316 " greater than the segment");
Lang Hames697e7cd2016-12-04 01:56:10 +0000317 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
318 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000319 s.addr < S.vmaddr)
320 return malformedError("addr field of section " + Twine(J) + " in " +
321 CmdName + " command " + Twine(LoadCommandIndex) +
322 " less than the segment's vmaddr");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000323 BigSize = s.addr;
324 BigSize += s.size;
325 uint64_t BigEnd = S.vmaddr;
326 BigEnd += S.vmsize;
327 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000328 return malformedError("addr field plus size of section " + Twine(J) +
329 " in " + CmdName + " command " +
330 Twine(LoadCommandIndex) +
331 " greater than than "
Kevin Enderbyc614d282016-08-12 20:10:25 +0000332 "the segment's vmaddr plus vmsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000333 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
334 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000335 s.flags != MachO::S_ZEROFILL &&
336 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
337 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
338 "section contents"))
339 return Err;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000340 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000341 return malformedError("reloff field of section " + Twine(J) + " in " +
342 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000343 " extends past the end of the file");
344 BigSize = s.nreloc;
345 BigSize *= sizeof(struct MachO::relocation_info);
346 BigSize += s.reloff;
347 if (BigSize > FileSize)
348 return malformedError("reloff field plus nreloc field times sizeof("
349 "struct relocation_info) of section " +
350 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000351 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000352 " extends past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000353 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
354 sizeof(struct
355 MachO::relocation_info),
356 "section relocation entries"))
357 return Err;
Lang Hames9e964f32016-03-25 17:25:34 +0000358 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000359 if (S.fileoff > FileSize)
360 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000361 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000362 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000363 uint64_t BigSize = S.fileoff;
364 BigSize += S.filesize;
365 if (BigSize > FileSize)
366 return malformedError("load command " + Twine(LoadCommandIndex) +
367 " fileoff field plus filesize field in " +
368 CmdName + " extends past the end of the file");
369 if (S.vmsize != 0 && S.filesize > S.vmsize)
370 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby86d8bd12017-02-07 21:20:44 +0000371 " filesize field in " + CmdName +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000372 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000373 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
374 } else
375 return SegOrErr.takeError();
376
377 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000378}
379
Lang Hames697e7cd2016-12-04 01:56:10 +0000380static Error checkSymtabCommand(const MachOObjectFile &Obj,
Kevin Enderby0e52c922016-08-26 19:34:07 +0000381 const MachOObjectFile::LoadCommandInfo &Load,
382 uint32_t LoadCommandIndex,
Kevin Enderbyd5039402016-10-31 20:29:48 +0000383 const char **SymtabLoadCmd,
384 std::list<MachOElement> &Elements) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000385 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
386 return malformedError("load command " + Twine(LoadCommandIndex) +
387 " LC_SYMTAB cmdsize too small");
388 if (*SymtabLoadCmd != nullptr)
389 return malformedError("more than one LC_SYMTAB command");
390 MachO::symtab_command Symtab =
391 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
392 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
393 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
394 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000395 uint64_t FileSize = Obj.getData().size();
Kevin Enderby0e52c922016-08-26 19:34:07 +0000396 if (Symtab.symoff > FileSize)
397 return malformedError("symoff field of LC_SYMTAB command " +
398 Twine(LoadCommandIndex) + " extends past the end "
399 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000400 uint64_t SymtabSize = Symtab.nsyms;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000401 const char *struct_nlist_name;
Lang Hames697e7cd2016-12-04 01:56:10 +0000402 if (Obj.is64Bit()) {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000403 SymtabSize *= sizeof(MachO::nlist_64);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000404 struct_nlist_name = "struct nlist_64";
405 } else {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000406 SymtabSize *= sizeof(MachO::nlist);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000407 struct_nlist_name = "struct nlist";
408 }
Kevin Enderbyd5039402016-10-31 20:29:48 +0000409 uint64_t BigSize = SymtabSize;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000410 BigSize += Symtab.symoff;
411 if (BigSize > FileSize)
412 return malformedError("symoff field plus nsyms field times sizeof(" +
413 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
414 Twine(LoadCommandIndex) + " extends past the end "
415 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000416 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
417 "symbol table"))
418 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000419 if (Symtab.stroff > FileSize)
420 return malformedError("stroff field of LC_SYMTAB command " +
421 Twine(LoadCommandIndex) + " extends past the end "
422 "of the file");
423 BigSize = Symtab.stroff;
424 BigSize += Symtab.strsize;
425 if (BigSize > FileSize)
426 return malformedError("stroff field plus strsize field of LC_SYMTAB "
427 "command " + Twine(LoadCommandIndex) + " extends "
428 "past the end of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000429 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
430 Symtab.strsize, "string table"))
431 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000432 *SymtabLoadCmd = Load.Ptr;
433 return Error::success();
434}
435
Lang Hames697e7cd2016-12-04 01:56:10 +0000436static Error checkDysymtabCommand(const MachOObjectFile &Obj,
437 const MachOObjectFile::LoadCommandInfo &Load,
438 uint32_t LoadCommandIndex,
439 const char **DysymtabLoadCmd,
440 std::list<MachOElement> &Elements) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000441 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
442 return malformedError("load command " + Twine(LoadCommandIndex) +
443 " LC_DYSYMTAB cmdsize too small");
444 if (*DysymtabLoadCmd != nullptr)
445 return malformedError("more than one LC_DYSYMTAB command");
446 MachO::dysymtab_command Dysymtab =
447 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
448 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
449 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
450 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000451 uint64_t FileSize = Obj.getData().size();
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000452 if (Dysymtab.tocoff > FileSize)
453 return malformedError("tocoff field of LC_DYSYMTAB command " +
454 Twine(LoadCommandIndex) + " extends past the end of "
455 "the file");
456 uint64_t BigSize = Dysymtab.ntoc;
457 BigSize *= sizeof(MachO::dylib_table_of_contents);
458 BigSize += Dysymtab.tocoff;
459 if (BigSize > FileSize)
460 return malformedError("tocoff field plus ntoc field times sizeof(struct "
461 "dylib_table_of_contents) of LC_DYSYMTAB command " +
462 Twine(LoadCommandIndex) + " extends past the end of "
463 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000464 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
465 Dysymtab.ntoc * sizeof(struct
466 MachO::dylib_table_of_contents),
467 "table of contents"))
468 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000469 if (Dysymtab.modtaboff > FileSize)
470 return malformedError("modtaboff field of LC_DYSYMTAB command " +
471 Twine(LoadCommandIndex) + " extends past the end of "
472 "the file");
473 BigSize = Dysymtab.nmodtab;
474 const char *struct_dylib_module_name;
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000475 uint64_t sizeof_modtab;
Lang Hames697e7cd2016-12-04 01:56:10 +0000476 if (Obj.is64Bit()) {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000477 sizeof_modtab = sizeof(MachO::dylib_module_64);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000478 struct_dylib_module_name = "struct dylib_module_64";
479 } else {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000480 sizeof_modtab = sizeof(MachO::dylib_module);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000481 struct_dylib_module_name = "struct dylib_module";
482 }
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000483 BigSize *= sizeof_modtab;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000484 BigSize += Dysymtab.modtaboff;
485 if (BigSize > FileSize)
486 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
487 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
488 "command " + Twine(LoadCommandIndex) + " extends "
489 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000490 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
491 Dysymtab.nmodtab * sizeof_modtab,
492 "module table"))
493 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000494 if (Dysymtab.extrefsymoff > FileSize)
495 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
496 Twine(LoadCommandIndex) + " extends past the end of "
497 "the file");
498 BigSize = Dysymtab.nextrefsyms;
499 BigSize *= sizeof(MachO::dylib_reference);
500 BigSize += Dysymtab.extrefsymoff;
501 if (BigSize > FileSize)
502 return malformedError("extrefsymoff field plus nextrefsyms field times "
503 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
504 "command " + Twine(LoadCommandIndex) + " extends "
505 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000506 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
507 Dysymtab.nextrefsyms *
508 sizeof(MachO::dylib_reference),
509 "reference table"))
510 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000511 if (Dysymtab.indirectsymoff > FileSize)
512 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
513 Twine(LoadCommandIndex) + " extends past the end of "
514 "the file");
515 BigSize = Dysymtab.nindirectsyms;
516 BigSize *= sizeof(uint32_t);
517 BigSize += Dysymtab.indirectsymoff;
518 if (BigSize > FileSize)
519 return malformedError("indirectsymoff field plus nindirectsyms field times "
520 "sizeof(uint32_t) of LC_DYSYMTAB command " +
521 Twine(LoadCommandIndex) + " extends past the end of "
522 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000523 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
524 Dysymtab.nindirectsyms *
525 sizeof(uint32_t),
526 "indirect table"))
527 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000528 if (Dysymtab.extreloff > FileSize)
529 return malformedError("extreloff field of LC_DYSYMTAB command " +
530 Twine(LoadCommandIndex) + " extends past the end of "
531 "the file");
532 BigSize = Dysymtab.nextrel;
533 BigSize *= sizeof(MachO::relocation_info);
534 BigSize += Dysymtab.extreloff;
535 if (BigSize > FileSize)
536 return malformedError("extreloff field plus nextrel field times sizeof"
537 "(struct relocation_info) of LC_DYSYMTAB command " +
538 Twine(LoadCommandIndex) + " extends past the end of "
539 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000540 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
541 Dysymtab.nextrel *
542 sizeof(MachO::relocation_info),
543 "external relocation table"))
544 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000545 if (Dysymtab.locreloff > FileSize)
546 return malformedError("locreloff field of LC_DYSYMTAB command " +
547 Twine(LoadCommandIndex) + " extends past the end of "
548 "the file");
549 BigSize = Dysymtab.nlocrel;
550 BigSize *= sizeof(MachO::relocation_info);
551 BigSize += Dysymtab.locreloff;
552 if (BigSize > FileSize)
553 return malformedError("locreloff field plus nlocrel field times sizeof"
554 "(struct relocation_info) of LC_DYSYMTAB command " +
555 Twine(LoadCommandIndex) + " extends past the end of "
556 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000557 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
558 Dysymtab.nlocrel *
559 sizeof(MachO::relocation_info),
560 "local relocation table"))
561 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000562 *DysymtabLoadCmd = Load.Ptr;
563 return Error::success();
564}
565
Lang Hames697e7cd2016-12-04 01:56:10 +0000566static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000567 const MachOObjectFile::LoadCommandInfo &Load,
568 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000569 const char **LoadCmd, const char *CmdName,
570 std::list<MachOElement> &Elements,
571 const char *ElementName) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000572 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
573 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
574 CmdName + " cmdsize too small");
575 if (*LoadCmd != nullptr)
576 return malformedError("more than one " + Twine(CmdName) + " command");
577 MachO::linkedit_data_command LinkData =
578 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
579 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
580 return malformedError(Twine(CmdName) + " command " +
581 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000582 uint64_t FileSize = Obj.getData().size();
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000583 if (LinkData.dataoff > FileSize)
584 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
585 Twine(LoadCommandIndex) + " extends past the end of "
586 "the file");
587 uint64_t BigSize = LinkData.dataoff;
588 BigSize += LinkData.datasize;
589 if (BigSize > FileSize)
590 return malformedError("dataoff field plus datasize field of " +
591 Twine(CmdName) + " command " +
592 Twine(LoadCommandIndex) + " extends past the end of "
593 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000594 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
595 LinkData.datasize, ElementName))
596 return Err;
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000597 *LoadCmd = Load.Ptr;
598 return Error::success();
599}
600
Lang Hames697e7cd2016-12-04 01:56:10 +0000601static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000602 const MachOObjectFile::LoadCommandInfo &Load,
603 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000604 const char **LoadCmd, const char *CmdName,
605 std::list<MachOElement> &Elements) {
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000606 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
607 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
608 CmdName + " cmdsize too small");
609 if (*LoadCmd != nullptr)
610 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
611 "command");
612 MachO::dyld_info_command DyldInfo =
613 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
614 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
615 return malformedError(Twine(CmdName) + " command " +
616 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000617 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000618 if (DyldInfo.rebase_off > FileSize)
619 return malformedError("rebase_off field of " + Twine(CmdName) +
620 " command " + Twine(LoadCommandIndex) + " extends "
621 "past the end of the file");
622 uint64_t BigSize = DyldInfo.rebase_off;
623 BigSize += DyldInfo.rebase_size;
624 if (BigSize > FileSize)
625 return malformedError("rebase_off field plus rebase_size field of " +
626 Twine(CmdName) + " command " +
627 Twine(LoadCommandIndex) + " extends past the end of "
628 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000629 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
630 DyldInfo.rebase_size,
631 "dyld rebase info"))
632 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000633 if (DyldInfo.bind_off > FileSize)
634 return malformedError("bind_off field of " + Twine(CmdName) +
635 " command " + Twine(LoadCommandIndex) + " extends "
636 "past the end of the file");
637 BigSize = DyldInfo.bind_off;
638 BigSize += DyldInfo.bind_size;
639 if (BigSize > FileSize)
640 return malformedError("bind_off field plus bind_size field of " +
641 Twine(CmdName) + " command " +
642 Twine(LoadCommandIndex) + " extends past the end of "
643 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000644 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
645 DyldInfo.bind_size,
646 "dyld bind info"))
647 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000648 if (DyldInfo.weak_bind_off > FileSize)
649 return malformedError("weak_bind_off field of " + Twine(CmdName) +
650 " command " + Twine(LoadCommandIndex) + " extends "
651 "past the end of the file");
652 BigSize = DyldInfo.weak_bind_off;
653 BigSize += DyldInfo.weak_bind_size;
654 if (BigSize > FileSize)
655 return malformedError("weak_bind_off field plus weak_bind_size field of " +
656 Twine(CmdName) + " command " +
657 Twine(LoadCommandIndex) + " extends past the end of "
658 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000659 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
660 DyldInfo.weak_bind_size,
661 "dyld weak bind info"))
662 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000663 if (DyldInfo.lazy_bind_off > FileSize)
664 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
665 " command " + Twine(LoadCommandIndex) + " extends "
666 "past the end of the file");
667 BigSize = DyldInfo.lazy_bind_off;
668 BigSize += DyldInfo.lazy_bind_size;
669 if (BigSize > FileSize)
670 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
671 Twine(CmdName) + " command " +
672 Twine(LoadCommandIndex) + " extends past the end of "
673 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000674 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
675 DyldInfo.lazy_bind_size,
676 "dyld lazy bind info"))
677 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000678 if (DyldInfo.export_off > FileSize)
679 return malformedError("export_off field of " + Twine(CmdName) +
680 " command " + Twine(LoadCommandIndex) + " extends "
681 "past the end of the file");
682 BigSize = DyldInfo.export_off;
683 BigSize += DyldInfo.export_size;
684 if (BigSize > FileSize)
685 return malformedError("export_off field plus export_size field of " +
686 Twine(CmdName) + " command " +
687 Twine(LoadCommandIndex) + " extends past the end of "
688 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000689 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
690 DyldInfo.export_size,
691 "dyld export info"))
692 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000693 *LoadCmd = Load.Ptr;
694 return Error::success();
695}
696
Lang Hames697e7cd2016-12-04 01:56:10 +0000697static Error checkDylibCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000698 const MachOObjectFile::LoadCommandInfo &Load,
699 uint32_t LoadCommandIndex, const char *CmdName) {
700 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
701 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
702 CmdName + " cmdsize too small");
703 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
704 if (D.dylib.name < sizeof(MachO::dylib_command))
705 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
706 CmdName + " name.offset field too small, not past "
707 "the end of the dylib_command struct");
708 if (D.dylib.name >= D.cmdsize)
709 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
710 CmdName + " name.offset field extends past the end "
711 "of the load command");
712 // Make sure there is a null between the starting offset of the name and
713 // the end of the load command.
714 uint32_t i;
715 const char *P = (const char *)Load.Ptr;
716 for (i = D.dylib.name; i < D.cmdsize; i++)
717 if (P[i] == '\0')
718 break;
719 if (i >= D.cmdsize)
720 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
721 CmdName + " library name extends past the end of the "
722 "load command");
723 return Error::success();
724}
725
Lang Hames697e7cd2016-12-04 01:56:10 +0000726static Error checkDylibIdCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000727 const MachOObjectFile::LoadCommandInfo &Load,
728 uint32_t LoadCommandIndex,
729 const char **LoadCmd) {
730 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
731 "LC_ID_DYLIB"))
732 return Err;
733 if (*LoadCmd != nullptr)
734 return malformedError("more than one LC_ID_DYLIB command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000735 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
736 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000737 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
738 "file type");
739 *LoadCmd = Load.Ptr;
740 return Error::success();
741}
742
Lang Hames697e7cd2016-12-04 01:56:10 +0000743static Error checkDyldCommand(const MachOObjectFile &Obj,
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000744 const MachOObjectFile::LoadCommandInfo &Load,
745 uint32_t LoadCommandIndex, const char *CmdName) {
746 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
747 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
748 CmdName + " cmdsize too small");
749 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
750 if (D.name < sizeof(MachO::dylinker_command))
751 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
752 CmdName + " name.offset field too small, not past "
753 "the end of the dylinker_command struct");
754 if (D.name >= D.cmdsize)
755 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
756 CmdName + " name.offset field extends past the end "
757 "of the load command");
758 // Make sure there is a null between the starting offset of the name and
759 // the end of the load command.
760 uint32_t i;
761 const char *P = (const char *)Load.Ptr;
762 for (i = D.name; i < D.cmdsize; i++)
763 if (P[i] == '\0')
764 break;
765 if (i >= D.cmdsize)
766 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
767 CmdName + " dyld name extends past the end of the "
768 "load command");
769 return Error::success();
770}
771
Lang Hames697e7cd2016-12-04 01:56:10 +0000772static Error checkVersCommand(const MachOObjectFile &Obj,
Kevin Enderby32359db2016-09-28 21:20:45 +0000773 const MachOObjectFile::LoadCommandInfo &Load,
774 uint32_t LoadCommandIndex,
775 const char **LoadCmd, const char *CmdName) {
776 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
777 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
778 CmdName + " has incorrect cmdsize");
779 if (*LoadCmd != nullptr)
780 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
781 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
782 "LC_VERSION_MIN_WATCHOS command");
783 *LoadCmd = Load.Ptr;
784 return Error::success();
785}
786
Kevin Enderbya4579c42017-01-19 17:36:31 +0000787static Error checkNoteCommand(const MachOObjectFile &Obj,
788 const MachOObjectFile::LoadCommandInfo &Load,
789 uint32_t LoadCommandIndex,
790 std::list<MachOElement> &Elements) {
791 if (Load.C.cmdsize != sizeof(MachO::note_command))
792 return malformedError("load command " + Twine(LoadCommandIndex) +
793 " LC_NOTE has incorrect cmdsize");
794 MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
795 uint64_t FileSize = Obj.getData().size();
796 if (Nt.offset > FileSize)
797 return malformedError("offset field of LC_NOTE command " +
798 Twine(LoadCommandIndex) + " extends "
799 "past the end of the file");
800 uint64_t BigSize = Nt.offset;
801 BigSize += Nt.size;
802 if (BigSize > FileSize)
803 return malformedError("size field plus offset field of LC_NOTE command " +
804 Twine(LoadCommandIndex) + " extends past the end of "
805 "the file");
806 if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
807 "LC_NOTE data"))
808 return Err;
809 return Error::success();
810}
811
Steven Wu5b54a422017-01-23 20:07:55 +0000812static Error
813parseBuildVersionCommand(const MachOObjectFile &Obj,
814 const MachOObjectFile::LoadCommandInfo &Load,
815 SmallVectorImpl<const char*> &BuildTools,
816 uint32_t LoadCommandIndex) {
817 MachO::build_version_command BVC =
818 getStruct<MachO::build_version_command>(Obj, Load.Ptr);
819 if (Load.C.cmdsize !=
820 sizeof(MachO::build_version_command) +
821 BVC.ntools * sizeof(MachO::build_tool_version))
822 return malformedError("load command " + Twine(LoadCommandIndex) +
823 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
824
825 auto Start = Load.Ptr + sizeof(MachO::build_version_command);
826 BuildTools.resize(BVC.ntools);
827 for (unsigned i = 0; i < BVC.ntools; ++i)
828 BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
829
830 return Error::success();
831}
832
Lang Hames697e7cd2016-12-04 01:56:10 +0000833static Error checkRpathCommand(const MachOObjectFile &Obj,
Kevin Enderby76966bf2016-09-28 23:16:01 +0000834 const MachOObjectFile::LoadCommandInfo &Load,
835 uint32_t LoadCommandIndex) {
836 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
837 return malformedError("load command " + Twine(LoadCommandIndex) +
838 " LC_RPATH cmdsize too small");
839 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
840 if (R.path < sizeof(MachO::rpath_command))
841 return malformedError("load command " + Twine(LoadCommandIndex) +
842 " LC_RPATH path.offset field too small, not past "
843 "the end of the rpath_command struct");
844 if (R.path >= R.cmdsize)
845 return malformedError("load command " + Twine(LoadCommandIndex) +
846 " LC_RPATH path.offset field extends past the end "
847 "of the load command");
848 // Make sure there is a null between the starting offset of the path and
849 // the end of the load command.
850 uint32_t i;
851 const char *P = (const char *)Load.Ptr;
852 for (i = R.path; i < R.cmdsize; i++)
853 if (P[i] == '\0')
854 break;
855 if (i >= R.cmdsize)
856 return malformedError("load command " + Twine(LoadCommandIndex) +
857 " LC_RPATH library name extends past the end of the "
858 "load command");
859 return Error::success();
860}
861
Lang Hames697e7cd2016-12-04 01:56:10 +0000862static Error checkEncryptCommand(const MachOObjectFile &Obj,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000863 const MachOObjectFile::LoadCommandInfo &Load,
864 uint32_t LoadCommandIndex,
865 uint64_t cryptoff, uint64_t cryptsize,
866 const char **LoadCmd, const char *CmdName) {
867 if (*LoadCmd != nullptr)
868 return malformedError("more than one LC_ENCRYPTION_INFO and or "
869 "LC_ENCRYPTION_INFO_64 command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000870 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000871 if (cryptoff > FileSize)
872 return malformedError("cryptoff field of " + Twine(CmdName) +
873 " command " + Twine(LoadCommandIndex) + " extends "
874 "past the end of the file");
875 uint64_t BigSize = cryptoff;
876 BigSize += cryptsize;
877 if (BigSize > FileSize)
878 return malformedError("cryptoff field plus cryptsize field of " +
879 Twine(CmdName) + " command " +
880 Twine(LoadCommandIndex) + " extends past the end of "
881 "the file");
882 *LoadCmd = Load.Ptr;
883 return Error::success();
884}
885
Lang Hames697e7cd2016-12-04 01:56:10 +0000886static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
Kevin Enderby68fffa82016-10-11 21:04:39 +0000887 const MachOObjectFile::LoadCommandInfo &Load,
888 uint32_t LoadCommandIndex) {
889 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
890 return malformedError("load command " + Twine(LoadCommandIndex) +
891 " LC_LINKER_OPTION cmdsize too small");
892 MachO::linker_option_command L =
893 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
894 // Make sure the count of strings is correct.
895 const char *string = (const char *)Load.Ptr +
896 sizeof(struct MachO::linker_option_command);
897 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
898 uint32_t i = 0;
899 while (left > 0) {
900 while (*string == '\0' && left > 0) {
901 string++;
902 left--;
903 }
904 if (left > 0) {
905 i++;
906 uint32_t NullPos = StringRef(string, left).find('\0');
907 uint32_t len = std::min(NullPos, left) + 1;
908 string += len;
909 left -= len;
910 }
911 }
912 if (L.count != i)
913 return malformedError("load command " + Twine(LoadCommandIndex) +
914 " LC_LINKER_OPTION string count " + Twine(L.count) +
915 " does not match number of strings");
916 return Error::success();
917}
918
Lang Hames697e7cd2016-12-04 01:56:10 +0000919static Error checkSubCommand(const MachOObjectFile &Obj,
Kevin Enderby2490de02016-10-17 22:09:25 +0000920 const MachOObjectFile::LoadCommandInfo &Load,
921 uint32_t LoadCommandIndex, const char *CmdName,
922 size_t SizeOfCmd, const char *CmdStructName,
923 uint32_t PathOffset, const char *PathFieldName) {
924 if (PathOffset < SizeOfCmd)
925 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
926 CmdName + " " + PathFieldName + ".offset field too "
927 "small, not past the end of the " + CmdStructName);
928 if (PathOffset >= Load.C.cmdsize)
929 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
930 CmdName + " " + PathFieldName + ".offset field "
931 "extends past the end of the load command");
932 // Make sure there is a null between the starting offset of the path and
933 // the end of the load command.
934 uint32_t i;
935 const char *P = (const char *)Load.Ptr;
936 for (i = PathOffset; i < Load.C.cmdsize; i++)
937 if (P[i] == '\0')
938 break;
939 if (i >= Load.C.cmdsize)
940 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
941 CmdName + " " + PathFieldName + " name extends past "
942 "the end of the load command");
943 return Error::success();
944}
945
Lang Hames697e7cd2016-12-04 01:56:10 +0000946static Error checkThreadCommand(const MachOObjectFile &Obj,
Kevin Enderby210030b2016-10-19 23:44:34 +0000947 const MachOObjectFile::LoadCommandInfo &Load,
948 uint32_t LoadCommandIndex,
949 const char *CmdName) {
950 if (Load.C.cmdsize < sizeof(MachO::thread_command))
951 return malformedError("load command " + Twine(LoadCommandIndex) +
952 CmdName + " cmdsize too small");
953 MachO::thread_command T =
954 getStruct<MachO::thread_command>(Obj, Load.Ptr);
955 const char *state = Load.Ptr + sizeof(MachO::thread_command);
956 const char *end = Load.Ptr + T.cmdsize;
957 uint32_t nflavor = 0;
958 uint32_t cputype = getCPUType(Obj);
959 while (state < end) {
960 if(state + sizeof(uint32_t) > end)
961 return malformedError("load command " + Twine(LoadCommandIndex) +
962 "flavor in " + CmdName + " extends past end of "
963 "command");
964 uint32_t flavor;
965 memcpy(&flavor, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000966 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000967 sys::swapByteOrder(flavor);
968 state += sizeof(uint32_t);
969
970 if(state + sizeof(uint32_t) > end)
971 return malformedError("load command " + Twine(LoadCommandIndex) +
972 " count in " + CmdName + " extends past end of "
973 "command");
974 uint32_t count;
975 memcpy(&count, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000976 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000977 sys::swapByteOrder(count);
978 state += sizeof(uint32_t);
979
Kevin Enderbyc3a035d2017-01-23 21:13:29 +0000980 if (cputype == MachO::CPU_TYPE_I386) {
981 if (flavor == MachO::x86_THREAD_STATE32) {
982 if (count != MachO::x86_THREAD_STATE32_COUNT)
983 return malformedError("load command " + Twine(LoadCommandIndex) +
984 " count not x86_THREAD_STATE32_COUNT for "
985 "flavor number " + Twine(nflavor) + " which is "
986 "a x86_THREAD_STATE32 flavor in " + CmdName +
987 " command");
988 if (state + sizeof(MachO::x86_thread_state32_t) > end)
989 return malformedError("load command " + Twine(LoadCommandIndex) +
990 " x86_THREAD_STATE32 extends past end of "
991 "command in " + CmdName + " command");
992 state += sizeof(MachO::x86_thread_state32_t);
993 } else {
994 return malformedError("load command " + Twine(LoadCommandIndex) +
995 " unknown flavor (" + Twine(flavor) + ") for "
996 "flavor number " + Twine(nflavor) + " in " +
997 CmdName + " command");
998 }
999 } else if (cputype == MachO::CPU_TYPE_X86_64) {
Kevin Enderby210030b2016-10-19 23:44:34 +00001000 if (flavor == MachO::x86_THREAD_STATE64) {
1001 if (count != MachO::x86_THREAD_STATE64_COUNT)
1002 return malformedError("load command " + Twine(LoadCommandIndex) +
1003 " count not x86_THREAD_STATE64_COUNT for "
1004 "flavor number " + Twine(nflavor) + " which is "
1005 "a x86_THREAD_STATE64 flavor in " + CmdName +
1006 " command");
1007 if (state + sizeof(MachO::x86_thread_state64_t) > end)
1008 return malformedError("load command " + Twine(LoadCommandIndex) +
1009 " x86_THREAD_STATE64 extends past end of "
1010 "command in " + CmdName + " command");
1011 state += sizeof(MachO::x86_thread_state64_t);
1012 } else {
1013 return malformedError("load command " + Twine(LoadCommandIndex) +
1014 " unknown flavor (" + Twine(flavor) + ") for "
1015 "flavor number " + Twine(nflavor) + " in " +
1016 CmdName + " command");
1017 }
1018 } else if (cputype == MachO::CPU_TYPE_ARM) {
1019 if (flavor == MachO::ARM_THREAD_STATE) {
1020 if (count != MachO::ARM_THREAD_STATE_COUNT)
1021 return malformedError("load command " + Twine(LoadCommandIndex) +
1022 " count not ARM_THREAD_STATE_COUNT for "
1023 "flavor number " + Twine(nflavor) + " which is "
1024 "a ARM_THREAD_STATE flavor in " + CmdName +
1025 " command");
1026 if (state + sizeof(MachO::arm_thread_state32_t) > end)
1027 return malformedError("load command " + Twine(LoadCommandIndex) +
1028 " ARM_THREAD_STATE extends past end of "
1029 "command in " + CmdName + " command");
1030 state += sizeof(MachO::arm_thread_state32_t);
1031 } else {
1032 return malformedError("load command " + Twine(LoadCommandIndex) +
1033 " unknown flavor (" + Twine(flavor) + ") for "
1034 "flavor number " + Twine(nflavor) + " in " +
1035 CmdName + " command");
1036 }
Kevin Enderby7747cb52016-11-03 20:51:28 +00001037 } else if (cputype == MachO::CPU_TYPE_ARM64) {
1038 if (flavor == MachO::ARM_THREAD_STATE64) {
1039 if (count != MachO::ARM_THREAD_STATE64_COUNT)
1040 return malformedError("load command " + Twine(LoadCommandIndex) +
1041 " count not ARM_THREAD_STATE64_COUNT for "
1042 "flavor number " + Twine(nflavor) + " which is "
1043 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1044 " command");
1045 if (state + sizeof(MachO::arm_thread_state64_t) > end)
1046 return malformedError("load command " + Twine(LoadCommandIndex) +
1047 " ARM_THREAD_STATE64 extends past end of "
1048 "command in " + CmdName + " command");
1049 state += sizeof(MachO::arm_thread_state64_t);
1050 } else {
1051 return malformedError("load command " + Twine(LoadCommandIndex) +
1052 " unknown flavor (" + Twine(flavor) + ") for "
1053 "flavor number " + Twine(nflavor) + " in " +
1054 CmdName + " command");
1055 }
Kevin Enderby210030b2016-10-19 23:44:34 +00001056 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1057 if (flavor == MachO::PPC_THREAD_STATE) {
1058 if (count != MachO::PPC_THREAD_STATE_COUNT)
1059 return malformedError("load command " + Twine(LoadCommandIndex) +
1060 " count not PPC_THREAD_STATE_COUNT for "
1061 "flavor number " + Twine(nflavor) + " which is "
1062 "a PPC_THREAD_STATE flavor in " + CmdName +
1063 " command");
1064 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1065 return malformedError("load command " + Twine(LoadCommandIndex) +
1066 " PPC_THREAD_STATE extends past end of "
1067 "command in " + CmdName + " command");
1068 state += sizeof(MachO::ppc_thread_state32_t);
1069 } else {
1070 return malformedError("load command " + Twine(LoadCommandIndex) +
1071 " unknown flavor (" + Twine(flavor) + ") for "
1072 "flavor number " + Twine(nflavor) + " in " +
1073 CmdName + " command");
1074 }
1075 } else {
1076 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1077 "command " + Twine(LoadCommandIndex) + " for " +
1078 CmdName + " command can't be checked");
1079 }
1080 nflavor++;
1081 }
1082 return Error::success();
1083}
1084
Lang Hames697e7cd2016-12-04 01:56:10 +00001085static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001086 const MachOObjectFile::LoadCommandInfo
1087 &Load,
1088 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001089 const char **LoadCmd,
1090 std::list<MachOElement> &Elements) {
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001091 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1092 return malformedError("load command " + Twine(LoadCommandIndex) +
1093 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1094 if (*LoadCmd != nullptr)
1095 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1096 MachO::twolevel_hints_command Hints =
1097 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
Lang Hames697e7cd2016-12-04 01:56:10 +00001098 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001099 if (Hints.offset > FileSize)
1100 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1101 Twine(LoadCommandIndex) + " extends past the end of "
1102 "the file");
1103 uint64_t BigSize = Hints.nhints;
1104 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
1105 BigSize += Hints.offset;
1106 if (BigSize > FileSize)
1107 return malformedError("offset field plus nhints times sizeof(struct "
1108 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1109 Twine(LoadCommandIndex) + " extends past the end of "
1110 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001111 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1112 sizeof(MachO::twolevel_hint),
1113 "two level hints"))
1114 return Err;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001115 *LoadCmd = Load.Ptr;
1116 return Error::success();
1117}
1118
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001119// Returns true if the libObject code does not support the load command and its
1120// contents. The cmd value it is treated as an unknown load command but with
1121// an error message that says the cmd value is obsolete.
1122static bool isLoadCommandObsolete(uint32_t cmd) {
1123 if (cmd == MachO::LC_SYMSEG ||
1124 cmd == MachO::LC_LOADFVMLIB ||
1125 cmd == MachO::LC_IDFVMLIB ||
1126 cmd == MachO::LC_IDENT ||
1127 cmd == MachO::LC_FVMFILE ||
1128 cmd == MachO::LC_PREPAGE ||
1129 cmd == MachO::LC_PREBOUND_DYLIB ||
1130 cmd == MachO::LC_TWOLEVEL_HINTS ||
1131 cmd == MachO::LC_PREBIND_CKSUM)
1132 return true;
1133 return false;
1134}
1135
Lang Hames82627642016-03-25 21:59:14 +00001136Expected<std::unique_ptr<MachOObjectFile>>
1137MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001138 bool Is64Bits, uint32_t UniversalCputype,
1139 uint32_t UniversalIndex) {
Mehdi Amini41af4302016-11-11 04:28:40 +00001140 Error Err = Error::success();
Lang Hames82627642016-03-25 21:59:14 +00001141 std::unique_ptr<MachOObjectFile> Obj(
1142 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001143 Is64Bits, Err, UniversalCputype,
1144 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +00001145 if (Err)
1146 return std::move(Err);
1147 return std::move(Obj);
1148}
1149
Rafael Espindola48af1c22014-08-19 18:44:46 +00001150MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001151 bool Is64bits, Error &Err,
1152 uint32_t UniversalCputype,
1153 uint32_t UniversalIndex)
Rafael Espindola48af1c22014-08-19 18:44:46 +00001154 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +00001155 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +00001156 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
1157 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
1158 HasPageZeroSegment(false) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001159 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001160 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001161 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001162 if (is64Bit()) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001163 parseHeader(*this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001164 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001165 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001166 } else {
Lang Hames697e7cd2016-12-04 01:56:10 +00001167 parseHeader(*this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001168 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001169 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001170 }
Lang Hames9e964f32016-03-25 17:25:34 +00001171 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001172 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001173 SizeOfHeaders += getHeader().sizeofcmds;
1174 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001175 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001176 return;
1177 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001178 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1179 Err = malformedError("universal header architecture: " +
1180 Twine(UniversalIndex) + "'s cputype does not match "
1181 "object file's mach header");
1182 return;
1183 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001184 std::list<MachOElement> Elements;
1185 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001186
1187 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001188 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001189 if (LoadCommandCount != 0) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001190 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001191 Load = *LoadOrErr;
1192 else {
1193 Err = LoadOrErr.takeError();
1194 return;
1195 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001196 }
Lang Hames9e964f32016-03-25 17:25:34 +00001197
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001198 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001199 const char *FuncStartsLoadCmd = nullptr;
1200 const char *SplitInfoLoadCmd = nullptr;
1201 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001202 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001203 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001204 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001205 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001206 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001207 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001208 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001209 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001210 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001211 if (is64Bit()) {
1212 if (Load.C.cmdsize % 8 != 0) {
1213 // We have a hack here to allow 64-bit Mach-O core files to have
1214 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1215 // allowed since the macOS kernel produces them.
1216 if (getHeader().filetype != MachO::MH_CORE ||
1217 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1218 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1219 "multiple of 8");
1220 return;
1221 }
1222 }
1223 } else {
1224 if (Load.C.cmdsize % 4 != 0) {
1225 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1226 "multiple of 4");
1227 return;
1228 }
1229 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001230 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001231 if (Load.C.cmd == MachO::LC_SYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001232 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001233 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001234 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001235 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001236 Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001237 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001238 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001239 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001240 "LC_DATA_IN_CODE", Elements,
1241 "data in code info")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001242 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001243 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001244 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001245 "LC_LINKER_OPTIMIZATION_HINT",
1246 Elements, "linker optimization "
1247 "hints")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001248 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001249 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001250 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001251 "LC_FUNCTION_STARTS", Elements,
1252 "function starts data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001253 return;
1254 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001255 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001256 "LC_SEGMENT_SPLIT_INFO", Elements,
1257 "split info data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001258 return;
1259 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001260 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001261 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1262 "code signing RDs data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001263 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001264 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001265 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001266 "LC_CODE_SIGNATURE", Elements,
1267 "code signature data")))
Kevin Enderby89baf992016-10-18 20:24:12 +00001268 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001269 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001270 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001271 "LC_DYLD_INFO", Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001272 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001273 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001274 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001275 "LC_DYLD_INFO_ONLY", Elements)))
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001276 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001277 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001278 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1279 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1280 "cmdsize");
1281 return;
1282 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001283 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001284 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001285 return;
1286 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001287 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001288 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001289 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1290 MachO::section_64>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001291 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001292 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001293 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001294 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001295 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1296 MachO::section>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001297 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001298 "LC_SEGMENT", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001299 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001300 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001301 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001302 return;
1303 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001304 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001305 return;
1306 Libraries.push_back(Load.Ptr);
1307 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001308 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001309 return;
1310 Libraries.push_back(Load.Ptr);
1311 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001312 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001313 return;
1314 Libraries.push_back(Load.Ptr);
1315 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001316 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001317 return;
1318 Libraries.push_back(Load.Ptr);
1319 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001320 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001321 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001322 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001323 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001324 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001325 return;
1326 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001327 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001328 return;
1329 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001330 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001331 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001332 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001333 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001334 "LC_VERSION_MIN_MACOSX")))
1335 return;
1336 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001337 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001338 "LC_VERSION_MIN_IPHONEOS")))
1339 return;
1340 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001341 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001342 "LC_VERSION_MIN_TVOS")))
1343 return;
1344 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001345 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001346 "LC_VERSION_MIN_WATCHOS")))
1347 return;
Kevin Enderbya4579c42017-01-19 17:36:31 +00001348 } else if (Load.C.cmd == MachO::LC_NOTE) {
1349 if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1350 return;
Steven Wu5b54a422017-01-23 20:07:55 +00001351 } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1352 if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1353 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001354 } else if (Load.C.cmd == MachO::LC_RPATH) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001355 if ((Err = checkRpathCommand(*this, Load, I)))
Kevin Enderby76966bf2016-09-28 23:16:01 +00001356 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001357 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1358 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1359 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1360 " has incorrect cmdsize");
1361 return;
1362 }
1363 if (SourceLoadCmd) {
1364 Err = malformedError("more than one LC_SOURCE_VERSION command");
1365 return;
1366 }
1367 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001368 } else if (Load.C.cmd == MachO::LC_MAIN) {
1369 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1370 Err = malformedError("LC_MAIN command " + Twine(I) +
1371 " has incorrect cmdsize");
1372 return;
1373 }
1374 if (EntryPointLoadCmd) {
1375 Err = malformedError("more than one LC_MAIN command");
1376 return;
1377 }
1378 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001379 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1380 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1381 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1382 " has incorrect cmdsize");
1383 return;
1384 }
1385 MachO::encryption_info_command E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001386 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1387 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001388 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1389 return;
1390 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1391 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1392 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1393 " has incorrect cmdsize");
1394 return;
1395 }
1396 MachO::encryption_info_command_64 E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001397 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1398 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001399 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1400 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001401 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001402 if ((Err = checkLinkerOptCommand(*this, Load, I)))
Kevin Enderby68fffa82016-10-11 21:04:39 +00001403 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001404 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1405 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1406 Err = malformedError("load command " + Twine(I) +
1407 " LC_SUB_FRAMEWORK cmdsize too small");
1408 return;
1409 }
1410 MachO::sub_framework_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001411 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1412 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
Kevin Enderby2490de02016-10-17 22:09:25 +00001413 sizeof(MachO::sub_framework_command),
1414 "sub_framework_command", S.umbrella,
1415 "umbrella")))
1416 return;
1417 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1418 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1419 Err = malformedError("load command " + Twine(I) +
1420 " LC_SUB_UMBRELLA cmdsize too small");
1421 return;
1422 }
1423 MachO::sub_umbrella_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001424 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1425 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
Kevin Enderby2490de02016-10-17 22:09:25 +00001426 sizeof(MachO::sub_umbrella_command),
1427 "sub_umbrella_command", S.sub_umbrella,
1428 "sub_umbrella")))
1429 return;
1430 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1431 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1432 Err = malformedError("load command " + Twine(I) +
1433 " LC_SUB_LIBRARY cmdsize too small");
1434 return;
1435 }
1436 MachO::sub_library_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001437 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1438 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
Kevin Enderby2490de02016-10-17 22:09:25 +00001439 sizeof(MachO::sub_library_command),
1440 "sub_library_command", S.sub_library,
1441 "sub_library")))
1442 return;
1443 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1444 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1445 Err = malformedError("load command " + Twine(I) +
1446 " LC_SUB_CLIENT cmdsize too small");
1447 return;
1448 }
1449 MachO::sub_client_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001450 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1451 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
Kevin Enderby2490de02016-10-17 22:09:25 +00001452 sizeof(MachO::sub_client_command),
1453 "sub_client_command", S.client, "client")))
1454 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001455 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1456 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1457 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1458 " has incorrect cmdsize");
1459 return;
1460 }
1461 if (RoutinesLoadCmd) {
1462 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1463 "command");
1464 return;
1465 }
1466 RoutinesLoadCmd = Load.Ptr;
1467 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1468 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1469 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1470 " has incorrect cmdsize");
1471 return;
1472 }
1473 if (RoutinesLoadCmd) {
1474 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1475 "command");
1476 return;
1477 }
1478 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001479 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001480 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001481 return;
1482 if (UnixThreadLoadCmd) {
1483 Err = malformedError("more than one LC_UNIXTHREAD command");
1484 return;
1485 }
1486 UnixThreadLoadCmd = Load.Ptr;
1487 } else if (Load.C.cmd == MachO::LC_THREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001488 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001489 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001490 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001491 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001492 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001493 &TwoLevelHintsLoadCmd, Elements)))
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001494 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001495 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1496 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1497 Twine(Load.C.cmd) + " is obsolete and not "
1498 "supported");
1499 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001500 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001501 // TODO: generate a error for unknown load commands by default. But still
1502 // need work out an approach to allow or not allow unknown values like this
1503 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001504 if (I < LoadCommandCount - 1) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001505 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001506 Load = *LoadOrErr;
1507 else {
1508 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001509 return;
1510 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001511 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001512 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001513 if (!SymtabLoadCmd) {
1514 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001515 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001516 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001517 return;
1518 }
1519 } else if (DysymtabLoadCmd) {
1520 MachO::symtab_command Symtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001521 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001522 MachO::dysymtab_command Dysymtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001523 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001524 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001525 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001526 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001527 return;
1528 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001529 uint64_t BigSize = Dysymtab.ilocalsym;
1530 BigSize += Dysymtab.nlocalsym;
1531 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001532 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001533 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001534 return;
1535 }
1536 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001537 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001538 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001539 return;
1540 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001541 BigSize = Dysymtab.iextdefsym;
1542 BigSize += Dysymtab.nextdefsym;
1543 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001544 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001545 "load command extends past the end of the symbol "
1546 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001547 return;
1548 }
1549 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001550 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001551 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001552 return;
1553 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001554 BigSize = Dysymtab.iundefsym;
1555 BigSize += Dysymtab.nundefsym;
1556 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001557 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001558 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001559 return;
1560 }
1561 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001562 if ((getHeader().filetype == MachO::MH_DYLIB ||
1563 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1564 DyldIdLoadCmd == nullptr) {
1565 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1566 "filetype");
1567 return;
1568 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001569 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001570
1571 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001572}
1573
Kevin Enderby22fc0072016-11-14 20:57:04 +00001574Error MachOObjectFile::checkSymbolTable() const {
1575 uint32_t Flags = 0;
1576 if (is64Bit()) {
1577 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1578 Flags = H_64.flags;
1579 } else {
1580 MachO::mach_header H = MachOObjectFile::getHeader();
1581 Flags = H.flags;
1582 }
1583 uint8_t NType = 0;
1584 uint8_t NSect = 0;
1585 uint16_t NDesc = 0;
1586 uint32_t NStrx = 0;
1587 uint64_t NValue = 0;
1588 uint32_t SymbolIndex = 0;
1589 MachO::symtab_command S = getSymtabLoadCommand();
1590 for (const SymbolRef &Symbol : symbols()) {
1591 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1592 if (is64Bit()) {
1593 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1594 NType = STE_64.n_type;
1595 NSect = STE_64.n_sect;
1596 NDesc = STE_64.n_desc;
1597 NStrx = STE_64.n_strx;
1598 NValue = STE_64.n_value;
1599 } else {
1600 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1601 NType = STE.n_type;
1602 NType = STE.n_type;
1603 NSect = STE.n_sect;
1604 NDesc = STE.n_desc;
1605 NStrx = STE.n_strx;
1606 NValue = STE.n_value;
1607 }
1608 if ((NType & MachO::N_STAB) == 0 &&
1609 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1610 if (NSect == 0 || NSect > Sections.size())
1611 return malformedError("bad section index: " + Twine((int)NSect) +
1612 " for symbol at index " + Twine(SymbolIndex));
1613 }
1614 if ((NType & MachO::N_STAB) == 0 &&
1615 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1616 if (NValue >= S.strsize)
1617 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1618 "the end of string table, for N_INDR symbol at "
1619 "index " + Twine(SymbolIndex));
1620 }
1621 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1622 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1623 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1624 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1625 if (LibraryOrdinal != 0 &&
1626 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1627 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1628 LibraryOrdinal - 1 >= Libraries.size() ) {
1629 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1630 " for symbol at index " + Twine(SymbolIndex));
1631 }
1632 }
1633 if (NStrx >= S.strsize)
1634 return malformedError("bad string table index: " + Twine((int)NStrx) +
1635 " past the end of string table, for symbol at "
1636 "index " + Twine(SymbolIndex));
1637 SymbolIndex++;
1638 }
1639 return Error::success();
1640}
1641
Rafael Espindola5e812af2014-01-30 02:49:50 +00001642void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001643 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001644 sizeof(MachO::nlist_64) :
1645 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001646 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001647}
1648
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001649Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001650 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001651 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001652 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001653 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001654 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001655 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001656 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001657 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001658}
1659
Rafael Espindola0e77a942014-12-10 20:46:55 +00001660unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1661 DataRefImpl DRI = Sec.getRawDataRefImpl();
Lang Hames697e7cd2016-12-04 01:56:10 +00001662 uint32_t Flags = getSectionFlags(*this, DRI);
Rafael Espindola0e77a942014-12-10 20:46:55 +00001663 return Flags & MachO::SECTION_TYPE;
1664}
1665
Rafael Espindola59128922015-06-24 18:14:41 +00001666uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1667 if (is64Bit()) {
1668 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1669 return Entry.n_value;
1670 }
1671 MachO::nlist Entry = getSymbolTableEntry(Sym);
1672 return Entry.n_value;
1673}
1674
Kevin Enderby980b2582014-06-05 21:21:57 +00001675// getIndirectName() returns the name of the alias'ed symbol who's string table
1676// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001677std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1678 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001679 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001680 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Rafael Espindola59128922015-06-24 18:14:41 +00001681 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1682 return object_error::parse_failed;
1683 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001684 if (NValue >= StringTable.size())
1685 return object_error::parse_failed;
1686 const char *Start = &StringTable.data()[NValue];
1687 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001688 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001689}
1690
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001691uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001692 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001693}
1694
Kevin Enderby931cb652016-06-24 18:24:42 +00001695Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001696 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001697}
1698
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001699uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001700 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001701 if (flags & SymbolRef::SF_Common) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001702 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001703 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001704 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001705 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001706}
1707
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001708uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001709 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001710}
1711
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001712Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001713MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001714 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001715 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001716
Rafael Espindola56f976f2013-04-18 18:08:55 +00001717 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001718 if (n_type & MachO::N_STAB)
1719 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001720
Charles Davis74ec8b02013-08-27 05:00:13 +00001721 switch (n_type & MachO::N_TYPE) {
1722 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001723 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001724 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001725 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001726 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001727 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001728 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001729 if (Sec->isData() || Sec->isBSS())
1730 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001731 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001732 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001733 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001734}
1735
Rafael Espindola20122a42014-01-31 20:57:12 +00001736uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001737 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001738
Charles Davis8bdfafd2013-09-01 04:28:48 +00001739 uint8_t MachOType = Entry.n_type;
1740 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001741
Rafael Espindola20122a42014-01-31 20:57:12 +00001742 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001743
Tim Northovereaef0742014-05-30 13:22:59 +00001744 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1745 Result |= SymbolRef::SF_Indirect;
1746
Rafael Espindolaa1356322013-11-02 05:03:24 +00001747 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001748 Result |= SymbolRef::SF_FormatSpecific;
1749
Charles Davis74ec8b02013-08-27 05:00:13 +00001750 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001751 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001752 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001753 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001754 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001755 else
1756 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001757 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001758
1759 if (!(MachOType & MachO::N_PEXT))
1760 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001761 }
1762
Charles Davis74ec8b02013-08-27 05:00:13 +00001763 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001764 Result |= SymbolRef::SF_Weak;
1765
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001766 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1767 Result |= SymbolRef::SF_Thumb;
1768
Charles Davis74ec8b02013-08-27 05:00:13 +00001769 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001770 Result |= SymbolRef::SF_Absolute;
1771
Rafael Espindola20122a42014-01-31 20:57:12 +00001772 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001773}
1774
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001775Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001776MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001777 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001778 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001779
Rafael Espindola8bab8892015-08-07 23:27:14 +00001780 if (index == 0)
1781 return section_end();
1782 DataRefImpl DRI;
1783 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001784 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001785 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001786 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001787 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001788 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001789}
1790
Rafael Espindola6bf32212015-06-24 19:57:32 +00001791unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1792 MachO::nlist_base Entry =
Lang Hames697e7cd2016-12-04 01:56:10 +00001793 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
Rafael Espindola6bf32212015-06-24 19:57:32 +00001794 return Entry.n_sect - 1;
1795}
1796
Rafael Espindola5e812af2014-01-30 02:49:50 +00001797void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001798 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001799}
1800
Rafael Espindola3acea392014-06-12 21:46:39 +00001801std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1802 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001803 ArrayRef<char> Raw = getSectionRawName(Sec);
1804 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001805 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001806}
1807
Rafael Espindola80291272014-10-08 15:28:58 +00001808uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1809 if (is64Bit())
1810 return getSection64(Sec).addr;
1811 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001812}
1813
Rafael Espindola80291272014-10-08 15:28:58 +00001814uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001815 // In the case if a malformed Mach-O file where the section offset is past
1816 // the end of the file or some part of the section size is past the end of
1817 // the file return a size of zero or a size that covers the rest of the file
1818 // but does not extend past the end of the file.
1819 uint32_t SectOffset, SectType;
1820 uint64_t SectSize;
1821
1822 if (is64Bit()) {
1823 MachO::section_64 Sect = getSection64(Sec);
1824 SectOffset = Sect.offset;
1825 SectSize = Sect.size;
1826 SectType = Sect.flags & MachO::SECTION_TYPE;
1827 } else {
1828 MachO::section Sect = getSection(Sec);
1829 SectOffset = Sect.offset;
1830 SectSize = Sect.size;
1831 SectType = Sect.flags & MachO::SECTION_TYPE;
1832 }
1833 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1834 return SectSize;
1835 uint64_t FileSize = getData().size();
1836 if (SectOffset > FileSize)
1837 return 0;
1838 if (FileSize - SectOffset < SectSize)
1839 return FileSize - SectOffset;
1840 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001841}
1842
Rafael Espindola3acea392014-06-12 21:46:39 +00001843std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1844 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001845 uint32_t Offset;
1846 uint64_t Size;
1847
1848 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001849 MachO::section_64 Sect = getSection64(Sec);
1850 Offset = Sect.offset;
1851 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001852 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001853 MachO::section Sect = getSection(Sec);
1854 Offset = Sect.offset;
1855 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001856 }
1857
1858 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001859 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001860}
1861
Rafael Espindola80291272014-10-08 15:28:58 +00001862uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001863 uint32_t Align;
1864 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001865 MachO::section_64 Sect = getSection64(Sec);
1866 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001867 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001868 MachO::section Sect = getSection(Sec);
1869 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001870 }
1871
Rafael Espindola80291272014-10-08 15:28:58 +00001872 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001873}
1874
George Rimar401e4e52016-05-24 12:48:46 +00001875bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1876 return false;
1877}
1878
Rafael Espindola80291272014-10-08 15:28:58 +00001879bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001880 uint32_t Flags = getSectionFlags(*this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001881 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001882}
1883
Rafael Espindola80291272014-10-08 15:28:58 +00001884bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001885 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001886 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001887 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1888 !(SectionType == MachO::S_ZEROFILL ||
1889 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001890}
1891
Rafael Espindola80291272014-10-08 15:28:58 +00001892bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001893 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001894 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001895 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1896 (SectionType == MachO::S_ZEROFILL ||
1897 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001898}
1899
Rafael Espindola6bf32212015-06-24 19:57:32 +00001900unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1901 return Sec.getRawDataRefImpl().d.a;
1902}
1903
Rafael Espindola80291272014-10-08 15:28:58 +00001904bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +00001905 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +00001906 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001907}
1908
Steven Wuf2fe0142016-02-29 19:40:10 +00001909bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1910 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1911 StringRef SectName;
1912 if (!getSectionName(Sec, SectName))
1913 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1914 return false;
1915}
1916
Rui Ueyamabc654b12013-09-27 21:47:05 +00001917relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001918 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001919 Ret.d.a = Sec.d.a;
1920 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001921 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001922}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001923
Rafael Espindola56f976f2013-04-18 18:08:55 +00001924relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00001925MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001926 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001927 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001928 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001929 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001930 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001931 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001932 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001933 }
Eric Christopher7b015c72011-04-22 03:19:48 +00001934
Rafael Espindola56f976f2013-04-18 18:08:55 +00001935 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001936 Ret.d.a = Sec.d.a;
1937 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001938 return relocation_iterator(RelocationRef(Ret, this));
1939}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001940
Rafael Espindola5e812af2014-01-30 02:49:50 +00001941void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001942 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001943}
Owen Anderson171f4852011-10-24 23:20:07 +00001944
Rafael Espindola96d071c2015-06-29 23:29:12 +00001945uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +00001946 assert(getHeader().filetype == MachO::MH_OBJECT &&
1947 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001948 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00001949 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00001950}
1951
Rafael Espindola806f0062013-06-05 01:33:53 +00001952symbol_iterator
1953MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001954 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00001955 if (isRelocationScattered(RE))
1956 return symbol_end();
1957
Rafael Espindola56f976f2013-04-18 18:08:55 +00001958 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1959 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00001960 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00001961 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00001962
Charles Davis8bdfafd2013-09-01 04:28:48 +00001963 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001964 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001965 sizeof(MachO::nlist_64) :
1966 sizeof(MachO::nlist);
1967 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001968 DataRefImpl Sym;
Lang Hames697e7cd2016-12-04 01:56:10 +00001969 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00001970 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001971}
1972
Keno Fischerc780e8e2015-05-21 21:24:32 +00001973section_iterator
1974MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
1975 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
1976}
1977
Rafael Espindola99c041b2015-06-30 01:53:01 +00001978uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001979 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00001980 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001981}
1982
Rafael Espindola41bb4322015-06-30 04:08:37 +00001983void MachOObjectFile::getRelocationTypeName(
1984 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001985 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00001986 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001987
1988 unsigned Arch = this->getArch();
1989
1990 switch (Arch) {
1991 case Triple::x86: {
1992 static const char *const Table[] = {
1993 "GENERIC_RELOC_VANILLA",
1994 "GENERIC_RELOC_PAIR",
1995 "GENERIC_RELOC_SECTDIFF",
1996 "GENERIC_RELOC_PB_LA_PTR",
1997 "GENERIC_RELOC_LOCAL_SECTDIFF",
1998 "GENERIC_RELOC_TLV" };
1999
Eric Christopher13250cb2013-12-06 02:33:38 +00002000 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002001 res = "Unknown";
2002 else
2003 res = Table[RType];
2004 break;
2005 }
2006 case Triple::x86_64: {
2007 static const char *const Table[] = {
2008 "X86_64_RELOC_UNSIGNED",
2009 "X86_64_RELOC_SIGNED",
2010 "X86_64_RELOC_BRANCH",
2011 "X86_64_RELOC_GOT_LOAD",
2012 "X86_64_RELOC_GOT",
2013 "X86_64_RELOC_SUBTRACTOR",
2014 "X86_64_RELOC_SIGNED_1",
2015 "X86_64_RELOC_SIGNED_2",
2016 "X86_64_RELOC_SIGNED_4",
2017 "X86_64_RELOC_TLV" };
2018
2019 if (RType > 9)
2020 res = "Unknown";
2021 else
2022 res = Table[RType];
2023 break;
2024 }
2025 case Triple::arm: {
2026 static const char *const Table[] = {
2027 "ARM_RELOC_VANILLA",
2028 "ARM_RELOC_PAIR",
2029 "ARM_RELOC_SECTDIFF",
2030 "ARM_RELOC_LOCAL_SECTDIFF",
2031 "ARM_RELOC_PB_LA_PTR",
2032 "ARM_RELOC_BR24",
2033 "ARM_THUMB_RELOC_BR22",
2034 "ARM_THUMB_32BIT_BRANCH",
2035 "ARM_RELOC_HALF",
2036 "ARM_RELOC_HALF_SECTDIFF" };
2037
2038 if (RType > 9)
2039 res = "Unknown";
2040 else
2041 res = Table[RType];
2042 break;
2043 }
Tim Northover00ed9962014-03-29 10:18:08 +00002044 case Triple::aarch64: {
2045 static const char *const Table[] = {
2046 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2047 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2048 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2049 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2050 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2051 "ARM64_RELOC_ADDEND"
2052 };
2053
2054 if (RType >= array_lengthof(Table))
2055 res = "Unknown";
2056 else
2057 res = Table[RType];
2058 break;
2059 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00002060 case Triple::ppc: {
2061 static const char *const Table[] = {
2062 "PPC_RELOC_VANILLA",
2063 "PPC_RELOC_PAIR",
2064 "PPC_RELOC_BR14",
2065 "PPC_RELOC_BR24",
2066 "PPC_RELOC_HI16",
2067 "PPC_RELOC_LO16",
2068 "PPC_RELOC_HA16",
2069 "PPC_RELOC_LO14",
2070 "PPC_RELOC_SECTDIFF",
2071 "PPC_RELOC_PB_LA_PTR",
2072 "PPC_RELOC_HI16_SECTDIFF",
2073 "PPC_RELOC_LO16_SECTDIFF",
2074 "PPC_RELOC_HA16_SECTDIFF",
2075 "PPC_RELOC_JBSR",
2076 "PPC_RELOC_LO14_SECTDIFF",
2077 "PPC_RELOC_LOCAL_SECTDIFF" };
2078
Eric Christopher13250cb2013-12-06 02:33:38 +00002079 if (RType > 15)
2080 res = "Unknown";
2081 else
2082 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00002083 break;
2084 }
2085 case Triple::UnknownArch:
2086 res = "Unknown";
2087 break;
2088 }
2089 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00002090}
2091
Keno Fischer281b6942015-05-30 19:44:53 +00002092uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2093 MachO::any_relocation_info RE = getRelocation(Rel);
2094 return getAnyRelocationLength(RE);
2095}
2096
Kevin Enderby980b2582014-06-05 21:21:57 +00002097//
2098// guessLibraryShortName() is passed a name of a dynamic library and returns a
2099// guess on what the short name is. Then name is returned as a substring of the
2100// StringRef Name passed in. The name of the dynamic library is recognized as
2101// a framework if it has one of the two following forms:
2102// Foo.framework/Versions/A/Foo
2103// Foo.framework/Foo
2104// Where A and Foo can be any string. And may contain a trailing suffix
2105// starting with an underbar. If the Name is recognized as a framework then
2106// isFramework is set to true else it is set to false. If the Name has a
2107// suffix then Suffix is set to the substring in Name that contains the suffix
2108// else it is set to a NULL StringRef.
2109//
2110// The Name of the dynamic library is recognized as a library name if it has
2111// one of the two following forms:
2112// libFoo.A.dylib
2113// libFoo.dylib
2114// The library may have a suffix trailing the name Foo of the form:
2115// libFoo_profile.A.dylib
2116// libFoo_profile.dylib
2117//
2118// The Name of the dynamic library is also recognized as a library name if it
2119// has the following form:
2120// Foo.qtx
2121//
2122// If the Name of the dynamic library is none of the forms above then a NULL
2123// StringRef is returned.
2124//
2125StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2126 bool &isFramework,
2127 StringRef &Suffix) {
2128 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2129 size_t a, b, c, d, Idx;
2130
2131 isFramework = false;
2132 Suffix = StringRef();
2133
2134 // Pull off the last component and make Foo point to it
2135 a = Name.rfind('/');
2136 if (a == Name.npos || a == 0)
2137 goto guess_library;
2138 Foo = Name.slice(a+1, Name.npos);
2139
2140 // Look for a suffix starting with a '_'
2141 Idx = Foo.rfind('_');
2142 if (Idx != Foo.npos && Foo.size() >= 2) {
2143 Suffix = Foo.slice(Idx, Foo.npos);
2144 Foo = Foo.slice(0, Idx);
2145 }
2146
2147 // First look for the form Foo.framework/Foo
2148 b = Name.rfind('/', a);
2149 if (b == Name.npos)
2150 Idx = 0;
2151 else
2152 Idx = b+1;
2153 F = Name.slice(Idx, Idx + Foo.size());
2154 DotFramework = Name.slice(Idx + Foo.size(),
2155 Idx + Foo.size() + sizeof(".framework/")-1);
2156 if (F == Foo && DotFramework == ".framework/") {
2157 isFramework = true;
2158 return Foo;
2159 }
2160
2161 // Next look for the form Foo.framework/Versions/A/Foo
2162 if (b == Name.npos)
2163 goto guess_library;
2164 c = Name.rfind('/', b);
2165 if (c == Name.npos || c == 0)
2166 goto guess_library;
2167 V = Name.slice(c+1, Name.npos);
2168 if (!V.startswith("Versions/"))
2169 goto guess_library;
2170 d = Name.rfind('/', c);
2171 if (d == Name.npos)
2172 Idx = 0;
2173 else
2174 Idx = d+1;
2175 F = Name.slice(Idx, Idx + Foo.size());
2176 DotFramework = Name.slice(Idx + Foo.size(),
2177 Idx + Foo.size() + sizeof(".framework/")-1);
2178 if (F == Foo && DotFramework == ".framework/") {
2179 isFramework = true;
2180 return Foo;
2181 }
2182
2183guess_library:
2184 // pull off the suffix after the "." and make a point to it
2185 a = Name.rfind('.');
2186 if (a == Name.npos || a == 0)
2187 return StringRef();
2188 Dylib = Name.slice(a, Name.npos);
2189 if (Dylib != ".dylib")
2190 goto guess_qtx;
2191
2192 // First pull off the version letter for the form Foo.A.dylib if any.
2193 if (a >= 3) {
2194 Dot = Name.slice(a-2, a-1);
2195 if (Dot == ".")
2196 a = a - 2;
2197 }
2198
2199 b = Name.rfind('/', a);
2200 if (b == Name.npos)
2201 b = 0;
2202 else
2203 b = b+1;
2204 // ignore any suffix after an underbar like Foo_profile.A.dylib
2205 Idx = Name.find('_', b);
2206 if (Idx != Name.npos && Idx != b) {
2207 Lib = Name.slice(b, Idx);
2208 Suffix = Name.slice(Idx, a);
2209 }
2210 else
2211 Lib = Name.slice(b, a);
2212 // There are incorrect library names of the form:
2213 // libATS.A_profile.dylib so check for these.
2214 if (Lib.size() >= 3) {
2215 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2216 if (Dot == ".")
2217 Lib = Lib.slice(0, Lib.size()-2);
2218 }
2219 return Lib;
2220
2221guess_qtx:
2222 Qtx = Name.slice(a, Name.npos);
2223 if (Qtx != ".qtx")
2224 return StringRef();
2225 b = Name.rfind('/', a);
2226 if (b == Name.npos)
2227 Lib = Name.slice(0, a);
2228 else
2229 Lib = Name.slice(b+1, a);
2230 // There are library names of the form: QT.A.qtx so check for these.
2231 if (Lib.size() >= 3) {
2232 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2233 if (Dot == ".")
2234 Lib = Lib.slice(0, Lib.size()-2);
2235 }
2236 return Lib;
2237}
2238
2239// getLibraryShortNameByIndex() is used to get the short name of the library
2240// for an undefined symbol in a linked Mach-O binary that was linked with the
2241// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2242// It is passed the index (0 - based) of the library as translated from
2243// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002244std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002245 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002246 if (Index >= Libraries.size())
2247 return object_error::parse_failed;
2248
Kevin Enderby980b2582014-06-05 21:21:57 +00002249 // If the cache of LibrariesShortNames is not built up do that first for
2250 // all the Libraries.
2251 if (LibrariesShortNames.size() == 0) {
2252 for (unsigned i = 0; i < Libraries.size(); i++) {
2253 MachO::dylib_command D =
Lang Hames697e7cd2016-12-04 01:56:10 +00002254 getStruct<MachO::dylib_command>(*this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002255 if (D.dylib.name >= D.cmdsize)
2256 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002257 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002258 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002259 if (D.dylib.name+Name.size() >= D.cmdsize)
2260 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002261 StringRef Suffix;
2262 bool isFramework;
2263 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002264 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002265 LibrariesShortNames.push_back(Name);
2266 else
2267 LibrariesShortNames.push_back(shortName);
2268 }
2269 }
2270
2271 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002272 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002273}
2274
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00002275uint32_t MachOObjectFile::getLibraryCount() const {
2276 return Libraries.size();
2277}
2278
Rafael Espindola76ad2322015-07-06 14:55:37 +00002279section_iterator
2280MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2281 DataRefImpl Sec;
2282 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2283 return section_iterator(SectionRef(Sec, this));
2284}
2285
Peter Collingbourne435890a2016-11-22 03:38:40 +00002286basic_symbol_iterator MachOObjectFile::symbol_begin() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002287 DataRefImpl DRI;
2288 MachO::symtab_command Symtab = getSymtabLoadCommand();
2289 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2290 return basic_symbol_iterator(SymbolRef(DRI, this));
2291
Lang Hames36072da2014-05-12 21:39:59 +00002292 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002293}
2294
Peter Collingbourne435890a2016-11-22 03:38:40 +00002295basic_symbol_iterator MachOObjectFile::symbol_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002296 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002297 MachO::symtab_command Symtab = getSymtabLoadCommand();
2298 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002299 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002300
Rafael Espindola75c30362013-04-24 19:47:55 +00002301 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002302 sizeof(MachO::nlist_64) :
2303 sizeof(MachO::nlist);
2304 unsigned Offset = Symtab.symoff +
2305 Symtab.nsyms * SymbolTableEntrySize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002306 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002307 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002308}
2309
Lang Hames36072da2014-05-12 21:39:59 +00002310basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002311 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002312 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002313 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002314 unsigned SymbolTableEntrySize =
2315 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002316 DataRefImpl DRI;
Lang Hames697e7cd2016-12-04 01:56:10 +00002317 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Lang Hames36072da2014-05-12 21:39:59 +00002318 DRI.p += Index * SymbolTableEntrySize;
2319 return basic_symbol_iterator(SymbolRef(DRI, this));
2320}
2321
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002322uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2323 MachO::symtab_command Symtab = getSymtabLoadCommand();
2324 if (!SymtabLoadCmd)
2325 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2326 unsigned SymbolTableEntrySize =
2327 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2328 DataRefImpl DRIstart;
Lang Hames697e7cd2016-12-04 01:56:10 +00002329 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002330 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2331 return Index;
2332}
2333
Rafael Espindolab5155a52014-02-10 20:24:04 +00002334section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002335 DataRefImpl DRI;
2336 return section_iterator(SectionRef(DRI, this));
2337}
2338
Rafael Espindolab5155a52014-02-10 20:24:04 +00002339section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002340 DataRefImpl DRI;
2341 DRI.d.a = Sections.size();
2342 return section_iterator(SectionRef(DRI, this));
2343}
2344
Rafael Espindola56f976f2013-04-18 18:08:55 +00002345uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002346 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002347}
2348
Rafael Espindola56f976f2013-04-18 18:08:55 +00002349StringRef MachOObjectFile::getFileFormatName() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002350 unsigned CPUType = getCPUType(*this);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002351 if (!is64Bit()) {
2352 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002353 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002354 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00002355 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002356 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00002357 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002358 return "Mach-O 32-bit ppc";
2359 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002360 return "Mach-O 32-bit unknown";
2361 }
2362 }
2363
Rafael Espindola56f976f2013-04-18 18:08:55 +00002364 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002365 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002366 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00002367 case llvm::MachO::CPU_TYPE_ARM64:
2368 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00002369 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002370 return "Mach-O 64-bit ppc64";
2371 default:
2372 return "Mach-O 64-bit unknown";
2373 }
2374}
2375
Alexey Samsonove6388e62013-06-18 15:03:28 +00002376Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2377 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002378 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002379 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00002380 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002381 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002382 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002383 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00002384 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002385 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002386 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002387 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00002388 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002389 return Triple::ppc64;
2390 default:
2391 return Triple::UnknownArch;
2392 }
2393}
2394
Tim Northover9e8eb412016-04-22 23:21:13 +00002395Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
Kevin Enderby59343a92016-12-16 22:54:02 +00002396 const char **McpuDefault,
2397 const char **ArchFlag) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002398 if (McpuDefault)
2399 *McpuDefault = nullptr;
Kevin Enderby59343a92016-12-16 22:54:02 +00002400 if (ArchFlag)
2401 *ArchFlag = nullptr;
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002402
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002403 switch (CPUType) {
2404 case MachO::CPU_TYPE_I386:
2405 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2406 case MachO::CPU_SUBTYPE_I386_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002407 if (ArchFlag)
2408 *ArchFlag = "i386";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002409 return Triple("i386-apple-darwin");
2410 default:
2411 return Triple();
2412 }
2413 case MachO::CPU_TYPE_X86_64:
2414 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2415 case MachO::CPU_SUBTYPE_X86_64_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002416 if (ArchFlag)
2417 *ArchFlag = "x86_64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002418 return Triple("x86_64-apple-darwin");
2419 case MachO::CPU_SUBTYPE_X86_64_H:
Kevin Enderby59343a92016-12-16 22:54:02 +00002420 if (ArchFlag)
2421 *ArchFlag = "x86_64h";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002422 return Triple("x86_64h-apple-darwin");
2423 default:
2424 return Triple();
2425 }
2426 case MachO::CPU_TYPE_ARM:
2427 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2428 case MachO::CPU_SUBTYPE_ARM_V4T:
Kevin Enderby59343a92016-12-16 22:54:02 +00002429 if (ArchFlag)
2430 *ArchFlag = "armv4t";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002431 return Triple("armv4t-apple-darwin");
2432 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
Kevin Enderby59343a92016-12-16 22:54:02 +00002433 if (ArchFlag)
2434 *ArchFlag = "armv5e";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002435 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002436 case MachO::CPU_SUBTYPE_ARM_XSCALE:
Kevin Enderby59343a92016-12-16 22:54:02 +00002437 if (ArchFlag)
2438 *ArchFlag = "xscale";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002439 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002440 case MachO::CPU_SUBTYPE_ARM_V6:
Kevin Enderby59343a92016-12-16 22:54:02 +00002441 if (ArchFlag)
2442 *ArchFlag = "armv6";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002443 return Triple("armv6-apple-darwin");
2444 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002445 if (McpuDefault)
2446 *McpuDefault = "cortex-m0";
Kevin Enderby59343a92016-12-16 22:54:02 +00002447 if (ArchFlag)
2448 *ArchFlag = "armv6m";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002449 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002450 case MachO::CPU_SUBTYPE_ARM_V7:
Kevin Enderby59343a92016-12-16 22:54:02 +00002451 if (ArchFlag)
2452 *ArchFlag = "armv7";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002453 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002454 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002455 if (McpuDefault)
2456 *McpuDefault = "cortex-m4";
Kevin Enderby59343a92016-12-16 22:54:02 +00002457 if (ArchFlag)
2458 *ArchFlag = "armv7em";
Tim Northover9e8eb412016-04-22 23:21:13 +00002459 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002460 case MachO::CPU_SUBTYPE_ARM_V7K:
Kevin Enderby7a165752017-01-24 23:41:04 +00002461 if (McpuDefault)
2462 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002463 if (ArchFlag)
2464 *ArchFlag = "armv7k";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002465 return Triple("armv7k-apple-darwin");
2466 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002467 if (McpuDefault)
2468 *McpuDefault = "cortex-m3";
Kevin Enderby59343a92016-12-16 22:54:02 +00002469 if (ArchFlag)
2470 *ArchFlag = "armv7m";
Tim Northover9e8eb412016-04-22 23:21:13 +00002471 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002472 case MachO::CPU_SUBTYPE_ARM_V7S:
Kevin Enderby7a165752017-01-24 23:41:04 +00002473 if (McpuDefault)
2474 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002475 if (ArchFlag)
2476 *ArchFlag = "armv7s";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002477 return Triple("armv7s-apple-darwin");
2478 default:
2479 return Triple();
2480 }
2481 case MachO::CPU_TYPE_ARM64:
2482 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2483 case MachO::CPU_SUBTYPE_ARM64_ALL:
Kevin Enderbydc412cc2017-02-10 19:27:10 +00002484 if (McpuDefault)
2485 *McpuDefault = "cyclone";
Kevin Enderby59343a92016-12-16 22:54:02 +00002486 if (ArchFlag)
2487 *ArchFlag = "arm64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002488 return Triple("arm64-apple-darwin");
2489 default:
2490 return Triple();
2491 }
2492 case MachO::CPU_TYPE_POWERPC:
2493 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2494 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002495 if (ArchFlag)
2496 *ArchFlag = "ppc";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002497 return Triple("ppc-apple-darwin");
2498 default:
2499 return Triple();
2500 }
2501 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002502 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002503 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002504 if (ArchFlag)
2505 *ArchFlag = "ppc64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002506 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002507 default:
2508 return Triple();
2509 }
2510 default:
2511 return Triple();
2512 }
2513}
2514
2515Triple MachOObjectFile::getHostArch() {
2516 return Triple(sys::getDefaultTargetTriple());
2517}
2518
Rafael Espindola72318b42014-08-08 16:30:17 +00002519bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2520 return StringSwitch<bool>(ArchFlag)
2521 .Case("i386", true)
2522 .Case("x86_64", true)
2523 .Case("x86_64h", true)
2524 .Case("armv4t", true)
2525 .Case("arm", true)
2526 .Case("armv5e", true)
2527 .Case("armv6", true)
2528 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002529 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002530 .Case("armv7em", true)
2531 .Case("armv7k", true)
2532 .Case("armv7m", true)
2533 .Case("armv7s", true)
2534 .Case("arm64", true)
2535 .Case("ppc", true)
2536 .Case("ppc64", true)
2537 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002538}
2539
Alexey Samsonove6388e62013-06-18 15:03:28 +00002540unsigned MachOObjectFile::getArch() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002541 return getArch(getCPUType(*this));
Alexey Samsonove6388e62013-06-18 15:03:28 +00002542}
2543
Tim Northover9e8eb412016-04-22 23:21:13 +00002544Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2545 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002546}
2547
Rui Ueyamabc654b12013-09-27 21:47:05 +00002548relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002549 DataRefImpl DRI;
2550 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002551 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002552}
2553
Rui Ueyamabc654b12013-09-27 21:47:05 +00002554relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002555 DataRefImpl DRI;
2556 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002557 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002558}
2559
Kevin Enderby273ae012013-06-06 17:20:50 +00002560dice_iterator MachOObjectFile::begin_dices() const {
2561 DataRefImpl DRI;
2562 if (!DataInCodeLoadCmd)
2563 return dice_iterator(DiceRef(DRI, this));
2564
Charles Davis8bdfafd2013-09-01 04:28:48 +00002565 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
Lang Hames697e7cd2016-12-04 01:56:10 +00002566 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002567 return dice_iterator(DiceRef(DRI, this));
2568}
2569
2570dice_iterator MachOObjectFile::end_dices() const {
2571 DataRefImpl DRI;
2572 if (!DataInCodeLoadCmd)
2573 return dice_iterator(DiceRef(DRI, this));
2574
Charles Davis8bdfafd2013-09-01 04:28:48 +00002575 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2576 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002577 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Kevin Enderby273ae012013-06-06 17:20:50 +00002578 return dice_iterator(DiceRef(DRI, this));
2579}
2580
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002581ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
2582 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002583
2584void ExportEntry::moveToFirst() {
2585 pushNode(0);
2586 pushDownUntilBottom();
2587}
2588
2589void ExportEntry::moveToEnd() {
2590 Stack.clear();
2591 Done = true;
2592}
2593
2594bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002595 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002596 if (Done || Other.Done)
2597 return (Done == Other.Done);
2598 // Not equal if different stack sizes.
2599 if (Stack.size() != Other.Stack.size())
2600 return false;
2601 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002602 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002603 return false;
2604 // Equal if all nodes in both stacks match.
2605 for (unsigned i=0; i < Stack.size(); ++i) {
2606 if (Stack[i].Start != Other.Stack[i].Start)
2607 return false;
2608 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002609 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002610}
2611
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002612uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
2613 unsigned Count;
2614 uint64_t Result = decodeULEB128(Ptr, &Count);
2615 Ptr += Count;
2616 if (Ptr > Trie.end()) {
2617 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002618 Malformed = true;
2619 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002620 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002621}
2622
2623StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002624 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002625}
2626
2627uint64_t ExportEntry::flags() const {
2628 return Stack.back().Flags;
2629}
2630
2631uint64_t ExportEntry::address() const {
2632 return Stack.back().Address;
2633}
2634
2635uint64_t ExportEntry::other() const {
2636 return Stack.back().Other;
2637}
2638
2639StringRef ExportEntry::otherName() const {
2640 const char* ImportName = Stack.back().ImportName;
2641 if (ImportName)
2642 return StringRef(ImportName);
2643 return StringRef();
2644}
2645
2646uint32_t ExportEntry::nodeOffset() const {
2647 return Stack.back().Start - Trie.begin();
2648}
2649
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002650ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2651 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
2652 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
2653 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002654
2655void ExportEntry::pushNode(uint64_t offset) {
2656 const uint8_t *Ptr = Trie.begin() + offset;
2657 NodeState State(Ptr);
2658 uint64_t ExportInfoSize = readULEB128(State.Current);
2659 State.IsExportNode = (ExportInfoSize != 0);
2660 const uint8_t* Children = State.Current + ExportInfoSize;
2661 if (State.IsExportNode) {
2662 State.Flags = readULEB128(State.Current);
2663 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2664 State.Address = 0;
2665 State.Other = readULEB128(State.Current); // dylib ordinal
2666 State.ImportName = reinterpret_cast<const char*>(State.Current);
2667 } else {
2668 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00002669 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002670 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002671 }
2672 }
2673 State.ChildCount = *Children;
2674 State.Current = Children + 1;
2675 State.NextChildIndex = 0;
2676 State.ParentStringLength = CumulativeString.size();
2677 Stack.push_back(State);
2678}
2679
2680void ExportEntry::pushDownUntilBottom() {
2681 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2682 NodeState &Top = Stack.back();
2683 CumulativeString.resize(Top.ParentStringLength);
2684 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002685 char C = *Top.Current;
2686 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002687 }
2688 Top.Current += 1;
2689 uint64_t childNodeIndex = readULEB128(Top.Current);
2690 Top.NextChildIndex += 1;
2691 pushNode(childNodeIndex);
2692 }
2693 if (!Stack.back().IsExportNode) {
2694 Malformed = true;
2695 moveToEnd();
2696 }
2697}
2698
2699// We have a trie data structure and need a way to walk it that is compatible
2700// with the C++ iterator model. The solution is a non-recursive depth first
2701// traversal where the iterator contains a stack of parent nodes along with a
2702// string that is the accumulation of all edge strings along the parent chain
2703// to this point.
2704//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002705// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002706// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002707// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002708//
2709// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2710// child until hitting a node with no children (which is an export node or
2711// else the trie is malformed). On the way down, each node is pushed on the
2712// stack ivar. If there is no more ways down, it pops up one and tries to go
2713// down a sibling path until a childless node is reached.
2714void ExportEntry::moveNext() {
2715 if (Stack.empty() || !Stack.back().IsExportNode) {
2716 Malformed = true;
2717 moveToEnd();
2718 return;
2719 }
2720
2721 Stack.pop_back();
2722 while (!Stack.empty()) {
2723 NodeState &Top = Stack.back();
2724 if (Top.NextChildIndex < Top.ChildCount) {
2725 pushDownUntilBottom();
2726 // Now at the next export node.
2727 return;
2728 } else {
2729 if (Top.IsExportNode) {
2730 // This node has no children but is itself an export node.
2731 CumulativeString.resize(Top.ParentStringLength);
2732 return;
2733 }
2734 Stack.pop_back();
2735 }
2736 }
2737 Done = true;
2738}
2739
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002740iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00002741MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
2742 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002743 if (Trie.size() == 0)
2744 Start.moveToEnd();
2745 else
2746 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002747
2748 ExportEntry Finish(Trie);
2749 Finish.moveToEnd();
2750
Craig Topper15576e12015-12-06 05:08:07 +00002751 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002752}
2753
2754iterator_range<export_iterator> MachOObjectFile::exports() const {
2755 return exports(getDyldInfoExportsTrie());
2756}
2757
Kevin Enderbya8d256c2017-03-20 19:46:55 +00002758MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
2759 ArrayRef<uint8_t> Bytes, bool is64Bit)
2760 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0),
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002761 SegmentIndex(-1), RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2762 PointerSize(is64Bit ? 8 : 4), Done(false) {}
Nick Kledzikac431442014-09-12 21:34:15 +00002763
2764void MachORebaseEntry::moveToFirst() {
2765 Ptr = Opcodes.begin();
2766 moveNext();
2767}
2768
2769void MachORebaseEntry::moveToEnd() {
2770 Ptr = Opcodes.end();
2771 RemainingLoopCount = 0;
2772 Done = true;
2773}
2774
2775void MachORebaseEntry::moveNext() {
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002776 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikac431442014-09-12 21:34:15 +00002777 // If in the middle of some loop, move to next rebasing in loop.
2778 SegmentOffset += AdvanceAmount;
2779 if (RemainingLoopCount) {
2780 --RemainingLoopCount;
2781 return;
2782 }
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002783 if (Ptr >= Opcodes.end()) {
2784 if (Opcodes.begin() != Opcodes.end() && Done != true) {
2785 *E = malformedError("missing REBASE_OPCODE_DONE at end of opcodes");
2786 moveToEnd();
2787 return;
2788 }
Nick Kledzikac431442014-09-12 21:34:15 +00002789 Done = true;
2790 return;
2791 }
2792 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002793 while (More) {
Nick Kledzikac431442014-09-12 21:34:15 +00002794 // Parse next opcode and set up next loop.
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002795 const uint8_t *OpcodeStart = Ptr;
Nick Kledzikac431442014-09-12 21:34:15 +00002796 uint8_t Byte = *Ptr++;
2797 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2798 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002799 uint32_t Count, Skip;
2800 const char *error = nullptr;
Nick Kledzikac431442014-09-12 21:34:15 +00002801 switch (Opcode) {
2802 case MachO::REBASE_OPCODE_DONE:
2803 More = false;
2804 Done = true;
2805 moveToEnd();
2806 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
2807 break;
2808 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2809 RebaseType = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002810 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
2811 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
2812 Twine((int)RebaseType) + " for opcode at: 0x" +
2813 utohexstr(OpcodeStart - Opcodes.begin()));
2814 moveToEnd();
2815 return;
2816 }
Nick Kledzikac431442014-09-12 21:34:15 +00002817 DEBUG_WITH_TYPE(
2818 "mach-o-rebase",
2819 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2820 << "RebaseType=" << (int) RebaseType << "\n");
2821 break;
2822 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2823 SegmentIndex = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002824 SegmentOffset = readULEB128(&error);
2825 if (error) {
2826 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
2827 Twine(error) + " for opcode at: 0x" +
2828 utohexstr(OpcodeStart - Opcodes.begin()));
2829 moveToEnd();
2830 return;
2831 }
2832 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2833 true);
2834 if (error) {
2835 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
2836 Twine(error) + " for opcode at: 0x" +
2837 utohexstr(OpcodeStart - Opcodes.begin()));
2838 moveToEnd();
2839 return;
2840 }
Nick Kledzikac431442014-09-12 21:34:15 +00002841 DEBUG_WITH_TYPE(
2842 "mach-o-rebase",
2843 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2844 << "SegmentIndex=" << SegmentIndex << ", "
2845 << format("SegmentOffset=0x%06X", SegmentOffset)
2846 << "\n");
2847 break;
2848 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002849 SegmentOffset += readULEB128(&error);
2850 if (error) {
2851 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
2852 Twine(error) + " for opcode at: 0x" +
2853 utohexstr(OpcodeStart - Opcodes.begin()));
2854 moveToEnd();
2855 return;
2856 }
2857 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2858 true);
2859 if (error) {
2860 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
2861 Twine(error) + " for opcode at: 0x" +
2862 utohexstr(OpcodeStart - Opcodes.begin()));
2863 moveToEnd();
2864 return;
2865 }
Nick Kledzikac431442014-09-12 21:34:15 +00002866 DEBUG_WITH_TYPE("mach-o-rebase",
2867 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
2868 << format("SegmentOffset=0x%06X",
2869 SegmentOffset) << "\n");
2870 break;
2871 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002872 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2873 true);
2874 if (error) {
2875 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
2876 Twine(error) + " for opcode at: 0x" +
2877 utohexstr(OpcodeStart - Opcodes.begin()));
2878 moveToEnd();
2879 return;
2880 }
Nick Kledzikac431442014-09-12 21:34:15 +00002881 SegmentOffset += ImmValue * PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002882 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2883 false);
2884 if (error) {
2885 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
2886 " (after adding immediate times the pointer size) " +
2887 Twine(error) + " for opcode at: 0x" +
2888 utohexstr(OpcodeStart - Opcodes.begin()));
2889 moveToEnd();
2890 return;
2891 }
Nick Kledzikac431442014-09-12 21:34:15 +00002892 DEBUG_WITH_TYPE("mach-o-rebase",
2893 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
2894 << format("SegmentOffset=0x%06X",
2895 SegmentOffset) << "\n");
2896 break;
2897 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002898 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2899 true);
2900 if (error) {
2901 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
2902 Twine(error) + " for opcode at: 0x" +
2903 utohexstr(OpcodeStart - Opcodes.begin()));
2904 moveToEnd();
2905 return;
2906 }
Nick Kledzikac431442014-09-12 21:34:15 +00002907 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002908 Skip = 0;
2909 Count = ImmValue;
2910 if (ImmValue != 0)
2911 RemainingLoopCount = ImmValue - 1;
2912 else
2913 RemainingLoopCount = 0;
2914 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2915 SegmentIndex, SegmentOffset);
2916 if (error) {
2917 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES "
2918 + Twine(error) + " for opcode at: 0x" +
2919 utohexstr(OpcodeStart - Opcodes.begin()));
2920 moveToEnd();
2921 return;
2922 }
Nick Kledzikac431442014-09-12 21:34:15 +00002923 DEBUG_WITH_TYPE(
2924 "mach-o-rebase",
2925 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
2926 << format("SegmentOffset=0x%06X", SegmentOffset)
2927 << ", AdvanceAmount=" << AdvanceAmount
2928 << ", RemainingLoopCount=" << RemainingLoopCount
2929 << "\n");
2930 return;
2931 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002932 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2933 true);
2934 if (error) {
2935 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
2936 Twine(error) + " for opcode at: 0x" +
2937 utohexstr(OpcodeStart - Opcodes.begin()));
2938 moveToEnd();
2939 return;
2940 }
Nick Kledzikac431442014-09-12 21:34:15 +00002941 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002942 Skip = 0;
2943 Count = readULEB128(&error);
2944 if (error) {
2945 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
2946 Twine(error) + " for opcode at: 0x" +
2947 utohexstr(OpcodeStart - Opcodes.begin()));
2948 moveToEnd();
2949 return;
2950 }
2951 if (Count != 0)
2952 RemainingLoopCount = Count - 1;
2953 else
2954 RemainingLoopCount = 0;
2955 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2956 SegmentIndex, SegmentOffset);
2957 if (error) {
2958 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES "
2959 + Twine(error) + " for opcode at: 0x" +
2960 utohexstr(OpcodeStart - Opcodes.begin()));
2961 moveToEnd();
2962 return;
2963 }
Nick Kledzikac431442014-09-12 21:34:15 +00002964 DEBUG_WITH_TYPE(
2965 "mach-o-rebase",
2966 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
2967 << format("SegmentOffset=0x%06X", SegmentOffset)
2968 << ", AdvanceAmount=" << AdvanceAmount
2969 << ", RemainingLoopCount=" << RemainingLoopCount
2970 << "\n");
2971 return;
2972 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002973 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2974 true);
2975 if (error) {
2976 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
2977 Twine(error) + " for opcode at: 0x" +
2978 utohexstr(OpcodeStart - Opcodes.begin()));
2979 moveToEnd();
2980 return;
2981 }
2982 Skip = readULEB128(&error);
2983 if (error) {
2984 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
2985 Twine(error) + " for opcode at: 0x" +
2986 utohexstr(OpcodeStart - Opcodes.begin()));
2987 moveToEnd();
2988 return;
2989 }
2990 AdvanceAmount = Skip + PointerSize;
2991 Count = 1;
Nick Kledzikac431442014-09-12 21:34:15 +00002992 RemainingLoopCount = 0;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002993 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2994 SegmentIndex, SegmentOffset);
2995 if (error) {
2996 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB "
2997 + Twine(error) + " for opcode at: 0x" +
2998 utohexstr(OpcodeStart - Opcodes.begin()));
2999 moveToEnd();
3000 return;
3001 }
Nick Kledzikac431442014-09-12 21:34:15 +00003002 DEBUG_WITH_TYPE(
3003 "mach-o-rebase",
3004 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3005 << format("SegmentOffset=0x%06X", SegmentOffset)
3006 << ", AdvanceAmount=" << AdvanceAmount
3007 << ", RemainingLoopCount=" << RemainingLoopCount
3008 << "\n");
3009 return;
3010 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003011 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3012 true);
3013 if (error) {
3014 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3015 "ULEB " + Twine(error) + " for opcode at: 0x" +
3016 utohexstr(OpcodeStart - Opcodes.begin()));
3017 moveToEnd();
3018 return;
3019 }
3020 Count = readULEB128(&error);
3021 if (error) {
3022 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3023 "ULEB " + Twine(error) + " for opcode at: 0x" +
3024 utohexstr(OpcodeStart - Opcodes.begin()));
3025 moveToEnd();
3026 return;
3027 }
3028 if (Count != 0)
3029 RemainingLoopCount = Count - 1;
3030 else
3031 RemainingLoopCount = 0;
3032 Skip = readULEB128(&error);
3033 if (error) {
3034 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3035 "ULEB " + Twine(error) + " for opcode at: 0x" +
3036 utohexstr(OpcodeStart - Opcodes.begin()));
3037 moveToEnd();
3038 return;
3039 }
3040 AdvanceAmount = Skip + PointerSize;
3041
3042 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3043 SegmentIndex, SegmentOffset);
3044 if (error) {
3045 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3046 "ULEB " + Twine(error) + " for opcode at: 0x" +
3047 utohexstr(OpcodeStart - Opcodes.begin()));
3048 moveToEnd();
3049 return;
3050 }
Nick Kledzikac431442014-09-12 21:34:15 +00003051 DEBUG_WITH_TYPE(
3052 "mach-o-rebase",
3053 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3054 << format("SegmentOffset=0x%06X", SegmentOffset)
3055 << ", AdvanceAmount=" << AdvanceAmount
3056 << ", RemainingLoopCount=" << RemainingLoopCount
3057 << "\n");
3058 return;
3059 default:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003060 *E = malformedError("bad rebase info (bad opcode value 0x" +
3061 utohexstr(Opcode) + " for opcode at: 0x" +
3062 utohexstr(OpcodeStart - Opcodes.begin()));
3063 moveToEnd();
3064 return;
Nick Kledzikac431442014-09-12 21:34:15 +00003065 }
3066 }
3067}
3068
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003069uint64_t MachORebaseEntry::readULEB128(const char **error) {
Nick Kledzikac431442014-09-12 21:34:15 +00003070 unsigned Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003071 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzikac431442014-09-12 21:34:15 +00003072 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003073 if (Ptr > Opcodes.end())
Nick Kledzikac431442014-09-12 21:34:15 +00003074 Ptr = Opcodes.end();
Nick Kledzikac431442014-09-12 21:34:15 +00003075 return Result;
3076}
3077
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003078int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzikac431442014-09-12 21:34:15 +00003079
3080uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3081
3082StringRef MachORebaseEntry::typeName() const {
3083 switch (RebaseType) {
3084 case MachO::REBASE_TYPE_POINTER:
3085 return "pointer";
3086 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3087 return "text abs32";
3088 case MachO::REBASE_TYPE_TEXT_PCREL32:
3089 return "text rel32";
3090 }
3091 return "unknown";
3092}
3093
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003094// For use with the SegIndex of a checked Mach-O Rebase entry
3095// to get the segment name.
3096StringRef MachORebaseEntry::segmentName() const {
3097 return O->BindRebaseSegmentName(SegmentIndex);
3098}
3099
3100// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3101// to get the section name.
3102StringRef MachORebaseEntry::sectionName() const {
3103 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3104}
3105
3106// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3107// to get the address.
3108uint64_t MachORebaseEntry::address() const {
3109 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3110}
3111
Nick Kledzikac431442014-09-12 21:34:15 +00003112bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003113#ifdef EXPENSIVE_CHECKS
Nick Kledzikac431442014-09-12 21:34:15 +00003114 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003115#else
3116 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3117#endif
Nick Kledzikac431442014-09-12 21:34:15 +00003118 return (Ptr == Other.Ptr) &&
3119 (RemainingLoopCount == Other.RemainingLoopCount) &&
3120 (Done == Other.Done);
3121}
3122
3123iterator_range<rebase_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003124MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3125 ArrayRef<uint8_t> Opcodes, bool is64) {
3126 if (O->BindRebaseSectionTable == nullptr)
3127 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3128 MachORebaseEntry Start(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003129 Start.moveToFirst();
3130
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003131 MachORebaseEntry Finish(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003132 Finish.moveToEnd();
3133
Craig Topper15576e12015-12-06 05:08:07 +00003134 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00003135}
3136
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003137iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3138 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
Nick Kledzikac431442014-09-12 21:34:15 +00003139}
3140
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003141MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3142 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003143 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0),
3144 SegmentIndex(-1), LibraryOrdinalSet(false), Ordinal(0), Flags(0),
3145 Addend(0), RemainingLoopCount(0), AdvanceAmount(0), BindType(0),
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003146 PointerSize(is64Bit ? 8 : 4), TableKind(BK), Done(false) {}
Nick Kledzik56ebef42014-09-16 01:41:51 +00003147
3148void MachOBindEntry::moveToFirst() {
3149 Ptr = Opcodes.begin();
3150 moveNext();
3151}
3152
3153void MachOBindEntry::moveToEnd() {
3154 Ptr = Opcodes.end();
3155 RemainingLoopCount = 0;
3156 Done = true;
3157}
3158
3159void MachOBindEntry::moveNext() {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003160 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003161 // If in the middle of some loop, move to next binding in loop.
3162 SegmentOffset += AdvanceAmount;
3163 if (RemainingLoopCount) {
3164 --RemainingLoopCount;
3165 return;
3166 }
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003167 if (Ptr >= Opcodes.end()) {
3168 if (Opcodes.begin() != Opcodes.end() && Done != true) {
3169 *E = malformedError("missing BIND_OPCODE_DONE at end of opcodes");
3170 moveToEnd();
3171 return;
3172 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003173 Done = true;
3174 return;
3175 }
3176 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003177 while (More) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003178 // Parse next opcode and set up next loop.
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003179 const uint8_t *OpcodeStart = Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003180 uint8_t Byte = *Ptr++;
3181 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3182 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3183 int8_t SignExtended;
3184 const uint8_t *SymStart;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003185 uint32_t Count, Skip;
3186 const char *error = nullptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003187 switch (Opcode) {
3188 case MachO::BIND_OPCODE_DONE:
3189 if (TableKind == Kind::Lazy) {
3190 // Lazying bindings have a DONE opcode between entries. Need to ignore
3191 // it to advance to next entry. But need not if this is last entry.
3192 bool NotLastEntry = false;
3193 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3194 if (*P) {
3195 NotLastEntry = true;
3196 }
3197 }
3198 if (NotLastEntry)
3199 break;
3200 }
3201 More = false;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003202 moveToEnd();
3203 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
3204 break;
3205 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003206 if (TableKind == Kind::Weak) {
3207 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3208 "weak bind table for opcode at: 0x" +
3209 utohexstr(OpcodeStart - Opcodes.begin()));
3210 moveToEnd();
3211 return;
3212 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003213 Ordinal = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003214 LibraryOrdinalSet = true;
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003215 if (ImmValue > O->getLibraryCount()) {
3216 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3217 "library ordinal: " + Twine((int)ImmValue) + " (max " +
3218 Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
3219 utohexstr(OpcodeStart - Opcodes.begin()));
3220 moveToEnd();
3221 return;
3222 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003223 DEBUG_WITH_TYPE(
3224 "mach-o-bind",
3225 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3226 << "Ordinal=" << Ordinal << "\n");
3227 break;
3228 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003229 if (TableKind == Kind::Weak) {
3230 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3231 "weak bind table for opcode at: 0x" +
3232 utohexstr(OpcodeStart - Opcodes.begin()));
3233 moveToEnd();
3234 return;
3235 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003236 Ordinal = readULEB128(&error);
3237 LibraryOrdinalSet = true;
3238 if (error) {
3239 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3240 Twine(error) + " for opcode at: 0x" +
3241 utohexstr(OpcodeStart - Opcodes.begin()));
3242 moveToEnd();
3243 return;
3244 }
3245 if (Ordinal > (int)O->getLibraryCount()) {
3246 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3247 "library ordinal: " + Twine((int)Ordinal) + " (max " +
3248 Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
3249 utohexstr(OpcodeStart - Opcodes.begin()));
3250 moveToEnd();
3251 return;
3252 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003253 DEBUG_WITH_TYPE(
3254 "mach-o-bind",
3255 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3256 << "Ordinal=" << Ordinal << "\n");
3257 break;
3258 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003259 if (TableKind == Kind::Weak) {
3260 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3261 "weak bind table for opcode at: 0x" +
3262 utohexstr(OpcodeStart - Opcodes.begin()));
3263 moveToEnd();
3264 return;
3265 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003266 if (ImmValue) {
3267 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3268 Ordinal = SignExtended;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003269 LibraryOrdinalSet = true;
3270 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3271 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3272 "special ordinal: " + Twine((int)Ordinal) + " for opcode at: "
3273 "0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3274 moveToEnd();
3275 return;
3276 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003277 } else
3278 Ordinal = 0;
3279 DEBUG_WITH_TYPE(
3280 "mach-o-bind",
3281 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3282 << "Ordinal=" << Ordinal << "\n");
3283 break;
3284 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3285 Flags = ImmValue;
3286 SymStart = Ptr;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003287 while (*Ptr && (Ptr < Opcodes.end())) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003288 ++Ptr;
3289 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003290 if (Ptr == Opcodes.end()) {
3291 *E = malformedError("for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3292 "symbol name extends past opcodes for opcode at: 0x" +
3293 utohexstr(OpcodeStart - Opcodes.begin()));
3294 moveToEnd();
3295 return;
3296 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003297 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3298 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00003299 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003300 DEBUG_WITH_TYPE(
3301 "mach-o-bind",
3302 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3303 << "SymbolName=" << SymbolName << "\n");
3304 if (TableKind == Kind::Weak) {
3305 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3306 return;
3307 }
3308 break;
3309 case MachO::BIND_OPCODE_SET_TYPE_IMM:
3310 BindType = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003311 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
3312 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3313 Twine((int)ImmValue) + " for opcode at: 0x" +
3314 utohexstr(OpcodeStart - Opcodes.begin()));
3315 moveToEnd();
3316 return;
3317 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003318 DEBUG_WITH_TYPE(
3319 "mach-o-bind",
3320 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3321 << "BindType=" << (int)BindType << "\n");
3322 break;
3323 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003324 Addend = readSLEB128(&error);
3325 if (error) {
3326 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " +
3327 Twine(error) + " for opcode at: 0x" +
3328 utohexstr(OpcodeStart - Opcodes.begin()));
3329 moveToEnd();
3330 return;
3331 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003332 DEBUG_WITH_TYPE(
3333 "mach-o-bind",
3334 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3335 << "Addend=" << Addend << "\n");
3336 break;
3337 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3338 SegmentIndex = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003339 SegmentOffset = readULEB128(&error);
3340 if (error) {
3341 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3342 Twine(error) + " for opcode at: 0x" +
3343 utohexstr(OpcodeStart - Opcodes.begin()));
3344 moveToEnd();
3345 return;
3346 }
3347 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3348 if (error) {
3349 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3350 Twine(error) + " for opcode at: 0x" +
3351 utohexstr(OpcodeStart - Opcodes.begin()));
3352 moveToEnd();
3353 return;
3354 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003355 DEBUG_WITH_TYPE(
3356 "mach-o-bind",
3357 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3358 << "SegmentIndex=" << SegmentIndex << ", "
3359 << format("SegmentOffset=0x%06X", SegmentOffset)
3360 << "\n");
3361 break;
3362 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003363 SegmentOffset += readULEB128(&error);
3364 if (error) {
3365 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
3366 Twine(error) + " for opcode at: 0x" +
3367 utohexstr(OpcodeStart - Opcodes.begin()));
3368 moveToEnd();
3369 return;
3370 }
3371 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3372 if (error) {
3373 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
3374 Twine(error) + " for opcode at: 0x" +
3375 utohexstr(OpcodeStart - Opcodes.begin()));
3376 moveToEnd();
3377 return;
3378 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003379 DEBUG_WITH_TYPE("mach-o-bind",
3380 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3381 << format("SegmentOffset=0x%06X",
3382 SegmentOffset) << "\n");
3383 break;
3384 case MachO::BIND_OPCODE_DO_BIND:
3385 AdvanceAmount = PointerSize;
3386 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003387 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3388 if (error) {
3389 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
3390 " for opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3391 moveToEnd();
3392 return;
3393 }
3394 if (SymbolName == StringRef()) {
3395 *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3396 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3397 utohexstr(OpcodeStart - Opcodes.begin()));
3398 moveToEnd();
3399 return;
3400 }
3401 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3402 *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3403 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3404 utohexstr(OpcodeStart - Opcodes.begin()));
3405 moveToEnd();
3406 return;
3407 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003408 DEBUG_WITH_TYPE("mach-o-bind",
3409 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
3410 << format("SegmentOffset=0x%06X",
3411 SegmentOffset) << "\n");
3412 return;
3413 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003414 if (TableKind == Kind::Lazy) {
3415 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3416 "lazy bind table for opcode at: 0x" +
3417 utohexstr(OpcodeStart - Opcodes.begin()));
3418 moveToEnd();
3419 return;
3420 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003421 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3422 if (error) {
3423 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3424 Twine(error) + " for opcode at: 0x" +
3425 utohexstr(OpcodeStart - Opcodes.begin()));
3426 moveToEnd();
3427 return;
3428 }
3429 if (SymbolName == StringRef()) {
3430 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3431 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3432 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3433 moveToEnd();
3434 return;
3435 }
3436 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3437 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3438 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3439 utohexstr(OpcodeStart - Opcodes.begin()));
3440 moveToEnd();
3441 return;
3442 }
3443 AdvanceAmount = readULEB128(&error) + PointerSize;
3444 if (error) {
3445 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3446 Twine(error) + " for opcode at: 0x" +
3447 utohexstr(OpcodeStart - Opcodes.begin()));
3448 moveToEnd();
3449 return;
3450 }
3451 // Note, this is not really an error until the next bind but make no sense
3452 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3453 // bind operation.
3454 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3455 AdvanceAmount, false);
3456 if (error) {
3457 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3458 "ULEB) " + Twine(error) + " for opcode at: 0x" +
3459 utohexstr(OpcodeStart - Opcodes.begin()));
3460 moveToEnd();
3461 return;
3462 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003463 RemainingLoopCount = 0;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003464 DEBUG_WITH_TYPE(
3465 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00003466 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00003467 << format("SegmentOffset=0x%06X", SegmentOffset)
3468 << ", AdvanceAmount=" << AdvanceAmount
3469 << ", RemainingLoopCount=" << RemainingLoopCount
3470 << "\n");
3471 return;
3472 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003473 if (TableKind == Kind::Lazy) {
3474 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3475 "allowed in lazy bind table for opcode at: 0x" +
3476 utohexstr(OpcodeStart - Opcodes.begin()));
3477 moveToEnd();
3478 return;
3479 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003480 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3481 if (error) {
3482 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3483 Twine(error) + " for opcode at: 0x" +
3484 utohexstr(OpcodeStart - Opcodes.begin()));
3485 moveToEnd();
3486 return;
3487 }
3488 if (SymbolName == StringRef()) {
3489 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3490 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3491 "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3492 moveToEnd();
3493 return;
3494 }
3495 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3496 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3497 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3498 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3499 moveToEnd();
3500 return;
3501 }
Nick Kledzik3b2aa052014-10-18 01:21:02 +00003502 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003503 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003504 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3505 AdvanceAmount, false);
3506 if (error) {
3507 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3508 " (after adding immediate times the pointer size) " +
3509 Twine(error) + " for opcode at: 0x" +
3510 utohexstr(OpcodeStart - Opcodes.begin()));
3511 moveToEnd();
3512 return;
3513 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003514 DEBUG_WITH_TYPE("mach-o-bind",
3515 llvm::dbgs()
3516 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3517 << format("SegmentOffset=0x%06X",
3518 SegmentOffset) << "\n");
3519 return;
3520 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003521 if (TableKind == Kind::Lazy) {
3522 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3523 "allowed in lazy bind table for opcode at: 0x" +
3524 utohexstr(OpcodeStart - Opcodes.begin()));
3525 moveToEnd();
3526 return;
3527 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003528 Count = readULEB128(&error);
3529 if (Count != 0)
3530 RemainingLoopCount = Count - 1;
3531 else
3532 RemainingLoopCount = 0;
3533 if (error) {
3534 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3535 " (count value) " + Twine(error) + " for opcode at"
3536 ": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3537 moveToEnd();
3538 return;
3539 }
3540 Skip = readULEB128(&error);
3541 AdvanceAmount = Skip + PointerSize;
3542 if (error) {
3543 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3544 " (skip value) " + Twine(error) + " for opcode at"
3545 ": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3546 moveToEnd();
3547 return;
3548 }
3549 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3550 if (error) {
3551 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3552 + Twine(error) + " for opcode at: 0x" +
3553 utohexstr(OpcodeStart - Opcodes.begin()));
3554 moveToEnd();
3555 return;
3556 }
3557 if (SymbolName == StringRef()) {
3558 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3559 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3560 "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3561 moveToEnd();
3562 return;
3563 }
3564 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3565 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3566 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3567 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3568 moveToEnd();
3569 return;
3570 }
3571 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
3572 SegmentIndex, SegmentOffset);
3573 if (error) {
3574 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3575 + Twine(error) + " for opcode at: 0x" +
3576 utohexstr(OpcodeStart - Opcodes.begin()));
3577 moveToEnd();
3578 return;
3579 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003580 DEBUG_WITH_TYPE(
3581 "mach-o-bind",
3582 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3583 << format("SegmentOffset=0x%06X", SegmentOffset)
3584 << ", AdvanceAmount=" << AdvanceAmount
3585 << ", RemainingLoopCount=" << RemainingLoopCount
3586 << "\n");
3587 return;
3588 default:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003589 *E = malformedError("bad bind info (bad opcode value 0x" +
3590 utohexstr(Opcode) + " for opcode at: 0x" +
3591 utohexstr(OpcodeStart - Opcodes.begin()));
3592 moveToEnd();
3593 return;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003594 }
3595 }
3596}
3597
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003598uint64_t MachOBindEntry::readULEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003599 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003600 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003601 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003602 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003603 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003604 return Result;
3605}
3606
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003607int64_t MachOBindEntry::readSLEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003608 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003609 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003610 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003611 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003612 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003613 return Result;
3614}
3615
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003616int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003617
3618uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3619
3620StringRef MachOBindEntry::typeName() const {
3621 switch (BindType) {
3622 case MachO::BIND_TYPE_POINTER:
3623 return "pointer";
3624 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3625 return "text abs32";
3626 case MachO::BIND_TYPE_TEXT_PCREL32:
3627 return "text rel32";
3628 }
3629 return "unknown";
3630}
3631
3632StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3633
3634int64_t MachOBindEntry::addend() const { return Addend; }
3635
3636uint32_t MachOBindEntry::flags() const { return Flags; }
3637
3638int MachOBindEntry::ordinal() const { return Ordinal; }
3639
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003640// For use with the SegIndex of a checked Mach-O Bind entry
3641// to get the segment name.
3642StringRef MachOBindEntry::segmentName() const {
3643 return O->BindRebaseSegmentName(SegmentIndex);
3644}
3645
3646// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3647// to get the section name.
3648StringRef MachOBindEntry::sectionName() const {
3649 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3650}
3651
3652// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3653// to get the address.
3654uint64_t MachOBindEntry::address() const {
3655 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3656}
3657
Nick Kledzik56ebef42014-09-16 01:41:51 +00003658bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003659#ifdef EXPENSIVE_CHECKS
Nick Kledzik56ebef42014-09-16 01:41:51 +00003660 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003661#else
3662 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3663#endif
Nick Kledzik56ebef42014-09-16 01:41:51 +00003664 return (Ptr == Other.Ptr) &&
3665 (RemainingLoopCount == Other.RemainingLoopCount) &&
3666 (Done == Other.Done);
3667}
3668
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003669// Build table of sections so SegIndex/SegOffset pairs can be translated.
3670BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3671 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
3672 StringRef CurSegName;
3673 uint64_t CurSegAddress;
3674 for (const SectionRef &Section : Obj->sections()) {
3675 SectionInfo Info;
3676 Section.getName(Info.SectionName);
3677 Info.Address = Section.getAddress();
3678 Info.Size = Section.getSize();
3679 Info.SegmentName =
3680 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3681 if (!Info.SegmentName.equals(CurSegName)) {
3682 ++CurSegIndex;
3683 CurSegName = Info.SegmentName;
3684 CurSegAddress = Info.Address;
3685 }
3686 Info.SegmentIndex = CurSegIndex - 1;
3687 Info.OffsetInSegment = Info.Address - CurSegAddress;
3688 Info.SegmentStartAddress = CurSegAddress;
3689 Sections.push_back(Info);
3690 }
3691 MaxSegIndex = CurSegIndex;
3692}
3693
3694// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003695// validate a MachOBindEntry or MachORebaseEntry.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003696const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
3697 uint64_t SegOffset,
3698 bool endInvalid) {
3699 if (SegIndex == -1)
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003700 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003701 if (SegIndex >= MaxSegIndex)
3702 return "bad segIndex (too large)";
3703 for (const SectionInfo &SI : Sections) {
3704 if (SI.SegmentIndex != SegIndex)
3705 continue;
3706 if (SI.OffsetInSegment > SegOffset)
3707 continue;
3708 if (SegOffset > (SI.OffsetInSegment + SI.Size))
3709 continue;
3710 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
3711 continue;
3712 return nullptr;
3713 }
3714 return "bad segOffset, too large";
3715}
3716
3717// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003718// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
3719// MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
3720// REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
3721// been already checked.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003722const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
3723 uint8_t PointerSize,
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003724 int32_t SegIndex,
3725 uint64_t SegOffset) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003726 const SectionInfo &SI = findSection(SegIndex, SegOffset);
3727 uint64_t addr = SI.SegmentStartAddress + SegOffset;
3728 if (addr >= SI.Address + SI.Size)
3729 return "bad segOffset, too large";
3730 uint64_t i = 0;
3731 if (Count > 1)
3732 i = (Skip + PointerSize) * (Count - 1);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003733 else if (Count == 1)
3734 i = Skip + PointerSize;
3735 if (addr + i >= SI.Address + SI.Size) {
3736 // For rebase opcodes they can step from one section to another.
3737 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
3738 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
3739 if (error)
3740 return "bad count and skip, too large";
3741 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003742 return nullptr;
3743}
3744
3745// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
3746// to get the segment name.
3747StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
3748 for (const SectionInfo &SI : Sections) {
3749 if (SI.SegmentIndex == SegIndex)
3750 return SI.SegmentName;
3751 }
3752 llvm_unreachable("invalid SegIndex");
3753}
3754
3755// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3756// to get the SectionInfo.
3757const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
3758 int32_t SegIndex, uint64_t SegOffset) {
3759 for (const SectionInfo &SI : Sections) {
3760 if (SI.SegmentIndex != SegIndex)
3761 continue;
3762 if (SI.OffsetInSegment > SegOffset)
3763 continue;
3764 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
3765 continue;
3766 return SI;
3767 }
3768 llvm_unreachable("SegIndex and SegOffset not in any section");
3769}
3770
3771// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3772// entry to get the section name.
3773StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
3774 uint64_t SegOffset) {
3775 return findSection(SegIndex, SegOffset).SectionName;
3776}
3777
3778// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3779// entry to get the address.
3780uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
3781 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
3782 return SI.SegmentStartAddress + OffsetInSeg;
3783}
3784
Nick Kledzik56ebef42014-09-16 01:41:51 +00003785iterator_range<bind_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003786MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003787 ArrayRef<uint8_t> Opcodes, bool is64,
Nick Kledzik56ebef42014-09-16 01:41:51 +00003788 MachOBindEntry::Kind BKind) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003789 if (O->BindRebaseSectionTable == nullptr)
3790 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003791 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003792 Start.moveToFirst();
3793
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003794 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003795 Finish.moveToEnd();
3796
Craig Topper15576e12015-12-06 05:08:07 +00003797 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00003798}
3799
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003800iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003801 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00003802 MachOBindEntry::Kind::Regular);
3803}
3804
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003805iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003806 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00003807 MachOBindEntry::Kind::Lazy);
3808}
3809
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003810iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003811 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00003812 MachOBindEntry::Kind::Weak);
3813}
3814
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00003815MachOObjectFile::load_command_iterator
3816MachOObjectFile::begin_load_commands() const {
3817 return LoadCommands.begin();
3818}
3819
3820MachOObjectFile::load_command_iterator
3821MachOObjectFile::end_load_commands() const {
3822 return LoadCommands.end();
3823}
3824
3825iterator_range<MachOObjectFile::load_command_iterator>
3826MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00003827 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00003828}
3829
Rafael Espindola56f976f2013-04-18 18:08:55 +00003830StringRef
3831MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
3832 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
3833 return parseSegmentOrSectionName(Raw.data());
3834}
3835
3836ArrayRef<char>
3837MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00003838 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003839 const section_base *Base =
3840 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00003841 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003842}
3843
3844ArrayRef<char>
3845MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00003846 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003847 const section_base *Base =
3848 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00003849 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003850}
3851
3852bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00003853MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00003854 const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003855 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00003856 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00003857 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003858}
3859
Eric Christopher1d62c252013-07-22 22:25:07 +00003860unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003861 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003862 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00003863 return RE.r_word1 & 0xffffff;
3864 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003865}
3866
Eric Christopher1d62c252013-07-22 22:25:07 +00003867bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003868 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003869 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00003870 return (RE.r_word1 >> 27) & 1;
3871 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003872}
3873
Eric Christopher1d62c252013-07-22 22:25:07 +00003874bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003875 const MachO::any_relocation_info &RE) const {
3876 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003877}
3878
Eric Christopher1d62c252013-07-22 22:25:07 +00003879uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003880 const MachO::any_relocation_info &RE) const {
3881 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003882}
3883
Kevin Enderby9907d0a2014-11-04 00:43:16 +00003884uint32_t MachOObjectFile::getScatteredRelocationType(
3885 const MachO::any_relocation_info &RE) const {
3886 return (RE.r_word0 >> 24) & 0xf;
3887}
3888
Eric Christopher1d62c252013-07-22 22:25:07 +00003889unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003890 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003891 if (isRelocationScattered(RE))
3892 return getScatteredRelocationAddress(RE);
3893 return getPlainRelocationAddress(RE);
3894}
3895
Charles Davis8bdfafd2013-09-01 04:28:48 +00003896unsigned MachOObjectFile::getAnyRelocationPCRel(
3897 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003898 if (isRelocationScattered(RE))
Lang Hames697e7cd2016-12-04 01:56:10 +00003899 return getScatteredRelocationPCRel(RE);
3900 return getPlainRelocationPCRel(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003901}
3902
Eric Christopher1d62c252013-07-22 22:25:07 +00003903unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003904 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003905 if (isRelocationScattered(RE))
3906 return getScatteredRelocationLength(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00003907 return getPlainRelocationLength(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003908}
3909
3910unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00003911MachOObjectFile::getAnyRelocationType(
3912 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003913 if (isRelocationScattered(RE))
3914 return getScatteredRelocationType(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00003915 return getPlainRelocationType(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003916}
3917
Rafael Espindola52501032013-04-30 15:40:54 +00003918SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00003919MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003920 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00003921 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00003922 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00003923 unsigned SecNum = getPlainRelocationSymbolNum(RE);
3924 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
3925 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00003926 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00003927 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00003928 return SectionRef(DRI, this);
3929}
3930
Charles Davis8bdfafd2013-09-01 04:28:48 +00003931MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00003932 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00003933 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003934}
3935
Charles Davis8bdfafd2013-09-01 04:28:48 +00003936MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00003937 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00003938 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003939}
3940
Charles Davis8bdfafd2013-09-01 04:28:48 +00003941MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00003942 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003943 const char *Sec = getSectionPtr(*this, L, Index);
3944 return getStruct<MachO::section>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003945}
3946
Charles Davis8bdfafd2013-09-01 04:28:48 +00003947MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
3948 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003949 const char *Sec = getSectionPtr(*this, L, Index);
3950 return getStruct<MachO::section_64>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003951}
3952
Charles Davis8bdfafd2013-09-01 04:28:48 +00003953MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00003954MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00003955 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00003956 return getStruct<MachO::nlist>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003957}
3958
Charles Davis8bdfafd2013-09-01 04:28:48 +00003959MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00003960MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00003961 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00003962 return getStruct<MachO::nlist_64>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003963}
3964
Charles Davis8bdfafd2013-09-01 04:28:48 +00003965MachO::linkedit_data_command
3966MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003967 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003968}
3969
Charles Davis8bdfafd2013-09-01 04:28:48 +00003970MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00003971MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003972 return getStruct<MachO::segment_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003973}
3974
Charles Davis8bdfafd2013-09-01 04:28:48 +00003975MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00003976MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003977 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003978}
3979
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00003980MachO::linker_option_command
3981MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003982 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003983}
3984
Jim Grosbach448334a2014-03-18 22:09:05 +00003985MachO::version_min_command
3986MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003987 return getStruct<MachO::version_min_command>(*this, L.Ptr);
Jim Grosbach448334a2014-03-18 22:09:05 +00003988}
3989
Kevin Enderbya4579c42017-01-19 17:36:31 +00003990MachO::note_command
3991MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
3992 return getStruct<MachO::note_command>(*this, L.Ptr);
3993}
3994
Steven Wu5b54a422017-01-23 20:07:55 +00003995MachO::build_version_command
3996MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
3997 return getStruct<MachO::build_version_command>(*this, L.Ptr);
3998}
3999
4000MachO::build_tool_version
4001MachOObjectFile::getBuildToolVersion(unsigned index) const {
4002 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4003}
4004
Tim Northover8f9590b2014-06-30 14:40:57 +00004005MachO::dylib_command
4006MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004007 return getStruct<MachO::dylib_command>(*this, L.Ptr);
Tim Northover8f9590b2014-06-30 14:40:57 +00004008}
4009
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004010MachO::dyld_info_command
4011MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004012 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004013}
4014
4015MachO::dylinker_command
4016MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004017 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004018}
4019
4020MachO::uuid_command
4021MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004022 return getStruct<MachO::uuid_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004023}
4024
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004025MachO::rpath_command
4026MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004027 return getStruct<MachO::rpath_command>(*this, L.Ptr);
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004028}
4029
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004030MachO::source_version_command
4031MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004032 return getStruct<MachO::source_version_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004033}
4034
4035MachO::entry_point_command
4036MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004037 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004038}
4039
Kevin Enderby0804f4672014-12-16 23:25:52 +00004040MachO::encryption_info_command
4041MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004042 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
Kevin Enderby0804f4672014-12-16 23:25:52 +00004043}
4044
Kevin Enderby57538292014-12-17 01:01:30 +00004045MachO::encryption_info_command_64
4046MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004047 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
Kevin Enderby57538292014-12-17 01:01:30 +00004048}
4049
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004050MachO::sub_framework_command
4051MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004052 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004053}
Tim Northover8f9590b2014-06-30 14:40:57 +00004054
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004055MachO::sub_umbrella_command
4056MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004057 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004058}
4059
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004060MachO::sub_library_command
4061MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004062 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004063}
4064
Kevin Enderby186eac32014-12-19 21:06:24 +00004065MachO::sub_client_command
4066MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004067 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
Kevin Enderby186eac32014-12-19 21:06:24 +00004068}
4069
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004070MachO::routines_command
4071MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004072 return getStruct<MachO::routines_command>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004073}
4074
4075MachO::routines_command_64
4076MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004077 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004078}
4079
Kevin Enderby48ef5342014-12-23 22:56:39 +00004080MachO::thread_command
4081MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004082 return getStruct<MachO::thread_command>(*this, L.Ptr);
Kevin Enderby48ef5342014-12-23 22:56:39 +00004083}
4084
Charles Davis8bdfafd2013-09-01 04:28:48 +00004085MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00004086MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00004087 DataRefImpl Sec;
4088 Sec.d.a = Rel.d.a;
4089 uint32_t Offset;
4090 if (is64Bit()) {
4091 MachO::section_64 Sect = getSection64(Sec);
4092 Offset = Sect.reloff;
4093 } else {
4094 MachO::section Sect = getSection(Sec);
4095 Offset = Sect.reloff;
4096 }
4097
4098 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004099 getPtr(*this, Offset)) + Rel.d.b;
Rafael Espindola128b8112014-04-03 23:51:28 +00004100 return getStruct<MachO::any_relocation_info>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004101 *this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00004102}
4103
Charles Davis8bdfafd2013-09-01 04:28:48 +00004104MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00004105MachOObjectFile::getDice(DataRefImpl Rel) const {
4106 const char *P = reinterpret_cast<const char *>(Rel.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004107 return getStruct<MachO::data_in_code_entry>(*this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00004108}
4109
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004110const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00004111 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004112}
4113
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004114const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4115 assert(is64Bit());
4116 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004117}
4118
Charles Davis8bdfafd2013-09-01 04:28:48 +00004119uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4120 const MachO::dysymtab_command &DLC,
4121 unsigned Index) const {
4122 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
Lang Hames697e7cd2016-12-04 01:56:10 +00004123 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004124}
4125
Charles Davis8bdfafd2013-09-01 04:28:48 +00004126MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00004127MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4128 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004129 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
Lang Hames697e7cd2016-12-04 01:56:10 +00004130 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004131}
4132
Charles Davis8bdfafd2013-09-01 04:28:48 +00004133MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004134 if (SymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004135 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004136
4137 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4138 MachO::symtab_command Cmd;
4139 Cmd.cmd = MachO::LC_SYMTAB;
4140 Cmd.cmdsize = sizeof(MachO::symtab_command);
4141 Cmd.symoff = 0;
4142 Cmd.nsyms = 0;
4143 Cmd.stroff = 0;
4144 Cmd.strsize = 0;
4145 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004146}
4147
Charles Davis8bdfafd2013-09-01 04:28:48 +00004148MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004149 if (DysymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004150 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004151
4152 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4153 MachO::dysymtab_command Cmd;
4154 Cmd.cmd = MachO::LC_DYSYMTAB;
4155 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4156 Cmd.ilocalsym = 0;
4157 Cmd.nlocalsym = 0;
4158 Cmd.iextdefsym = 0;
4159 Cmd.nextdefsym = 0;
4160 Cmd.iundefsym = 0;
4161 Cmd.nundefsym = 0;
4162 Cmd.tocoff = 0;
4163 Cmd.ntoc = 0;
4164 Cmd.modtaboff = 0;
4165 Cmd.nmodtab = 0;
4166 Cmd.extrefsymoff = 0;
4167 Cmd.nextrefsyms = 0;
4168 Cmd.indirectsymoff = 0;
4169 Cmd.nindirectsyms = 0;
4170 Cmd.extreloff = 0;
4171 Cmd.nextrel = 0;
4172 Cmd.locreloff = 0;
4173 Cmd.nlocrel = 0;
4174 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004175}
4176
Charles Davis8bdfafd2013-09-01 04:28:48 +00004177MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00004178MachOObjectFile::getDataInCodeLoadCommand() const {
4179 if (DataInCodeLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004180 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00004181
4182 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00004183 MachO::linkedit_data_command Cmd;
4184 Cmd.cmd = MachO::LC_DATA_IN_CODE;
4185 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4186 Cmd.dataoff = 0;
4187 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00004188 return Cmd;
4189}
4190
Kevin Enderby9a509442015-01-27 21:28:24 +00004191MachO::linkedit_data_command
4192MachOObjectFile::getLinkOptHintsLoadCommand() const {
4193 if (LinkOptHintsLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004194 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
Kevin Enderby9a509442015-01-27 21:28:24 +00004195
4196 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4197 // fields.
4198 MachO::linkedit_data_command Cmd;
4199 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4200 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4201 Cmd.dataoff = 0;
4202 Cmd.datasize = 0;
4203 return Cmd;
4204}
4205
Nick Kledzikd04bc352014-08-30 00:20:14 +00004206ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004207 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004208 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004209
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004210 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004211 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004212 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004213 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00004214 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004215}
4216
4217ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004218 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004219 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004220
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004221 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004222 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004223 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004224 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004225 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004226}
4227
4228ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004229 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004230 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004231
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004232 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004233 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004234 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004235 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004236 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004237}
4238
4239ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004240 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004241 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004242
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004243 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004244 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004245 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004246 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004247 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004248}
4249
4250ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004251 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004252 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004253
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004254 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004255 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004256 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004257 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00004258 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004259}
4260
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004261ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4262 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004263 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00004264 // Returning a pointer is fine as uuid doesn't need endian swapping.
4265 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00004266 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004267}
Nick Kledzikd04bc352014-08-30 00:20:14 +00004268
Rafael Espindola6e040c02013-04-26 20:07:33 +00004269StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004270 MachO::symtab_command S = getSymtabLoadCommand();
4271 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004272}
4273
Rafael Espindola56f976f2013-04-18 18:08:55 +00004274bool MachOObjectFile::is64Bit() const {
4275 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00004276 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004277}
4278
4279void MachOObjectFile::ReadULEB128s(uint64_t Index,
4280 SmallVectorImpl<uint64_t> &Out) const {
4281 DataExtractor extractor(ObjectFile::getData(), true, 0);
4282
4283 uint32_t offset = Index;
4284 uint64_t data = 0;
4285 while (uint64_t delta = extractor.getULEB128(&offset)) {
4286 data += delta;
4287 Out.push_back(data);
4288 }
4289}
4290
Rafael Espindolac66d7612014-08-17 19:09:37 +00004291bool MachOObjectFile::isRelocatableObject() const {
4292 return getHeader().filetype == MachO::MH_OBJECT;
4293}
4294
Lang Hamesff044b12016-03-25 23:11:52 +00004295Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00004296ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4297 uint32_t UniversalCputype,
4298 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00004299 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00004300 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004301 return MachOObjectFile::create(Buffer, false, false,
4302 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004303 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004304 return MachOObjectFile::create(Buffer, true, false,
4305 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004306 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004307 return MachOObjectFile::create(Buffer, false, true,
4308 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004309 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004310 return MachOObjectFile::create(Buffer, true, true,
4311 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00004312 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00004313 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004314}