blob: 724056f492a0bda13dae69c347e4b2e8811b028c [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>
Artyom Skrobov7d602f72014-07-20 12:08:28 +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
53 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
54 report_fatal_error("Malformed MachO file.");
55
Rafael Espindola3cdeb172013-04-19 13:45:05 +000056 T Cmd;
57 memcpy(&Cmd, P, sizeof(T));
58 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 Hames9e964f32016-03-25 17:25:34 +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
66 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));
71 if (O->isLittleEndian() != sys::IsLittleEndianHost)
72 MachO::swapStruct(Cmd);
73 return Cmd;
74}
75
Rafael Espindola6e040c02013-04-26 20:07:33 +000076static const char *
77getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
78 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000079 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
80
81 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
Rafael Espindola56f976f2013-04-18 18:08:55 +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
Rafael Espindola56f976f2013-04-18 18:08:55 +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
116static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000117 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
130static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +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
138getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000139 const MachO::any_relocation_info &RE) {
140 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000141}
142
143static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000144 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000145 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000146 return (RE.r_word1 >> 25) & 3;
147 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000148}
149
150static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000151getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
152 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000153}
154
155static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000156 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000157 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000158 return RE.r_word1 >> 28;
159 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000160}
161
Rafael Espindola56f976f2013-04-18 18:08:55 +0000162static uint32_t getSectionFlags(const MachOObjectFile *O,
163 DataRefImpl Sec) {
164 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000165 MachO::section_64 Sect = O->getSection64(Sec);
166 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000167 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000168 MachO::section Sect = O->getSection(Sec);
169 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000170}
171
Lang Hames9e964f32016-03-25 17:25:34 +0000172static Expected<MachOObjectFile::LoadCommandInfo>
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000173getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr,
174 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000175 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
176 if (CmdOrErr->cmdsize < 8)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000177 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000178 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000179 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
180 } else
181 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000182}
183
Lang Hames9e964f32016-03-25 17:25:34 +0000184static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000185getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
186 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
187 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000188 if (sizeof(MachO::load_command) > Obj->getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000189 return malformedError("load command 0 extends past the end all load "
Kevin Enderby89134962016-05-05 23:41:05 +0000190 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000191 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000192}
193
Lang Hames9e964f32016-03-25 17:25:34 +0000194static Expected<MachOObjectFile::LoadCommandInfo>
Kevin Enderby368e7142016-05-03 17:16:08 +0000195getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000196 const MachOObjectFile::LoadCommandInfo &L) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000197 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
198 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000199 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
Kevin Enderby368e7142016-05-03 17:16:08 +0000200 Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000201 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
Kevin Enderby89134962016-05-05 23:41:05 +0000202 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000203 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000204}
205
Alexey Samsonov9f336632015-06-04 19:45:22 +0000206template <typename T>
207static void parseHeader(const MachOObjectFile *Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000208 Error &Err) {
Kevin Enderby87025742016-04-13 21:17:58 +0000209 if (sizeof(T) > Obj->getData().size()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000210 Err = malformedError("the mach header extends past the end of the "
Kevin Enderby89134962016-05-05 23:41:05 +0000211 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000212 return;
213 }
Lang Hames9e964f32016-03-25 17:25:34 +0000214 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
215 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000216 else
Lang Hames9e964f32016-03-25 17:25:34 +0000217 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000218}
219
Kevin Enderbyd5039402016-10-31 20:29:48 +0000220// This is used to check for overlapping of Mach-O elements.
221struct MachOElement {
222 uint64_t Offset;
223 uint64_t Size;
224 const char *Name;
225};
226
227static Error checkOverlappingElement(std::list<MachOElement> &Elements,
228 uint64_t Offset, uint64_t Size,
229 const char *Name) {
230 if (Size == 0)
231 return Error::success();
232
233 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
234 auto E = *it;
235 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
236 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
237 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
238 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
239 " with a size of " + Twine(Size) + ", overlaps " +
240 E.Name + " at offset " + Twine(E.Offset) + " with "
241 "a size of " + Twine(E.Size));
242 auto nt = it;
243 nt++;
244 if (nt != Elements.end()) {
245 auto N = *nt;
246 if (Offset + Size <= N.Offset) {
247 Elements.insert(nt, {Offset, Size, Name});
248 return Error::success();
249 }
250 }
251 }
252 Elements.push_back({Offset, Size, Name});
253 return Error::success();
254}
255
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000256// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
257// sections to \param Sections, and optionally sets
258// \param IsPageZeroSegment to true.
Kevin Enderbyc614d282016-08-12 20:10:25 +0000259template <typename Segment, typename Section>
Lang Hames9e964f32016-03-25 17:25:34 +0000260static Error parseSegmentLoadCommand(
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000261 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000262 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
Kevin Enderbyc614d282016-08-12 20:10:25 +0000263 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders) {
264 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);
271 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);
281 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
282 Obj->getHeader().filetype != MachO::MH_DSYM &&
283 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");
289 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
290 Obj->getHeader().filetype != MachO::MH_DSYM &&
291 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;
299 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
300 Obj->getHeader().filetype != MachO::MH_DSYM &&
301 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");
308 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
309 Obj->getHeader().filetype != MachO::MH_DSYM &&
310 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");
317 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000318 Obj->getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
319 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");
333 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000334 return malformedError("reloff field of section " + Twine(J) + " in " +
335 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000336 " extends past the end of the file");
337 BigSize = s.nreloc;
338 BigSize *= sizeof(struct MachO::relocation_info);
339 BigSize += s.reloff;
340 if (BigSize > FileSize)
341 return malformedError("reloff field plus nreloc field times sizeof("
342 "struct relocation_info) of section " +
343 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000344 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000345 " extends past the end of the file");
Lang Hames9e964f32016-03-25 17:25:34 +0000346 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000347 if (S.fileoff > FileSize)
348 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000349 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000350 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000351 uint64_t BigSize = S.fileoff;
352 BigSize += S.filesize;
353 if (BigSize > FileSize)
354 return malformedError("load command " + Twine(LoadCommandIndex) +
355 " fileoff field plus filesize field in " +
356 CmdName + " extends past the end of the file");
357 if (S.vmsize != 0 && S.filesize > S.vmsize)
358 return malformedError("load command " + Twine(LoadCommandIndex) +
359 " fileoff field in " + CmdName +
360 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000361 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
362 } else
363 return SegOrErr.takeError();
364
365 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000366}
367
Kevin Enderby0e52c922016-08-26 19:34:07 +0000368static Error checkSymtabCommand(const MachOObjectFile *Obj,
369 const MachOObjectFile::LoadCommandInfo &Load,
370 uint32_t LoadCommandIndex,
Kevin Enderbyd5039402016-10-31 20:29:48 +0000371 const char **SymtabLoadCmd,
372 std::list<MachOElement> &Elements) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000373 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
374 return malformedError("load command " + Twine(LoadCommandIndex) +
375 " LC_SYMTAB cmdsize too small");
376 if (*SymtabLoadCmd != nullptr)
377 return malformedError("more than one LC_SYMTAB command");
378 MachO::symtab_command Symtab =
379 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
380 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
381 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
382 " has incorrect cmdsize");
383 uint64_t FileSize = Obj->getData().size();
384 if (Symtab.symoff > FileSize)
385 return malformedError("symoff field of LC_SYMTAB command " +
386 Twine(LoadCommandIndex) + " extends past the end "
387 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000388 uint64_t SymtabSize = Symtab.nsyms;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000389 const char *struct_nlist_name;
390 if (Obj->is64Bit()) {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000391 SymtabSize *= sizeof(MachO::nlist_64);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000392 struct_nlist_name = "struct nlist_64";
393 } else {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000394 SymtabSize *= sizeof(MachO::nlist);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000395 struct_nlist_name = "struct nlist";
396 }
Kevin Enderbyd5039402016-10-31 20:29:48 +0000397 uint64_t BigSize = SymtabSize;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000398 BigSize += Symtab.symoff;
399 if (BigSize > FileSize)
400 return malformedError("symoff field plus nsyms field times sizeof(" +
401 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
402 Twine(LoadCommandIndex) + " extends past the end "
403 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000404 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
405 "symbol table"))
406 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000407 if (Symtab.stroff > FileSize)
408 return malformedError("stroff field of LC_SYMTAB command " +
409 Twine(LoadCommandIndex) + " extends past the end "
410 "of the file");
411 BigSize = Symtab.stroff;
412 BigSize += Symtab.strsize;
413 if (BigSize > FileSize)
414 return malformedError("stroff field plus strsize field of LC_SYMTAB "
415 "command " + Twine(LoadCommandIndex) + " extends "
416 "past the end of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000417 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
418 Symtab.strsize, "string table"))
419 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000420 *SymtabLoadCmd = Load.Ptr;
421 return Error::success();
422}
423
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000424static Error checkDysymtabCommand(const MachOObjectFile *Obj,
425 const MachOObjectFile::LoadCommandInfo &Load,
426 uint32_t LoadCommandIndex,
427 const char **DysymtabLoadCmd) {
428 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
429 return malformedError("load command " + Twine(LoadCommandIndex) +
430 " LC_DYSYMTAB cmdsize too small");
431 if (*DysymtabLoadCmd != nullptr)
432 return malformedError("more than one LC_DYSYMTAB command");
433 MachO::dysymtab_command Dysymtab =
434 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
435 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
436 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
437 " has incorrect cmdsize");
438 uint64_t FileSize = Obj->getData().size();
439 if (Dysymtab.tocoff > FileSize)
440 return malformedError("tocoff field of LC_DYSYMTAB command " +
441 Twine(LoadCommandIndex) + " extends past the end of "
442 "the file");
443 uint64_t BigSize = Dysymtab.ntoc;
444 BigSize *= sizeof(MachO::dylib_table_of_contents);
445 BigSize += Dysymtab.tocoff;
446 if (BigSize > FileSize)
447 return malformedError("tocoff field plus ntoc field times sizeof(struct "
448 "dylib_table_of_contents) of LC_DYSYMTAB command " +
449 Twine(LoadCommandIndex) + " extends past the end of "
450 "the file");
451 if (Dysymtab.modtaboff > FileSize)
452 return malformedError("modtaboff field of LC_DYSYMTAB command " +
453 Twine(LoadCommandIndex) + " extends past the end of "
454 "the file");
455 BigSize = Dysymtab.nmodtab;
456 const char *struct_dylib_module_name;
457 if (Obj->is64Bit()) {
458 BigSize *= sizeof(MachO::dylib_module_64);
459 struct_dylib_module_name = "struct dylib_module_64";
460 } else {
461 BigSize *= sizeof(MachO::dylib_module);
462 struct_dylib_module_name = "struct dylib_module";
463 }
464 BigSize += Dysymtab.modtaboff;
465 if (BigSize > FileSize)
466 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
467 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
468 "command " + Twine(LoadCommandIndex) + " extends "
469 "past the end of the file");
470 if (Dysymtab.extrefsymoff > FileSize)
471 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
472 Twine(LoadCommandIndex) + " extends past the end of "
473 "the file");
474 BigSize = Dysymtab.nextrefsyms;
475 BigSize *= sizeof(MachO::dylib_reference);
476 BigSize += Dysymtab.extrefsymoff;
477 if (BigSize > FileSize)
478 return malformedError("extrefsymoff field plus nextrefsyms field times "
479 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
480 "command " + Twine(LoadCommandIndex) + " extends "
481 "past the end of the file");
482 if (Dysymtab.indirectsymoff > FileSize)
483 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
484 Twine(LoadCommandIndex) + " extends past the end of "
485 "the file");
486 BigSize = Dysymtab.nindirectsyms;
487 BigSize *= sizeof(uint32_t);
488 BigSize += Dysymtab.indirectsymoff;
489 if (BigSize > FileSize)
490 return malformedError("indirectsymoff field plus nindirectsyms field times "
491 "sizeof(uint32_t) of LC_DYSYMTAB command " +
492 Twine(LoadCommandIndex) + " extends past the end of "
493 "the file");
494 if (Dysymtab.extreloff > FileSize)
495 return malformedError("extreloff field of LC_DYSYMTAB command " +
496 Twine(LoadCommandIndex) + " extends past the end of "
497 "the file");
498 BigSize = Dysymtab.nextrel;
499 BigSize *= sizeof(MachO::relocation_info);
500 BigSize += Dysymtab.extreloff;
501 if (BigSize > FileSize)
502 return malformedError("extreloff field plus nextrel field times sizeof"
503 "(struct relocation_info) of LC_DYSYMTAB command " +
504 Twine(LoadCommandIndex) + " extends past the end of "
505 "the file");
506 if (Dysymtab.locreloff > FileSize)
507 return malformedError("locreloff field of LC_DYSYMTAB command " +
508 Twine(LoadCommandIndex) + " extends past the end of "
509 "the file");
510 BigSize = Dysymtab.nlocrel;
511 BigSize *= sizeof(MachO::relocation_info);
512 BigSize += Dysymtab.locreloff;
513 if (BigSize > FileSize)
514 return malformedError("locreloff field plus nlocrel field times sizeof"
515 "(struct relocation_info) of LC_DYSYMTAB command " +
516 Twine(LoadCommandIndex) + " extends past the end of "
517 "the file");
518 *DysymtabLoadCmd = Load.Ptr;
519 return Error::success();
520}
521
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000522static Error checkLinkeditDataCommand(const MachOObjectFile *Obj,
523 const MachOObjectFile::LoadCommandInfo &Load,
524 uint32_t LoadCommandIndex,
525 const char **LoadCmd, const char *CmdName) {
526 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
527 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
528 CmdName + " cmdsize too small");
529 if (*LoadCmd != nullptr)
530 return malformedError("more than one " + Twine(CmdName) + " command");
531 MachO::linkedit_data_command LinkData =
532 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
533 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
534 return malformedError(Twine(CmdName) + " command " +
535 Twine(LoadCommandIndex) + " has incorrect cmdsize");
536 uint64_t FileSize = Obj->getData().size();
537 if (LinkData.dataoff > FileSize)
538 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
539 Twine(LoadCommandIndex) + " extends past the end of "
540 "the file");
541 uint64_t BigSize = LinkData.dataoff;
542 BigSize += LinkData.datasize;
543 if (BigSize > FileSize)
544 return malformedError("dataoff field plus datasize field of " +
545 Twine(CmdName) + " command " +
546 Twine(LoadCommandIndex) + " extends past the end of "
547 "the file");
548 *LoadCmd = Load.Ptr;
549 return Error::success();
550}
551
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000552static Error checkDyldInfoCommand(const MachOObjectFile *Obj,
553 const MachOObjectFile::LoadCommandInfo &Load,
554 uint32_t LoadCommandIndex,
555 const char **LoadCmd, const char *CmdName) {
556 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
557 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
558 CmdName + " cmdsize too small");
559 if (*LoadCmd != nullptr)
560 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
561 "command");
562 MachO::dyld_info_command DyldInfo =
563 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
564 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
565 return malformedError(Twine(CmdName) + " command " +
566 Twine(LoadCommandIndex) + " has incorrect cmdsize");
567 uint64_t FileSize = Obj->getData().size();
568 if (DyldInfo.rebase_off > FileSize)
569 return malformedError("rebase_off field of " + Twine(CmdName) +
570 " command " + Twine(LoadCommandIndex) + " extends "
571 "past the end of the file");
572 uint64_t BigSize = DyldInfo.rebase_off;
573 BigSize += DyldInfo.rebase_size;
574 if (BigSize > FileSize)
575 return malformedError("rebase_off field plus rebase_size field of " +
576 Twine(CmdName) + " command " +
577 Twine(LoadCommandIndex) + " extends past the end of "
578 "the file");
579 if (DyldInfo.bind_off > FileSize)
580 return malformedError("bind_off field of " + Twine(CmdName) +
581 " command " + Twine(LoadCommandIndex) + " extends "
582 "past the end of the file");
583 BigSize = DyldInfo.bind_off;
584 BigSize += DyldInfo.bind_size;
585 if (BigSize > FileSize)
586 return malformedError("bind_off field plus bind_size field of " +
587 Twine(CmdName) + " command " +
588 Twine(LoadCommandIndex) + " extends past the end of "
589 "the file");
590 if (DyldInfo.weak_bind_off > FileSize)
591 return malformedError("weak_bind_off field of " + Twine(CmdName) +
592 " command " + Twine(LoadCommandIndex) + " extends "
593 "past the end of the file");
594 BigSize = DyldInfo.weak_bind_off;
595 BigSize += DyldInfo.weak_bind_size;
596 if (BigSize > FileSize)
597 return malformedError("weak_bind_off field plus weak_bind_size field of " +
598 Twine(CmdName) + " command " +
599 Twine(LoadCommandIndex) + " extends past the end of "
600 "the file");
601 if (DyldInfo.lazy_bind_off > FileSize)
602 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
603 " command " + Twine(LoadCommandIndex) + " extends "
604 "past the end of the file");
605 BigSize = DyldInfo.lazy_bind_off;
606 BigSize += DyldInfo.lazy_bind_size;
607 if (BigSize > FileSize)
608 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
609 Twine(CmdName) + " command " +
610 Twine(LoadCommandIndex) + " extends past the end of "
611 "the file");
612 if (DyldInfo.export_off > FileSize)
613 return malformedError("export_off field of " + Twine(CmdName) +
614 " command " + Twine(LoadCommandIndex) + " extends "
615 "past the end of the file");
616 BigSize = DyldInfo.export_off;
617 BigSize += DyldInfo.export_size;
618 if (BigSize > FileSize)
619 return malformedError("export_off field plus export_size field of " +
620 Twine(CmdName) + " command " +
621 Twine(LoadCommandIndex) + " extends past the end of "
622 "the file");
623 *LoadCmd = Load.Ptr;
624 return Error::success();
625}
626
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000627static Error checkDylibCommand(const MachOObjectFile *Obj,
628 const MachOObjectFile::LoadCommandInfo &Load,
629 uint32_t LoadCommandIndex, const char *CmdName) {
630 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
631 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
632 CmdName + " cmdsize too small");
633 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
634 if (D.dylib.name < sizeof(MachO::dylib_command))
635 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
636 CmdName + " name.offset field too small, not past "
637 "the end of the dylib_command struct");
638 if (D.dylib.name >= D.cmdsize)
639 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
640 CmdName + " name.offset field extends past the end "
641 "of the load command");
642 // Make sure there is a null between the starting offset of the name and
643 // the end of the load command.
644 uint32_t i;
645 const char *P = (const char *)Load.Ptr;
646 for (i = D.dylib.name; i < D.cmdsize; i++)
647 if (P[i] == '\0')
648 break;
649 if (i >= D.cmdsize)
650 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
651 CmdName + " library name extends past the end of the "
652 "load command");
653 return Error::success();
654}
655
656static Error checkDylibIdCommand(const MachOObjectFile *Obj,
657 const MachOObjectFile::LoadCommandInfo &Load,
658 uint32_t LoadCommandIndex,
659 const char **LoadCmd) {
660 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
661 "LC_ID_DYLIB"))
662 return Err;
663 if (*LoadCmd != nullptr)
664 return malformedError("more than one LC_ID_DYLIB command");
665 if (Obj->getHeader().filetype != MachO::MH_DYLIB &&
666 Obj->getHeader().filetype != MachO::MH_DYLIB_STUB)
667 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
668 "file type");
669 *LoadCmd = Load.Ptr;
670 return Error::success();
671}
672
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000673static Error checkDyldCommand(const MachOObjectFile *Obj,
674 const MachOObjectFile::LoadCommandInfo &Load,
675 uint32_t LoadCommandIndex, const char *CmdName) {
676 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
677 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
678 CmdName + " cmdsize too small");
679 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
680 if (D.name < sizeof(MachO::dylinker_command))
681 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
682 CmdName + " name.offset field too small, not past "
683 "the end of the dylinker_command struct");
684 if (D.name >= D.cmdsize)
685 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
686 CmdName + " name.offset field extends past the end "
687 "of the load command");
688 // Make sure there is a null between the starting offset of the name and
689 // the end of the load command.
690 uint32_t i;
691 const char *P = (const char *)Load.Ptr;
692 for (i = D.name; i < D.cmdsize; i++)
693 if (P[i] == '\0')
694 break;
695 if (i >= D.cmdsize)
696 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
697 CmdName + " dyld name extends past the end of the "
698 "load command");
699 return Error::success();
700}
701
Kevin Enderby32359db2016-09-28 21:20:45 +0000702static Error checkVersCommand(const MachOObjectFile *Obj,
703 const MachOObjectFile::LoadCommandInfo &Load,
704 uint32_t LoadCommandIndex,
705 const char **LoadCmd, const char *CmdName) {
706 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
707 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
708 CmdName + " has incorrect cmdsize");
709 if (*LoadCmd != nullptr)
710 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
711 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
712 "LC_VERSION_MIN_WATCHOS command");
713 *LoadCmd = Load.Ptr;
714 return Error::success();
715}
716
Kevin Enderby76966bf2016-09-28 23:16:01 +0000717static Error checkRpathCommand(const MachOObjectFile *Obj,
718 const MachOObjectFile::LoadCommandInfo &Load,
719 uint32_t LoadCommandIndex) {
720 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
721 return malformedError("load command " + Twine(LoadCommandIndex) +
722 " LC_RPATH cmdsize too small");
723 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
724 if (R.path < sizeof(MachO::rpath_command))
725 return malformedError("load command " + Twine(LoadCommandIndex) +
726 " LC_RPATH path.offset field too small, not past "
727 "the end of the rpath_command struct");
728 if (R.path >= R.cmdsize)
729 return malformedError("load command " + Twine(LoadCommandIndex) +
730 " LC_RPATH path.offset field extends past the end "
731 "of the load command");
732 // Make sure there is a null between the starting offset of the path and
733 // the end of the load command.
734 uint32_t i;
735 const char *P = (const char *)Load.Ptr;
736 for (i = R.path; i < R.cmdsize; i++)
737 if (P[i] == '\0')
738 break;
739 if (i >= R.cmdsize)
740 return malformedError("load command " + Twine(LoadCommandIndex) +
741 " LC_RPATH library name extends past the end of the "
742 "load command");
743 return Error::success();
744}
745
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000746static Error checkEncryptCommand(const MachOObjectFile *Obj,
747 const MachOObjectFile::LoadCommandInfo &Load,
748 uint32_t LoadCommandIndex,
749 uint64_t cryptoff, uint64_t cryptsize,
750 const char **LoadCmd, const char *CmdName) {
751 if (*LoadCmd != nullptr)
752 return malformedError("more than one LC_ENCRYPTION_INFO and or "
753 "LC_ENCRYPTION_INFO_64 command");
754 uint64_t FileSize = Obj->getData().size();
755 if (cryptoff > FileSize)
756 return malformedError("cryptoff field of " + Twine(CmdName) +
757 " command " + Twine(LoadCommandIndex) + " extends "
758 "past the end of the file");
759 uint64_t BigSize = cryptoff;
760 BigSize += cryptsize;
761 if (BigSize > FileSize)
762 return malformedError("cryptoff field plus cryptsize field of " +
763 Twine(CmdName) + " command " +
764 Twine(LoadCommandIndex) + " extends past the end of "
765 "the file");
766 *LoadCmd = Load.Ptr;
767 return Error::success();
768}
769
Kevin Enderby68fffa82016-10-11 21:04:39 +0000770static Error checkLinkerOptCommand(const MachOObjectFile *Obj,
771 const MachOObjectFile::LoadCommandInfo &Load,
772 uint32_t LoadCommandIndex) {
773 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
774 return malformedError("load command " + Twine(LoadCommandIndex) +
775 " LC_LINKER_OPTION cmdsize too small");
776 MachO::linker_option_command L =
777 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
778 // Make sure the count of strings is correct.
779 const char *string = (const char *)Load.Ptr +
780 sizeof(struct MachO::linker_option_command);
781 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
782 uint32_t i = 0;
783 while (left > 0) {
784 while (*string == '\0' && left > 0) {
785 string++;
786 left--;
787 }
788 if (left > 0) {
789 i++;
790 uint32_t NullPos = StringRef(string, left).find('\0');
791 uint32_t len = std::min(NullPos, left) + 1;
792 string += len;
793 left -= len;
794 }
795 }
796 if (L.count != i)
797 return malformedError("load command " + Twine(LoadCommandIndex) +
798 " LC_LINKER_OPTION string count " + Twine(L.count) +
799 " does not match number of strings");
800 return Error::success();
801}
802
Kevin Enderby2490de02016-10-17 22:09:25 +0000803static Error checkSubCommand(const MachOObjectFile *Obj,
804 const MachOObjectFile::LoadCommandInfo &Load,
805 uint32_t LoadCommandIndex, const char *CmdName,
806 size_t SizeOfCmd, const char *CmdStructName,
807 uint32_t PathOffset, const char *PathFieldName) {
808 if (PathOffset < SizeOfCmd)
809 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
810 CmdName + " " + PathFieldName + ".offset field too "
811 "small, not past the end of the " + CmdStructName);
812 if (PathOffset >= Load.C.cmdsize)
813 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
814 CmdName + " " + PathFieldName + ".offset field "
815 "extends past the end of the load command");
816 // Make sure there is a null between the starting offset of the path and
817 // the end of the load command.
818 uint32_t i;
819 const char *P = (const char *)Load.Ptr;
820 for (i = PathOffset; i < Load.C.cmdsize; i++)
821 if (P[i] == '\0')
822 break;
823 if (i >= Load.C.cmdsize)
824 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
825 CmdName + " " + PathFieldName + " name extends past "
826 "the end of the load command");
827 return Error::success();
828}
829
Kevin Enderby210030b2016-10-19 23:44:34 +0000830static Error checkThreadCommand(const MachOObjectFile *Obj,
831 const MachOObjectFile::LoadCommandInfo &Load,
832 uint32_t LoadCommandIndex,
833 const char *CmdName) {
834 if (Load.C.cmdsize < sizeof(MachO::thread_command))
835 return malformedError("load command " + Twine(LoadCommandIndex) +
836 CmdName + " cmdsize too small");
837 MachO::thread_command T =
838 getStruct<MachO::thread_command>(Obj, Load.Ptr);
839 const char *state = Load.Ptr + sizeof(MachO::thread_command);
840 const char *end = Load.Ptr + T.cmdsize;
841 uint32_t nflavor = 0;
842 uint32_t cputype = getCPUType(Obj);
843 while (state < end) {
844 if(state + sizeof(uint32_t) > end)
845 return malformedError("load command " + Twine(LoadCommandIndex) +
846 "flavor in " + CmdName + " extends past end of "
847 "command");
848 uint32_t flavor;
849 memcpy(&flavor, state, sizeof(uint32_t));
850 if (Obj->isLittleEndian() != sys::IsLittleEndianHost)
851 sys::swapByteOrder(flavor);
852 state += sizeof(uint32_t);
853
854 if(state + sizeof(uint32_t) > end)
855 return malformedError("load command " + Twine(LoadCommandIndex) +
856 " count in " + CmdName + " extends past end of "
857 "command");
858 uint32_t count;
859 memcpy(&count, state, sizeof(uint32_t));
860 if (Obj->isLittleEndian() != sys::IsLittleEndianHost)
861 sys::swapByteOrder(count);
862 state += sizeof(uint32_t);
863
864 if (cputype == MachO::CPU_TYPE_X86_64) {
865 if (flavor == MachO::x86_THREAD_STATE64) {
866 if (count != MachO::x86_THREAD_STATE64_COUNT)
867 return malformedError("load command " + Twine(LoadCommandIndex) +
868 " count not x86_THREAD_STATE64_COUNT for "
869 "flavor number " + Twine(nflavor) + " which is "
870 "a x86_THREAD_STATE64 flavor in " + CmdName +
871 " command");
872 if (state + sizeof(MachO::x86_thread_state64_t) > end)
873 return malformedError("load command " + Twine(LoadCommandIndex) +
874 " x86_THREAD_STATE64 extends past end of "
875 "command in " + CmdName + " command");
876 state += sizeof(MachO::x86_thread_state64_t);
877 } else {
878 return malformedError("load command " + Twine(LoadCommandIndex) +
879 " unknown flavor (" + Twine(flavor) + ") for "
880 "flavor number " + Twine(nflavor) + " in " +
881 CmdName + " command");
882 }
883 } else if (cputype == MachO::CPU_TYPE_ARM) {
884 if (flavor == MachO::ARM_THREAD_STATE) {
885 if (count != MachO::ARM_THREAD_STATE_COUNT)
886 return malformedError("load command " + Twine(LoadCommandIndex) +
887 " count not ARM_THREAD_STATE_COUNT for "
888 "flavor number " + Twine(nflavor) + " which is "
889 "a ARM_THREAD_STATE flavor in " + CmdName +
890 " command");
891 if (state + sizeof(MachO::arm_thread_state32_t) > end)
892 return malformedError("load command " + Twine(LoadCommandIndex) +
893 " ARM_THREAD_STATE extends past end of "
894 "command in " + CmdName + " command");
895 state += sizeof(MachO::arm_thread_state32_t);
896 } else {
897 return malformedError("load command " + Twine(LoadCommandIndex) +
898 " unknown flavor (" + Twine(flavor) + ") for "
899 "flavor number " + Twine(nflavor) + " in " +
900 CmdName + " command");
901 }
902 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
903 if (flavor == MachO::PPC_THREAD_STATE) {
904 if (count != MachO::PPC_THREAD_STATE_COUNT)
905 return malformedError("load command " + Twine(LoadCommandIndex) +
906 " count not PPC_THREAD_STATE_COUNT for "
907 "flavor number " + Twine(nflavor) + " which is "
908 "a PPC_THREAD_STATE flavor in " + CmdName +
909 " command");
910 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
911 return malformedError("load command " + Twine(LoadCommandIndex) +
912 " PPC_THREAD_STATE extends past end of "
913 "command in " + CmdName + " command");
914 state += sizeof(MachO::ppc_thread_state32_t);
915 } else {
916 return malformedError("load command " + Twine(LoadCommandIndex) +
917 " unknown flavor (" + Twine(flavor) + ") for "
918 "flavor number " + Twine(nflavor) + " in " +
919 CmdName + " command");
920 }
921 } else {
922 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
923 "command " + Twine(LoadCommandIndex) + " for " +
924 CmdName + " command can't be checked");
925 }
926 nflavor++;
927 }
928 return Error::success();
929}
930
Kevin Enderbyc8bb4222016-10-20 20:10:30 +0000931static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj,
932 const MachOObjectFile::LoadCommandInfo
933 &Load,
934 uint32_t LoadCommandIndex,
935 const char **LoadCmd) {
936 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
937 return malformedError("load command " + Twine(LoadCommandIndex) +
938 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
939 if (*LoadCmd != nullptr)
940 return malformedError("more than one LC_TWOLEVEL_HINTS command");
941 MachO::twolevel_hints_command Hints =
942 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
943 uint64_t FileSize = Obj->getData().size();
944 if (Hints.offset > FileSize)
945 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
946 Twine(LoadCommandIndex) + " extends past the end of "
947 "the file");
948 uint64_t BigSize = Hints.nhints;
949 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
950 BigSize += Hints.offset;
951 if (BigSize > FileSize)
952 return malformedError("offset field plus nhints times sizeof(struct "
953 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
954 Twine(LoadCommandIndex) + " extends past the end of "
955 "the file");
956 *LoadCmd = Load.Ptr;
957 return Error::success();
958}
959
Kevin Enderbybc5c29a2016-10-27 20:59:10 +0000960// Returns true if the libObject code does not support the load command and its
961// contents. The cmd value it is treated as an unknown load command but with
962// an error message that says the cmd value is obsolete.
963static bool isLoadCommandObsolete(uint32_t cmd) {
964 if (cmd == MachO::LC_SYMSEG ||
965 cmd == MachO::LC_LOADFVMLIB ||
966 cmd == MachO::LC_IDFVMLIB ||
967 cmd == MachO::LC_IDENT ||
968 cmd == MachO::LC_FVMFILE ||
969 cmd == MachO::LC_PREPAGE ||
970 cmd == MachO::LC_PREBOUND_DYLIB ||
971 cmd == MachO::LC_TWOLEVEL_HINTS ||
972 cmd == MachO::LC_PREBIND_CKSUM)
973 return true;
974 return false;
975}
976
Lang Hames82627642016-03-25 21:59:14 +0000977Expected<std::unique_ptr<MachOObjectFile>>
978MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +0000979 bool Is64Bits, uint32_t UniversalCputype,
980 uint32_t UniversalIndex) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000981 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000982 std::unique_ptr<MachOObjectFile> Obj(
983 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +0000984 Is64Bits, Err, UniversalCputype,
985 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +0000986 if (Err)
987 return std::move(Err);
988 return std::move(Obj);
989}
990
Rafael Espindola48af1c22014-08-19 18:44:46 +0000991MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +0000992 bool Is64bits, Error &Err,
993 uint32_t UniversalCputype,
994 uint32_t UniversalIndex)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000995 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000996 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000997 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
998 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
999 HasPageZeroSegment(false) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001000 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001001 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001002 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001003 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +00001004 parseHeader(this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001005 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001006 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001007 } else {
Lang Hames9e964f32016-03-25 17:25:34 +00001008 parseHeader(this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001009 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001010 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001011 }
Lang Hames9e964f32016-03-25 17:25:34 +00001012 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001013 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001014 SizeOfHeaders += getHeader().sizeofcmds;
1015 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001016 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001017 return;
1018 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001019 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1020 Err = malformedError("universal header architecture: " +
1021 Twine(UniversalIndex) + "'s cputype does not match "
1022 "object file's mach header");
1023 return;
1024 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001025 std::list<MachOElement> Elements;
1026 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001027
1028 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001029 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001030 if (LoadCommandCount != 0) {
1031 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
1032 Load = *LoadOrErr;
1033 else {
1034 Err = LoadOrErr.takeError();
1035 return;
1036 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001037 }
Lang Hames9e964f32016-03-25 17:25:34 +00001038
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001039 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001040 const char *FuncStartsLoadCmd = nullptr;
1041 const char *SplitInfoLoadCmd = nullptr;
1042 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001043 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001044 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001045 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001046 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001047 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001048 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001049 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001050 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001051 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001052 if (is64Bit()) {
1053 if (Load.C.cmdsize % 8 != 0) {
1054 // We have a hack here to allow 64-bit Mach-O core files to have
1055 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1056 // allowed since the macOS kernel produces them.
1057 if (getHeader().filetype != MachO::MH_CORE ||
1058 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1059 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1060 "multiple of 8");
1061 return;
1062 }
1063 }
1064 } else {
1065 if (Load.C.cmdsize % 4 != 0) {
1066 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1067 "multiple of 4");
1068 return;
1069 }
1070 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001071 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001072 if (Load.C.cmd == MachO::LC_SYMTAB) {
Kevin Enderbyd5039402016-10-31 20:29:48 +00001073 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001074 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001075 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +00001076 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001077 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001078 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +00001079 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd,
1080 "LC_DATA_IN_CODE")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001081 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001082 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +00001083 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd,
1084 "LC_LINKER_OPTIMIZATION_HINT")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001085 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001086 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1087 if ((Err = checkLinkeditDataCommand(this, Load, I, &FuncStartsLoadCmd,
1088 "LC_FUNCTION_STARTS")))
1089 return;
1090 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1091 if ((Err = checkLinkeditDataCommand(this, Load, I, &SplitInfoLoadCmd,
1092 "LC_SEGMENT_SPLIT_INFO")))
1093 return;
1094 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1095 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignDrsLoadCmd,
1096 "LC_DYLIB_CODE_SIGN_DRS")))
1097 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001098 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1099 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignLoadCmd,
1100 "LC_CODE_SIGNATURE")))
1101 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001102 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1103 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd,
1104 "LC_DYLD_INFO")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001105 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001106 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1107 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd,
1108 "LC_DYLD_INFO_ONLY")))
1109 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001110 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001111 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1112 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1113 "cmdsize");
1114 return;
1115 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001116 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001117 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001118 return;
1119 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001120 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001121 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001122 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1123 MachO::section_64>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +00001124 this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyc614d282016-08-12 20:10:25 +00001125 "LC_SEGMENT_64", SizeOfHeaders)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001126 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001127 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001128 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1129 MachO::section>(
1130 this, Load, Sections, HasPageZeroSegment, I,
1131 "LC_SEGMENT", SizeOfHeaders)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001132 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001133 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1134 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd)))
1135 return;
1136 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1137 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB")))
1138 return;
1139 Libraries.push_back(Load.Ptr);
1140 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1141 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1142 return;
1143 Libraries.push_back(Load.Ptr);
1144 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1145 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1146 return;
1147 Libraries.push_back(Load.Ptr);
1148 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1149 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB")))
1150 return;
1151 Libraries.push_back(Load.Ptr);
1152 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1153 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1154 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001155 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001156 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1157 if ((Err = checkDyldCommand(this, Load, I, "LC_ID_DYLINKER")))
1158 return;
1159 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1160 if ((Err = checkDyldCommand(this, Load, I, "LC_LOAD_DYLINKER")))
1161 return;
1162 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1163 if ((Err = checkDyldCommand(this, Load, I, "LC_DYLD_ENVIRONMENT")))
1164 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001165 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1166 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1167 "LC_VERSION_MIN_MACOSX")))
1168 return;
1169 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1170 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1171 "LC_VERSION_MIN_IPHONEOS")))
1172 return;
1173 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1174 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1175 "LC_VERSION_MIN_TVOS")))
1176 return;
1177 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1178 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1179 "LC_VERSION_MIN_WATCHOS")))
1180 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001181 } else if (Load.C.cmd == MachO::LC_RPATH) {
1182 if ((Err = checkRpathCommand(this, Load, I)))
1183 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001184 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1185 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1186 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1187 " has incorrect cmdsize");
1188 return;
1189 }
1190 if (SourceLoadCmd) {
1191 Err = malformedError("more than one LC_SOURCE_VERSION command");
1192 return;
1193 }
1194 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001195 } else if (Load.C.cmd == MachO::LC_MAIN) {
1196 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1197 Err = malformedError("LC_MAIN command " + Twine(I) +
1198 " has incorrect cmdsize");
1199 return;
1200 }
1201 if (EntryPointLoadCmd) {
1202 Err = malformedError("more than one LC_MAIN command");
1203 return;
1204 }
1205 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001206 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1207 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1208 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1209 " has incorrect cmdsize");
1210 return;
1211 }
1212 MachO::encryption_info_command E =
1213 getStruct<MachO::encryption_info_command>(this, Load.Ptr);
1214 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize,
1215 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1216 return;
1217 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1218 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1219 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1220 " has incorrect cmdsize");
1221 return;
1222 }
1223 MachO::encryption_info_command_64 E =
1224 getStruct<MachO::encryption_info_command_64>(this, Load.Ptr);
1225 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize,
1226 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1227 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001228 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1229 if ((Err = checkLinkerOptCommand(this, Load, I)))
1230 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001231 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1232 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1233 Err = malformedError("load command " + Twine(I) +
1234 " LC_SUB_FRAMEWORK cmdsize too small");
1235 return;
1236 }
1237 MachO::sub_framework_command S =
1238 getStruct<MachO::sub_framework_command>(this, Load.Ptr);
1239 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK",
1240 sizeof(MachO::sub_framework_command),
1241 "sub_framework_command", S.umbrella,
1242 "umbrella")))
1243 return;
1244 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1245 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1246 Err = malformedError("load command " + Twine(I) +
1247 " LC_SUB_UMBRELLA cmdsize too small");
1248 return;
1249 }
1250 MachO::sub_umbrella_command S =
1251 getStruct<MachO::sub_umbrella_command>(this, Load.Ptr);
1252 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA",
1253 sizeof(MachO::sub_umbrella_command),
1254 "sub_umbrella_command", S.sub_umbrella,
1255 "sub_umbrella")))
1256 return;
1257 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1258 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1259 Err = malformedError("load command " + Twine(I) +
1260 " LC_SUB_LIBRARY cmdsize too small");
1261 return;
1262 }
1263 MachO::sub_library_command S =
1264 getStruct<MachO::sub_library_command>(this, Load.Ptr);
1265 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY",
1266 sizeof(MachO::sub_library_command),
1267 "sub_library_command", S.sub_library,
1268 "sub_library")))
1269 return;
1270 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1271 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1272 Err = malformedError("load command " + Twine(I) +
1273 " LC_SUB_CLIENT cmdsize too small");
1274 return;
1275 }
1276 MachO::sub_client_command S =
1277 getStruct<MachO::sub_client_command>(this, Load.Ptr);
1278 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT",
1279 sizeof(MachO::sub_client_command),
1280 "sub_client_command", S.client, "client")))
1281 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001282 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1283 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1284 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1285 " has incorrect cmdsize");
1286 return;
1287 }
1288 if (RoutinesLoadCmd) {
1289 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1290 "command");
1291 return;
1292 }
1293 RoutinesLoadCmd = Load.Ptr;
1294 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1295 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1296 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1297 " has incorrect cmdsize");
1298 return;
1299 }
1300 if (RoutinesLoadCmd) {
1301 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1302 "command");
1303 return;
1304 }
1305 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001306 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1307 if ((Err = checkThreadCommand(this, Load, I, "LC_UNIXTHREAD")))
1308 return;
1309 if (UnixThreadLoadCmd) {
1310 Err = malformedError("more than one LC_UNIXTHREAD command");
1311 return;
1312 }
1313 UnixThreadLoadCmd = Load.Ptr;
1314 } else if (Load.C.cmd == MachO::LC_THREAD) {
1315 if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD")))
1316 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001317 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001318 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1319 if ((Err = checkTwoLevelHintsCommand(this, Load, I,
1320 &TwoLevelHintsLoadCmd)))
1321 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001322 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1323 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1324 Twine(Load.C.cmd) + " is obsolete and not "
1325 "supported");
1326 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001327 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001328 // TODO: generate a error for unknown load commands by default. But still
1329 // need work out an approach to allow or not allow unknown values like this
1330 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001331 if (I < LoadCommandCount - 1) {
Kevin Enderby368e7142016-05-03 17:16:08 +00001332 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001333 Load = *LoadOrErr;
1334 else {
1335 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001336 return;
1337 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001338 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001339 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001340 if (!SymtabLoadCmd) {
1341 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001342 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001343 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001344 return;
1345 }
1346 } else if (DysymtabLoadCmd) {
1347 MachO::symtab_command Symtab =
1348 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1349 MachO::dysymtab_command Dysymtab =
1350 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1351 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001352 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001353 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001354 return;
1355 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001356 uint64_t BigSize = Dysymtab.ilocalsym;
1357 BigSize += Dysymtab.nlocalsym;
1358 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001359 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001360 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001361 return;
1362 }
1363 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001364 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001365 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001366 return;
1367 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001368 BigSize = Dysymtab.iextdefsym;
1369 BigSize += Dysymtab.nextdefsym;
1370 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001371 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001372 "load command extends past the end of the symbol "
1373 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001374 return;
1375 }
1376 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001377 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001378 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001379 return;
1380 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001381 BigSize = Dysymtab.iundefsym;
1382 BigSize += Dysymtab.nundefsym;
1383 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001384 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001385 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001386 return;
1387 }
1388 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001389 if ((getHeader().filetype == MachO::MH_DYLIB ||
1390 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1391 DyldIdLoadCmd == nullptr) {
1392 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1393 "filetype");
1394 return;
1395 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001396 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001397
1398 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001399}
1400
Rafael Espindola5e812af2014-01-30 02:49:50 +00001401void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001402 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001403 sizeof(MachO::nlist_64) :
1404 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001405 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001406}
1407
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001408Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001409 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001411 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001412 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001413 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001414 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001415 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001416 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001417}
1418
Rafael Espindola0e77a942014-12-10 20:46:55 +00001419unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1420 DataRefImpl DRI = Sec.getRawDataRefImpl();
1421 uint32_t Flags = getSectionFlags(this, DRI);
1422 return Flags & MachO::SECTION_TYPE;
1423}
1424
Rafael Espindola59128922015-06-24 18:14:41 +00001425uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1426 if (is64Bit()) {
1427 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1428 return Entry.n_value;
1429 }
1430 MachO::nlist Entry = getSymbolTableEntry(Sym);
1431 return Entry.n_value;
1432}
1433
Kevin Enderby980b2582014-06-05 21:21:57 +00001434// getIndirectName() returns the name of the alias'ed symbol who's string table
1435// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001436std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1437 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001438 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +00001439 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
1440 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1441 return object_error::parse_failed;
1442 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001443 if (NValue >= StringTable.size())
1444 return object_error::parse_failed;
1445 const char *Start = &StringTable.data()[NValue];
1446 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001447 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001448}
1449
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001450uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001451 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001452}
1453
Kevin Enderby931cb652016-06-24 18:24:42 +00001454Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001455 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001456}
1457
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001458uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001459 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001460 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001461 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001462 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001463 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001464 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001465}
1466
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001467uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001468 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001469}
1470
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001471Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001472MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001473 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001474 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001475
Rafael Espindola56f976f2013-04-18 18:08:55 +00001476 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001477 if (n_type & MachO::N_STAB)
1478 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001479
Charles Davis74ec8b02013-08-27 05:00:13 +00001480 switch (n_type & MachO::N_TYPE) {
1481 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001482 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001483 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001484 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001485 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001486 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001487 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001488 if (Sec->isData() || Sec->isBSS())
1489 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001490 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001491 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001492 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001493}
1494
Rafael Espindola20122a42014-01-31 20:57:12 +00001495uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001496 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001497
Charles Davis8bdfafd2013-09-01 04:28:48 +00001498 uint8_t MachOType = Entry.n_type;
1499 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001500
Rafael Espindola20122a42014-01-31 20:57:12 +00001501 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001502
Tim Northovereaef0742014-05-30 13:22:59 +00001503 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1504 Result |= SymbolRef::SF_Indirect;
1505
Rafael Espindolaa1356322013-11-02 05:03:24 +00001506 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001507 Result |= SymbolRef::SF_FormatSpecific;
1508
Charles Davis74ec8b02013-08-27 05:00:13 +00001509 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001510 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001511 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001512 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001513 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001514 else
1515 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001516 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001517
1518 if (!(MachOType & MachO::N_PEXT))
1519 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001520 }
1521
Charles Davis74ec8b02013-08-27 05:00:13 +00001522 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001523 Result |= SymbolRef::SF_Weak;
1524
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001525 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1526 Result |= SymbolRef::SF_Thumb;
1527
Charles Davis74ec8b02013-08-27 05:00:13 +00001528 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001529 Result |= SymbolRef::SF_Absolute;
1530
Rafael Espindola20122a42014-01-31 20:57:12 +00001531 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001532}
1533
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001534Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001535MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001536 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001537 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001538
Rafael Espindola8bab8892015-08-07 23:27:14 +00001539 if (index == 0)
1540 return section_end();
1541 DataRefImpl DRI;
1542 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001543 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001544 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001545 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001546 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001547 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001548}
1549
Rafael Espindola6bf32212015-06-24 19:57:32 +00001550unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1551 MachO::nlist_base Entry =
1552 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
1553 return Entry.n_sect - 1;
1554}
1555
Rafael Espindola5e812af2014-01-30 02:49:50 +00001556void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001557 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001558}
1559
Rafael Espindola3acea392014-06-12 21:46:39 +00001560std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1561 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001562 ArrayRef<char> Raw = getSectionRawName(Sec);
1563 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001564 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001565}
1566
Rafael Espindola80291272014-10-08 15:28:58 +00001567uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1568 if (is64Bit())
1569 return getSection64(Sec).addr;
1570 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001571}
1572
Rafael Espindola80291272014-10-08 15:28:58 +00001573uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001574 // In the case if a malformed Mach-O file where the section offset is past
1575 // the end of the file or some part of the section size is past the end of
1576 // the file return a size of zero or a size that covers the rest of the file
1577 // but does not extend past the end of the file.
1578 uint32_t SectOffset, SectType;
1579 uint64_t SectSize;
1580
1581 if (is64Bit()) {
1582 MachO::section_64 Sect = getSection64(Sec);
1583 SectOffset = Sect.offset;
1584 SectSize = Sect.size;
1585 SectType = Sect.flags & MachO::SECTION_TYPE;
1586 } else {
1587 MachO::section Sect = getSection(Sec);
1588 SectOffset = Sect.offset;
1589 SectSize = Sect.size;
1590 SectType = Sect.flags & MachO::SECTION_TYPE;
1591 }
1592 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1593 return SectSize;
1594 uint64_t FileSize = getData().size();
1595 if (SectOffset > FileSize)
1596 return 0;
1597 if (FileSize - SectOffset < SectSize)
1598 return FileSize - SectOffset;
1599 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001600}
1601
Rafael Espindola3acea392014-06-12 21:46:39 +00001602std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1603 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001604 uint32_t Offset;
1605 uint64_t Size;
1606
1607 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001608 MachO::section_64 Sect = getSection64(Sec);
1609 Offset = Sect.offset;
1610 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001611 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001612 MachO::section Sect = getSection(Sec);
1613 Offset = Sect.offset;
1614 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001615 }
1616
1617 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001618 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001619}
1620
Rafael Espindola80291272014-10-08 15:28:58 +00001621uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001622 uint32_t Align;
1623 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001624 MachO::section_64 Sect = getSection64(Sec);
1625 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001626 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001627 MachO::section Sect = getSection(Sec);
1628 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001629 }
1630
Rafael Espindola80291272014-10-08 15:28:58 +00001631 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001632}
1633
George Rimar401e4e52016-05-24 12:48:46 +00001634bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1635 return false;
1636}
1637
Rafael Espindola80291272014-10-08 15:28:58 +00001638bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001639 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001640 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001641}
1642
Rafael Espindola80291272014-10-08 15:28:58 +00001643bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +00001644 uint32_t Flags = getSectionFlags(this, Sec);
1645 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001646 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1647 !(SectionType == MachO::S_ZEROFILL ||
1648 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001649}
1650
Rafael Espindola80291272014-10-08 15:28:58 +00001651bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +00001652 uint32_t Flags = getSectionFlags(this, Sec);
1653 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001654 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1655 (SectionType == MachO::S_ZEROFILL ||
1656 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001657}
1658
Rafael Espindola6bf32212015-06-24 19:57:32 +00001659unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1660 return Sec.getRawDataRefImpl().d.a;
1661}
1662
Rafael Espindola80291272014-10-08 15:28:58 +00001663bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +00001664 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +00001665 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001666}
1667
Steven Wuf2fe0142016-02-29 19:40:10 +00001668bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1669 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1670 StringRef SectName;
1671 if (!getSectionName(Sec, SectName))
1672 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1673 return false;
1674}
1675
Rui Ueyamabc654b12013-09-27 21:47:05 +00001676relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001677 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001678 Ret.d.a = Sec.d.a;
1679 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001680 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001681}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001682
Rafael Espindola56f976f2013-04-18 18:08:55 +00001683relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00001684MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001685 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001686 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001687 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001688 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001689 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001690 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001691 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001692 }
Eric Christopher7b015c72011-04-22 03:19:48 +00001693
Rafael Espindola56f976f2013-04-18 18:08:55 +00001694 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001695 Ret.d.a = Sec.d.a;
1696 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001697 return relocation_iterator(RelocationRef(Ret, this));
1698}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001699
Rafael Espindola5e812af2014-01-30 02:49:50 +00001700void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001701 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001702}
Owen Anderson171f4852011-10-24 23:20:07 +00001703
Rafael Espindola96d071c2015-06-29 23:29:12 +00001704uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +00001705 assert(getHeader().filetype == MachO::MH_OBJECT &&
1706 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001707 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00001708 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00001709}
1710
Rafael Espindola806f0062013-06-05 01:33:53 +00001711symbol_iterator
1712MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001713 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00001714 if (isRelocationScattered(RE))
1715 return symbol_end();
1716
Rafael Espindola56f976f2013-04-18 18:08:55 +00001717 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1718 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00001719 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00001720 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00001721
Charles Davis8bdfafd2013-09-01 04:28:48 +00001722 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001723 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001724 sizeof(MachO::nlist_64) :
1725 sizeof(MachO::nlist);
1726 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001727 DataRefImpl Sym;
1728 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00001729 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001730}
1731
Keno Fischerc780e8e2015-05-21 21:24:32 +00001732section_iterator
1733MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
1734 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
1735}
1736
Rafael Espindola99c041b2015-06-30 01:53:01 +00001737uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001738 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00001739 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001740}
1741
Rafael Espindola41bb4322015-06-30 04:08:37 +00001742void MachOObjectFile::getRelocationTypeName(
1743 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001744 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00001745 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001746
1747 unsigned Arch = this->getArch();
1748
1749 switch (Arch) {
1750 case Triple::x86: {
1751 static const char *const Table[] = {
1752 "GENERIC_RELOC_VANILLA",
1753 "GENERIC_RELOC_PAIR",
1754 "GENERIC_RELOC_SECTDIFF",
1755 "GENERIC_RELOC_PB_LA_PTR",
1756 "GENERIC_RELOC_LOCAL_SECTDIFF",
1757 "GENERIC_RELOC_TLV" };
1758
Eric Christopher13250cb2013-12-06 02:33:38 +00001759 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001760 res = "Unknown";
1761 else
1762 res = Table[RType];
1763 break;
1764 }
1765 case Triple::x86_64: {
1766 static const char *const Table[] = {
1767 "X86_64_RELOC_UNSIGNED",
1768 "X86_64_RELOC_SIGNED",
1769 "X86_64_RELOC_BRANCH",
1770 "X86_64_RELOC_GOT_LOAD",
1771 "X86_64_RELOC_GOT",
1772 "X86_64_RELOC_SUBTRACTOR",
1773 "X86_64_RELOC_SIGNED_1",
1774 "X86_64_RELOC_SIGNED_2",
1775 "X86_64_RELOC_SIGNED_4",
1776 "X86_64_RELOC_TLV" };
1777
1778 if (RType > 9)
1779 res = "Unknown";
1780 else
1781 res = Table[RType];
1782 break;
1783 }
1784 case Triple::arm: {
1785 static const char *const Table[] = {
1786 "ARM_RELOC_VANILLA",
1787 "ARM_RELOC_PAIR",
1788 "ARM_RELOC_SECTDIFF",
1789 "ARM_RELOC_LOCAL_SECTDIFF",
1790 "ARM_RELOC_PB_LA_PTR",
1791 "ARM_RELOC_BR24",
1792 "ARM_THUMB_RELOC_BR22",
1793 "ARM_THUMB_32BIT_BRANCH",
1794 "ARM_RELOC_HALF",
1795 "ARM_RELOC_HALF_SECTDIFF" };
1796
1797 if (RType > 9)
1798 res = "Unknown";
1799 else
1800 res = Table[RType];
1801 break;
1802 }
Tim Northover00ed9962014-03-29 10:18:08 +00001803 case Triple::aarch64: {
1804 static const char *const Table[] = {
1805 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
1806 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
1807 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
1808 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
1809 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
1810 "ARM64_RELOC_ADDEND"
1811 };
1812
1813 if (RType >= array_lengthof(Table))
1814 res = "Unknown";
1815 else
1816 res = Table[RType];
1817 break;
1818 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001819 case Triple::ppc: {
1820 static const char *const Table[] = {
1821 "PPC_RELOC_VANILLA",
1822 "PPC_RELOC_PAIR",
1823 "PPC_RELOC_BR14",
1824 "PPC_RELOC_BR24",
1825 "PPC_RELOC_HI16",
1826 "PPC_RELOC_LO16",
1827 "PPC_RELOC_HA16",
1828 "PPC_RELOC_LO14",
1829 "PPC_RELOC_SECTDIFF",
1830 "PPC_RELOC_PB_LA_PTR",
1831 "PPC_RELOC_HI16_SECTDIFF",
1832 "PPC_RELOC_LO16_SECTDIFF",
1833 "PPC_RELOC_HA16_SECTDIFF",
1834 "PPC_RELOC_JBSR",
1835 "PPC_RELOC_LO14_SECTDIFF",
1836 "PPC_RELOC_LOCAL_SECTDIFF" };
1837
Eric Christopher13250cb2013-12-06 02:33:38 +00001838 if (RType > 15)
1839 res = "Unknown";
1840 else
1841 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00001842 break;
1843 }
1844 case Triple::UnknownArch:
1845 res = "Unknown";
1846 break;
1847 }
1848 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00001849}
1850
Keno Fischer281b6942015-05-30 19:44:53 +00001851uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
1852 MachO::any_relocation_info RE = getRelocation(Rel);
1853 return getAnyRelocationLength(RE);
1854}
1855
Kevin Enderby980b2582014-06-05 21:21:57 +00001856//
1857// guessLibraryShortName() is passed a name of a dynamic library and returns a
1858// guess on what the short name is. Then name is returned as a substring of the
1859// StringRef Name passed in. The name of the dynamic library is recognized as
1860// a framework if it has one of the two following forms:
1861// Foo.framework/Versions/A/Foo
1862// Foo.framework/Foo
1863// Where A and Foo can be any string. And may contain a trailing suffix
1864// starting with an underbar. If the Name is recognized as a framework then
1865// isFramework is set to true else it is set to false. If the Name has a
1866// suffix then Suffix is set to the substring in Name that contains the suffix
1867// else it is set to a NULL StringRef.
1868//
1869// The Name of the dynamic library is recognized as a library name if it has
1870// one of the two following forms:
1871// libFoo.A.dylib
1872// libFoo.dylib
1873// The library may have a suffix trailing the name Foo of the form:
1874// libFoo_profile.A.dylib
1875// libFoo_profile.dylib
1876//
1877// The Name of the dynamic library is also recognized as a library name if it
1878// has the following form:
1879// Foo.qtx
1880//
1881// If the Name of the dynamic library is none of the forms above then a NULL
1882// StringRef is returned.
1883//
1884StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1885 bool &isFramework,
1886 StringRef &Suffix) {
1887 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1888 size_t a, b, c, d, Idx;
1889
1890 isFramework = false;
1891 Suffix = StringRef();
1892
1893 // Pull off the last component and make Foo point to it
1894 a = Name.rfind('/');
1895 if (a == Name.npos || a == 0)
1896 goto guess_library;
1897 Foo = Name.slice(a+1, Name.npos);
1898
1899 // Look for a suffix starting with a '_'
1900 Idx = Foo.rfind('_');
1901 if (Idx != Foo.npos && Foo.size() >= 2) {
1902 Suffix = Foo.slice(Idx, Foo.npos);
1903 Foo = Foo.slice(0, Idx);
1904 }
1905
1906 // First look for the form Foo.framework/Foo
1907 b = Name.rfind('/', a);
1908 if (b == Name.npos)
1909 Idx = 0;
1910 else
1911 Idx = b+1;
1912 F = Name.slice(Idx, Idx + Foo.size());
1913 DotFramework = Name.slice(Idx + Foo.size(),
1914 Idx + Foo.size() + sizeof(".framework/")-1);
1915 if (F == Foo && DotFramework == ".framework/") {
1916 isFramework = true;
1917 return Foo;
1918 }
1919
1920 // Next look for the form Foo.framework/Versions/A/Foo
1921 if (b == Name.npos)
1922 goto guess_library;
1923 c = Name.rfind('/', b);
1924 if (c == Name.npos || c == 0)
1925 goto guess_library;
1926 V = Name.slice(c+1, Name.npos);
1927 if (!V.startswith("Versions/"))
1928 goto guess_library;
1929 d = Name.rfind('/', c);
1930 if (d == Name.npos)
1931 Idx = 0;
1932 else
1933 Idx = d+1;
1934 F = Name.slice(Idx, Idx + Foo.size());
1935 DotFramework = Name.slice(Idx + Foo.size(),
1936 Idx + Foo.size() + sizeof(".framework/")-1);
1937 if (F == Foo && DotFramework == ".framework/") {
1938 isFramework = true;
1939 return Foo;
1940 }
1941
1942guess_library:
1943 // pull off the suffix after the "." and make a point to it
1944 a = Name.rfind('.');
1945 if (a == Name.npos || a == 0)
1946 return StringRef();
1947 Dylib = Name.slice(a, Name.npos);
1948 if (Dylib != ".dylib")
1949 goto guess_qtx;
1950
1951 // First pull off the version letter for the form Foo.A.dylib if any.
1952 if (a >= 3) {
1953 Dot = Name.slice(a-2, a-1);
1954 if (Dot == ".")
1955 a = a - 2;
1956 }
1957
1958 b = Name.rfind('/', a);
1959 if (b == Name.npos)
1960 b = 0;
1961 else
1962 b = b+1;
1963 // ignore any suffix after an underbar like Foo_profile.A.dylib
1964 Idx = Name.find('_', b);
1965 if (Idx != Name.npos && Idx != b) {
1966 Lib = Name.slice(b, Idx);
1967 Suffix = Name.slice(Idx, a);
1968 }
1969 else
1970 Lib = Name.slice(b, a);
1971 // There are incorrect library names of the form:
1972 // libATS.A_profile.dylib so check for these.
1973 if (Lib.size() >= 3) {
1974 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1975 if (Dot == ".")
1976 Lib = Lib.slice(0, Lib.size()-2);
1977 }
1978 return Lib;
1979
1980guess_qtx:
1981 Qtx = Name.slice(a, Name.npos);
1982 if (Qtx != ".qtx")
1983 return StringRef();
1984 b = Name.rfind('/', a);
1985 if (b == Name.npos)
1986 Lib = Name.slice(0, a);
1987 else
1988 Lib = Name.slice(b+1, a);
1989 // There are library names of the form: QT.A.qtx so check for these.
1990 if (Lib.size() >= 3) {
1991 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1992 if (Dot == ".")
1993 Lib = Lib.slice(0, Lib.size()-2);
1994 }
1995 return Lib;
1996}
1997
1998// getLibraryShortNameByIndex() is used to get the short name of the library
1999// for an undefined symbol in a linked Mach-O binary that was linked with the
2000// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2001// It is passed the index (0 - based) of the library as translated from
2002// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002003std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002004 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002005 if (Index >= Libraries.size())
2006 return object_error::parse_failed;
2007
Kevin Enderby980b2582014-06-05 21:21:57 +00002008 // If the cache of LibrariesShortNames is not built up do that first for
2009 // all the Libraries.
2010 if (LibrariesShortNames.size() == 0) {
2011 for (unsigned i = 0; i < Libraries.size(); i++) {
2012 MachO::dylib_command D =
2013 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002014 if (D.dylib.name >= D.cmdsize)
2015 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002016 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002017 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002018 if (D.dylib.name+Name.size() >= D.cmdsize)
2019 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002020 StringRef Suffix;
2021 bool isFramework;
2022 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002023 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002024 LibrariesShortNames.push_back(Name);
2025 else
2026 LibrariesShortNames.push_back(shortName);
2027 }
2028 }
2029
2030 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002031 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002032}
2033
Rafael Espindola76ad2322015-07-06 14:55:37 +00002034section_iterator
2035MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2036 DataRefImpl Sec;
2037 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2038 return section_iterator(SectionRef(Sec, this));
2039}
2040
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002041basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002042 DataRefImpl DRI;
2043 MachO::symtab_command Symtab = getSymtabLoadCommand();
2044 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2045 return basic_symbol_iterator(SymbolRef(DRI, this));
2046
Lang Hames36072da2014-05-12 21:39:59 +00002047 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002048}
2049
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002050basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002051 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002052 MachO::symtab_command Symtab = getSymtabLoadCommand();
2053 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002054 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002055
Rafael Espindola75c30362013-04-24 19:47:55 +00002056 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002057 sizeof(MachO::nlist_64) :
2058 sizeof(MachO::nlist);
2059 unsigned Offset = Symtab.symoff +
2060 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00002061 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002062 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002063}
2064
Lang Hames36072da2014-05-12 21:39:59 +00002065basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002066 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002067 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002068 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002069 unsigned SymbolTableEntrySize =
2070 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002071 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00002072 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
2073 DRI.p += Index * SymbolTableEntrySize;
2074 return basic_symbol_iterator(SymbolRef(DRI, this));
2075}
2076
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002077uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2078 MachO::symtab_command Symtab = getSymtabLoadCommand();
2079 if (!SymtabLoadCmd)
2080 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2081 unsigned SymbolTableEntrySize =
2082 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2083 DataRefImpl DRIstart;
2084 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
2085 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2086 return Index;
2087}
2088
Rafael Espindolab5155a52014-02-10 20:24:04 +00002089section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002090 DataRefImpl DRI;
2091 return section_iterator(SectionRef(DRI, this));
2092}
2093
Rafael Espindolab5155a52014-02-10 20:24:04 +00002094section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002095 DataRefImpl DRI;
2096 DRI.d.a = Sections.size();
2097 return section_iterator(SectionRef(DRI, this));
2098}
2099
Rafael Espindola56f976f2013-04-18 18:08:55 +00002100uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002101 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002102}
2103
Rafael Espindola56f976f2013-04-18 18:08:55 +00002104StringRef MachOObjectFile::getFileFormatName() const {
2105 unsigned CPUType = getCPUType(this);
2106 if (!is64Bit()) {
2107 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002108 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002109 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00002110 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002111 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00002112 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002113 return "Mach-O 32-bit ppc";
2114 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002115 return "Mach-O 32-bit unknown";
2116 }
2117 }
2118
Rafael Espindola56f976f2013-04-18 18:08:55 +00002119 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002120 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002121 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00002122 case llvm::MachO::CPU_TYPE_ARM64:
2123 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00002124 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002125 return "Mach-O 64-bit ppc64";
2126 default:
2127 return "Mach-O 64-bit unknown";
2128 }
2129}
2130
Alexey Samsonove6388e62013-06-18 15:03:28 +00002131Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2132 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002133 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002134 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00002135 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002136 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002137 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002138 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00002139 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002140 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002141 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002142 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00002143 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002144 return Triple::ppc64;
2145 default:
2146 return Triple::UnknownArch;
2147 }
2148}
2149
Tim Northover9e8eb412016-04-22 23:21:13 +00002150Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2151 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002152 if (McpuDefault)
2153 *McpuDefault = nullptr;
2154
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002155 switch (CPUType) {
2156 case MachO::CPU_TYPE_I386:
2157 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2158 case MachO::CPU_SUBTYPE_I386_ALL:
2159 return Triple("i386-apple-darwin");
2160 default:
2161 return Triple();
2162 }
2163 case MachO::CPU_TYPE_X86_64:
2164 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2165 case MachO::CPU_SUBTYPE_X86_64_ALL:
2166 return Triple("x86_64-apple-darwin");
2167 case MachO::CPU_SUBTYPE_X86_64_H:
2168 return Triple("x86_64h-apple-darwin");
2169 default:
2170 return Triple();
2171 }
2172 case MachO::CPU_TYPE_ARM:
2173 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2174 case MachO::CPU_SUBTYPE_ARM_V4T:
2175 return Triple("armv4t-apple-darwin");
2176 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2177 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002178 case MachO::CPU_SUBTYPE_ARM_XSCALE:
2179 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002180 case MachO::CPU_SUBTYPE_ARM_V6:
2181 return Triple("armv6-apple-darwin");
2182 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002183 if (McpuDefault)
2184 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002185 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002186 case MachO::CPU_SUBTYPE_ARM_V7:
2187 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002188 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002189 if (McpuDefault)
2190 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00002191 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002192 case MachO::CPU_SUBTYPE_ARM_V7K:
2193 return Triple("armv7k-apple-darwin");
2194 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002195 if (McpuDefault)
2196 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00002197 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002198 case MachO::CPU_SUBTYPE_ARM_V7S:
2199 return Triple("armv7s-apple-darwin");
2200 default:
2201 return Triple();
2202 }
2203 case MachO::CPU_TYPE_ARM64:
2204 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2205 case MachO::CPU_SUBTYPE_ARM64_ALL:
2206 return Triple("arm64-apple-darwin");
2207 default:
2208 return Triple();
2209 }
2210 case MachO::CPU_TYPE_POWERPC:
2211 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2212 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2213 return Triple("ppc-apple-darwin");
2214 default:
2215 return Triple();
2216 }
2217 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002218 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002219 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2220 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002221 default:
2222 return Triple();
2223 }
2224 default:
2225 return Triple();
2226 }
2227}
2228
2229Triple MachOObjectFile::getHostArch() {
2230 return Triple(sys::getDefaultTargetTriple());
2231}
2232
Rafael Espindola72318b42014-08-08 16:30:17 +00002233bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2234 return StringSwitch<bool>(ArchFlag)
2235 .Case("i386", true)
2236 .Case("x86_64", true)
2237 .Case("x86_64h", true)
2238 .Case("armv4t", true)
2239 .Case("arm", true)
2240 .Case("armv5e", true)
2241 .Case("armv6", true)
2242 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002243 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002244 .Case("armv7em", true)
2245 .Case("armv7k", true)
2246 .Case("armv7m", true)
2247 .Case("armv7s", true)
2248 .Case("arm64", true)
2249 .Case("ppc", true)
2250 .Case("ppc64", true)
2251 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002252}
2253
Alexey Samsonove6388e62013-06-18 15:03:28 +00002254unsigned MachOObjectFile::getArch() const {
2255 return getArch(getCPUType(this));
2256}
2257
Tim Northover9e8eb412016-04-22 23:21:13 +00002258Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2259 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002260}
2261
Rui Ueyamabc654b12013-09-27 21:47:05 +00002262relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002263 DataRefImpl DRI;
2264 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002265 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002266}
2267
Rui Ueyamabc654b12013-09-27 21:47:05 +00002268relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002269 DataRefImpl DRI;
2270 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002271 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002272}
2273
Kevin Enderby273ae012013-06-06 17:20:50 +00002274dice_iterator MachOObjectFile::begin_dices() const {
2275 DataRefImpl DRI;
2276 if (!DataInCodeLoadCmd)
2277 return dice_iterator(DiceRef(DRI, this));
2278
Charles Davis8bdfafd2013-09-01 04:28:48 +00002279 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2280 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002281 return dice_iterator(DiceRef(DRI, this));
2282}
2283
2284dice_iterator MachOObjectFile::end_dices() const {
2285 DataRefImpl DRI;
2286 if (!DataInCodeLoadCmd)
2287 return dice_iterator(DiceRef(DRI, this));
2288
Charles Davis8bdfafd2013-09-01 04:28:48 +00002289 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2290 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00002291 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
2292 return dice_iterator(DiceRef(DRI, this));
2293}
2294
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002295ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
2296 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002297
2298void ExportEntry::moveToFirst() {
2299 pushNode(0);
2300 pushDownUntilBottom();
2301}
2302
2303void ExportEntry::moveToEnd() {
2304 Stack.clear();
2305 Done = true;
2306}
2307
2308bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002309 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002310 if (Done || Other.Done)
2311 return (Done == Other.Done);
2312 // Not equal if different stack sizes.
2313 if (Stack.size() != Other.Stack.size())
2314 return false;
2315 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002316 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002317 return false;
2318 // Equal if all nodes in both stacks match.
2319 for (unsigned i=0; i < Stack.size(); ++i) {
2320 if (Stack[i].Start != Other.Stack[i].Start)
2321 return false;
2322 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002323 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002324}
2325
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002326uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
2327 unsigned Count;
2328 uint64_t Result = decodeULEB128(Ptr, &Count);
2329 Ptr += Count;
2330 if (Ptr > Trie.end()) {
2331 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002332 Malformed = true;
2333 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002334 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002335}
2336
2337StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002338 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002339}
2340
2341uint64_t ExportEntry::flags() const {
2342 return Stack.back().Flags;
2343}
2344
2345uint64_t ExportEntry::address() const {
2346 return Stack.back().Address;
2347}
2348
2349uint64_t ExportEntry::other() const {
2350 return Stack.back().Other;
2351}
2352
2353StringRef ExportEntry::otherName() const {
2354 const char* ImportName = Stack.back().ImportName;
2355 if (ImportName)
2356 return StringRef(ImportName);
2357 return StringRef();
2358}
2359
2360uint32_t ExportEntry::nodeOffset() const {
2361 return Stack.back().Start - Trie.begin();
2362}
2363
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002364ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2365 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
2366 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
2367 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002368
2369void ExportEntry::pushNode(uint64_t offset) {
2370 const uint8_t *Ptr = Trie.begin() + offset;
2371 NodeState State(Ptr);
2372 uint64_t ExportInfoSize = readULEB128(State.Current);
2373 State.IsExportNode = (ExportInfoSize != 0);
2374 const uint8_t* Children = State.Current + ExportInfoSize;
2375 if (State.IsExportNode) {
2376 State.Flags = readULEB128(State.Current);
2377 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2378 State.Address = 0;
2379 State.Other = readULEB128(State.Current); // dylib ordinal
2380 State.ImportName = reinterpret_cast<const char*>(State.Current);
2381 } else {
2382 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00002383 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002384 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002385 }
2386 }
2387 State.ChildCount = *Children;
2388 State.Current = Children + 1;
2389 State.NextChildIndex = 0;
2390 State.ParentStringLength = CumulativeString.size();
2391 Stack.push_back(State);
2392}
2393
2394void ExportEntry::pushDownUntilBottom() {
2395 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2396 NodeState &Top = Stack.back();
2397 CumulativeString.resize(Top.ParentStringLength);
2398 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002399 char C = *Top.Current;
2400 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002401 }
2402 Top.Current += 1;
2403 uint64_t childNodeIndex = readULEB128(Top.Current);
2404 Top.NextChildIndex += 1;
2405 pushNode(childNodeIndex);
2406 }
2407 if (!Stack.back().IsExportNode) {
2408 Malformed = true;
2409 moveToEnd();
2410 }
2411}
2412
2413// We have a trie data structure and need a way to walk it that is compatible
2414// with the C++ iterator model. The solution is a non-recursive depth first
2415// traversal where the iterator contains a stack of parent nodes along with a
2416// string that is the accumulation of all edge strings along the parent chain
2417// to this point.
2418//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002419// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002420// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002421// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002422//
2423// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2424// child until hitting a node with no children (which is an export node or
2425// else the trie is malformed). On the way down, each node is pushed on the
2426// stack ivar. If there is no more ways down, it pops up one and tries to go
2427// down a sibling path until a childless node is reached.
2428void ExportEntry::moveNext() {
2429 if (Stack.empty() || !Stack.back().IsExportNode) {
2430 Malformed = true;
2431 moveToEnd();
2432 return;
2433 }
2434
2435 Stack.pop_back();
2436 while (!Stack.empty()) {
2437 NodeState &Top = Stack.back();
2438 if (Top.NextChildIndex < Top.ChildCount) {
2439 pushDownUntilBottom();
2440 // Now at the next export node.
2441 return;
2442 } else {
2443 if (Top.IsExportNode) {
2444 // This node has no children but is itself an export node.
2445 CumulativeString.resize(Top.ParentStringLength);
2446 return;
2447 }
2448 Stack.pop_back();
2449 }
2450 }
2451 Done = true;
2452}
2453
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002454iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00002455MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
2456 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002457 if (Trie.size() == 0)
2458 Start.moveToEnd();
2459 else
2460 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002461
2462 ExportEntry Finish(Trie);
2463 Finish.moveToEnd();
2464
Craig Topper15576e12015-12-06 05:08:07 +00002465 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002466}
2467
2468iterator_range<export_iterator> MachOObjectFile::exports() const {
2469 return exports(getDyldInfoExportsTrie());
2470}
2471
Nick Kledzikac431442014-09-12 21:34:15 +00002472MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
2473 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2474 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2475 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
2476
2477void MachORebaseEntry::moveToFirst() {
2478 Ptr = Opcodes.begin();
2479 moveNext();
2480}
2481
2482void MachORebaseEntry::moveToEnd() {
2483 Ptr = Opcodes.end();
2484 RemainingLoopCount = 0;
2485 Done = true;
2486}
2487
2488void MachORebaseEntry::moveNext() {
2489 // If in the middle of some loop, move to next rebasing in loop.
2490 SegmentOffset += AdvanceAmount;
2491 if (RemainingLoopCount) {
2492 --RemainingLoopCount;
2493 return;
2494 }
2495 if (Ptr == Opcodes.end()) {
2496 Done = true;
2497 return;
2498 }
2499 bool More = true;
2500 while (More && !Malformed) {
2501 // Parse next opcode and set up next loop.
2502 uint8_t Byte = *Ptr++;
2503 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2504 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
2505 switch (Opcode) {
2506 case MachO::REBASE_OPCODE_DONE:
2507 More = false;
2508 Done = true;
2509 moveToEnd();
2510 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
2511 break;
2512 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2513 RebaseType = ImmValue;
2514 DEBUG_WITH_TYPE(
2515 "mach-o-rebase",
2516 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2517 << "RebaseType=" << (int) RebaseType << "\n");
2518 break;
2519 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2520 SegmentIndex = ImmValue;
2521 SegmentOffset = readULEB128();
2522 DEBUG_WITH_TYPE(
2523 "mach-o-rebase",
2524 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2525 << "SegmentIndex=" << SegmentIndex << ", "
2526 << format("SegmentOffset=0x%06X", SegmentOffset)
2527 << "\n");
2528 break;
2529 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
2530 SegmentOffset += readULEB128();
2531 DEBUG_WITH_TYPE("mach-o-rebase",
2532 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
2533 << format("SegmentOffset=0x%06X",
2534 SegmentOffset) << "\n");
2535 break;
2536 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
2537 SegmentOffset += ImmValue * PointerSize;
2538 DEBUG_WITH_TYPE("mach-o-rebase",
2539 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
2540 << format("SegmentOffset=0x%06X",
2541 SegmentOffset) << "\n");
2542 break;
2543 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
2544 AdvanceAmount = PointerSize;
2545 RemainingLoopCount = ImmValue - 1;
2546 DEBUG_WITH_TYPE(
2547 "mach-o-rebase",
2548 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
2549 << format("SegmentOffset=0x%06X", SegmentOffset)
2550 << ", AdvanceAmount=" << AdvanceAmount
2551 << ", RemainingLoopCount=" << RemainingLoopCount
2552 << "\n");
2553 return;
2554 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
2555 AdvanceAmount = PointerSize;
2556 RemainingLoopCount = readULEB128() - 1;
2557 DEBUG_WITH_TYPE(
2558 "mach-o-rebase",
2559 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
2560 << format("SegmentOffset=0x%06X", SegmentOffset)
2561 << ", AdvanceAmount=" << AdvanceAmount
2562 << ", RemainingLoopCount=" << RemainingLoopCount
2563 << "\n");
2564 return;
2565 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
2566 AdvanceAmount = readULEB128() + PointerSize;
2567 RemainingLoopCount = 0;
2568 DEBUG_WITH_TYPE(
2569 "mach-o-rebase",
2570 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
2571 << format("SegmentOffset=0x%06X", SegmentOffset)
2572 << ", AdvanceAmount=" << AdvanceAmount
2573 << ", RemainingLoopCount=" << RemainingLoopCount
2574 << "\n");
2575 return;
2576 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
2577 RemainingLoopCount = readULEB128() - 1;
2578 AdvanceAmount = readULEB128() + PointerSize;
2579 DEBUG_WITH_TYPE(
2580 "mach-o-rebase",
2581 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
2582 << format("SegmentOffset=0x%06X", SegmentOffset)
2583 << ", AdvanceAmount=" << AdvanceAmount
2584 << ", RemainingLoopCount=" << RemainingLoopCount
2585 << "\n");
2586 return;
2587 default:
2588 Malformed = true;
2589 }
2590 }
2591}
2592
2593uint64_t MachORebaseEntry::readULEB128() {
2594 unsigned Count;
2595 uint64_t Result = decodeULEB128(Ptr, &Count);
2596 Ptr += Count;
2597 if (Ptr > Opcodes.end()) {
2598 Ptr = Opcodes.end();
2599 Malformed = true;
2600 }
2601 return Result;
2602}
2603
2604uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
2605
2606uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
2607
2608StringRef MachORebaseEntry::typeName() const {
2609 switch (RebaseType) {
2610 case MachO::REBASE_TYPE_POINTER:
2611 return "pointer";
2612 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
2613 return "text abs32";
2614 case MachO::REBASE_TYPE_TEXT_PCREL32:
2615 return "text rel32";
2616 }
2617 return "unknown";
2618}
2619
2620bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
2621 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2622 return (Ptr == Other.Ptr) &&
2623 (RemainingLoopCount == Other.RemainingLoopCount) &&
2624 (Done == Other.Done);
2625}
2626
2627iterator_range<rebase_iterator>
2628MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
2629 MachORebaseEntry Start(Opcodes, is64);
2630 Start.moveToFirst();
2631
2632 MachORebaseEntry Finish(Opcodes, is64);
2633 Finish.moveToEnd();
2634
Craig Topper15576e12015-12-06 05:08:07 +00002635 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00002636}
2637
2638iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
2639 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
2640}
2641
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002642MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00002643 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2644 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
2645 BindType(0), PointerSize(is64Bit ? 8 : 4),
2646 TableKind(BK), Malformed(false), Done(false) {}
2647
2648void MachOBindEntry::moveToFirst() {
2649 Ptr = Opcodes.begin();
2650 moveNext();
2651}
2652
2653void MachOBindEntry::moveToEnd() {
2654 Ptr = Opcodes.end();
2655 RemainingLoopCount = 0;
2656 Done = true;
2657}
2658
2659void MachOBindEntry::moveNext() {
2660 // If in the middle of some loop, move to next binding in loop.
2661 SegmentOffset += AdvanceAmount;
2662 if (RemainingLoopCount) {
2663 --RemainingLoopCount;
2664 return;
2665 }
2666 if (Ptr == Opcodes.end()) {
2667 Done = true;
2668 return;
2669 }
2670 bool More = true;
2671 while (More && !Malformed) {
2672 // Parse next opcode and set up next loop.
2673 uint8_t Byte = *Ptr++;
2674 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
2675 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
2676 int8_t SignExtended;
2677 const uint8_t *SymStart;
2678 switch (Opcode) {
2679 case MachO::BIND_OPCODE_DONE:
2680 if (TableKind == Kind::Lazy) {
2681 // Lazying bindings have a DONE opcode between entries. Need to ignore
2682 // it to advance to next entry. But need not if this is last entry.
2683 bool NotLastEntry = false;
2684 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
2685 if (*P) {
2686 NotLastEntry = true;
2687 }
2688 }
2689 if (NotLastEntry)
2690 break;
2691 }
2692 More = false;
2693 Done = true;
2694 moveToEnd();
2695 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
2696 break;
2697 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
2698 Ordinal = ImmValue;
2699 DEBUG_WITH_TYPE(
2700 "mach-o-bind",
2701 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
2702 << "Ordinal=" << Ordinal << "\n");
2703 break;
2704 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
2705 Ordinal = readULEB128();
2706 DEBUG_WITH_TYPE(
2707 "mach-o-bind",
2708 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
2709 << "Ordinal=" << Ordinal << "\n");
2710 break;
2711 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
2712 if (ImmValue) {
2713 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
2714 Ordinal = SignExtended;
2715 } else
2716 Ordinal = 0;
2717 DEBUG_WITH_TYPE(
2718 "mach-o-bind",
2719 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
2720 << "Ordinal=" << Ordinal << "\n");
2721 break;
2722 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
2723 Flags = ImmValue;
2724 SymStart = Ptr;
2725 while (*Ptr) {
2726 ++Ptr;
2727 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00002728 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
2729 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00002730 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002731 DEBUG_WITH_TYPE(
2732 "mach-o-bind",
2733 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
2734 << "SymbolName=" << SymbolName << "\n");
2735 if (TableKind == Kind::Weak) {
2736 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
2737 return;
2738 }
2739 break;
2740 case MachO::BIND_OPCODE_SET_TYPE_IMM:
2741 BindType = ImmValue;
2742 DEBUG_WITH_TYPE(
2743 "mach-o-bind",
2744 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
2745 << "BindType=" << (int)BindType << "\n");
2746 break;
2747 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
2748 Addend = readSLEB128();
2749 if (TableKind == Kind::Lazy)
2750 Malformed = true;
2751 DEBUG_WITH_TYPE(
2752 "mach-o-bind",
2753 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
2754 << "Addend=" << Addend << "\n");
2755 break;
2756 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2757 SegmentIndex = ImmValue;
2758 SegmentOffset = readULEB128();
2759 DEBUG_WITH_TYPE(
2760 "mach-o-bind",
2761 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2762 << "SegmentIndex=" << SegmentIndex << ", "
2763 << format("SegmentOffset=0x%06X", SegmentOffset)
2764 << "\n");
2765 break;
2766 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2767 SegmentOffset += readULEB128();
2768 DEBUG_WITH_TYPE("mach-o-bind",
2769 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2770 << format("SegmentOffset=0x%06X",
2771 SegmentOffset) << "\n");
2772 break;
2773 case MachO::BIND_OPCODE_DO_BIND:
2774 AdvanceAmount = PointerSize;
2775 RemainingLoopCount = 0;
2776 DEBUG_WITH_TYPE("mach-o-bind",
2777 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2778 << format("SegmentOffset=0x%06X",
2779 SegmentOffset) << "\n");
2780 return;
2781 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002782 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002783 RemainingLoopCount = 0;
2784 if (TableKind == Kind::Lazy)
2785 Malformed = true;
2786 DEBUG_WITH_TYPE(
2787 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002788 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00002789 << format("SegmentOffset=0x%06X", SegmentOffset)
2790 << ", AdvanceAmount=" << AdvanceAmount
2791 << ", RemainingLoopCount=" << RemainingLoopCount
2792 << "\n");
2793 return;
2794 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002795 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002796 RemainingLoopCount = 0;
2797 if (TableKind == Kind::Lazy)
2798 Malformed = true;
2799 DEBUG_WITH_TYPE("mach-o-bind",
2800 llvm::dbgs()
2801 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2802 << format("SegmentOffset=0x%06X",
2803 SegmentOffset) << "\n");
2804 return;
2805 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2806 RemainingLoopCount = readULEB128() - 1;
2807 AdvanceAmount = readULEB128() + PointerSize;
2808 if (TableKind == Kind::Lazy)
2809 Malformed = true;
2810 DEBUG_WITH_TYPE(
2811 "mach-o-bind",
2812 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2813 << format("SegmentOffset=0x%06X", SegmentOffset)
2814 << ", AdvanceAmount=" << AdvanceAmount
2815 << ", RemainingLoopCount=" << RemainingLoopCount
2816 << "\n");
2817 return;
2818 default:
2819 Malformed = true;
2820 }
2821 }
2822}
2823
2824uint64_t MachOBindEntry::readULEB128() {
2825 unsigned Count;
2826 uint64_t Result = decodeULEB128(Ptr, &Count);
2827 Ptr += Count;
2828 if (Ptr > Opcodes.end()) {
2829 Ptr = Opcodes.end();
2830 Malformed = true;
2831 }
2832 return Result;
2833}
2834
2835int64_t MachOBindEntry::readSLEB128() {
2836 unsigned Count;
2837 int64_t Result = decodeSLEB128(Ptr, &Count);
2838 Ptr += Count;
2839 if (Ptr > Opcodes.end()) {
2840 Ptr = Opcodes.end();
2841 Malformed = true;
2842 }
2843 return Result;
2844}
2845
Nick Kledzik56ebef42014-09-16 01:41:51 +00002846uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2847
2848uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2849
2850StringRef MachOBindEntry::typeName() const {
2851 switch (BindType) {
2852 case MachO::BIND_TYPE_POINTER:
2853 return "pointer";
2854 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2855 return "text abs32";
2856 case MachO::BIND_TYPE_TEXT_PCREL32:
2857 return "text rel32";
2858 }
2859 return "unknown";
2860}
2861
2862StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2863
2864int64_t MachOBindEntry::addend() const { return Addend; }
2865
2866uint32_t MachOBindEntry::flags() const { return Flags; }
2867
2868int MachOBindEntry::ordinal() const { return Ordinal; }
2869
2870bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2871 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2872 return (Ptr == Other.Ptr) &&
2873 (RemainingLoopCount == Other.RemainingLoopCount) &&
2874 (Done == Other.Done);
2875}
2876
2877iterator_range<bind_iterator>
2878MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2879 MachOBindEntry::Kind BKind) {
2880 MachOBindEntry Start(Opcodes, is64, BKind);
2881 Start.moveToFirst();
2882
2883 MachOBindEntry Finish(Opcodes, is64, BKind);
2884 Finish.moveToEnd();
2885
Craig Topper15576e12015-12-06 05:08:07 +00002886 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00002887}
2888
2889iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2890 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2891 MachOBindEntry::Kind::Regular);
2892}
2893
2894iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2895 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2896 MachOBindEntry::Kind::Lazy);
2897}
2898
2899iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2900 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2901 MachOBindEntry::Kind::Weak);
2902}
2903
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00002904MachOObjectFile::load_command_iterator
2905MachOObjectFile::begin_load_commands() const {
2906 return LoadCommands.begin();
2907}
2908
2909MachOObjectFile::load_command_iterator
2910MachOObjectFile::end_load_commands() const {
2911 return LoadCommands.end();
2912}
2913
2914iterator_range<MachOObjectFile::load_command_iterator>
2915MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00002916 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00002917}
2918
Rafael Espindola56f976f2013-04-18 18:08:55 +00002919StringRef
2920MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2921 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2922 return parseSegmentOrSectionName(Raw.data());
2923}
2924
2925ArrayRef<char>
2926MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002927 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002928 const section_base *Base =
2929 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002930 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002931}
2932
2933ArrayRef<char>
2934MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002935 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002936 const section_base *Base =
2937 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002938 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002939}
2940
2941bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002942MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002943 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002944 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002945 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002946 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002947}
2948
Eric Christopher1d62c252013-07-22 22:25:07 +00002949unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002950 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002951 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002952 return RE.r_word1 & 0xffffff;
2953 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002954}
2955
Eric Christopher1d62c252013-07-22 22:25:07 +00002956bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002957 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002958 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002959 return (RE.r_word1 >> 27) & 1;
2960 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002961}
2962
Eric Christopher1d62c252013-07-22 22:25:07 +00002963bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002964 const MachO::any_relocation_info &RE) const {
2965 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002966}
2967
Eric Christopher1d62c252013-07-22 22:25:07 +00002968uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002969 const MachO::any_relocation_info &RE) const {
2970 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002971}
2972
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002973uint32_t MachOObjectFile::getScatteredRelocationType(
2974 const MachO::any_relocation_info &RE) const {
2975 return (RE.r_word0 >> 24) & 0xf;
2976}
2977
Eric Christopher1d62c252013-07-22 22:25:07 +00002978unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002979 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002980 if (isRelocationScattered(RE))
2981 return getScatteredRelocationAddress(RE);
2982 return getPlainRelocationAddress(RE);
2983}
2984
Charles Davis8bdfafd2013-09-01 04:28:48 +00002985unsigned MachOObjectFile::getAnyRelocationPCRel(
2986 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002987 if (isRelocationScattered(RE))
2988 return getScatteredRelocationPCRel(this, RE);
2989 return getPlainRelocationPCRel(this, RE);
2990}
2991
Eric Christopher1d62c252013-07-22 22:25:07 +00002992unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002993 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002994 if (isRelocationScattered(RE))
2995 return getScatteredRelocationLength(RE);
2996 return getPlainRelocationLength(this, RE);
2997}
2998
2999unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00003000MachOObjectFile::getAnyRelocationType(
3001 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003002 if (isRelocationScattered(RE))
3003 return getScatteredRelocationType(RE);
3004 return getPlainRelocationType(this, RE);
3005}
3006
Rafael Espindola52501032013-04-30 15:40:54 +00003007SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00003008MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003009 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00003010 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00003011 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00003012 unsigned SecNum = getPlainRelocationSymbolNum(RE);
3013 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
3014 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00003015 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00003016 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00003017 return SectionRef(DRI, this);
3018}
3019
Charles Davis8bdfafd2013-09-01 04:28:48 +00003020MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00003021 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003022 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003023}
3024
Charles Davis8bdfafd2013-09-01 04:28:48 +00003025MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00003026 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003027 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003028}
3029
Charles Davis8bdfafd2013-09-01 04:28:48 +00003030MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00003031 unsigned Index) const {
3032 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003033 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003034}
3035
Charles Davis8bdfafd2013-09-01 04:28:48 +00003036MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
3037 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00003038 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003039 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003040}
3041
Charles Davis8bdfafd2013-09-01 04:28:48 +00003042MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00003043MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00003044 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003045 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003046}
3047
Charles Davis8bdfafd2013-09-01 04:28:48 +00003048MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00003049MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00003050 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003051 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003052}
3053
Charles Davis8bdfafd2013-09-01 04:28:48 +00003054MachO::linkedit_data_command
3055MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
3056 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003057}
3058
Charles Davis8bdfafd2013-09-01 04:28:48 +00003059MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00003060MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003061 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003062}
3063
Charles Davis8bdfafd2013-09-01 04:28:48 +00003064MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00003065MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003066 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003067}
3068
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00003069MachO::linker_option_command
3070MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
3071 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003072}
3073
Jim Grosbach448334a2014-03-18 22:09:05 +00003074MachO::version_min_command
3075MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
3076 return getStruct<MachO::version_min_command>(this, L.Ptr);
3077}
3078
Tim Northover8f9590b2014-06-30 14:40:57 +00003079MachO::dylib_command
3080MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
3081 return getStruct<MachO::dylib_command>(this, L.Ptr);
3082}
3083
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003084MachO::dyld_info_command
3085MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
3086 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
3087}
3088
3089MachO::dylinker_command
3090MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
3091 return getStruct<MachO::dylinker_command>(this, L.Ptr);
3092}
3093
3094MachO::uuid_command
3095MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
3096 return getStruct<MachO::uuid_command>(this, L.Ptr);
3097}
3098
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00003099MachO::rpath_command
3100MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
3101 return getStruct<MachO::rpath_command>(this, L.Ptr);
3102}
3103
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003104MachO::source_version_command
3105MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
3106 return getStruct<MachO::source_version_command>(this, L.Ptr);
3107}
3108
3109MachO::entry_point_command
3110MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
3111 return getStruct<MachO::entry_point_command>(this, L.Ptr);
3112}
3113
Kevin Enderby0804f4672014-12-16 23:25:52 +00003114MachO::encryption_info_command
3115MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
3116 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
3117}
3118
Kevin Enderby57538292014-12-17 01:01:30 +00003119MachO::encryption_info_command_64
3120MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
3121 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
3122}
3123
Kevin Enderbyb4b79312014-12-18 19:24:35 +00003124MachO::sub_framework_command
3125MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
3126 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
3127}
Tim Northover8f9590b2014-06-30 14:40:57 +00003128
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00003129MachO::sub_umbrella_command
3130MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
3131 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
3132}
3133
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00003134MachO::sub_library_command
3135MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
3136 return getStruct<MachO::sub_library_command>(this, L.Ptr);
3137}
3138
Kevin Enderby186eac32014-12-19 21:06:24 +00003139MachO::sub_client_command
3140MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
3141 return getStruct<MachO::sub_client_command>(this, L.Ptr);
3142}
3143
Kevin Enderby52e4ce42014-12-19 22:25:22 +00003144MachO::routines_command
3145MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
3146 return getStruct<MachO::routines_command>(this, L.Ptr);
3147}
3148
3149MachO::routines_command_64
3150MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
3151 return getStruct<MachO::routines_command_64>(this, L.Ptr);
3152}
3153
Kevin Enderby48ef5342014-12-23 22:56:39 +00003154MachO::thread_command
3155MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
3156 return getStruct<MachO::thread_command>(this, L.Ptr);
3157}
3158
Charles Davis8bdfafd2013-09-01 04:28:48 +00003159MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00003160MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00003161 DataRefImpl Sec;
3162 Sec.d.a = Rel.d.a;
3163 uint32_t Offset;
3164 if (is64Bit()) {
3165 MachO::section_64 Sect = getSection64(Sec);
3166 Offset = Sect.reloff;
3167 } else {
3168 MachO::section Sect = getSection(Sec);
3169 Offset = Sect.reloff;
3170 }
3171
3172 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
3173 getPtr(this, Offset)) + Rel.d.b;
3174 return getStruct<MachO::any_relocation_info>(
3175 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00003176}
3177
Charles Davis8bdfafd2013-09-01 04:28:48 +00003178MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00003179MachOObjectFile::getDice(DataRefImpl Rel) const {
3180 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003181 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00003182}
3183
Alexey Samsonov13415ed2015-06-04 19:22:03 +00003184const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00003185 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003186}
3187
Alexey Samsonov13415ed2015-06-04 19:22:03 +00003188const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
3189 assert(is64Bit());
3190 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00003191}
3192
Charles Davis8bdfafd2013-09-01 04:28:48 +00003193uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
3194 const MachO::dysymtab_command &DLC,
3195 unsigned Index) const {
3196 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
3197 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00003198}
3199
Charles Davis8bdfafd2013-09-01 04:28:48 +00003200MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00003201MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
3202 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003203 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
3204 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00003205}
3206
Charles Davis8bdfafd2013-09-01 04:28:48 +00003207MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003208 if (SymtabLoadCmd)
3209 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
3210
3211 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
3212 MachO::symtab_command Cmd;
3213 Cmd.cmd = MachO::LC_SYMTAB;
3214 Cmd.cmdsize = sizeof(MachO::symtab_command);
3215 Cmd.symoff = 0;
3216 Cmd.nsyms = 0;
3217 Cmd.stroff = 0;
3218 Cmd.strsize = 0;
3219 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003220}
3221
Charles Davis8bdfafd2013-09-01 04:28:48 +00003222MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003223 if (DysymtabLoadCmd)
3224 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
3225
3226 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
3227 MachO::dysymtab_command Cmd;
3228 Cmd.cmd = MachO::LC_DYSYMTAB;
3229 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
3230 Cmd.ilocalsym = 0;
3231 Cmd.nlocalsym = 0;
3232 Cmd.iextdefsym = 0;
3233 Cmd.nextdefsym = 0;
3234 Cmd.iundefsym = 0;
3235 Cmd.nundefsym = 0;
3236 Cmd.tocoff = 0;
3237 Cmd.ntoc = 0;
3238 Cmd.modtaboff = 0;
3239 Cmd.nmodtab = 0;
3240 Cmd.extrefsymoff = 0;
3241 Cmd.nextrefsyms = 0;
3242 Cmd.indirectsymoff = 0;
3243 Cmd.nindirectsyms = 0;
3244 Cmd.extreloff = 0;
3245 Cmd.nextrel = 0;
3246 Cmd.locreloff = 0;
3247 Cmd.nlocrel = 0;
3248 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00003249}
3250
Charles Davis8bdfafd2013-09-01 04:28:48 +00003251MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00003252MachOObjectFile::getDataInCodeLoadCommand() const {
3253 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00003254 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00003255
3256 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00003257 MachO::linkedit_data_command Cmd;
3258 Cmd.cmd = MachO::LC_DATA_IN_CODE;
3259 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3260 Cmd.dataoff = 0;
3261 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00003262 return Cmd;
3263}
3264
Kevin Enderby9a509442015-01-27 21:28:24 +00003265MachO::linkedit_data_command
3266MachOObjectFile::getLinkOptHintsLoadCommand() const {
3267 if (LinkOptHintsLoadCmd)
3268 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
3269
3270 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
3271 // fields.
3272 MachO::linkedit_data_command Cmd;
3273 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
3274 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3275 Cmd.dataoff = 0;
3276 Cmd.datasize = 0;
3277 return Cmd;
3278}
3279
Nick Kledzikd04bc352014-08-30 00:20:14 +00003280ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003281 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003282 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003283
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003284 MachO::dyld_info_command DyldInfo =
3285 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3286 const uint8_t *Ptr =
3287 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00003288 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003289}
3290
3291ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003292 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003293 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003294
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003295 MachO::dyld_info_command DyldInfo =
3296 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3297 const uint8_t *Ptr =
3298 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003299 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003300}
3301
3302ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003303 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003304 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003305
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003306 MachO::dyld_info_command DyldInfo =
3307 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3308 const uint8_t *Ptr =
3309 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003310 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003311}
3312
3313ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003314 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003315 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003316
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003317 MachO::dyld_info_command DyldInfo =
3318 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3319 const uint8_t *Ptr =
3320 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003321 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003322}
3323
3324ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003325 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003326 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003327
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003328 MachO::dyld_info_command DyldInfo =
3329 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3330 const uint8_t *Ptr =
3331 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00003332 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003333}
3334
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00003335ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
3336 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003337 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00003338 // Returning a pointer is fine as uuid doesn't need endian swapping.
3339 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00003340 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00003341}
Nick Kledzikd04bc352014-08-30 00:20:14 +00003342
Rafael Espindola6e040c02013-04-26 20:07:33 +00003343StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003344 MachO::symtab_command S = getSymtabLoadCommand();
3345 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003346}
3347
Rafael Espindola56f976f2013-04-18 18:08:55 +00003348bool MachOObjectFile::is64Bit() const {
3349 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00003350 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003351}
3352
3353void MachOObjectFile::ReadULEB128s(uint64_t Index,
3354 SmallVectorImpl<uint64_t> &Out) const {
3355 DataExtractor extractor(ObjectFile::getData(), true, 0);
3356
3357 uint32_t offset = Index;
3358 uint64_t data = 0;
3359 while (uint64_t delta = extractor.getULEB128(&offset)) {
3360 data += delta;
3361 Out.push_back(data);
3362 }
3363}
3364
Rafael Espindolac66d7612014-08-17 19:09:37 +00003365bool MachOObjectFile::isRelocatableObject() const {
3366 return getHeader().filetype == MachO::MH_OBJECT;
3367}
3368
Lang Hamesff044b12016-03-25 23:11:52 +00003369Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00003370ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
3371 uint32_t UniversalCputype,
3372 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00003373 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00003374 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003375 return MachOObjectFile::create(Buffer, false, false,
3376 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003377 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003378 return MachOObjectFile::create(Buffer, true, false,
3379 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003380 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003381 return MachOObjectFile::create(Buffer, false, true,
3382 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003383 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003384 return MachOObjectFile::create(Buffer, true, true,
3385 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00003386 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00003387 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003388}