blob: cd0c2006f003874087ea2c95e806ca1bd760ad57 [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 Enderbyfbebe162016-11-02 21:08:39 +0000263 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
264 std::list<MachOElement> &Elements) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000265 const unsigned SegmentLoadSize = sizeof(Segment);
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000266 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000267 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000268 " " + CmdName + " cmdsize too small");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000269 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
270 Segment S = SegOrErr.get();
271 const unsigned SectionSize = sizeof(Section);
272 uint64_t FileSize = Obj->getData().size();
Lang Hames9e964f32016-03-25 17:25:34 +0000273 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
274 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000275 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000276 " inconsistent cmdsize in " + CmdName +
Kevin Enderby89134962016-05-05 23:41:05 +0000277 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000278 for (unsigned J = 0; J < S.nsects; ++J) {
279 const char *Sec = getSectionPtr(Obj, Load, J);
280 Sections.push_back(Sec);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000281 Section s = getStruct<Section>(Obj, Sec);
282 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
283 Obj->getHeader().filetype != MachO::MH_DSYM &&
284 s.flags != MachO::S_ZEROFILL &&
285 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
286 s.offset > FileSize)
287 return malformedError("offset field of section " + Twine(J) + " in " +
288 CmdName + " command " + Twine(LoadCommandIndex) +
289 " extends past the end of the file");
290 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
291 Obj->getHeader().filetype != MachO::MH_DSYM &&
292 s.flags != MachO::S_ZEROFILL &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000293 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
294 s.offset < SizeOfHeaders && s.size != 0)
Kevin Enderbyc614d282016-08-12 20:10:25 +0000295 return malformedError("offset field of section " + Twine(J) + " in " +
296 CmdName + " command " + Twine(LoadCommandIndex) +
297 " not past the headers of the file");
298 uint64_t BigSize = s.offset;
299 BigSize += s.size;
300 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
301 Obj->getHeader().filetype != MachO::MH_DSYM &&
302 s.flags != MachO::S_ZEROFILL &&
303 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
304 BigSize > FileSize)
305 return malformedError("offset field plus size field of section " +
306 Twine(J) + " in " + CmdName + " command " +
307 Twine(LoadCommandIndex) +
308 " extends past the end of the file");
309 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
310 Obj->getHeader().filetype != MachO::MH_DSYM &&
311 s.flags != MachO::S_ZEROFILL &&
312 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
313 s.size > S.filesize)
314 return malformedError("size field of section " +
315 Twine(J) + " in " + CmdName + " command " +
316 Twine(LoadCommandIndex) +
317 " greater than the segment");
318 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000319 Obj->getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
320 s.addr < S.vmaddr)
321 return malformedError("addr field of section " + Twine(J) + " in " +
322 CmdName + " command " + Twine(LoadCommandIndex) +
323 " less than the segment's vmaddr");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000324 BigSize = s.addr;
325 BigSize += s.size;
326 uint64_t BigEnd = S.vmaddr;
327 BigEnd += S.vmsize;
328 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000329 return malformedError("addr field plus size of section " + Twine(J) +
330 " in " + CmdName + " command " +
331 Twine(LoadCommandIndex) +
332 " greater than than "
Kevin Enderbyc614d282016-08-12 20:10:25 +0000333 "the segment's vmaddr plus vmsize");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000334 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
335 Obj->getHeader().filetype != MachO::MH_DSYM &&
336 s.flags != MachO::S_ZEROFILL &&
337 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
338 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
339 "section contents"))
340 return Err;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000341 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000342 return malformedError("reloff field of section " + Twine(J) + " in " +
343 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000344 " extends past the end of the file");
345 BigSize = s.nreloc;
346 BigSize *= sizeof(struct MachO::relocation_info);
347 BigSize += s.reloff;
348 if (BigSize > FileSize)
349 return malformedError("reloff field plus nreloc field times sizeof("
350 "struct relocation_info) of section " +
351 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000352 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000353 " extends past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000354 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
355 sizeof(struct
356 MachO::relocation_info),
357 "section relocation entries"))
358 return Err;
Lang Hames9e964f32016-03-25 17:25:34 +0000359 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000360 if (S.fileoff > FileSize)
361 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000362 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000363 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000364 uint64_t BigSize = S.fileoff;
365 BigSize += S.filesize;
366 if (BigSize > FileSize)
367 return malformedError("load command " + Twine(LoadCommandIndex) +
368 " fileoff field plus filesize field in " +
369 CmdName + " extends past the end of the file");
370 if (S.vmsize != 0 && S.filesize > S.vmsize)
371 return malformedError("load command " + Twine(LoadCommandIndex) +
372 " fileoff field in " + CmdName +
373 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000374 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
375 } else
376 return SegOrErr.takeError();
377
378 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000379}
380
Kevin Enderby0e52c922016-08-26 19:34:07 +0000381static Error checkSymtabCommand(const MachOObjectFile *Obj,
382 const MachOObjectFile::LoadCommandInfo &Load,
383 uint32_t LoadCommandIndex,
Kevin Enderbyd5039402016-10-31 20:29:48 +0000384 const char **SymtabLoadCmd,
385 std::list<MachOElement> &Elements) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000386 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
387 return malformedError("load command " + Twine(LoadCommandIndex) +
388 " LC_SYMTAB cmdsize too small");
389 if (*SymtabLoadCmd != nullptr)
390 return malformedError("more than one LC_SYMTAB command");
391 MachO::symtab_command Symtab =
392 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
393 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
394 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
395 " has incorrect cmdsize");
396 uint64_t FileSize = Obj->getData().size();
397 if (Symtab.symoff > FileSize)
398 return malformedError("symoff field of LC_SYMTAB command " +
399 Twine(LoadCommandIndex) + " extends past the end "
400 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000401 uint64_t SymtabSize = Symtab.nsyms;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000402 const char *struct_nlist_name;
403 if (Obj->is64Bit()) {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000404 SymtabSize *= sizeof(MachO::nlist_64);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000405 struct_nlist_name = "struct nlist_64";
406 } else {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000407 SymtabSize *= sizeof(MachO::nlist);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000408 struct_nlist_name = "struct nlist";
409 }
Kevin Enderbyd5039402016-10-31 20:29:48 +0000410 uint64_t BigSize = SymtabSize;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000411 BigSize += Symtab.symoff;
412 if (BigSize > FileSize)
413 return malformedError("symoff field plus nsyms field times sizeof(" +
414 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
415 Twine(LoadCommandIndex) + " extends past the end "
416 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000417 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
418 "symbol table"))
419 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000420 if (Symtab.stroff > FileSize)
421 return malformedError("stroff field of LC_SYMTAB command " +
422 Twine(LoadCommandIndex) + " extends past the end "
423 "of the file");
424 BigSize = Symtab.stroff;
425 BigSize += Symtab.strsize;
426 if (BigSize > FileSize)
427 return malformedError("stroff field plus strsize field of LC_SYMTAB "
428 "command " + Twine(LoadCommandIndex) + " extends "
429 "past the end of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000430 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
431 Symtab.strsize, "string table"))
432 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000433 *SymtabLoadCmd = Load.Ptr;
434 return Error::success();
435}
436
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000437static Error checkDysymtabCommand(const MachOObjectFile *Obj,
438 const MachOObjectFile::LoadCommandInfo &Load,
439 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000440 const char **DysymtabLoadCmd,
441 std::list<MachOElement> &Elements) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000442 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
443 return malformedError("load command " + Twine(LoadCommandIndex) +
444 " LC_DYSYMTAB cmdsize too small");
445 if (*DysymtabLoadCmd != nullptr)
446 return malformedError("more than one LC_DYSYMTAB command");
447 MachO::dysymtab_command Dysymtab =
448 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
449 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
450 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
451 " has incorrect cmdsize");
452 uint64_t FileSize = Obj->getData().size();
453 if (Dysymtab.tocoff > FileSize)
454 return malformedError("tocoff field of LC_DYSYMTAB command " +
455 Twine(LoadCommandIndex) + " extends past the end of "
456 "the file");
457 uint64_t BigSize = Dysymtab.ntoc;
458 BigSize *= sizeof(MachO::dylib_table_of_contents);
459 BigSize += Dysymtab.tocoff;
460 if (BigSize > FileSize)
461 return malformedError("tocoff field plus ntoc field times sizeof(struct "
462 "dylib_table_of_contents) of LC_DYSYMTAB command " +
463 Twine(LoadCommandIndex) + " extends past the end of "
464 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000465 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
466 Dysymtab.ntoc * sizeof(struct
467 MachO::dylib_table_of_contents),
468 "table of contents"))
469 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000470 if (Dysymtab.modtaboff > FileSize)
471 return malformedError("modtaboff field of LC_DYSYMTAB command " +
472 Twine(LoadCommandIndex) + " extends past the end of "
473 "the file");
474 BigSize = Dysymtab.nmodtab;
475 const char *struct_dylib_module_name;
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000476 uint64_t sizeof_modtab;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000477 if (Obj->is64Bit()) {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000478 sizeof_modtab = sizeof(MachO::dylib_module_64);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000479 struct_dylib_module_name = "struct dylib_module_64";
480 } else {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000481 sizeof_modtab = sizeof(MachO::dylib_module);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000482 struct_dylib_module_name = "struct dylib_module";
483 }
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000484 BigSize *= sizeof_modtab;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000485 BigSize += Dysymtab.modtaboff;
486 if (BigSize > FileSize)
487 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
488 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
489 "command " + Twine(LoadCommandIndex) + " extends "
490 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000491 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
492 Dysymtab.nmodtab * sizeof_modtab,
493 "module table"))
494 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000495 if (Dysymtab.extrefsymoff > FileSize)
496 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
497 Twine(LoadCommandIndex) + " extends past the end of "
498 "the file");
499 BigSize = Dysymtab.nextrefsyms;
500 BigSize *= sizeof(MachO::dylib_reference);
501 BigSize += Dysymtab.extrefsymoff;
502 if (BigSize > FileSize)
503 return malformedError("extrefsymoff field plus nextrefsyms field times "
504 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
505 "command " + Twine(LoadCommandIndex) + " extends "
506 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000507 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
508 Dysymtab.nextrefsyms *
509 sizeof(MachO::dylib_reference),
510 "reference table"))
511 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000512 if (Dysymtab.indirectsymoff > FileSize)
513 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
514 Twine(LoadCommandIndex) + " extends past the end of "
515 "the file");
516 BigSize = Dysymtab.nindirectsyms;
517 BigSize *= sizeof(uint32_t);
518 BigSize += Dysymtab.indirectsymoff;
519 if (BigSize > FileSize)
520 return malformedError("indirectsymoff field plus nindirectsyms field times "
521 "sizeof(uint32_t) of LC_DYSYMTAB command " +
522 Twine(LoadCommandIndex) + " extends past the end of "
523 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000524 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
525 Dysymtab.nindirectsyms *
526 sizeof(uint32_t),
527 "indirect table"))
528 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000529 if (Dysymtab.extreloff > FileSize)
530 return malformedError("extreloff field of LC_DYSYMTAB command " +
531 Twine(LoadCommandIndex) + " extends past the end of "
532 "the file");
533 BigSize = Dysymtab.nextrel;
534 BigSize *= sizeof(MachO::relocation_info);
535 BigSize += Dysymtab.extreloff;
536 if (BigSize > FileSize)
537 return malformedError("extreloff field plus nextrel field times sizeof"
538 "(struct relocation_info) of LC_DYSYMTAB command " +
539 Twine(LoadCommandIndex) + " extends past the end of "
540 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000541 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
542 Dysymtab.nextrel *
543 sizeof(MachO::relocation_info),
544 "external relocation table"))
545 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000546 if (Dysymtab.locreloff > FileSize)
547 return malformedError("locreloff field of LC_DYSYMTAB command " +
548 Twine(LoadCommandIndex) + " extends past the end of "
549 "the file");
550 BigSize = Dysymtab.nlocrel;
551 BigSize *= sizeof(MachO::relocation_info);
552 BigSize += Dysymtab.locreloff;
553 if (BigSize > FileSize)
554 return malformedError("locreloff field plus nlocrel field times sizeof"
555 "(struct relocation_info) of LC_DYSYMTAB command " +
556 Twine(LoadCommandIndex) + " extends past the end of "
557 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000558 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
559 Dysymtab.nlocrel *
560 sizeof(MachO::relocation_info),
561 "local relocation table"))
562 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000563 *DysymtabLoadCmd = Load.Ptr;
564 return Error::success();
565}
566
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000567static Error checkLinkeditDataCommand(const MachOObjectFile *Obj,
568 const MachOObjectFile::LoadCommandInfo &Load,
569 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000570 const char **LoadCmd, const char *CmdName,
571 std::list<MachOElement> &Elements,
572 const char *ElementName) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000573 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
574 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
575 CmdName + " cmdsize too small");
576 if (*LoadCmd != nullptr)
577 return malformedError("more than one " + Twine(CmdName) + " command");
578 MachO::linkedit_data_command LinkData =
579 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
580 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
581 return malformedError(Twine(CmdName) + " command " +
582 Twine(LoadCommandIndex) + " has incorrect cmdsize");
583 uint64_t FileSize = Obj->getData().size();
584 if (LinkData.dataoff > FileSize)
585 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
586 Twine(LoadCommandIndex) + " extends past the end of "
587 "the file");
588 uint64_t BigSize = LinkData.dataoff;
589 BigSize += LinkData.datasize;
590 if (BigSize > FileSize)
591 return malformedError("dataoff field plus datasize field of " +
592 Twine(CmdName) + " command " +
593 Twine(LoadCommandIndex) + " extends past the end of "
594 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000595 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
596 LinkData.datasize, ElementName))
597 return Err;
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000598 *LoadCmd = Load.Ptr;
599 return Error::success();
600}
601
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000602static Error checkDyldInfoCommand(const MachOObjectFile *Obj,
603 const MachOObjectFile::LoadCommandInfo &Load,
604 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000605 const char **LoadCmd, const char *CmdName,
606 std::list<MachOElement> &Elements) {
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000607 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
608 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
609 CmdName + " cmdsize too small");
610 if (*LoadCmd != nullptr)
611 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
612 "command");
613 MachO::dyld_info_command DyldInfo =
614 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
615 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
616 return malformedError(Twine(CmdName) + " command " +
617 Twine(LoadCommandIndex) + " has incorrect cmdsize");
618 uint64_t FileSize = Obj->getData().size();
619 if (DyldInfo.rebase_off > FileSize)
620 return malformedError("rebase_off field of " + Twine(CmdName) +
621 " command " + Twine(LoadCommandIndex) + " extends "
622 "past the end of the file");
623 uint64_t BigSize = DyldInfo.rebase_off;
624 BigSize += DyldInfo.rebase_size;
625 if (BigSize > FileSize)
626 return malformedError("rebase_off field plus rebase_size field of " +
627 Twine(CmdName) + " command " +
628 Twine(LoadCommandIndex) + " extends past the end of "
629 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000630 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
631 DyldInfo.rebase_size,
632 "dyld rebase info"))
633 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000634 if (DyldInfo.bind_off > FileSize)
635 return malformedError("bind_off field of " + Twine(CmdName) +
636 " command " + Twine(LoadCommandIndex) + " extends "
637 "past the end of the file");
638 BigSize = DyldInfo.bind_off;
639 BigSize += DyldInfo.bind_size;
640 if (BigSize > FileSize)
641 return malformedError("bind_off field plus bind_size field of " +
642 Twine(CmdName) + " command " +
643 Twine(LoadCommandIndex) + " extends past the end of "
644 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000645 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
646 DyldInfo.bind_size,
647 "dyld bind info"))
648 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000649 if (DyldInfo.weak_bind_off > FileSize)
650 return malformedError("weak_bind_off field of " + Twine(CmdName) +
651 " command " + Twine(LoadCommandIndex) + " extends "
652 "past the end of the file");
653 BigSize = DyldInfo.weak_bind_off;
654 BigSize += DyldInfo.weak_bind_size;
655 if (BigSize > FileSize)
656 return malformedError("weak_bind_off field plus weak_bind_size field of " +
657 Twine(CmdName) + " command " +
658 Twine(LoadCommandIndex) + " extends past the end of "
659 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000660 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
661 DyldInfo.weak_bind_size,
662 "dyld weak bind info"))
663 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000664 if (DyldInfo.lazy_bind_off > FileSize)
665 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
666 " command " + Twine(LoadCommandIndex) + " extends "
667 "past the end of the file");
668 BigSize = DyldInfo.lazy_bind_off;
669 BigSize += DyldInfo.lazy_bind_size;
670 if (BigSize > FileSize)
671 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
672 Twine(CmdName) + " command " +
673 Twine(LoadCommandIndex) + " extends past the end of "
674 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000675 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
676 DyldInfo.lazy_bind_size,
677 "dyld lazy bind info"))
678 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000679 if (DyldInfo.export_off > FileSize)
680 return malformedError("export_off field of " + Twine(CmdName) +
681 " command " + Twine(LoadCommandIndex) + " extends "
682 "past the end of the file");
683 BigSize = DyldInfo.export_off;
684 BigSize += DyldInfo.export_size;
685 if (BigSize > FileSize)
686 return malformedError("export_off field plus export_size field of " +
687 Twine(CmdName) + " command " +
688 Twine(LoadCommandIndex) + " extends past the end of "
689 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000690 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
691 DyldInfo.export_size,
692 "dyld export info"))
693 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000694 *LoadCmd = Load.Ptr;
695 return Error::success();
696}
697
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000698static Error checkDylibCommand(const MachOObjectFile *Obj,
699 const MachOObjectFile::LoadCommandInfo &Load,
700 uint32_t LoadCommandIndex, const char *CmdName) {
701 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
702 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
703 CmdName + " cmdsize too small");
704 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
705 if (D.dylib.name < sizeof(MachO::dylib_command))
706 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
707 CmdName + " name.offset field too small, not past "
708 "the end of the dylib_command struct");
709 if (D.dylib.name >= D.cmdsize)
710 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
711 CmdName + " name.offset field extends past the end "
712 "of the load command");
713 // Make sure there is a null between the starting offset of the name and
714 // the end of the load command.
715 uint32_t i;
716 const char *P = (const char *)Load.Ptr;
717 for (i = D.dylib.name; i < D.cmdsize; i++)
718 if (P[i] == '\0')
719 break;
720 if (i >= D.cmdsize)
721 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
722 CmdName + " library name extends past the end of the "
723 "load command");
724 return Error::success();
725}
726
727static Error checkDylibIdCommand(const MachOObjectFile *Obj,
728 const MachOObjectFile::LoadCommandInfo &Load,
729 uint32_t LoadCommandIndex,
730 const char **LoadCmd) {
731 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
732 "LC_ID_DYLIB"))
733 return Err;
734 if (*LoadCmd != nullptr)
735 return malformedError("more than one LC_ID_DYLIB command");
736 if (Obj->getHeader().filetype != MachO::MH_DYLIB &&
737 Obj->getHeader().filetype != MachO::MH_DYLIB_STUB)
738 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
739 "file type");
740 *LoadCmd = Load.Ptr;
741 return Error::success();
742}
743
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000744static Error checkDyldCommand(const MachOObjectFile *Obj,
745 const MachOObjectFile::LoadCommandInfo &Load,
746 uint32_t LoadCommandIndex, const char *CmdName) {
747 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
748 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
749 CmdName + " cmdsize too small");
750 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
751 if (D.name < sizeof(MachO::dylinker_command))
752 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
753 CmdName + " name.offset field too small, not past "
754 "the end of the dylinker_command struct");
755 if (D.name >= D.cmdsize)
756 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
757 CmdName + " name.offset field extends past the end "
758 "of the load command");
759 // Make sure there is a null between the starting offset of the name and
760 // the end of the load command.
761 uint32_t i;
762 const char *P = (const char *)Load.Ptr;
763 for (i = D.name; i < D.cmdsize; i++)
764 if (P[i] == '\0')
765 break;
766 if (i >= D.cmdsize)
767 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
768 CmdName + " dyld name extends past the end of the "
769 "load command");
770 return Error::success();
771}
772
Kevin Enderby32359db2016-09-28 21:20:45 +0000773static Error checkVersCommand(const MachOObjectFile *Obj,
774 const MachOObjectFile::LoadCommandInfo &Load,
775 uint32_t LoadCommandIndex,
776 const char **LoadCmd, const char *CmdName) {
777 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
778 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
779 CmdName + " has incorrect cmdsize");
780 if (*LoadCmd != nullptr)
781 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
782 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
783 "LC_VERSION_MIN_WATCHOS command");
784 *LoadCmd = Load.Ptr;
785 return Error::success();
786}
787
Kevin Enderby76966bf2016-09-28 23:16:01 +0000788static Error checkRpathCommand(const MachOObjectFile *Obj,
789 const MachOObjectFile::LoadCommandInfo &Load,
790 uint32_t LoadCommandIndex) {
791 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
792 return malformedError("load command " + Twine(LoadCommandIndex) +
793 " LC_RPATH cmdsize too small");
794 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
795 if (R.path < sizeof(MachO::rpath_command))
796 return malformedError("load command " + Twine(LoadCommandIndex) +
797 " LC_RPATH path.offset field too small, not past "
798 "the end of the rpath_command struct");
799 if (R.path >= R.cmdsize)
800 return malformedError("load command " + Twine(LoadCommandIndex) +
801 " LC_RPATH path.offset field extends past the end "
802 "of the load command");
803 // Make sure there is a null between the starting offset of the path and
804 // the end of the load command.
805 uint32_t i;
806 const char *P = (const char *)Load.Ptr;
807 for (i = R.path; i < R.cmdsize; i++)
808 if (P[i] == '\0')
809 break;
810 if (i >= R.cmdsize)
811 return malformedError("load command " + Twine(LoadCommandIndex) +
812 " LC_RPATH library name extends past the end of the "
813 "load command");
814 return Error::success();
815}
816
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000817static Error checkEncryptCommand(const MachOObjectFile *Obj,
818 const MachOObjectFile::LoadCommandInfo &Load,
819 uint32_t LoadCommandIndex,
820 uint64_t cryptoff, uint64_t cryptsize,
821 const char **LoadCmd, const char *CmdName) {
822 if (*LoadCmd != nullptr)
823 return malformedError("more than one LC_ENCRYPTION_INFO and or "
824 "LC_ENCRYPTION_INFO_64 command");
825 uint64_t FileSize = Obj->getData().size();
826 if (cryptoff > FileSize)
827 return malformedError("cryptoff field of " + Twine(CmdName) +
828 " command " + Twine(LoadCommandIndex) + " extends "
829 "past the end of the file");
830 uint64_t BigSize = cryptoff;
831 BigSize += cryptsize;
832 if (BigSize > FileSize)
833 return malformedError("cryptoff field plus cryptsize field of " +
834 Twine(CmdName) + " command " +
835 Twine(LoadCommandIndex) + " extends past the end of "
836 "the file");
837 *LoadCmd = Load.Ptr;
838 return Error::success();
839}
840
Kevin Enderby68fffa82016-10-11 21:04:39 +0000841static Error checkLinkerOptCommand(const MachOObjectFile *Obj,
842 const MachOObjectFile::LoadCommandInfo &Load,
843 uint32_t LoadCommandIndex) {
844 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
845 return malformedError("load command " + Twine(LoadCommandIndex) +
846 " LC_LINKER_OPTION cmdsize too small");
847 MachO::linker_option_command L =
848 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
849 // Make sure the count of strings is correct.
850 const char *string = (const char *)Load.Ptr +
851 sizeof(struct MachO::linker_option_command);
852 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
853 uint32_t i = 0;
854 while (left > 0) {
855 while (*string == '\0' && left > 0) {
856 string++;
857 left--;
858 }
859 if (left > 0) {
860 i++;
861 uint32_t NullPos = StringRef(string, left).find('\0');
862 uint32_t len = std::min(NullPos, left) + 1;
863 string += len;
864 left -= len;
865 }
866 }
867 if (L.count != i)
868 return malformedError("load command " + Twine(LoadCommandIndex) +
869 " LC_LINKER_OPTION string count " + Twine(L.count) +
870 " does not match number of strings");
871 return Error::success();
872}
873
Kevin Enderby2490de02016-10-17 22:09:25 +0000874static Error checkSubCommand(const MachOObjectFile *Obj,
875 const MachOObjectFile::LoadCommandInfo &Load,
876 uint32_t LoadCommandIndex, const char *CmdName,
877 size_t SizeOfCmd, const char *CmdStructName,
878 uint32_t PathOffset, const char *PathFieldName) {
879 if (PathOffset < SizeOfCmd)
880 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
881 CmdName + " " + PathFieldName + ".offset field too "
882 "small, not past the end of the " + CmdStructName);
883 if (PathOffset >= Load.C.cmdsize)
884 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
885 CmdName + " " + PathFieldName + ".offset field "
886 "extends past the end of the load command");
887 // Make sure there is a null between the starting offset of the path and
888 // the end of the load command.
889 uint32_t i;
890 const char *P = (const char *)Load.Ptr;
891 for (i = PathOffset; i < Load.C.cmdsize; i++)
892 if (P[i] == '\0')
893 break;
894 if (i >= Load.C.cmdsize)
895 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
896 CmdName + " " + PathFieldName + " name extends past "
897 "the end of the load command");
898 return Error::success();
899}
900
Kevin Enderby210030b2016-10-19 23:44:34 +0000901static Error checkThreadCommand(const MachOObjectFile *Obj,
902 const MachOObjectFile::LoadCommandInfo &Load,
903 uint32_t LoadCommandIndex,
904 const char *CmdName) {
905 if (Load.C.cmdsize < sizeof(MachO::thread_command))
906 return malformedError("load command " + Twine(LoadCommandIndex) +
907 CmdName + " cmdsize too small");
908 MachO::thread_command T =
909 getStruct<MachO::thread_command>(Obj, Load.Ptr);
910 const char *state = Load.Ptr + sizeof(MachO::thread_command);
911 const char *end = Load.Ptr + T.cmdsize;
912 uint32_t nflavor = 0;
913 uint32_t cputype = getCPUType(Obj);
914 while (state < end) {
915 if(state + sizeof(uint32_t) > end)
916 return malformedError("load command " + Twine(LoadCommandIndex) +
917 "flavor in " + CmdName + " extends past end of "
918 "command");
919 uint32_t flavor;
920 memcpy(&flavor, state, sizeof(uint32_t));
921 if (Obj->isLittleEndian() != sys::IsLittleEndianHost)
922 sys::swapByteOrder(flavor);
923 state += sizeof(uint32_t);
924
925 if(state + sizeof(uint32_t) > end)
926 return malformedError("load command " + Twine(LoadCommandIndex) +
927 " count in " + CmdName + " extends past end of "
928 "command");
929 uint32_t count;
930 memcpy(&count, state, sizeof(uint32_t));
931 if (Obj->isLittleEndian() != sys::IsLittleEndianHost)
932 sys::swapByteOrder(count);
933 state += sizeof(uint32_t);
934
935 if (cputype == MachO::CPU_TYPE_X86_64) {
936 if (flavor == MachO::x86_THREAD_STATE64) {
937 if (count != MachO::x86_THREAD_STATE64_COUNT)
938 return malformedError("load command " + Twine(LoadCommandIndex) +
939 " count not x86_THREAD_STATE64_COUNT for "
940 "flavor number " + Twine(nflavor) + " which is "
941 "a x86_THREAD_STATE64 flavor in " + CmdName +
942 " command");
943 if (state + sizeof(MachO::x86_thread_state64_t) > end)
944 return malformedError("load command " + Twine(LoadCommandIndex) +
945 " x86_THREAD_STATE64 extends past end of "
946 "command in " + CmdName + " command");
947 state += sizeof(MachO::x86_thread_state64_t);
948 } else {
949 return malformedError("load command " + Twine(LoadCommandIndex) +
950 " unknown flavor (" + Twine(flavor) + ") for "
951 "flavor number " + Twine(nflavor) + " in " +
952 CmdName + " command");
953 }
954 } else if (cputype == MachO::CPU_TYPE_ARM) {
955 if (flavor == MachO::ARM_THREAD_STATE) {
956 if (count != MachO::ARM_THREAD_STATE_COUNT)
957 return malformedError("load command " + Twine(LoadCommandIndex) +
958 " count not ARM_THREAD_STATE_COUNT for "
959 "flavor number " + Twine(nflavor) + " which is "
960 "a ARM_THREAD_STATE flavor in " + CmdName +
961 " command");
962 if (state + sizeof(MachO::arm_thread_state32_t) > end)
963 return malformedError("load command " + Twine(LoadCommandIndex) +
964 " ARM_THREAD_STATE extends past end of "
965 "command in " + CmdName + " command");
966 state += sizeof(MachO::arm_thread_state32_t);
967 } else {
968 return malformedError("load command " + Twine(LoadCommandIndex) +
969 " unknown flavor (" + Twine(flavor) + ") for "
970 "flavor number " + Twine(nflavor) + " in " +
971 CmdName + " command");
972 }
Kevin Enderby7747cb52016-11-03 20:51:28 +0000973 } else if (cputype == MachO::CPU_TYPE_ARM64) {
974 if (flavor == MachO::ARM_THREAD_STATE64) {
975 if (count != MachO::ARM_THREAD_STATE64_COUNT)
976 return malformedError("load command " + Twine(LoadCommandIndex) +
977 " count not ARM_THREAD_STATE64_COUNT for "
978 "flavor number " + Twine(nflavor) + " which is "
979 "a ARM_THREAD_STATE64 flavor in " + CmdName +
980 " command");
981 if (state + sizeof(MachO::arm_thread_state64_t) > end)
982 return malformedError("load command " + Twine(LoadCommandIndex) +
983 " ARM_THREAD_STATE64 extends past end of "
984 "command in " + CmdName + " command");
985 state += sizeof(MachO::arm_thread_state64_t);
986 } else {
987 return malformedError("load command " + Twine(LoadCommandIndex) +
988 " unknown flavor (" + Twine(flavor) + ") for "
989 "flavor number " + Twine(nflavor) + " in " +
990 CmdName + " command");
991 }
Kevin Enderby210030b2016-10-19 23:44:34 +0000992 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
993 if (flavor == MachO::PPC_THREAD_STATE) {
994 if (count != MachO::PPC_THREAD_STATE_COUNT)
995 return malformedError("load command " + Twine(LoadCommandIndex) +
996 " count not PPC_THREAD_STATE_COUNT for "
997 "flavor number " + Twine(nflavor) + " which is "
998 "a PPC_THREAD_STATE flavor in " + CmdName +
999 " command");
1000 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1001 return malformedError("load command " + Twine(LoadCommandIndex) +
1002 " PPC_THREAD_STATE extends past end of "
1003 "command in " + CmdName + " command");
1004 state += sizeof(MachO::ppc_thread_state32_t);
1005 } else {
1006 return malformedError("load command " + Twine(LoadCommandIndex) +
1007 " unknown flavor (" + Twine(flavor) + ") for "
1008 "flavor number " + Twine(nflavor) + " in " +
1009 CmdName + " command");
1010 }
1011 } else {
1012 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1013 "command " + Twine(LoadCommandIndex) + " for " +
1014 CmdName + " command can't be checked");
1015 }
1016 nflavor++;
1017 }
1018 return Error::success();
1019}
1020
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001021static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj,
1022 const MachOObjectFile::LoadCommandInfo
1023 &Load,
1024 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001025 const char **LoadCmd,
1026 std::list<MachOElement> &Elements) {
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001027 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1028 return malformedError("load command " + Twine(LoadCommandIndex) +
1029 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1030 if (*LoadCmd != nullptr)
1031 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1032 MachO::twolevel_hints_command Hints =
1033 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1034 uint64_t FileSize = Obj->getData().size();
1035 if (Hints.offset > FileSize)
1036 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1037 Twine(LoadCommandIndex) + " extends past the end of "
1038 "the file");
1039 uint64_t BigSize = Hints.nhints;
1040 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
1041 BigSize += Hints.offset;
1042 if (BigSize > FileSize)
1043 return malformedError("offset field plus nhints times sizeof(struct "
1044 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1045 Twine(LoadCommandIndex) + " extends past the end of "
1046 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001047 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1048 sizeof(MachO::twolevel_hint),
1049 "two level hints"))
1050 return Err;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001051 *LoadCmd = Load.Ptr;
1052 return Error::success();
1053}
1054
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001055// Returns true if the libObject code does not support the load command and its
1056// contents. The cmd value it is treated as an unknown load command but with
1057// an error message that says the cmd value is obsolete.
1058static bool isLoadCommandObsolete(uint32_t cmd) {
1059 if (cmd == MachO::LC_SYMSEG ||
1060 cmd == MachO::LC_LOADFVMLIB ||
1061 cmd == MachO::LC_IDFVMLIB ||
1062 cmd == MachO::LC_IDENT ||
1063 cmd == MachO::LC_FVMFILE ||
1064 cmd == MachO::LC_PREPAGE ||
1065 cmd == MachO::LC_PREBOUND_DYLIB ||
1066 cmd == MachO::LC_TWOLEVEL_HINTS ||
1067 cmd == MachO::LC_PREBIND_CKSUM)
1068 return true;
1069 return false;
1070}
1071
Lang Hames82627642016-03-25 21:59:14 +00001072Expected<std::unique_ptr<MachOObjectFile>>
1073MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001074 bool Is64Bits, uint32_t UniversalCputype,
1075 uint32_t UniversalIndex) {
Mehdi Amini41af4302016-11-11 04:28:40 +00001076 Error Err = Error::success();
Lang Hames82627642016-03-25 21:59:14 +00001077 std::unique_ptr<MachOObjectFile> Obj(
1078 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001079 Is64Bits, Err, UniversalCputype,
1080 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +00001081 if (Err)
1082 return std::move(Err);
1083 return std::move(Obj);
1084}
1085
Rafael Espindola48af1c22014-08-19 18:44:46 +00001086MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001087 bool Is64bits, Error &Err,
1088 uint32_t UniversalCputype,
1089 uint32_t UniversalIndex)
Rafael Espindola48af1c22014-08-19 18:44:46 +00001090 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +00001091 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +00001092 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
1093 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
1094 HasPageZeroSegment(false) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001095 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001096 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001097 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001098 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +00001099 parseHeader(this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001100 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001101 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001102 } else {
Lang Hames9e964f32016-03-25 17:25:34 +00001103 parseHeader(this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001104 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001105 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001106 }
Lang Hames9e964f32016-03-25 17:25:34 +00001107 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001108 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001109 SizeOfHeaders += getHeader().sizeofcmds;
1110 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001111 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001112 return;
1113 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001114 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1115 Err = malformedError("universal header architecture: " +
1116 Twine(UniversalIndex) + "'s cputype does not match "
1117 "object file's mach header");
1118 return;
1119 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001120 std::list<MachOElement> Elements;
1121 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001122
1123 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001124 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001125 if (LoadCommandCount != 0) {
1126 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
1127 Load = *LoadOrErr;
1128 else {
1129 Err = LoadOrErr.takeError();
1130 return;
1131 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001132 }
Lang Hames9e964f32016-03-25 17:25:34 +00001133
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001134 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001135 const char *FuncStartsLoadCmd = nullptr;
1136 const char *SplitInfoLoadCmd = nullptr;
1137 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001138 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001139 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001140 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001141 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001142 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001143 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001144 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001145 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001146 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001147 if (is64Bit()) {
1148 if (Load.C.cmdsize % 8 != 0) {
1149 // We have a hack here to allow 64-bit Mach-O core files to have
1150 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1151 // allowed since the macOS kernel produces them.
1152 if (getHeader().filetype != MachO::MH_CORE ||
1153 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1154 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1155 "multiple of 8");
1156 return;
1157 }
1158 }
1159 } else {
1160 if (Load.C.cmdsize % 4 != 0) {
1161 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1162 "multiple of 4");
1163 return;
1164 }
1165 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001166 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001167 if (Load.C.cmd == MachO::LC_SYMTAB) {
Kevin Enderbyd5039402016-10-31 20:29:48 +00001168 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001169 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001170 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001171 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd,
1172 Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001173 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001174 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +00001175 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001176 "LC_DATA_IN_CODE", Elements,
1177 "data in code info")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001178 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001179 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +00001180 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001181 "LC_LINKER_OPTIMIZATION_HINT",
1182 Elements, "linker optimization "
1183 "hints")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001184 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001185 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1186 if ((Err = checkLinkeditDataCommand(this, Load, I, &FuncStartsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001187 "LC_FUNCTION_STARTS", Elements,
1188 "function starts data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001189 return;
1190 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1191 if ((Err = checkLinkeditDataCommand(this, Load, I, &SplitInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001192 "LC_SEGMENT_SPLIT_INFO", Elements,
1193 "split info data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001194 return;
1195 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1196 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignDrsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001197 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1198 "code signing RDs data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001199 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001200 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1201 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001202 "LC_CODE_SIGNATURE", Elements,
1203 "code signature data")))
Kevin Enderby89baf992016-10-18 20:24:12 +00001204 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001205 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1206 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001207 "LC_DYLD_INFO", Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001208 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001209 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1210 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001211 "LC_DYLD_INFO_ONLY", Elements)))
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001212 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001213 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001214 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1215 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1216 "cmdsize");
1217 return;
1218 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001219 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001220 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001221 return;
1222 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001223 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001224 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001225 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1226 MachO::section_64>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +00001227 this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001228 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001229 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001230 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001231 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1232 MachO::section>(
1233 this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001234 "LC_SEGMENT", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001235 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001236 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1237 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd)))
1238 return;
1239 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1240 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB")))
1241 return;
1242 Libraries.push_back(Load.Ptr);
1243 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1244 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1245 return;
1246 Libraries.push_back(Load.Ptr);
1247 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1248 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1249 return;
1250 Libraries.push_back(Load.Ptr);
1251 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1252 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB")))
1253 return;
1254 Libraries.push_back(Load.Ptr);
1255 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1256 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1257 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001258 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001259 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1260 if ((Err = checkDyldCommand(this, Load, I, "LC_ID_DYLINKER")))
1261 return;
1262 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1263 if ((Err = checkDyldCommand(this, Load, I, "LC_LOAD_DYLINKER")))
1264 return;
1265 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1266 if ((Err = checkDyldCommand(this, Load, I, "LC_DYLD_ENVIRONMENT")))
1267 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001268 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1269 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1270 "LC_VERSION_MIN_MACOSX")))
1271 return;
1272 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1273 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1274 "LC_VERSION_MIN_IPHONEOS")))
1275 return;
1276 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1277 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1278 "LC_VERSION_MIN_TVOS")))
1279 return;
1280 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1281 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1282 "LC_VERSION_MIN_WATCHOS")))
1283 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001284 } else if (Load.C.cmd == MachO::LC_RPATH) {
1285 if ((Err = checkRpathCommand(this, Load, I)))
1286 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001287 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1288 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1289 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1290 " has incorrect cmdsize");
1291 return;
1292 }
1293 if (SourceLoadCmd) {
1294 Err = malformedError("more than one LC_SOURCE_VERSION command");
1295 return;
1296 }
1297 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001298 } else if (Load.C.cmd == MachO::LC_MAIN) {
1299 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1300 Err = malformedError("LC_MAIN command " + Twine(I) +
1301 " has incorrect cmdsize");
1302 return;
1303 }
1304 if (EntryPointLoadCmd) {
1305 Err = malformedError("more than one LC_MAIN command");
1306 return;
1307 }
1308 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001309 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1310 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1311 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1312 " has incorrect cmdsize");
1313 return;
1314 }
1315 MachO::encryption_info_command E =
1316 getStruct<MachO::encryption_info_command>(this, Load.Ptr);
1317 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize,
1318 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1319 return;
1320 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1321 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1322 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1323 " has incorrect cmdsize");
1324 return;
1325 }
1326 MachO::encryption_info_command_64 E =
1327 getStruct<MachO::encryption_info_command_64>(this, Load.Ptr);
1328 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize,
1329 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1330 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001331 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1332 if ((Err = checkLinkerOptCommand(this, Load, I)))
1333 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001334 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1335 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1336 Err = malformedError("load command " + Twine(I) +
1337 " LC_SUB_FRAMEWORK cmdsize too small");
1338 return;
1339 }
1340 MachO::sub_framework_command S =
1341 getStruct<MachO::sub_framework_command>(this, Load.Ptr);
1342 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK",
1343 sizeof(MachO::sub_framework_command),
1344 "sub_framework_command", S.umbrella,
1345 "umbrella")))
1346 return;
1347 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1348 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1349 Err = malformedError("load command " + Twine(I) +
1350 " LC_SUB_UMBRELLA cmdsize too small");
1351 return;
1352 }
1353 MachO::sub_umbrella_command S =
1354 getStruct<MachO::sub_umbrella_command>(this, Load.Ptr);
1355 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA",
1356 sizeof(MachO::sub_umbrella_command),
1357 "sub_umbrella_command", S.sub_umbrella,
1358 "sub_umbrella")))
1359 return;
1360 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1361 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1362 Err = malformedError("load command " + Twine(I) +
1363 " LC_SUB_LIBRARY cmdsize too small");
1364 return;
1365 }
1366 MachO::sub_library_command S =
1367 getStruct<MachO::sub_library_command>(this, Load.Ptr);
1368 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY",
1369 sizeof(MachO::sub_library_command),
1370 "sub_library_command", S.sub_library,
1371 "sub_library")))
1372 return;
1373 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1374 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1375 Err = malformedError("load command " + Twine(I) +
1376 " LC_SUB_CLIENT cmdsize too small");
1377 return;
1378 }
1379 MachO::sub_client_command S =
1380 getStruct<MachO::sub_client_command>(this, Load.Ptr);
1381 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT",
1382 sizeof(MachO::sub_client_command),
1383 "sub_client_command", S.client, "client")))
1384 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001385 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1386 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1387 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1388 " has incorrect cmdsize");
1389 return;
1390 }
1391 if (RoutinesLoadCmd) {
1392 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1393 "command");
1394 return;
1395 }
1396 RoutinesLoadCmd = Load.Ptr;
1397 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1398 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1399 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1400 " has incorrect cmdsize");
1401 return;
1402 }
1403 if (RoutinesLoadCmd) {
1404 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1405 "command");
1406 return;
1407 }
1408 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001409 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1410 if ((Err = checkThreadCommand(this, Load, I, "LC_UNIXTHREAD")))
1411 return;
1412 if (UnixThreadLoadCmd) {
1413 Err = malformedError("more than one LC_UNIXTHREAD command");
1414 return;
1415 }
1416 UnixThreadLoadCmd = Load.Ptr;
1417 } else if (Load.C.cmd == MachO::LC_THREAD) {
1418 if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD")))
1419 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001420 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001421 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1422 if ((Err = checkTwoLevelHintsCommand(this, Load, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001423 &TwoLevelHintsLoadCmd, Elements)))
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001424 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001425 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1426 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1427 Twine(Load.C.cmd) + " is obsolete and not "
1428 "supported");
1429 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001430 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001431 // TODO: generate a error for unknown load commands by default. But still
1432 // need work out an approach to allow or not allow unknown values like this
1433 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001434 if (I < LoadCommandCount - 1) {
Kevin Enderby368e7142016-05-03 17:16:08 +00001435 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001436 Load = *LoadOrErr;
1437 else {
1438 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001439 return;
1440 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001441 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001442 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001443 if (!SymtabLoadCmd) {
1444 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001445 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001446 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001447 return;
1448 }
1449 } else if (DysymtabLoadCmd) {
1450 MachO::symtab_command Symtab =
1451 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1452 MachO::dysymtab_command Dysymtab =
1453 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1454 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001455 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001456 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001457 return;
1458 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001459 uint64_t BigSize = Dysymtab.ilocalsym;
1460 BigSize += Dysymtab.nlocalsym;
1461 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001462 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001463 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001464 return;
1465 }
1466 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001467 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001468 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001469 return;
1470 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001471 BigSize = Dysymtab.iextdefsym;
1472 BigSize += Dysymtab.nextdefsym;
1473 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001474 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001475 "load command extends past the end of the symbol "
1476 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001477 return;
1478 }
1479 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001480 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001481 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001482 return;
1483 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001484 BigSize = Dysymtab.iundefsym;
1485 BigSize += Dysymtab.nundefsym;
1486 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001487 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001488 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001489 return;
1490 }
1491 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001492 if ((getHeader().filetype == MachO::MH_DYLIB ||
1493 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1494 DyldIdLoadCmd == nullptr) {
1495 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1496 "filetype");
1497 return;
1498 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001499 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001500
1501 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001502}
1503
Kevin Enderby22fc0072016-11-14 20:57:04 +00001504Error MachOObjectFile::checkSymbolTable() const {
1505 uint32_t Flags = 0;
1506 if (is64Bit()) {
1507 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1508 Flags = H_64.flags;
1509 } else {
1510 MachO::mach_header H = MachOObjectFile::getHeader();
1511 Flags = H.flags;
1512 }
1513 uint8_t NType = 0;
1514 uint8_t NSect = 0;
1515 uint16_t NDesc = 0;
1516 uint32_t NStrx = 0;
1517 uint64_t NValue = 0;
1518 uint32_t SymbolIndex = 0;
1519 MachO::symtab_command S = getSymtabLoadCommand();
1520 for (const SymbolRef &Symbol : symbols()) {
1521 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1522 if (is64Bit()) {
1523 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1524 NType = STE_64.n_type;
1525 NSect = STE_64.n_sect;
1526 NDesc = STE_64.n_desc;
1527 NStrx = STE_64.n_strx;
1528 NValue = STE_64.n_value;
1529 } else {
1530 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1531 NType = STE.n_type;
1532 NType = STE.n_type;
1533 NSect = STE.n_sect;
1534 NDesc = STE.n_desc;
1535 NStrx = STE.n_strx;
1536 NValue = STE.n_value;
1537 }
1538 if ((NType & MachO::N_STAB) == 0 &&
1539 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1540 if (NSect == 0 || NSect > Sections.size())
1541 return malformedError("bad section index: " + Twine((int)NSect) +
1542 " for symbol at index " + Twine(SymbolIndex));
1543 }
1544 if ((NType & MachO::N_STAB) == 0 &&
1545 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1546 if (NValue >= S.strsize)
1547 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1548 "the end of string table, for N_INDR symbol at "
1549 "index " + Twine(SymbolIndex));
1550 }
1551 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1552 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1553 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1554 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1555 if (LibraryOrdinal != 0 &&
1556 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1557 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1558 LibraryOrdinal - 1 >= Libraries.size() ) {
1559 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1560 " for symbol at index " + Twine(SymbolIndex));
1561 }
1562 }
1563 if (NStrx >= S.strsize)
1564 return malformedError("bad string table index: " + Twine((int)NStrx) +
1565 " past the end of string table, for symbol at "
1566 "index " + Twine(SymbolIndex));
1567 SymbolIndex++;
1568 }
1569 return Error::success();
1570}
1571
Rafael Espindola5e812af2014-01-30 02:49:50 +00001572void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001573 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001574 sizeof(MachO::nlist_64) :
1575 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001576 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001577}
1578
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001579Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001580 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001581 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001582 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001583 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001584 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001585 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001586 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001587 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001588}
1589
Rafael Espindola0e77a942014-12-10 20:46:55 +00001590unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1591 DataRefImpl DRI = Sec.getRawDataRefImpl();
1592 uint32_t Flags = getSectionFlags(this, DRI);
1593 return Flags & MachO::SECTION_TYPE;
1594}
1595
Rafael Espindola59128922015-06-24 18:14:41 +00001596uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1597 if (is64Bit()) {
1598 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1599 return Entry.n_value;
1600 }
1601 MachO::nlist Entry = getSymbolTableEntry(Sym);
1602 return Entry.n_value;
1603}
1604
Kevin Enderby980b2582014-06-05 21:21:57 +00001605// getIndirectName() returns the name of the alias'ed symbol who's string table
1606// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001607std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1608 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001609 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +00001610 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
1611 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1612 return object_error::parse_failed;
1613 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001614 if (NValue >= StringTable.size())
1615 return object_error::parse_failed;
1616 const char *Start = &StringTable.data()[NValue];
1617 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001618 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001619}
1620
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001621uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001622 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001623}
1624
Kevin Enderby931cb652016-06-24 18:24:42 +00001625Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001626 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001627}
1628
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001629uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001630 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001631 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001632 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001633 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001634 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001635 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001636}
1637
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001638uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001639 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001640}
1641
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001642Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001643MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001644 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001645 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001646
Rafael Espindola56f976f2013-04-18 18:08:55 +00001647 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001648 if (n_type & MachO::N_STAB)
1649 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001650
Charles Davis74ec8b02013-08-27 05:00:13 +00001651 switch (n_type & MachO::N_TYPE) {
1652 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001653 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001654 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001655 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001656 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001657 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001658 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001659 if (Sec->isData() || Sec->isBSS())
1660 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001661 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001662 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001663 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001664}
1665
Rafael Espindola20122a42014-01-31 20:57:12 +00001666uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001667 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001668
Charles Davis8bdfafd2013-09-01 04:28:48 +00001669 uint8_t MachOType = Entry.n_type;
1670 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001671
Rafael Espindola20122a42014-01-31 20:57:12 +00001672 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001673
Tim Northovereaef0742014-05-30 13:22:59 +00001674 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1675 Result |= SymbolRef::SF_Indirect;
1676
Rafael Espindolaa1356322013-11-02 05:03:24 +00001677 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001678 Result |= SymbolRef::SF_FormatSpecific;
1679
Charles Davis74ec8b02013-08-27 05:00:13 +00001680 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001681 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001682 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001683 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001684 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001685 else
1686 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001687 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001688
1689 if (!(MachOType & MachO::N_PEXT))
1690 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001691 }
1692
Charles Davis74ec8b02013-08-27 05:00:13 +00001693 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001694 Result |= SymbolRef::SF_Weak;
1695
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001696 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1697 Result |= SymbolRef::SF_Thumb;
1698
Charles Davis74ec8b02013-08-27 05:00:13 +00001699 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001700 Result |= SymbolRef::SF_Absolute;
1701
Rafael Espindola20122a42014-01-31 20:57:12 +00001702 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001703}
1704
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001705Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001706MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001707 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001708 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001709
Rafael Espindola8bab8892015-08-07 23:27:14 +00001710 if (index == 0)
1711 return section_end();
1712 DataRefImpl DRI;
1713 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001714 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001715 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001716 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001717 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001718 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001719}
1720
Rafael Espindola6bf32212015-06-24 19:57:32 +00001721unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1722 MachO::nlist_base Entry =
1723 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
1724 return Entry.n_sect - 1;
1725}
1726
Rafael Espindola5e812af2014-01-30 02:49:50 +00001727void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001728 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001729}
1730
Rafael Espindola3acea392014-06-12 21:46:39 +00001731std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1732 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001733 ArrayRef<char> Raw = getSectionRawName(Sec);
1734 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001735 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001736}
1737
Rafael Espindola80291272014-10-08 15:28:58 +00001738uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1739 if (is64Bit())
1740 return getSection64(Sec).addr;
1741 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001742}
1743
Rafael Espindola80291272014-10-08 15:28:58 +00001744uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001745 // In the case if a malformed Mach-O file where the section offset is past
1746 // the end of the file or some part of the section size is past the end of
1747 // the file return a size of zero or a size that covers the rest of the file
1748 // but does not extend past the end of the file.
1749 uint32_t SectOffset, SectType;
1750 uint64_t SectSize;
1751
1752 if (is64Bit()) {
1753 MachO::section_64 Sect = getSection64(Sec);
1754 SectOffset = Sect.offset;
1755 SectSize = Sect.size;
1756 SectType = Sect.flags & MachO::SECTION_TYPE;
1757 } else {
1758 MachO::section Sect = getSection(Sec);
1759 SectOffset = Sect.offset;
1760 SectSize = Sect.size;
1761 SectType = Sect.flags & MachO::SECTION_TYPE;
1762 }
1763 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1764 return SectSize;
1765 uint64_t FileSize = getData().size();
1766 if (SectOffset > FileSize)
1767 return 0;
1768 if (FileSize - SectOffset < SectSize)
1769 return FileSize - SectOffset;
1770 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001771}
1772
Rafael Espindola3acea392014-06-12 21:46:39 +00001773std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1774 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001775 uint32_t Offset;
1776 uint64_t Size;
1777
1778 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001779 MachO::section_64 Sect = getSection64(Sec);
1780 Offset = Sect.offset;
1781 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001782 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001783 MachO::section Sect = getSection(Sec);
1784 Offset = Sect.offset;
1785 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001786 }
1787
1788 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001789 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001790}
1791
Rafael Espindola80291272014-10-08 15:28:58 +00001792uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001793 uint32_t Align;
1794 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001795 MachO::section_64 Sect = getSection64(Sec);
1796 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001797 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001798 MachO::section Sect = getSection(Sec);
1799 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001800 }
1801
Rafael Espindola80291272014-10-08 15:28:58 +00001802 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001803}
1804
George Rimar401e4e52016-05-24 12:48:46 +00001805bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1806 return false;
1807}
1808
Rafael Espindola80291272014-10-08 15:28:58 +00001809bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001810 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001811 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001812}
1813
Rafael Espindola80291272014-10-08 15:28:58 +00001814bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +00001815 uint32_t Flags = getSectionFlags(this, Sec);
1816 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001817 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1818 !(SectionType == MachO::S_ZEROFILL ||
1819 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001820}
1821
Rafael Espindola80291272014-10-08 15:28:58 +00001822bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +00001823 uint32_t Flags = getSectionFlags(this, Sec);
1824 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001825 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1826 (SectionType == MachO::S_ZEROFILL ||
1827 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001828}
1829
Rafael Espindola6bf32212015-06-24 19:57:32 +00001830unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1831 return Sec.getRawDataRefImpl().d.a;
1832}
1833
Rafael Espindola80291272014-10-08 15:28:58 +00001834bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +00001835 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +00001836 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001837}
1838
Steven Wuf2fe0142016-02-29 19:40:10 +00001839bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1840 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1841 StringRef SectName;
1842 if (!getSectionName(Sec, SectName))
1843 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1844 return false;
1845}
1846
Rui Ueyamabc654b12013-09-27 21:47:05 +00001847relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001848 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001849 Ret.d.a = Sec.d.a;
1850 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001851 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001852}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001853
Rafael Espindola56f976f2013-04-18 18:08:55 +00001854relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00001855MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001856 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001857 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001858 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001859 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001860 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001861 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001862 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001863 }
Eric Christopher7b015c72011-04-22 03:19:48 +00001864
Rafael Espindola56f976f2013-04-18 18:08:55 +00001865 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001866 Ret.d.a = Sec.d.a;
1867 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001868 return relocation_iterator(RelocationRef(Ret, this));
1869}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001870
Rafael Espindola5e812af2014-01-30 02:49:50 +00001871void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001872 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001873}
Owen Anderson171f4852011-10-24 23:20:07 +00001874
Rafael Espindola96d071c2015-06-29 23:29:12 +00001875uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +00001876 assert(getHeader().filetype == MachO::MH_OBJECT &&
1877 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001878 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00001879 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00001880}
1881
Rafael Espindola806f0062013-06-05 01:33:53 +00001882symbol_iterator
1883MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001884 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00001885 if (isRelocationScattered(RE))
1886 return symbol_end();
1887
Rafael Espindola56f976f2013-04-18 18:08:55 +00001888 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1889 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00001890 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00001891 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00001892
Charles Davis8bdfafd2013-09-01 04:28:48 +00001893 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001894 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001895 sizeof(MachO::nlist_64) :
1896 sizeof(MachO::nlist);
1897 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001898 DataRefImpl Sym;
1899 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00001900 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001901}
1902
Keno Fischerc780e8e2015-05-21 21:24:32 +00001903section_iterator
1904MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
1905 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
1906}
1907
Rafael Espindola99c041b2015-06-30 01:53:01 +00001908uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001909 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00001910 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001911}
1912
Rafael Espindola41bb4322015-06-30 04:08:37 +00001913void MachOObjectFile::getRelocationTypeName(
1914 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001915 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00001916 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001917
1918 unsigned Arch = this->getArch();
1919
1920 switch (Arch) {
1921 case Triple::x86: {
1922 static const char *const Table[] = {
1923 "GENERIC_RELOC_VANILLA",
1924 "GENERIC_RELOC_PAIR",
1925 "GENERIC_RELOC_SECTDIFF",
1926 "GENERIC_RELOC_PB_LA_PTR",
1927 "GENERIC_RELOC_LOCAL_SECTDIFF",
1928 "GENERIC_RELOC_TLV" };
1929
Eric Christopher13250cb2013-12-06 02:33:38 +00001930 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001931 res = "Unknown";
1932 else
1933 res = Table[RType];
1934 break;
1935 }
1936 case Triple::x86_64: {
1937 static const char *const Table[] = {
1938 "X86_64_RELOC_UNSIGNED",
1939 "X86_64_RELOC_SIGNED",
1940 "X86_64_RELOC_BRANCH",
1941 "X86_64_RELOC_GOT_LOAD",
1942 "X86_64_RELOC_GOT",
1943 "X86_64_RELOC_SUBTRACTOR",
1944 "X86_64_RELOC_SIGNED_1",
1945 "X86_64_RELOC_SIGNED_2",
1946 "X86_64_RELOC_SIGNED_4",
1947 "X86_64_RELOC_TLV" };
1948
1949 if (RType > 9)
1950 res = "Unknown";
1951 else
1952 res = Table[RType];
1953 break;
1954 }
1955 case Triple::arm: {
1956 static const char *const Table[] = {
1957 "ARM_RELOC_VANILLA",
1958 "ARM_RELOC_PAIR",
1959 "ARM_RELOC_SECTDIFF",
1960 "ARM_RELOC_LOCAL_SECTDIFF",
1961 "ARM_RELOC_PB_LA_PTR",
1962 "ARM_RELOC_BR24",
1963 "ARM_THUMB_RELOC_BR22",
1964 "ARM_THUMB_32BIT_BRANCH",
1965 "ARM_RELOC_HALF",
1966 "ARM_RELOC_HALF_SECTDIFF" };
1967
1968 if (RType > 9)
1969 res = "Unknown";
1970 else
1971 res = Table[RType];
1972 break;
1973 }
Tim Northover00ed9962014-03-29 10:18:08 +00001974 case Triple::aarch64: {
1975 static const char *const Table[] = {
1976 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
1977 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
1978 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
1979 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
1980 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
1981 "ARM64_RELOC_ADDEND"
1982 };
1983
1984 if (RType >= array_lengthof(Table))
1985 res = "Unknown";
1986 else
1987 res = Table[RType];
1988 break;
1989 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001990 case Triple::ppc: {
1991 static const char *const Table[] = {
1992 "PPC_RELOC_VANILLA",
1993 "PPC_RELOC_PAIR",
1994 "PPC_RELOC_BR14",
1995 "PPC_RELOC_BR24",
1996 "PPC_RELOC_HI16",
1997 "PPC_RELOC_LO16",
1998 "PPC_RELOC_HA16",
1999 "PPC_RELOC_LO14",
2000 "PPC_RELOC_SECTDIFF",
2001 "PPC_RELOC_PB_LA_PTR",
2002 "PPC_RELOC_HI16_SECTDIFF",
2003 "PPC_RELOC_LO16_SECTDIFF",
2004 "PPC_RELOC_HA16_SECTDIFF",
2005 "PPC_RELOC_JBSR",
2006 "PPC_RELOC_LO14_SECTDIFF",
2007 "PPC_RELOC_LOCAL_SECTDIFF" };
2008
Eric Christopher13250cb2013-12-06 02:33:38 +00002009 if (RType > 15)
2010 res = "Unknown";
2011 else
2012 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00002013 break;
2014 }
2015 case Triple::UnknownArch:
2016 res = "Unknown";
2017 break;
2018 }
2019 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00002020}
2021
Keno Fischer281b6942015-05-30 19:44:53 +00002022uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2023 MachO::any_relocation_info RE = getRelocation(Rel);
2024 return getAnyRelocationLength(RE);
2025}
2026
Kevin Enderby980b2582014-06-05 21:21:57 +00002027//
2028// guessLibraryShortName() is passed a name of a dynamic library and returns a
2029// guess on what the short name is. Then name is returned as a substring of the
2030// StringRef Name passed in. The name of the dynamic library is recognized as
2031// a framework if it has one of the two following forms:
2032// Foo.framework/Versions/A/Foo
2033// Foo.framework/Foo
2034// Where A and Foo can be any string. And may contain a trailing suffix
2035// starting with an underbar. If the Name is recognized as a framework then
2036// isFramework is set to true else it is set to false. If the Name has a
2037// suffix then Suffix is set to the substring in Name that contains the suffix
2038// else it is set to a NULL StringRef.
2039//
2040// The Name of the dynamic library is recognized as a library name if it has
2041// one of the two following forms:
2042// libFoo.A.dylib
2043// libFoo.dylib
2044// The library may have a suffix trailing the name Foo of the form:
2045// libFoo_profile.A.dylib
2046// libFoo_profile.dylib
2047//
2048// The Name of the dynamic library is also recognized as a library name if it
2049// has the following form:
2050// Foo.qtx
2051//
2052// If the Name of the dynamic library is none of the forms above then a NULL
2053// StringRef is returned.
2054//
2055StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2056 bool &isFramework,
2057 StringRef &Suffix) {
2058 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2059 size_t a, b, c, d, Idx;
2060
2061 isFramework = false;
2062 Suffix = StringRef();
2063
2064 // Pull off the last component and make Foo point to it
2065 a = Name.rfind('/');
2066 if (a == Name.npos || a == 0)
2067 goto guess_library;
2068 Foo = Name.slice(a+1, Name.npos);
2069
2070 // Look for a suffix starting with a '_'
2071 Idx = Foo.rfind('_');
2072 if (Idx != Foo.npos && Foo.size() >= 2) {
2073 Suffix = Foo.slice(Idx, Foo.npos);
2074 Foo = Foo.slice(0, Idx);
2075 }
2076
2077 // First look for the form Foo.framework/Foo
2078 b = Name.rfind('/', a);
2079 if (b == Name.npos)
2080 Idx = 0;
2081 else
2082 Idx = b+1;
2083 F = Name.slice(Idx, Idx + Foo.size());
2084 DotFramework = Name.slice(Idx + Foo.size(),
2085 Idx + Foo.size() + sizeof(".framework/")-1);
2086 if (F == Foo && DotFramework == ".framework/") {
2087 isFramework = true;
2088 return Foo;
2089 }
2090
2091 // Next look for the form Foo.framework/Versions/A/Foo
2092 if (b == Name.npos)
2093 goto guess_library;
2094 c = Name.rfind('/', b);
2095 if (c == Name.npos || c == 0)
2096 goto guess_library;
2097 V = Name.slice(c+1, Name.npos);
2098 if (!V.startswith("Versions/"))
2099 goto guess_library;
2100 d = Name.rfind('/', c);
2101 if (d == Name.npos)
2102 Idx = 0;
2103 else
2104 Idx = d+1;
2105 F = Name.slice(Idx, Idx + Foo.size());
2106 DotFramework = Name.slice(Idx + Foo.size(),
2107 Idx + Foo.size() + sizeof(".framework/")-1);
2108 if (F == Foo && DotFramework == ".framework/") {
2109 isFramework = true;
2110 return Foo;
2111 }
2112
2113guess_library:
2114 // pull off the suffix after the "." and make a point to it
2115 a = Name.rfind('.');
2116 if (a == Name.npos || a == 0)
2117 return StringRef();
2118 Dylib = Name.slice(a, Name.npos);
2119 if (Dylib != ".dylib")
2120 goto guess_qtx;
2121
2122 // First pull off the version letter for the form Foo.A.dylib if any.
2123 if (a >= 3) {
2124 Dot = Name.slice(a-2, a-1);
2125 if (Dot == ".")
2126 a = a - 2;
2127 }
2128
2129 b = Name.rfind('/', a);
2130 if (b == Name.npos)
2131 b = 0;
2132 else
2133 b = b+1;
2134 // ignore any suffix after an underbar like Foo_profile.A.dylib
2135 Idx = Name.find('_', b);
2136 if (Idx != Name.npos && Idx != b) {
2137 Lib = Name.slice(b, Idx);
2138 Suffix = Name.slice(Idx, a);
2139 }
2140 else
2141 Lib = Name.slice(b, a);
2142 // There are incorrect library names of the form:
2143 // libATS.A_profile.dylib so check for these.
2144 if (Lib.size() >= 3) {
2145 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2146 if (Dot == ".")
2147 Lib = Lib.slice(0, Lib.size()-2);
2148 }
2149 return Lib;
2150
2151guess_qtx:
2152 Qtx = Name.slice(a, Name.npos);
2153 if (Qtx != ".qtx")
2154 return StringRef();
2155 b = Name.rfind('/', a);
2156 if (b == Name.npos)
2157 Lib = Name.slice(0, a);
2158 else
2159 Lib = Name.slice(b+1, a);
2160 // There are library names of the form: QT.A.qtx so check for these.
2161 if (Lib.size() >= 3) {
2162 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2163 if (Dot == ".")
2164 Lib = Lib.slice(0, Lib.size()-2);
2165 }
2166 return Lib;
2167}
2168
2169// getLibraryShortNameByIndex() is used to get the short name of the library
2170// for an undefined symbol in a linked Mach-O binary that was linked with the
2171// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2172// It is passed the index (0 - based) of the library as translated from
2173// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002174std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002175 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002176 if (Index >= Libraries.size())
2177 return object_error::parse_failed;
2178
Kevin Enderby980b2582014-06-05 21:21:57 +00002179 // If the cache of LibrariesShortNames is not built up do that first for
2180 // all the Libraries.
2181 if (LibrariesShortNames.size() == 0) {
2182 for (unsigned i = 0; i < Libraries.size(); i++) {
2183 MachO::dylib_command D =
2184 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002185 if (D.dylib.name >= D.cmdsize)
2186 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002187 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002188 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002189 if (D.dylib.name+Name.size() >= D.cmdsize)
2190 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002191 StringRef Suffix;
2192 bool isFramework;
2193 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002194 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002195 LibrariesShortNames.push_back(Name);
2196 else
2197 LibrariesShortNames.push_back(shortName);
2198 }
2199 }
2200
2201 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002202 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002203}
2204
Rafael Espindola76ad2322015-07-06 14:55:37 +00002205section_iterator
2206MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2207 DataRefImpl Sec;
2208 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2209 return section_iterator(SectionRef(Sec, this));
2210}
2211
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002212basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002213 DataRefImpl DRI;
2214 MachO::symtab_command Symtab = getSymtabLoadCommand();
2215 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2216 return basic_symbol_iterator(SymbolRef(DRI, this));
2217
Lang Hames36072da2014-05-12 21:39:59 +00002218 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002219}
2220
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002221basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002222 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002223 MachO::symtab_command Symtab = getSymtabLoadCommand();
2224 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002225 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002226
Rafael Espindola75c30362013-04-24 19:47:55 +00002227 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002228 sizeof(MachO::nlist_64) :
2229 sizeof(MachO::nlist);
2230 unsigned Offset = Symtab.symoff +
2231 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00002232 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002233 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002234}
2235
Lang Hames36072da2014-05-12 21:39:59 +00002236basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002237 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002238 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002239 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002240 unsigned SymbolTableEntrySize =
2241 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002242 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00002243 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
2244 DRI.p += Index * SymbolTableEntrySize;
2245 return basic_symbol_iterator(SymbolRef(DRI, this));
2246}
2247
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002248uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2249 MachO::symtab_command Symtab = getSymtabLoadCommand();
2250 if (!SymtabLoadCmd)
2251 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2252 unsigned SymbolTableEntrySize =
2253 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2254 DataRefImpl DRIstart;
2255 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
2256 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2257 return Index;
2258}
2259
Rafael Espindolab5155a52014-02-10 20:24:04 +00002260section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002261 DataRefImpl DRI;
2262 return section_iterator(SectionRef(DRI, this));
2263}
2264
Rafael Espindolab5155a52014-02-10 20:24:04 +00002265section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002266 DataRefImpl DRI;
2267 DRI.d.a = Sections.size();
2268 return section_iterator(SectionRef(DRI, this));
2269}
2270
Rafael Espindola56f976f2013-04-18 18:08:55 +00002271uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002272 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002273}
2274
Rafael Espindola56f976f2013-04-18 18:08:55 +00002275StringRef MachOObjectFile::getFileFormatName() const {
2276 unsigned CPUType = getCPUType(this);
2277 if (!is64Bit()) {
2278 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002279 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002280 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00002281 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002282 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00002283 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002284 return "Mach-O 32-bit ppc";
2285 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002286 return "Mach-O 32-bit unknown";
2287 }
2288 }
2289
Rafael Espindola56f976f2013-04-18 18:08:55 +00002290 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002291 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002292 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00002293 case llvm::MachO::CPU_TYPE_ARM64:
2294 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00002295 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002296 return "Mach-O 64-bit ppc64";
2297 default:
2298 return "Mach-O 64-bit unknown";
2299 }
2300}
2301
Alexey Samsonove6388e62013-06-18 15:03:28 +00002302Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2303 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002304 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002305 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00002306 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002307 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002308 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002309 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00002310 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002311 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002312 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002313 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00002314 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002315 return Triple::ppc64;
2316 default:
2317 return Triple::UnknownArch;
2318 }
2319}
2320
Tim Northover9e8eb412016-04-22 23:21:13 +00002321Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2322 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002323 if (McpuDefault)
2324 *McpuDefault = nullptr;
2325
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002326 switch (CPUType) {
2327 case MachO::CPU_TYPE_I386:
2328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2329 case MachO::CPU_SUBTYPE_I386_ALL:
2330 return Triple("i386-apple-darwin");
2331 default:
2332 return Triple();
2333 }
2334 case MachO::CPU_TYPE_X86_64:
2335 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2336 case MachO::CPU_SUBTYPE_X86_64_ALL:
2337 return Triple("x86_64-apple-darwin");
2338 case MachO::CPU_SUBTYPE_X86_64_H:
2339 return Triple("x86_64h-apple-darwin");
2340 default:
2341 return Triple();
2342 }
2343 case MachO::CPU_TYPE_ARM:
2344 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2345 case MachO::CPU_SUBTYPE_ARM_V4T:
2346 return Triple("armv4t-apple-darwin");
2347 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2348 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002349 case MachO::CPU_SUBTYPE_ARM_XSCALE:
2350 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002351 case MachO::CPU_SUBTYPE_ARM_V6:
2352 return Triple("armv6-apple-darwin");
2353 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002354 if (McpuDefault)
2355 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002356 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002357 case MachO::CPU_SUBTYPE_ARM_V7:
2358 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002359 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002360 if (McpuDefault)
2361 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00002362 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002363 case MachO::CPU_SUBTYPE_ARM_V7K:
2364 return Triple("armv7k-apple-darwin");
2365 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002366 if (McpuDefault)
2367 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00002368 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002369 case MachO::CPU_SUBTYPE_ARM_V7S:
2370 return Triple("armv7s-apple-darwin");
2371 default:
2372 return Triple();
2373 }
2374 case MachO::CPU_TYPE_ARM64:
2375 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2376 case MachO::CPU_SUBTYPE_ARM64_ALL:
2377 return Triple("arm64-apple-darwin");
2378 default:
2379 return Triple();
2380 }
2381 case MachO::CPU_TYPE_POWERPC:
2382 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2383 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2384 return Triple("ppc-apple-darwin");
2385 default:
2386 return Triple();
2387 }
2388 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002389 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002390 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2391 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002392 default:
2393 return Triple();
2394 }
2395 default:
2396 return Triple();
2397 }
2398}
2399
2400Triple MachOObjectFile::getHostArch() {
2401 return Triple(sys::getDefaultTargetTriple());
2402}
2403
Rafael Espindola72318b42014-08-08 16:30:17 +00002404bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2405 return StringSwitch<bool>(ArchFlag)
2406 .Case("i386", true)
2407 .Case("x86_64", true)
2408 .Case("x86_64h", true)
2409 .Case("armv4t", true)
2410 .Case("arm", true)
2411 .Case("armv5e", true)
2412 .Case("armv6", true)
2413 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002414 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002415 .Case("armv7em", true)
2416 .Case("armv7k", true)
2417 .Case("armv7m", true)
2418 .Case("armv7s", true)
2419 .Case("arm64", true)
2420 .Case("ppc", true)
2421 .Case("ppc64", true)
2422 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002423}
2424
Alexey Samsonove6388e62013-06-18 15:03:28 +00002425unsigned MachOObjectFile::getArch() const {
2426 return getArch(getCPUType(this));
2427}
2428
Tim Northover9e8eb412016-04-22 23:21:13 +00002429Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2430 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002431}
2432
Rui Ueyamabc654b12013-09-27 21:47:05 +00002433relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002434 DataRefImpl DRI;
2435 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002436 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002437}
2438
Rui Ueyamabc654b12013-09-27 21:47:05 +00002439relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002440 DataRefImpl DRI;
2441 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002442 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002443}
2444
Kevin Enderby273ae012013-06-06 17:20:50 +00002445dice_iterator MachOObjectFile::begin_dices() const {
2446 DataRefImpl DRI;
2447 if (!DataInCodeLoadCmd)
2448 return dice_iterator(DiceRef(DRI, this));
2449
Charles Davis8bdfafd2013-09-01 04:28:48 +00002450 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2451 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002452 return dice_iterator(DiceRef(DRI, this));
2453}
2454
2455dice_iterator MachOObjectFile::end_dices() const {
2456 DataRefImpl DRI;
2457 if (!DataInCodeLoadCmd)
2458 return dice_iterator(DiceRef(DRI, this));
2459
Charles Davis8bdfafd2013-09-01 04:28:48 +00002460 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2461 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00002462 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
2463 return dice_iterator(DiceRef(DRI, this));
2464}
2465
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002466ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
2467 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002468
2469void ExportEntry::moveToFirst() {
2470 pushNode(0);
2471 pushDownUntilBottom();
2472}
2473
2474void ExportEntry::moveToEnd() {
2475 Stack.clear();
2476 Done = true;
2477}
2478
2479bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002480 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002481 if (Done || Other.Done)
2482 return (Done == Other.Done);
2483 // Not equal if different stack sizes.
2484 if (Stack.size() != Other.Stack.size())
2485 return false;
2486 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002487 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002488 return false;
2489 // Equal if all nodes in both stacks match.
2490 for (unsigned i=0; i < Stack.size(); ++i) {
2491 if (Stack[i].Start != Other.Stack[i].Start)
2492 return false;
2493 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002494 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002495}
2496
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002497uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
2498 unsigned Count;
2499 uint64_t Result = decodeULEB128(Ptr, &Count);
2500 Ptr += Count;
2501 if (Ptr > Trie.end()) {
2502 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002503 Malformed = true;
2504 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002505 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002506}
2507
2508StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002509 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002510}
2511
2512uint64_t ExportEntry::flags() const {
2513 return Stack.back().Flags;
2514}
2515
2516uint64_t ExportEntry::address() const {
2517 return Stack.back().Address;
2518}
2519
2520uint64_t ExportEntry::other() const {
2521 return Stack.back().Other;
2522}
2523
2524StringRef ExportEntry::otherName() const {
2525 const char* ImportName = Stack.back().ImportName;
2526 if (ImportName)
2527 return StringRef(ImportName);
2528 return StringRef();
2529}
2530
2531uint32_t ExportEntry::nodeOffset() const {
2532 return Stack.back().Start - Trie.begin();
2533}
2534
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002535ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2536 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
2537 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
2538 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002539
2540void ExportEntry::pushNode(uint64_t offset) {
2541 const uint8_t *Ptr = Trie.begin() + offset;
2542 NodeState State(Ptr);
2543 uint64_t ExportInfoSize = readULEB128(State.Current);
2544 State.IsExportNode = (ExportInfoSize != 0);
2545 const uint8_t* Children = State.Current + ExportInfoSize;
2546 if (State.IsExportNode) {
2547 State.Flags = readULEB128(State.Current);
2548 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2549 State.Address = 0;
2550 State.Other = readULEB128(State.Current); // dylib ordinal
2551 State.ImportName = reinterpret_cast<const char*>(State.Current);
2552 } else {
2553 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00002554 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002555 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002556 }
2557 }
2558 State.ChildCount = *Children;
2559 State.Current = Children + 1;
2560 State.NextChildIndex = 0;
2561 State.ParentStringLength = CumulativeString.size();
2562 Stack.push_back(State);
2563}
2564
2565void ExportEntry::pushDownUntilBottom() {
2566 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2567 NodeState &Top = Stack.back();
2568 CumulativeString.resize(Top.ParentStringLength);
2569 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002570 char C = *Top.Current;
2571 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002572 }
2573 Top.Current += 1;
2574 uint64_t childNodeIndex = readULEB128(Top.Current);
2575 Top.NextChildIndex += 1;
2576 pushNode(childNodeIndex);
2577 }
2578 if (!Stack.back().IsExportNode) {
2579 Malformed = true;
2580 moveToEnd();
2581 }
2582}
2583
2584// We have a trie data structure and need a way to walk it that is compatible
2585// with the C++ iterator model. The solution is a non-recursive depth first
2586// traversal where the iterator contains a stack of parent nodes along with a
2587// string that is the accumulation of all edge strings along the parent chain
2588// to this point.
2589//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002590// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002591// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002592// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002593//
2594// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2595// child until hitting a node with no children (which is an export node or
2596// else the trie is malformed). On the way down, each node is pushed on the
2597// stack ivar. If there is no more ways down, it pops up one and tries to go
2598// down a sibling path until a childless node is reached.
2599void ExportEntry::moveNext() {
2600 if (Stack.empty() || !Stack.back().IsExportNode) {
2601 Malformed = true;
2602 moveToEnd();
2603 return;
2604 }
2605
2606 Stack.pop_back();
2607 while (!Stack.empty()) {
2608 NodeState &Top = Stack.back();
2609 if (Top.NextChildIndex < Top.ChildCount) {
2610 pushDownUntilBottom();
2611 // Now at the next export node.
2612 return;
2613 } else {
2614 if (Top.IsExportNode) {
2615 // This node has no children but is itself an export node.
2616 CumulativeString.resize(Top.ParentStringLength);
2617 return;
2618 }
2619 Stack.pop_back();
2620 }
2621 }
2622 Done = true;
2623}
2624
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002625iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00002626MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
2627 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002628 if (Trie.size() == 0)
2629 Start.moveToEnd();
2630 else
2631 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002632
2633 ExportEntry Finish(Trie);
2634 Finish.moveToEnd();
2635
Craig Topper15576e12015-12-06 05:08:07 +00002636 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002637}
2638
2639iterator_range<export_iterator> MachOObjectFile::exports() const {
2640 return exports(getDyldInfoExportsTrie());
2641}
2642
Nick Kledzikac431442014-09-12 21:34:15 +00002643MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
2644 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2645 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2646 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
2647
2648void MachORebaseEntry::moveToFirst() {
2649 Ptr = Opcodes.begin();
2650 moveNext();
2651}
2652
2653void MachORebaseEntry::moveToEnd() {
2654 Ptr = Opcodes.end();
2655 RemainingLoopCount = 0;
2656 Done = true;
2657}
2658
2659void MachORebaseEntry::moveNext() {
2660 // If in the middle of some loop, move to next rebasing 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::REBASE_IMMEDIATE_MASK;
2675 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
2676 switch (Opcode) {
2677 case MachO::REBASE_OPCODE_DONE:
2678 More = false;
2679 Done = true;
2680 moveToEnd();
2681 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
2682 break;
2683 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2684 RebaseType = ImmValue;
2685 DEBUG_WITH_TYPE(
2686 "mach-o-rebase",
2687 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2688 << "RebaseType=" << (int) RebaseType << "\n");
2689 break;
2690 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2691 SegmentIndex = ImmValue;
2692 SegmentOffset = readULEB128();
2693 DEBUG_WITH_TYPE(
2694 "mach-o-rebase",
2695 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2696 << "SegmentIndex=" << SegmentIndex << ", "
2697 << format("SegmentOffset=0x%06X", SegmentOffset)
2698 << "\n");
2699 break;
2700 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
2701 SegmentOffset += readULEB128();
2702 DEBUG_WITH_TYPE("mach-o-rebase",
2703 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
2704 << format("SegmentOffset=0x%06X",
2705 SegmentOffset) << "\n");
2706 break;
2707 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
2708 SegmentOffset += ImmValue * PointerSize;
2709 DEBUG_WITH_TYPE("mach-o-rebase",
2710 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
2711 << format("SegmentOffset=0x%06X",
2712 SegmentOffset) << "\n");
2713 break;
2714 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
2715 AdvanceAmount = PointerSize;
2716 RemainingLoopCount = ImmValue - 1;
2717 DEBUG_WITH_TYPE(
2718 "mach-o-rebase",
2719 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
2720 << format("SegmentOffset=0x%06X", SegmentOffset)
2721 << ", AdvanceAmount=" << AdvanceAmount
2722 << ", RemainingLoopCount=" << RemainingLoopCount
2723 << "\n");
2724 return;
2725 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
2726 AdvanceAmount = PointerSize;
2727 RemainingLoopCount = readULEB128() - 1;
2728 DEBUG_WITH_TYPE(
2729 "mach-o-rebase",
2730 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
2731 << format("SegmentOffset=0x%06X", SegmentOffset)
2732 << ", AdvanceAmount=" << AdvanceAmount
2733 << ", RemainingLoopCount=" << RemainingLoopCount
2734 << "\n");
2735 return;
2736 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
2737 AdvanceAmount = readULEB128() + PointerSize;
2738 RemainingLoopCount = 0;
2739 DEBUG_WITH_TYPE(
2740 "mach-o-rebase",
2741 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
2742 << format("SegmentOffset=0x%06X", SegmentOffset)
2743 << ", AdvanceAmount=" << AdvanceAmount
2744 << ", RemainingLoopCount=" << RemainingLoopCount
2745 << "\n");
2746 return;
2747 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
2748 RemainingLoopCount = readULEB128() - 1;
2749 AdvanceAmount = readULEB128() + PointerSize;
2750 DEBUG_WITH_TYPE(
2751 "mach-o-rebase",
2752 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
2753 << format("SegmentOffset=0x%06X", SegmentOffset)
2754 << ", AdvanceAmount=" << AdvanceAmount
2755 << ", RemainingLoopCount=" << RemainingLoopCount
2756 << "\n");
2757 return;
2758 default:
2759 Malformed = true;
2760 }
2761 }
2762}
2763
2764uint64_t MachORebaseEntry::readULEB128() {
2765 unsigned Count;
2766 uint64_t Result = decodeULEB128(Ptr, &Count);
2767 Ptr += Count;
2768 if (Ptr > Opcodes.end()) {
2769 Ptr = Opcodes.end();
2770 Malformed = true;
2771 }
2772 return Result;
2773}
2774
2775uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
2776
2777uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
2778
2779StringRef MachORebaseEntry::typeName() const {
2780 switch (RebaseType) {
2781 case MachO::REBASE_TYPE_POINTER:
2782 return "pointer";
2783 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
2784 return "text abs32";
2785 case MachO::REBASE_TYPE_TEXT_PCREL32:
2786 return "text rel32";
2787 }
2788 return "unknown";
2789}
2790
2791bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
2792 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2793 return (Ptr == Other.Ptr) &&
2794 (RemainingLoopCount == Other.RemainingLoopCount) &&
2795 (Done == Other.Done);
2796}
2797
2798iterator_range<rebase_iterator>
2799MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
2800 MachORebaseEntry Start(Opcodes, is64);
2801 Start.moveToFirst();
2802
2803 MachORebaseEntry Finish(Opcodes, is64);
2804 Finish.moveToEnd();
2805
Craig Topper15576e12015-12-06 05:08:07 +00002806 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00002807}
2808
2809iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
2810 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
2811}
2812
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002813MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00002814 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2815 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
2816 BindType(0), PointerSize(is64Bit ? 8 : 4),
2817 TableKind(BK), Malformed(false), Done(false) {}
2818
2819void MachOBindEntry::moveToFirst() {
2820 Ptr = Opcodes.begin();
2821 moveNext();
2822}
2823
2824void MachOBindEntry::moveToEnd() {
2825 Ptr = Opcodes.end();
2826 RemainingLoopCount = 0;
2827 Done = true;
2828}
2829
2830void MachOBindEntry::moveNext() {
2831 // If in the middle of some loop, move to next binding in loop.
2832 SegmentOffset += AdvanceAmount;
2833 if (RemainingLoopCount) {
2834 --RemainingLoopCount;
2835 return;
2836 }
2837 if (Ptr == Opcodes.end()) {
2838 Done = true;
2839 return;
2840 }
2841 bool More = true;
2842 while (More && !Malformed) {
2843 // Parse next opcode and set up next loop.
2844 uint8_t Byte = *Ptr++;
2845 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
2846 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
2847 int8_t SignExtended;
2848 const uint8_t *SymStart;
2849 switch (Opcode) {
2850 case MachO::BIND_OPCODE_DONE:
2851 if (TableKind == Kind::Lazy) {
2852 // Lazying bindings have a DONE opcode between entries. Need to ignore
2853 // it to advance to next entry. But need not if this is last entry.
2854 bool NotLastEntry = false;
2855 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
2856 if (*P) {
2857 NotLastEntry = true;
2858 }
2859 }
2860 if (NotLastEntry)
2861 break;
2862 }
2863 More = false;
2864 Done = true;
2865 moveToEnd();
2866 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
2867 break;
2868 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
2869 Ordinal = ImmValue;
2870 DEBUG_WITH_TYPE(
2871 "mach-o-bind",
2872 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
2873 << "Ordinal=" << Ordinal << "\n");
2874 break;
2875 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
2876 Ordinal = readULEB128();
2877 DEBUG_WITH_TYPE(
2878 "mach-o-bind",
2879 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
2880 << "Ordinal=" << Ordinal << "\n");
2881 break;
2882 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
2883 if (ImmValue) {
2884 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
2885 Ordinal = SignExtended;
2886 } else
2887 Ordinal = 0;
2888 DEBUG_WITH_TYPE(
2889 "mach-o-bind",
2890 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
2891 << "Ordinal=" << Ordinal << "\n");
2892 break;
2893 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
2894 Flags = ImmValue;
2895 SymStart = Ptr;
2896 while (*Ptr) {
2897 ++Ptr;
2898 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00002899 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
2900 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00002901 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002902 DEBUG_WITH_TYPE(
2903 "mach-o-bind",
2904 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
2905 << "SymbolName=" << SymbolName << "\n");
2906 if (TableKind == Kind::Weak) {
2907 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
2908 return;
2909 }
2910 break;
2911 case MachO::BIND_OPCODE_SET_TYPE_IMM:
2912 BindType = ImmValue;
2913 DEBUG_WITH_TYPE(
2914 "mach-o-bind",
2915 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
2916 << "BindType=" << (int)BindType << "\n");
2917 break;
2918 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
2919 Addend = readSLEB128();
2920 if (TableKind == Kind::Lazy)
2921 Malformed = true;
2922 DEBUG_WITH_TYPE(
2923 "mach-o-bind",
2924 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
2925 << "Addend=" << Addend << "\n");
2926 break;
2927 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2928 SegmentIndex = ImmValue;
2929 SegmentOffset = readULEB128();
2930 DEBUG_WITH_TYPE(
2931 "mach-o-bind",
2932 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2933 << "SegmentIndex=" << SegmentIndex << ", "
2934 << format("SegmentOffset=0x%06X", SegmentOffset)
2935 << "\n");
2936 break;
2937 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2938 SegmentOffset += readULEB128();
2939 DEBUG_WITH_TYPE("mach-o-bind",
2940 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2941 << format("SegmentOffset=0x%06X",
2942 SegmentOffset) << "\n");
2943 break;
2944 case MachO::BIND_OPCODE_DO_BIND:
2945 AdvanceAmount = PointerSize;
2946 RemainingLoopCount = 0;
2947 DEBUG_WITH_TYPE("mach-o-bind",
2948 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2949 << format("SegmentOffset=0x%06X",
2950 SegmentOffset) << "\n");
2951 return;
2952 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002953 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002954 RemainingLoopCount = 0;
2955 if (TableKind == Kind::Lazy)
2956 Malformed = true;
2957 DEBUG_WITH_TYPE(
2958 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002959 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00002960 << format("SegmentOffset=0x%06X", SegmentOffset)
2961 << ", AdvanceAmount=" << AdvanceAmount
2962 << ", RemainingLoopCount=" << RemainingLoopCount
2963 << "\n");
2964 return;
2965 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002966 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002967 RemainingLoopCount = 0;
2968 if (TableKind == Kind::Lazy)
2969 Malformed = true;
2970 DEBUG_WITH_TYPE("mach-o-bind",
2971 llvm::dbgs()
2972 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2973 << format("SegmentOffset=0x%06X",
2974 SegmentOffset) << "\n");
2975 return;
2976 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2977 RemainingLoopCount = readULEB128() - 1;
2978 AdvanceAmount = readULEB128() + PointerSize;
2979 if (TableKind == Kind::Lazy)
2980 Malformed = true;
2981 DEBUG_WITH_TYPE(
2982 "mach-o-bind",
2983 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2984 << format("SegmentOffset=0x%06X", SegmentOffset)
2985 << ", AdvanceAmount=" << AdvanceAmount
2986 << ", RemainingLoopCount=" << RemainingLoopCount
2987 << "\n");
2988 return;
2989 default:
2990 Malformed = true;
2991 }
2992 }
2993}
2994
2995uint64_t MachOBindEntry::readULEB128() {
2996 unsigned Count;
2997 uint64_t Result = decodeULEB128(Ptr, &Count);
2998 Ptr += Count;
2999 if (Ptr > Opcodes.end()) {
3000 Ptr = Opcodes.end();
3001 Malformed = true;
3002 }
3003 return Result;
3004}
3005
3006int64_t MachOBindEntry::readSLEB128() {
3007 unsigned Count;
3008 int64_t Result = decodeSLEB128(Ptr, &Count);
3009 Ptr += Count;
3010 if (Ptr > Opcodes.end()) {
3011 Ptr = Opcodes.end();
3012 Malformed = true;
3013 }
3014 return Result;
3015}
3016
Nick Kledzik56ebef42014-09-16 01:41:51 +00003017uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3018
3019uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3020
3021StringRef MachOBindEntry::typeName() const {
3022 switch (BindType) {
3023 case MachO::BIND_TYPE_POINTER:
3024 return "pointer";
3025 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3026 return "text abs32";
3027 case MachO::BIND_TYPE_TEXT_PCREL32:
3028 return "text rel32";
3029 }
3030 return "unknown";
3031}
3032
3033StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3034
3035int64_t MachOBindEntry::addend() const { return Addend; }
3036
3037uint32_t MachOBindEntry::flags() const { return Flags; }
3038
3039int MachOBindEntry::ordinal() const { return Ordinal; }
3040
3041bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3042 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3043 return (Ptr == Other.Ptr) &&
3044 (RemainingLoopCount == Other.RemainingLoopCount) &&
3045 (Done == Other.Done);
3046}
3047
3048iterator_range<bind_iterator>
3049MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
3050 MachOBindEntry::Kind BKind) {
3051 MachOBindEntry Start(Opcodes, is64, BKind);
3052 Start.moveToFirst();
3053
3054 MachOBindEntry Finish(Opcodes, is64, BKind);
3055 Finish.moveToEnd();
3056
Craig Topper15576e12015-12-06 05:08:07 +00003057 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00003058}
3059
3060iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
3061 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
3062 MachOBindEntry::Kind::Regular);
3063}
3064
3065iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
3066 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
3067 MachOBindEntry::Kind::Lazy);
3068}
3069
3070iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
3071 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
3072 MachOBindEntry::Kind::Weak);
3073}
3074
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00003075MachOObjectFile::load_command_iterator
3076MachOObjectFile::begin_load_commands() const {
3077 return LoadCommands.begin();
3078}
3079
3080MachOObjectFile::load_command_iterator
3081MachOObjectFile::end_load_commands() const {
3082 return LoadCommands.end();
3083}
3084
3085iterator_range<MachOObjectFile::load_command_iterator>
3086MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00003087 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00003088}
3089
Rafael Espindola56f976f2013-04-18 18:08:55 +00003090StringRef
3091MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
3092 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
3093 return parseSegmentOrSectionName(Raw.data());
3094}
3095
3096ArrayRef<char>
3097MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00003098 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003099 const section_base *Base =
3100 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00003101 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003102}
3103
3104ArrayRef<char>
3105MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00003106 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003107 const section_base *Base =
3108 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00003109 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003110}
3111
3112bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00003113MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00003114 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003115 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00003116 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00003117 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003118}
3119
Eric Christopher1d62c252013-07-22 22:25:07 +00003120unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003121 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003122 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00003123 return RE.r_word1 & 0xffffff;
3124 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003125}
3126
Eric Christopher1d62c252013-07-22 22:25:07 +00003127bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003128 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003129 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00003130 return (RE.r_word1 >> 27) & 1;
3131 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003132}
3133
Eric Christopher1d62c252013-07-22 22:25:07 +00003134bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003135 const MachO::any_relocation_info &RE) const {
3136 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003137}
3138
Eric Christopher1d62c252013-07-22 22:25:07 +00003139uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003140 const MachO::any_relocation_info &RE) const {
3141 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003142}
3143
Kevin Enderby9907d0a2014-11-04 00:43:16 +00003144uint32_t MachOObjectFile::getScatteredRelocationType(
3145 const MachO::any_relocation_info &RE) const {
3146 return (RE.r_word0 >> 24) & 0xf;
3147}
3148
Eric Christopher1d62c252013-07-22 22:25:07 +00003149unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003150 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003151 if (isRelocationScattered(RE))
3152 return getScatteredRelocationAddress(RE);
3153 return getPlainRelocationAddress(RE);
3154}
3155
Charles Davis8bdfafd2013-09-01 04:28:48 +00003156unsigned MachOObjectFile::getAnyRelocationPCRel(
3157 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003158 if (isRelocationScattered(RE))
3159 return getScatteredRelocationPCRel(this, RE);
3160 return getPlainRelocationPCRel(this, RE);
3161}
3162
Eric Christopher1d62c252013-07-22 22:25:07 +00003163unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003164 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003165 if (isRelocationScattered(RE))
3166 return getScatteredRelocationLength(RE);
3167 return getPlainRelocationLength(this, RE);
3168}
3169
3170unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00003171MachOObjectFile::getAnyRelocationType(
3172 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003173 if (isRelocationScattered(RE))
3174 return getScatteredRelocationType(RE);
3175 return getPlainRelocationType(this, RE);
3176}
3177
Rafael Espindola52501032013-04-30 15:40:54 +00003178SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00003179MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003180 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00003181 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00003182 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00003183 unsigned SecNum = getPlainRelocationSymbolNum(RE);
3184 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
3185 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00003186 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00003187 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00003188 return SectionRef(DRI, this);
3189}
3190
Charles Davis8bdfafd2013-09-01 04:28:48 +00003191MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00003192 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003193 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003194}
3195
Charles Davis8bdfafd2013-09-01 04:28:48 +00003196MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00003197 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003198 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003199}
3200
Charles Davis8bdfafd2013-09-01 04:28:48 +00003201MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00003202 unsigned Index) const {
3203 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003204 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003205}
3206
Charles Davis8bdfafd2013-09-01 04:28:48 +00003207MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
3208 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00003209 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003210 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003211}
3212
Charles Davis8bdfafd2013-09-01 04:28:48 +00003213MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00003214MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00003215 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003216 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003217}
3218
Charles Davis8bdfafd2013-09-01 04:28:48 +00003219MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00003220MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00003221 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003222 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003223}
3224
Charles Davis8bdfafd2013-09-01 04:28:48 +00003225MachO::linkedit_data_command
3226MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
3227 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003228}
3229
Charles Davis8bdfafd2013-09-01 04:28:48 +00003230MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00003231MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003232 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003233}
3234
Charles Davis8bdfafd2013-09-01 04:28:48 +00003235MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00003236MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003237 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003238}
3239
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00003240MachO::linker_option_command
3241MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
3242 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003243}
3244
Jim Grosbach448334a2014-03-18 22:09:05 +00003245MachO::version_min_command
3246MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
3247 return getStruct<MachO::version_min_command>(this, L.Ptr);
3248}
3249
Tim Northover8f9590b2014-06-30 14:40:57 +00003250MachO::dylib_command
3251MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
3252 return getStruct<MachO::dylib_command>(this, L.Ptr);
3253}
3254
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003255MachO::dyld_info_command
3256MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
3257 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
3258}
3259
3260MachO::dylinker_command
3261MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
3262 return getStruct<MachO::dylinker_command>(this, L.Ptr);
3263}
3264
3265MachO::uuid_command
3266MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
3267 return getStruct<MachO::uuid_command>(this, L.Ptr);
3268}
3269
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00003270MachO::rpath_command
3271MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
3272 return getStruct<MachO::rpath_command>(this, L.Ptr);
3273}
3274
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003275MachO::source_version_command
3276MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
3277 return getStruct<MachO::source_version_command>(this, L.Ptr);
3278}
3279
3280MachO::entry_point_command
3281MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
3282 return getStruct<MachO::entry_point_command>(this, L.Ptr);
3283}
3284
Kevin Enderby0804f4672014-12-16 23:25:52 +00003285MachO::encryption_info_command
3286MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
3287 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
3288}
3289
Kevin Enderby57538292014-12-17 01:01:30 +00003290MachO::encryption_info_command_64
3291MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
3292 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
3293}
3294
Kevin Enderbyb4b79312014-12-18 19:24:35 +00003295MachO::sub_framework_command
3296MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
3297 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
3298}
Tim Northover8f9590b2014-06-30 14:40:57 +00003299
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00003300MachO::sub_umbrella_command
3301MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
3302 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
3303}
3304
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00003305MachO::sub_library_command
3306MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
3307 return getStruct<MachO::sub_library_command>(this, L.Ptr);
3308}
3309
Kevin Enderby186eac32014-12-19 21:06:24 +00003310MachO::sub_client_command
3311MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
3312 return getStruct<MachO::sub_client_command>(this, L.Ptr);
3313}
3314
Kevin Enderby52e4ce42014-12-19 22:25:22 +00003315MachO::routines_command
3316MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
3317 return getStruct<MachO::routines_command>(this, L.Ptr);
3318}
3319
3320MachO::routines_command_64
3321MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
3322 return getStruct<MachO::routines_command_64>(this, L.Ptr);
3323}
3324
Kevin Enderby48ef5342014-12-23 22:56:39 +00003325MachO::thread_command
3326MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
3327 return getStruct<MachO::thread_command>(this, L.Ptr);
3328}
3329
Charles Davis8bdfafd2013-09-01 04:28:48 +00003330MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00003331MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00003332 DataRefImpl Sec;
3333 Sec.d.a = Rel.d.a;
3334 uint32_t Offset;
3335 if (is64Bit()) {
3336 MachO::section_64 Sect = getSection64(Sec);
3337 Offset = Sect.reloff;
3338 } else {
3339 MachO::section Sect = getSection(Sec);
3340 Offset = Sect.reloff;
3341 }
3342
3343 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
3344 getPtr(this, Offset)) + Rel.d.b;
3345 return getStruct<MachO::any_relocation_info>(
3346 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00003347}
3348
Charles Davis8bdfafd2013-09-01 04:28:48 +00003349MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00003350MachOObjectFile::getDice(DataRefImpl Rel) const {
3351 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003352 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00003353}
3354
Alexey Samsonov13415ed2015-06-04 19:22:03 +00003355const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00003356 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003357}
3358
Alexey Samsonov13415ed2015-06-04 19:22:03 +00003359const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
3360 assert(is64Bit());
3361 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00003362}
3363
Charles Davis8bdfafd2013-09-01 04:28:48 +00003364uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
3365 const MachO::dysymtab_command &DLC,
3366 unsigned Index) const {
3367 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
3368 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00003369}
3370
Charles Davis8bdfafd2013-09-01 04:28:48 +00003371MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00003372MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
3373 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003374 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
3375 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00003376}
3377
Charles Davis8bdfafd2013-09-01 04:28:48 +00003378MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003379 if (SymtabLoadCmd)
3380 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
3381
3382 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
3383 MachO::symtab_command Cmd;
3384 Cmd.cmd = MachO::LC_SYMTAB;
3385 Cmd.cmdsize = sizeof(MachO::symtab_command);
3386 Cmd.symoff = 0;
3387 Cmd.nsyms = 0;
3388 Cmd.stroff = 0;
3389 Cmd.strsize = 0;
3390 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003391}
3392
Charles Davis8bdfafd2013-09-01 04:28:48 +00003393MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003394 if (DysymtabLoadCmd)
3395 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
3396
3397 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
3398 MachO::dysymtab_command Cmd;
3399 Cmd.cmd = MachO::LC_DYSYMTAB;
3400 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
3401 Cmd.ilocalsym = 0;
3402 Cmd.nlocalsym = 0;
3403 Cmd.iextdefsym = 0;
3404 Cmd.nextdefsym = 0;
3405 Cmd.iundefsym = 0;
3406 Cmd.nundefsym = 0;
3407 Cmd.tocoff = 0;
3408 Cmd.ntoc = 0;
3409 Cmd.modtaboff = 0;
3410 Cmd.nmodtab = 0;
3411 Cmd.extrefsymoff = 0;
3412 Cmd.nextrefsyms = 0;
3413 Cmd.indirectsymoff = 0;
3414 Cmd.nindirectsyms = 0;
3415 Cmd.extreloff = 0;
3416 Cmd.nextrel = 0;
3417 Cmd.locreloff = 0;
3418 Cmd.nlocrel = 0;
3419 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00003420}
3421
Charles Davis8bdfafd2013-09-01 04:28:48 +00003422MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00003423MachOObjectFile::getDataInCodeLoadCommand() const {
3424 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00003425 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00003426
3427 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00003428 MachO::linkedit_data_command Cmd;
3429 Cmd.cmd = MachO::LC_DATA_IN_CODE;
3430 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3431 Cmd.dataoff = 0;
3432 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00003433 return Cmd;
3434}
3435
Kevin Enderby9a509442015-01-27 21:28:24 +00003436MachO::linkedit_data_command
3437MachOObjectFile::getLinkOptHintsLoadCommand() const {
3438 if (LinkOptHintsLoadCmd)
3439 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
3440
3441 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
3442 // fields.
3443 MachO::linkedit_data_command Cmd;
3444 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
3445 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3446 Cmd.dataoff = 0;
3447 Cmd.datasize = 0;
3448 return Cmd;
3449}
3450
Nick Kledzikd04bc352014-08-30 00:20:14 +00003451ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003452 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003453 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003454
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003455 MachO::dyld_info_command DyldInfo =
3456 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3457 const uint8_t *Ptr =
3458 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00003459 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003460}
3461
3462ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003463 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003464 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003465
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003466 MachO::dyld_info_command DyldInfo =
3467 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3468 const uint8_t *Ptr =
3469 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003470 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003471}
3472
3473ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003474 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003475 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003476
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003477 MachO::dyld_info_command DyldInfo =
3478 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3479 const uint8_t *Ptr =
3480 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003481 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003482}
3483
3484ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003485 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003486 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003487
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003488 MachO::dyld_info_command DyldInfo =
3489 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3490 const uint8_t *Ptr =
3491 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003492 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003493}
3494
3495ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003496 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003497 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003498
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003499 MachO::dyld_info_command DyldInfo =
3500 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3501 const uint8_t *Ptr =
3502 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00003503 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003504}
3505
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00003506ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
3507 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003508 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00003509 // Returning a pointer is fine as uuid doesn't need endian swapping.
3510 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00003511 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00003512}
Nick Kledzikd04bc352014-08-30 00:20:14 +00003513
Rafael Espindola6e040c02013-04-26 20:07:33 +00003514StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003515 MachO::symtab_command S = getSymtabLoadCommand();
3516 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003517}
3518
Rafael Espindola56f976f2013-04-18 18:08:55 +00003519bool MachOObjectFile::is64Bit() const {
3520 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00003521 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003522}
3523
3524void MachOObjectFile::ReadULEB128s(uint64_t Index,
3525 SmallVectorImpl<uint64_t> &Out) const {
3526 DataExtractor extractor(ObjectFile::getData(), true, 0);
3527
3528 uint32_t offset = Index;
3529 uint64_t data = 0;
3530 while (uint64_t delta = extractor.getULEB128(&offset)) {
3531 data += delta;
3532 Out.push_back(data);
3533 }
3534}
3535
Rafael Espindolac66d7612014-08-17 19:09:37 +00003536bool MachOObjectFile::isRelocatableObject() const {
3537 return getHeader().filetype == MachO::MH_OBJECT;
3538}
3539
Lang Hamesff044b12016-03-25 23:11:52 +00003540Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00003541ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
3542 uint32_t UniversalCputype,
3543 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00003544 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00003545 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003546 return MachOObjectFile::create(Buffer, false, false,
3547 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003548 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003549 return MachOObjectFile::create(Buffer, true, false,
3550 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003551 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003552 return MachOObjectFile::create(Buffer, false, true,
3553 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003554 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003555 return MachOObjectFile::create(Buffer, true, true,
3556 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00003557 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00003558 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003559}