blob: 5bfc51ecf620992e70239f66e2d563ddbae1d2b2 [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>
30
31using namespace llvm;
32using namespace object;
33
Artyom Skrobov7d602f72014-07-20 12:08:28 +000034namespace {
35 struct section_base {
36 char sectname[16];
37 char segname[16];
38 };
39}
Rafael Espindola56f976f2013-04-18 18:08:55 +000040
Lang Hames9e964f32016-03-25 17:25:34 +000041static Error
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000042malformedError(Twine Msg) {
Kevin Enderby89134962016-05-05 23:41:05 +000043 std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")";
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000044 return make_error<GenericBinaryError>(std::move(StringMsg),
Kevin Enderby89134962016-05-05 23:41:05 +000045 object_error::parse_failed);
Lang Hames9e964f32016-03-25 17:25:34 +000046}
47
Alexey Samsonov9f336632015-06-04 19:45:22 +000048// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000049template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000050static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000051 // Don't read before the beginning or past the end of the file
52 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
53 report_fatal_error("Malformed MachO file.");
54
Rafael Espindola3cdeb172013-04-19 13:45:05 +000055 T Cmd;
56 memcpy(&Cmd, P, sizeof(T));
57 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000058 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000059 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000060}
61
Alexey Samsonov9f336632015-06-04 19:45:22 +000062template <typename T>
Lang Hames9e964f32016-03-25 17:25:34 +000063static Expected<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000064 // Don't read before the beginning or past the end of the file
65 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000066 return malformedError("Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000067
68 T Cmd;
69 memcpy(&Cmd, P, sizeof(T));
70 if (O->isLittleEndian() != sys::IsLittleEndianHost)
71 MachO::swapStruct(Cmd);
72 return Cmd;
73}
74
Rafael Espindola6e040c02013-04-26 20:07:33 +000075static const char *
76getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
77 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000078 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
79
80 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000081 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
82 sizeof(MachO::segment_command);
83 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
84 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000085
86 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000087 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000088}
89
Rafael Espindola56f976f2013-04-18 18:08:55 +000090static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
91 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000092}
93
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000094static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000095getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000096 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000097 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000098}
99
Rafael Espindola56f976f2013-04-18 18:08:55 +0000100static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000101 if (P[15] == 0)
102 // Null terminated.
103 return P;
104 // Not null terminated, so this is a 16 char string.
105 return StringRef(P, 16);
106}
107
Rafael Espindola56f976f2013-04-18 18:08:55 +0000108// Helper to advance a section or symbol iterator multiple increments at a time.
109template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000110static void advance(T &it, size_t Val) {
111 while (Val--)
112 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000113}
114
115static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000116 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000117}
118
Charles Davis8bdfafd2013-09-01 04:28:48 +0000119static uint32_t
120getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
121 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000122}
123
124static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000125getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
126 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000127}
128
129static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000130 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000131 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000132 return (RE.r_word1 >> 24) & 1;
133 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134}
135
136static bool
137getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000138 const MachO::any_relocation_info &RE) {
139 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140}
141
142static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000143 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000144 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000145 return (RE.r_word1 >> 25) & 3;
146 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000147}
148
149static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
151 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152}
153
154static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000155 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000156 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000157 return RE.r_word1 >> 28;
158 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159}
160
Rafael Espindola56f976f2013-04-18 18:08:55 +0000161static uint32_t getSectionFlags(const MachOObjectFile *O,
162 DataRefImpl Sec) {
163 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000164 MachO::section_64 Sect = O->getSection64(Sec);
165 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000166 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000167 MachO::section Sect = O->getSection(Sec);
168 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000169}
170
Lang Hames9e964f32016-03-25 17:25:34 +0000171static Expected<MachOObjectFile::LoadCommandInfo>
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000172getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr,
173 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000174 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
175 if (CmdOrErr->cmdsize < 8)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000176 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000177 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000178 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
179 } else
180 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000181}
182
Lang Hames9e964f32016-03-25 17:25:34 +0000183static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000184getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
185 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
186 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000187 if (sizeof(MachO::load_command) > Obj->getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000188 return malformedError("load command 0 extends past the end all load "
Kevin Enderby89134962016-05-05 23:41:05 +0000189 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000190 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000191}
192
Lang Hames9e964f32016-03-25 17:25:34 +0000193static Expected<MachOObjectFile::LoadCommandInfo>
Kevin Enderby368e7142016-05-03 17:16:08 +0000194getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000195 const MachOObjectFile::LoadCommandInfo &L) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000196 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
197 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000198 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
Kevin Enderby368e7142016-05-03 17:16:08 +0000199 Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000200 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
Kevin Enderby89134962016-05-05 23:41:05 +0000201 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000202 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000203}
204
Alexey Samsonov9f336632015-06-04 19:45:22 +0000205template <typename T>
206static void parseHeader(const MachOObjectFile *Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000207 Error &Err) {
Kevin Enderby87025742016-04-13 21:17:58 +0000208 if (sizeof(T) > Obj->getData().size()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000209 Err = malformedError("the mach header extends past the end of the "
Kevin Enderby89134962016-05-05 23:41:05 +0000210 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000211 return;
212 }
Lang Hames9e964f32016-03-25 17:25:34 +0000213 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
214 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000215 else
Lang Hames9e964f32016-03-25 17:25:34 +0000216 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000217}
218
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000219// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
220// sections to \param Sections, and optionally sets
221// \param IsPageZeroSegment to true.
Kevin Enderbyc614d282016-08-12 20:10:25 +0000222template <typename Segment, typename Section>
Lang Hames9e964f32016-03-25 17:25:34 +0000223static Error parseSegmentLoadCommand(
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000224 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000225 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
Kevin Enderbyc614d282016-08-12 20:10:25 +0000226 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders) {
227 const unsigned SegmentLoadSize = sizeof(Segment);
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000228 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000229 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000230 " " + CmdName + " cmdsize too small");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000231 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
232 Segment S = SegOrErr.get();
233 const unsigned SectionSize = sizeof(Section);
234 uint64_t FileSize = Obj->getData().size();
Lang Hames9e964f32016-03-25 17:25:34 +0000235 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
236 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000237 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000238 " inconsistent cmdsize in " + CmdName +
Kevin Enderby89134962016-05-05 23:41:05 +0000239 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000240 for (unsigned J = 0; J < S.nsects; ++J) {
241 const char *Sec = getSectionPtr(Obj, Load, J);
242 Sections.push_back(Sec);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000243 Section s = getStruct<Section>(Obj, Sec);
244 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
245 Obj->getHeader().filetype != MachO::MH_DSYM &&
246 s.flags != MachO::S_ZEROFILL &&
247 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
248 s.offset > FileSize)
249 return malformedError("offset field of section " + Twine(J) + " in " +
250 CmdName + " command " + Twine(LoadCommandIndex) +
251 " extends past the end of the file");
252 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
253 Obj->getHeader().filetype != MachO::MH_DSYM &&
254 s.flags != MachO::S_ZEROFILL &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000255 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
256 s.offset < SizeOfHeaders && s.size != 0)
Kevin Enderbyc614d282016-08-12 20:10:25 +0000257 return malformedError("offset field of section " + Twine(J) + " in " +
258 CmdName + " command " + Twine(LoadCommandIndex) +
259 " not past the headers of the file");
260 uint64_t BigSize = s.offset;
261 BigSize += s.size;
262 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
263 Obj->getHeader().filetype != MachO::MH_DSYM &&
264 s.flags != MachO::S_ZEROFILL &&
265 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
266 BigSize > FileSize)
267 return malformedError("offset field plus size field of section " +
268 Twine(J) + " in " + CmdName + " command " +
269 Twine(LoadCommandIndex) +
270 " extends past the end of the file");
271 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
272 Obj->getHeader().filetype != MachO::MH_DSYM &&
273 s.flags != MachO::S_ZEROFILL &&
274 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
275 s.size > S.filesize)
276 return malformedError("size field of section " +
277 Twine(J) + " in " + CmdName + " command " +
278 Twine(LoadCommandIndex) +
279 " greater than the segment");
280 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000281 Obj->getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
282 s.addr < S.vmaddr)
283 return malformedError("addr field of section " + Twine(J) + " in " +
284 CmdName + " command " + Twine(LoadCommandIndex) +
285 " less than the segment's vmaddr");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000286 BigSize = s.addr;
287 BigSize += s.size;
288 uint64_t BigEnd = S.vmaddr;
289 BigEnd += S.vmsize;
290 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000291 return malformedError("addr field plus size of section " + Twine(J) +
292 " in " + CmdName + " command " +
293 Twine(LoadCommandIndex) +
294 " greater than than "
Kevin Enderbyc614d282016-08-12 20:10:25 +0000295 "the segment's vmaddr plus vmsize");
296 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000297 return malformedError("reloff field of section " + Twine(J) + " in " +
298 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000299 " extends past the end of the file");
300 BigSize = s.nreloc;
301 BigSize *= sizeof(struct MachO::relocation_info);
302 BigSize += s.reloff;
303 if (BigSize > FileSize)
304 return malformedError("reloff field plus nreloc field times sizeof("
305 "struct relocation_info) of section " +
306 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000307 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000308 " extends past the end of the file");
Lang Hames9e964f32016-03-25 17:25:34 +0000309 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000310 if (S.fileoff > FileSize)
311 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000312 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000313 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000314 uint64_t BigSize = S.fileoff;
315 BigSize += S.filesize;
316 if (BigSize > FileSize)
317 return malformedError("load command " + Twine(LoadCommandIndex) +
318 " fileoff field plus filesize field in " +
319 CmdName + " extends past the end of the file");
320 if (S.vmsize != 0 && S.filesize > S.vmsize)
321 return malformedError("load command " + Twine(LoadCommandIndex) +
322 " fileoff field in " + CmdName +
323 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000324 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
325 } else
326 return SegOrErr.takeError();
327
328 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000329}
330
Kevin Enderby0e52c922016-08-26 19:34:07 +0000331static Error checkSymtabCommand(const MachOObjectFile *Obj,
332 const MachOObjectFile::LoadCommandInfo &Load,
333 uint32_t LoadCommandIndex,
334 const char **SymtabLoadCmd) {
335 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
336 return malformedError("load command " + Twine(LoadCommandIndex) +
337 " LC_SYMTAB cmdsize too small");
338 if (*SymtabLoadCmd != nullptr)
339 return malformedError("more than one LC_SYMTAB command");
340 MachO::symtab_command Symtab =
341 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
342 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
343 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
344 " has incorrect cmdsize");
345 uint64_t FileSize = Obj->getData().size();
346 if (Symtab.symoff > FileSize)
347 return malformedError("symoff field of LC_SYMTAB command " +
348 Twine(LoadCommandIndex) + " extends past the end "
349 "of the file");
350 uint64_t BigSize = Symtab.nsyms;
351 const char *struct_nlist_name;
352 if (Obj->is64Bit()) {
353 BigSize *= sizeof(MachO::nlist_64);
354 struct_nlist_name = "struct nlist_64";
355 } else {
356 BigSize *= sizeof(MachO::nlist);
357 struct_nlist_name = "struct nlist";
358 }
359 BigSize += Symtab.symoff;
360 if (BigSize > FileSize)
361 return malformedError("symoff field plus nsyms field times sizeof(" +
362 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
363 Twine(LoadCommandIndex) + " extends past the end "
364 "of the file");
365 if (Symtab.stroff > FileSize)
366 return malformedError("stroff field of LC_SYMTAB command " +
367 Twine(LoadCommandIndex) + " extends past the end "
368 "of the file");
369 BigSize = Symtab.stroff;
370 BigSize += Symtab.strsize;
371 if (BigSize > FileSize)
372 return malformedError("stroff field plus strsize field of LC_SYMTAB "
373 "command " + Twine(LoadCommandIndex) + " extends "
374 "past the end of the file");
Kevin Enderby0e52c922016-08-26 19:34:07 +0000375 *SymtabLoadCmd = Load.Ptr;
376 return Error::success();
377}
378
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000379static Error checkDysymtabCommand(const MachOObjectFile *Obj,
380 const MachOObjectFile::LoadCommandInfo &Load,
381 uint32_t LoadCommandIndex,
382 const char **DysymtabLoadCmd) {
383 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
384 return malformedError("load command " + Twine(LoadCommandIndex) +
385 " LC_DYSYMTAB cmdsize too small");
386 if (*DysymtabLoadCmd != nullptr)
387 return malformedError("more than one LC_DYSYMTAB command");
388 MachO::dysymtab_command Dysymtab =
389 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
390 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
391 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
392 " has incorrect cmdsize");
393 uint64_t FileSize = Obj->getData().size();
394 if (Dysymtab.tocoff > FileSize)
395 return malformedError("tocoff field of LC_DYSYMTAB command " +
396 Twine(LoadCommandIndex) + " extends past the end of "
397 "the file");
398 uint64_t BigSize = Dysymtab.ntoc;
399 BigSize *= sizeof(MachO::dylib_table_of_contents);
400 BigSize += Dysymtab.tocoff;
401 if (BigSize > FileSize)
402 return malformedError("tocoff field plus ntoc field times sizeof(struct "
403 "dylib_table_of_contents) of LC_DYSYMTAB command " +
404 Twine(LoadCommandIndex) + " extends past the end of "
405 "the file");
406 if (Dysymtab.modtaboff > FileSize)
407 return malformedError("modtaboff field of LC_DYSYMTAB command " +
408 Twine(LoadCommandIndex) + " extends past the end of "
409 "the file");
410 BigSize = Dysymtab.nmodtab;
411 const char *struct_dylib_module_name;
412 if (Obj->is64Bit()) {
413 BigSize *= sizeof(MachO::dylib_module_64);
414 struct_dylib_module_name = "struct dylib_module_64";
415 } else {
416 BigSize *= sizeof(MachO::dylib_module);
417 struct_dylib_module_name = "struct dylib_module";
418 }
419 BigSize += Dysymtab.modtaboff;
420 if (BigSize > FileSize)
421 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
422 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
423 "command " + Twine(LoadCommandIndex) + " extends "
424 "past the end of the file");
425 if (Dysymtab.extrefsymoff > FileSize)
426 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
427 Twine(LoadCommandIndex) + " extends past the end of "
428 "the file");
429 BigSize = Dysymtab.nextrefsyms;
430 BigSize *= sizeof(MachO::dylib_reference);
431 BigSize += Dysymtab.extrefsymoff;
432 if (BigSize > FileSize)
433 return malformedError("extrefsymoff field plus nextrefsyms field times "
434 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
435 "command " + Twine(LoadCommandIndex) + " extends "
436 "past the end of the file");
437 if (Dysymtab.indirectsymoff > FileSize)
438 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
439 Twine(LoadCommandIndex) + " extends past the end of "
440 "the file");
441 BigSize = Dysymtab.nindirectsyms;
442 BigSize *= sizeof(uint32_t);
443 BigSize += Dysymtab.indirectsymoff;
444 if (BigSize > FileSize)
445 return malformedError("indirectsymoff field plus nindirectsyms field times "
446 "sizeof(uint32_t) of LC_DYSYMTAB command " +
447 Twine(LoadCommandIndex) + " extends past the end of "
448 "the file");
449 if (Dysymtab.extreloff > FileSize)
450 return malformedError("extreloff field of LC_DYSYMTAB command " +
451 Twine(LoadCommandIndex) + " extends past the end of "
452 "the file");
453 BigSize = Dysymtab.nextrel;
454 BigSize *= sizeof(MachO::relocation_info);
455 BigSize += Dysymtab.extreloff;
456 if (BigSize > FileSize)
457 return malformedError("extreloff field plus nextrel field times sizeof"
458 "(struct relocation_info) of LC_DYSYMTAB command " +
459 Twine(LoadCommandIndex) + " extends past the end of "
460 "the file");
461 if (Dysymtab.locreloff > FileSize)
462 return malformedError("locreloff field of LC_DYSYMTAB command " +
463 Twine(LoadCommandIndex) + " extends past the end of "
464 "the file");
465 BigSize = Dysymtab.nlocrel;
466 BigSize *= sizeof(MachO::relocation_info);
467 BigSize += Dysymtab.locreloff;
468 if (BigSize > FileSize)
469 return malformedError("locreloff field plus nlocrel field times sizeof"
470 "(struct relocation_info) of LC_DYSYMTAB command " +
471 Twine(LoadCommandIndex) + " extends past the end of "
472 "the file");
473 *DysymtabLoadCmd = Load.Ptr;
474 return Error::success();
475}
476
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000477static Error checkLinkeditDataCommand(const MachOObjectFile *Obj,
478 const MachOObjectFile::LoadCommandInfo &Load,
479 uint32_t LoadCommandIndex,
480 const char **LoadCmd, const char *CmdName) {
481 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
482 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
483 CmdName + " cmdsize too small");
484 if (*LoadCmd != nullptr)
485 return malformedError("more than one " + Twine(CmdName) + " command");
486 MachO::linkedit_data_command LinkData =
487 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
488 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
489 return malformedError(Twine(CmdName) + " command " +
490 Twine(LoadCommandIndex) + " has incorrect cmdsize");
491 uint64_t FileSize = Obj->getData().size();
492 if (LinkData.dataoff > FileSize)
493 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
494 Twine(LoadCommandIndex) + " extends past the end of "
495 "the file");
496 uint64_t BigSize = LinkData.dataoff;
497 BigSize += LinkData.datasize;
498 if (BigSize > FileSize)
499 return malformedError("dataoff field plus datasize field of " +
500 Twine(CmdName) + " command " +
501 Twine(LoadCommandIndex) + " extends past the end of "
502 "the file");
503 *LoadCmd = Load.Ptr;
504 return Error::success();
505}
506
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000507static Error checkDyldInfoCommand(const MachOObjectFile *Obj,
508 const MachOObjectFile::LoadCommandInfo &Load,
509 uint32_t LoadCommandIndex,
510 const char **LoadCmd, const char *CmdName) {
511 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
512 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
513 CmdName + " cmdsize too small");
514 if (*LoadCmd != nullptr)
515 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
516 "command");
517 MachO::dyld_info_command DyldInfo =
518 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
519 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
520 return malformedError(Twine(CmdName) + " command " +
521 Twine(LoadCommandIndex) + " has incorrect cmdsize");
522 uint64_t FileSize = Obj->getData().size();
523 if (DyldInfo.rebase_off > FileSize)
524 return malformedError("rebase_off field of " + Twine(CmdName) +
525 " command " + Twine(LoadCommandIndex) + " extends "
526 "past the end of the file");
527 uint64_t BigSize = DyldInfo.rebase_off;
528 BigSize += DyldInfo.rebase_size;
529 if (BigSize > FileSize)
530 return malformedError("rebase_off field plus rebase_size field of " +
531 Twine(CmdName) + " command " +
532 Twine(LoadCommandIndex) + " extends past the end of "
533 "the file");
534 if (DyldInfo.bind_off > FileSize)
535 return malformedError("bind_off field of " + Twine(CmdName) +
536 " command " + Twine(LoadCommandIndex) + " extends "
537 "past the end of the file");
538 BigSize = DyldInfo.bind_off;
539 BigSize += DyldInfo.bind_size;
540 if (BigSize > FileSize)
541 return malformedError("bind_off field plus bind_size field of " +
542 Twine(CmdName) + " command " +
543 Twine(LoadCommandIndex) + " extends past the end of "
544 "the file");
545 if (DyldInfo.weak_bind_off > FileSize)
546 return malformedError("weak_bind_off field of " + Twine(CmdName) +
547 " command " + Twine(LoadCommandIndex) + " extends "
548 "past the end of the file");
549 BigSize = DyldInfo.weak_bind_off;
550 BigSize += DyldInfo.weak_bind_size;
551 if (BigSize > FileSize)
552 return malformedError("weak_bind_off field plus weak_bind_size field of " +
553 Twine(CmdName) + " command " +
554 Twine(LoadCommandIndex) + " extends past the end of "
555 "the file");
556 if (DyldInfo.lazy_bind_off > FileSize)
557 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
558 " command " + Twine(LoadCommandIndex) + " extends "
559 "past the end of the file");
560 BigSize = DyldInfo.lazy_bind_off;
561 BigSize += DyldInfo.lazy_bind_size;
562 if (BigSize > FileSize)
563 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
564 Twine(CmdName) + " command " +
565 Twine(LoadCommandIndex) + " extends past the end of "
566 "the file");
567 if (DyldInfo.export_off > FileSize)
568 return malformedError("export_off field of " + Twine(CmdName) +
569 " command " + Twine(LoadCommandIndex) + " extends "
570 "past the end of the file");
571 BigSize = DyldInfo.export_off;
572 BigSize += DyldInfo.export_size;
573 if (BigSize > FileSize)
574 return malformedError("export_off field plus export_size field of " +
575 Twine(CmdName) + " command " +
576 Twine(LoadCommandIndex) + " extends past the end of "
577 "the file");
578 *LoadCmd = Load.Ptr;
579 return Error::success();
580}
581
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000582static Error checkDylibCommand(const MachOObjectFile *Obj,
583 const MachOObjectFile::LoadCommandInfo &Load,
584 uint32_t LoadCommandIndex, const char *CmdName) {
585 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
586 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
587 CmdName + " cmdsize too small");
588 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
589 if (D.dylib.name < sizeof(MachO::dylib_command))
590 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
591 CmdName + " name.offset field too small, not past "
592 "the end of the dylib_command struct");
593 if (D.dylib.name >= D.cmdsize)
594 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
595 CmdName + " name.offset field extends past the end "
596 "of the load command");
597 // Make sure there is a null between the starting offset of the name and
598 // the end of the load command.
599 uint32_t i;
600 const char *P = (const char *)Load.Ptr;
601 for (i = D.dylib.name; i < D.cmdsize; i++)
602 if (P[i] == '\0')
603 break;
604 if (i >= D.cmdsize)
605 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
606 CmdName + " library name extends past the end of the "
607 "load command");
608 return Error::success();
609}
610
611static Error checkDylibIdCommand(const MachOObjectFile *Obj,
612 const MachOObjectFile::LoadCommandInfo &Load,
613 uint32_t LoadCommandIndex,
614 const char **LoadCmd) {
615 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
616 "LC_ID_DYLIB"))
617 return Err;
618 if (*LoadCmd != nullptr)
619 return malformedError("more than one LC_ID_DYLIB command");
620 if (Obj->getHeader().filetype != MachO::MH_DYLIB &&
621 Obj->getHeader().filetype != MachO::MH_DYLIB_STUB)
622 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
623 "file type");
624 *LoadCmd = Load.Ptr;
625 return Error::success();
626}
627
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000628static Error checkDyldCommand(const MachOObjectFile *Obj,
629 const MachOObjectFile::LoadCommandInfo &Load,
630 uint32_t LoadCommandIndex, const char *CmdName) {
631 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
632 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
633 CmdName + " cmdsize too small");
634 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
635 if (D.name < sizeof(MachO::dylinker_command))
636 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
637 CmdName + " name.offset field too small, not past "
638 "the end of the dylinker_command struct");
639 if (D.name >= D.cmdsize)
640 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
641 CmdName + " name.offset field extends past the end "
642 "of the load command");
643 // Make sure there is a null between the starting offset of the name and
644 // the end of the load command.
645 uint32_t i;
646 const char *P = (const char *)Load.Ptr;
647 for (i = D.name; i < D.cmdsize; i++)
648 if (P[i] == '\0')
649 break;
650 if (i >= D.cmdsize)
651 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
652 CmdName + " dyld name extends past the end of the "
653 "load command");
654 return Error::success();
655}
656
Kevin Enderby32359db2016-09-28 21:20:45 +0000657static Error checkVersCommand(const MachOObjectFile *Obj,
658 const MachOObjectFile::LoadCommandInfo &Load,
659 uint32_t LoadCommandIndex,
660 const char **LoadCmd, const char *CmdName) {
661 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
662 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
663 CmdName + " has incorrect cmdsize");
664 if (*LoadCmd != nullptr)
665 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
666 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
667 "LC_VERSION_MIN_WATCHOS command");
668 *LoadCmd = Load.Ptr;
669 return Error::success();
670}
671
Kevin Enderby76966bf2016-09-28 23:16:01 +0000672static Error checkRpathCommand(const MachOObjectFile *Obj,
673 const MachOObjectFile::LoadCommandInfo &Load,
674 uint32_t LoadCommandIndex) {
675 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
676 return malformedError("load command " + Twine(LoadCommandIndex) +
677 " LC_RPATH cmdsize too small");
678 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
679 if (R.path < sizeof(MachO::rpath_command))
680 return malformedError("load command " + Twine(LoadCommandIndex) +
681 " LC_RPATH path.offset field too small, not past "
682 "the end of the rpath_command struct");
683 if (R.path >= R.cmdsize)
684 return malformedError("load command " + Twine(LoadCommandIndex) +
685 " LC_RPATH path.offset field extends past the end "
686 "of the load command");
687 // Make sure there is a null between the starting offset of the path and
688 // the end of the load command.
689 uint32_t i;
690 const char *P = (const char *)Load.Ptr;
691 for (i = R.path; i < R.cmdsize; i++)
692 if (P[i] == '\0')
693 break;
694 if (i >= R.cmdsize)
695 return malformedError("load command " + Twine(LoadCommandIndex) +
696 " LC_RPATH library name extends past the end of the "
697 "load command");
698 return Error::success();
699}
700
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000701static Error checkEncryptCommand(const MachOObjectFile *Obj,
702 const MachOObjectFile::LoadCommandInfo &Load,
703 uint32_t LoadCommandIndex,
704 uint64_t cryptoff, uint64_t cryptsize,
705 const char **LoadCmd, const char *CmdName) {
706 if (*LoadCmd != nullptr)
707 return malformedError("more than one LC_ENCRYPTION_INFO and or "
708 "LC_ENCRYPTION_INFO_64 command");
709 uint64_t FileSize = Obj->getData().size();
710 if (cryptoff > FileSize)
711 return malformedError("cryptoff field of " + Twine(CmdName) +
712 " command " + Twine(LoadCommandIndex) + " extends "
713 "past the end of the file");
714 uint64_t BigSize = cryptoff;
715 BigSize += cryptsize;
716 if (BigSize > FileSize)
717 return malformedError("cryptoff field plus cryptsize field of " +
718 Twine(CmdName) + " command " +
719 Twine(LoadCommandIndex) + " extends past the end of "
720 "the file");
721 *LoadCmd = Load.Ptr;
722 return Error::success();
723}
724
Kevin Enderby68fffa82016-10-11 21:04:39 +0000725static Error checkLinkerOptCommand(const MachOObjectFile *Obj,
726 const MachOObjectFile::LoadCommandInfo &Load,
727 uint32_t LoadCommandIndex) {
728 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
729 return malformedError("load command " + Twine(LoadCommandIndex) +
730 " LC_LINKER_OPTION cmdsize too small");
731 MachO::linker_option_command L =
732 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
733 // Make sure the count of strings is correct.
734 const char *string = (const char *)Load.Ptr +
735 sizeof(struct MachO::linker_option_command);
736 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
737 uint32_t i = 0;
738 while (left > 0) {
739 while (*string == '\0' && left > 0) {
740 string++;
741 left--;
742 }
743 if (left > 0) {
744 i++;
745 uint32_t NullPos = StringRef(string, left).find('\0');
746 uint32_t len = std::min(NullPos, left) + 1;
747 string += len;
748 left -= len;
749 }
750 }
751 if (L.count != i)
752 return malformedError("load command " + Twine(LoadCommandIndex) +
753 " LC_LINKER_OPTION string count " + Twine(L.count) +
754 " does not match number of strings");
755 return Error::success();
756}
757
Kevin Enderby2490de02016-10-17 22:09:25 +0000758static Error checkSubCommand(const MachOObjectFile *Obj,
759 const MachOObjectFile::LoadCommandInfo &Load,
760 uint32_t LoadCommandIndex, const char *CmdName,
761 size_t SizeOfCmd, const char *CmdStructName,
762 uint32_t PathOffset, const char *PathFieldName) {
763 if (PathOffset < SizeOfCmd)
764 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
765 CmdName + " " + PathFieldName + ".offset field too "
766 "small, not past the end of the " + CmdStructName);
767 if (PathOffset >= Load.C.cmdsize)
768 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
769 CmdName + " " + PathFieldName + ".offset field "
770 "extends past the end of the load command");
771 // Make sure there is a null between the starting offset of the path and
772 // the end of the load command.
773 uint32_t i;
774 const char *P = (const char *)Load.Ptr;
775 for (i = PathOffset; i < Load.C.cmdsize; i++)
776 if (P[i] == '\0')
777 break;
778 if (i >= Load.C.cmdsize)
779 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
780 CmdName + " " + PathFieldName + " name extends past "
781 "the end of the load command");
782 return Error::success();
783}
784
Kevin Enderby210030b2016-10-19 23:44:34 +0000785static Error checkThreadCommand(const MachOObjectFile *Obj,
786 const MachOObjectFile::LoadCommandInfo &Load,
787 uint32_t LoadCommandIndex,
788 const char *CmdName) {
789 if (Load.C.cmdsize < sizeof(MachO::thread_command))
790 return malformedError("load command " + Twine(LoadCommandIndex) +
791 CmdName + " cmdsize too small");
792 MachO::thread_command T =
793 getStruct<MachO::thread_command>(Obj, Load.Ptr);
794 const char *state = Load.Ptr + sizeof(MachO::thread_command);
795 const char *end = Load.Ptr + T.cmdsize;
796 uint32_t nflavor = 0;
797 uint32_t cputype = getCPUType(Obj);
798 while (state < end) {
799 if(state + sizeof(uint32_t) > end)
800 return malformedError("load command " + Twine(LoadCommandIndex) +
801 "flavor in " + CmdName + " extends past end of "
802 "command");
803 uint32_t flavor;
804 memcpy(&flavor, state, sizeof(uint32_t));
805 if (Obj->isLittleEndian() != sys::IsLittleEndianHost)
806 sys::swapByteOrder(flavor);
807 state += sizeof(uint32_t);
808
809 if(state + sizeof(uint32_t) > end)
810 return malformedError("load command " + Twine(LoadCommandIndex) +
811 " count in " + CmdName + " extends past end of "
812 "command");
813 uint32_t count;
814 memcpy(&count, state, sizeof(uint32_t));
815 if (Obj->isLittleEndian() != sys::IsLittleEndianHost)
816 sys::swapByteOrder(count);
817 state += sizeof(uint32_t);
818
819 if (cputype == MachO::CPU_TYPE_X86_64) {
820 if (flavor == MachO::x86_THREAD_STATE64) {
821 if (count != MachO::x86_THREAD_STATE64_COUNT)
822 return malformedError("load command " + Twine(LoadCommandIndex) +
823 " count not x86_THREAD_STATE64_COUNT for "
824 "flavor number " + Twine(nflavor) + " which is "
825 "a x86_THREAD_STATE64 flavor in " + CmdName +
826 " command");
827 if (state + sizeof(MachO::x86_thread_state64_t) > end)
828 return malformedError("load command " + Twine(LoadCommandIndex) +
829 " x86_THREAD_STATE64 extends past end of "
830 "command in " + CmdName + " command");
831 state += sizeof(MachO::x86_thread_state64_t);
832 } else {
833 return malformedError("load command " + Twine(LoadCommandIndex) +
834 " unknown flavor (" + Twine(flavor) + ") for "
835 "flavor number " + Twine(nflavor) + " in " +
836 CmdName + " command");
837 }
838 } else if (cputype == MachO::CPU_TYPE_ARM) {
839 if (flavor == MachO::ARM_THREAD_STATE) {
840 if (count != MachO::ARM_THREAD_STATE_COUNT)
841 return malformedError("load command " + Twine(LoadCommandIndex) +
842 " count not ARM_THREAD_STATE_COUNT for "
843 "flavor number " + Twine(nflavor) + " which is "
844 "a ARM_THREAD_STATE flavor in " + CmdName +
845 " command");
846 if (state + sizeof(MachO::arm_thread_state32_t) > end)
847 return malformedError("load command " + Twine(LoadCommandIndex) +
848 " ARM_THREAD_STATE extends past end of "
849 "command in " + CmdName + " command");
850 state += sizeof(MachO::arm_thread_state32_t);
851 } else {
852 return malformedError("load command " + Twine(LoadCommandIndex) +
853 " unknown flavor (" + Twine(flavor) + ") for "
854 "flavor number " + Twine(nflavor) + " in " +
855 CmdName + " command");
856 }
857 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
858 if (flavor == MachO::PPC_THREAD_STATE) {
859 if (count != MachO::PPC_THREAD_STATE_COUNT)
860 return malformedError("load command " + Twine(LoadCommandIndex) +
861 " count not PPC_THREAD_STATE_COUNT for "
862 "flavor number " + Twine(nflavor) + " which is "
863 "a PPC_THREAD_STATE flavor in " + CmdName +
864 " command");
865 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
866 return malformedError("load command " + Twine(LoadCommandIndex) +
867 " PPC_THREAD_STATE extends past end of "
868 "command in " + CmdName + " command");
869 state += sizeof(MachO::ppc_thread_state32_t);
870 } else {
871 return malformedError("load command " + Twine(LoadCommandIndex) +
872 " unknown flavor (" + Twine(flavor) + ") for "
873 "flavor number " + Twine(nflavor) + " in " +
874 CmdName + " command");
875 }
876 } else {
877 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
878 "command " + Twine(LoadCommandIndex) + " for " +
879 CmdName + " command can't be checked");
880 }
881 nflavor++;
882 }
883 return Error::success();
884}
885
Kevin Enderbyc8bb4222016-10-20 20:10:30 +0000886static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj,
887 const MachOObjectFile::LoadCommandInfo
888 &Load,
889 uint32_t LoadCommandIndex,
890 const char **LoadCmd) {
891 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
892 return malformedError("load command " + Twine(LoadCommandIndex) +
893 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
894 if (*LoadCmd != nullptr)
895 return malformedError("more than one LC_TWOLEVEL_HINTS command");
896 MachO::twolevel_hints_command Hints =
897 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
898 uint64_t FileSize = Obj->getData().size();
899 if (Hints.offset > FileSize)
900 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
901 Twine(LoadCommandIndex) + " extends past the end of "
902 "the file");
903 uint64_t BigSize = Hints.nhints;
904 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
905 BigSize += Hints.offset;
906 if (BigSize > FileSize)
907 return malformedError("offset field plus nhints times sizeof(struct "
908 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
909 Twine(LoadCommandIndex) + " extends past the end of "
910 "the file");
911 *LoadCmd = Load.Ptr;
912 return Error::success();
913}
914
Lang Hames82627642016-03-25 21:59:14 +0000915Expected<std::unique_ptr<MachOObjectFile>>
916MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +0000917 bool Is64Bits, uint32_t UniversalCputype,
918 uint32_t UniversalIndex) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000919 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000920 std::unique_ptr<MachOObjectFile> Obj(
921 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +0000922 Is64Bits, Err, UniversalCputype,
923 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +0000924 if (Err)
925 return std::move(Err);
926 return std::move(Obj);
927}
928
Rafael Espindola48af1c22014-08-19 18:44:46 +0000929MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +0000930 bool Is64bits, Error &Err,
931 uint32_t UniversalCputype,
932 uint32_t UniversalIndex)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000933 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000934 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000935 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
936 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
937 HasPageZeroSegment(false) {
Lang Hames5e51a2e2016-07-22 16:11:25 +0000938 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000939 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +0000940 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +0000941 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +0000942 parseHeader(this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000943 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +0000944 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +0000945 } else {
Lang Hames9e964f32016-03-25 17:25:34 +0000946 parseHeader(this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000947 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +0000948 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +0000949 }
Lang Hames9e964f32016-03-25 17:25:34 +0000950 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000951 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000952 SizeOfHeaders += getHeader().sizeofcmds;
953 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000954 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +0000955 return;
956 }
Kevin Enderby79d6c632016-10-24 21:15:11 +0000957 if (UniversalCputype != 0 && cputype != UniversalCputype) {
958 Err = malformedError("universal header architecture: " +
959 Twine(UniversalIndex) + "'s cputype does not match "
960 "object file's mach header");
961 return;
962 }
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000963
964 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +0000965 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000966 if (LoadCommandCount != 0) {
967 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
968 Load = *LoadOrErr;
969 else {
970 Err = LoadOrErr.takeError();
971 return;
972 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000973 }
Lang Hames9e964f32016-03-25 17:25:34 +0000974
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000975 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +0000976 const char *FuncStartsLoadCmd = nullptr;
977 const char *SplitInfoLoadCmd = nullptr;
978 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +0000979 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +0000980 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +0000981 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +0000982 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000983 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +0000984 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +0000985 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +0000986 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000987 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +0000988 if (is64Bit()) {
989 if (Load.C.cmdsize % 8 != 0) {
990 // We have a hack here to allow 64-bit Mach-O core files to have
991 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
992 // allowed since the macOS kernel produces them.
993 if (getHeader().filetype != MachO::MH_CORE ||
994 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
995 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
996 "multiple of 8");
997 return;
998 }
999 }
1000 } else {
1001 if (Load.C.cmdsize % 4 != 0) {
1002 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1003 "multiple of 4");
1004 return;
1005 }
1006 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001007 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001008 if (Load.C.cmd == MachO::LC_SYMTAB) {
Kevin Enderby0e52c922016-08-26 19:34:07 +00001009 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001010 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001011 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +00001012 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001013 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001014 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +00001015 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd,
1016 "LC_DATA_IN_CODE")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001017 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001018 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +00001019 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd,
1020 "LC_LINKER_OPTIMIZATION_HINT")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001021 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001022 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1023 if ((Err = checkLinkeditDataCommand(this, Load, I, &FuncStartsLoadCmd,
1024 "LC_FUNCTION_STARTS")))
1025 return;
1026 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1027 if ((Err = checkLinkeditDataCommand(this, Load, I, &SplitInfoLoadCmd,
1028 "LC_SEGMENT_SPLIT_INFO")))
1029 return;
1030 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1031 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignDrsLoadCmd,
1032 "LC_DYLIB_CODE_SIGN_DRS")))
1033 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001034 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1035 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignLoadCmd,
1036 "LC_CODE_SIGNATURE")))
1037 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001038 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1039 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd,
1040 "LC_DYLD_INFO")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001041 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001042 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1043 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd,
1044 "LC_DYLD_INFO_ONLY")))
1045 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001046 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001047 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1048 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1049 "cmdsize");
1050 return;
1051 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001052 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001053 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001054 return;
1055 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001056 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001057 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001058 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1059 MachO::section_64>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +00001060 this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyc614d282016-08-12 20:10:25 +00001061 "LC_SEGMENT_64", SizeOfHeaders)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001062 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001063 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001064 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1065 MachO::section>(
1066 this, Load, Sections, HasPageZeroSegment, I,
1067 "LC_SEGMENT", SizeOfHeaders)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001068 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001069 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1070 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd)))
1071 return;
1072 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1073 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB")))
1074 return;
1075 Libraries.push_back(Load.Ptr);
1076 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1077 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1078 return;
1079 Libraries.push_back(Load.Ptr);
1080 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1081 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1082 return;
1083 Libraries.push_back(Load.Ptr);
1084 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1085 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB")))
1086 return;
1087 Libraries.push_back(Load.Ptr);
1088 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1089 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1090 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001091 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001092 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1093 if ((Err = checkDyldCommand(this, Load, I, "LC_ID_DYLINKER")))
1094 return;
1095 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1096 if ((Err = checkDyldCommand(this, Load, I, "LC_LOAD_DYLINKER")))
1097 return;
1098 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1099 if ((Err = checkDyldCommand(this, Load, I, "LC_DYLD_ENVIRONMENT")))
1100 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001101 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1102 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1103 "LC_VERSION_MIN_MACOSX")))
1104 return;
1105 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1106 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1107 "LC_VERSION_MIN_IPHONEOS")))
1108 return;
1109 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1110 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1111 "LC_VERSION_MIN_TVOS")))
1112 return;
1113 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1114 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd,
1115 "LC_VERSION_MIN_WATCHOS")))
1116 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001117 } else if (Load.C.cmd == MachO::LC_RPATH) {
1118 if ((Err = checkRpathCommand(this, Load, I)))
1119 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001120 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1121 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1122 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1123 " has incorrect cmdsize");
1124 return;
1125 }
1126 if (SourceLoadCmd) {
1127 Err = malformedError("more than one LC_SOURCE_VERSION command");
1128 return;
1129 }
1130 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001131 } else if (Load.C.cmd == MachO::LC_MAIN) {
1132 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1133 Err = malformedError("LC_MAIN command " + Twine(I) +
1134 " has incorrect cmdsize");
1135 return;
1136 }
1137 if (EntryPointLoadCmd) {
1138 Err = malformedError("more than one LC_MAIN command");
1139 return;
1140 }
1141 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001142 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1143 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1144 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1145 " has incorrect cmdsize");
1146 return;
1147 }
1148 MachO::encryption_info_command E =
1149 getStruct<MachO::encryption_info_command>(this, Load.Ptr);
1150 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize,
1151 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1152 return;
1153 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1154 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1155 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1156 " has incorrect cmdsize");
1157 return;
1158 }
1159 MachO::encryption_info_command_64 E =
1160 getStruct<MachO::encryption_info_command_64>(this, Load.Ptr);
1161 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize,
1162 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1163 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001164 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1165 if ((Err = checkLinkerOptCommand(this, Load, I)))
1166 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001167 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1168 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1169 Err = malformedError("load command " + Twine(I) +
1170 " LC_SUB_FRAMEWORK cmdsize too small");
1171 return;
1172 }
1173 MachO::sub_framework_command S =
1174 getStruct<MachO::sub_framework_command>(this, Load.Ptr);
1175 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK",
1176 sizeof(MachO::sub_framework_command),
1177 "sub_framework_command", S.umbrella,
1178 "umbrella")))
1179 return;
1180 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1181 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1182 Err = malformedError("load command " + Twine(I) +
1183 " LC_SUB_UMBRELLA cmdsize too small");
1184 return;
1185 }
1186 MachO::sub_umbrella_command S =
1187 getStruct<MachO::sub_umbrella_command>(this, Load.Ptr);
1188 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA",
1189 sizeof(MachO::sub_umbrella_command),
1190 "sub_umbrella_command", S.sub_umbrella,
1191 "sub_umbrella")))
1192 return;
1193 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1194 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1195 Err = malformedError("load command " + Twine(I) +
1196 " LC_SUB_LIBRARY cmdsize too small");
1197 return;
1198 }
1199 MachO::sub_library_command S =
1200 getStruct<MachO::sub_library_command>(this, Load.Ptr);
1201 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY",
1202 sizeof(MachO::sub_library_command),
1203 "sub_library_command", S.sub_library,
1204 "sub_library")))
1205 return;
1206 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1207 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1208 Err = malformedError("load command " + Twine(I) +
1209 " LC_SUB_CLIENT cmdsize too small");
1210 return;
1211 }
1212 MachO::sub_client_command S =
1213 getStruct<MachO::sub_client_command>(this, Load.Ptr);
1214 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT",
1215 sizeof(MachO::sub_client_command),
1216 "sub_client_command", S.client, "client")))
1217 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001218 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1219 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1220 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1221 " has incorrect cmdsize");
1222 return;
1223 }
1224 if (RoutinesLoadCmd) {
1225 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1226 "command");
1227 return;
1228 }
1229 RoutinesLoadCmd = Load.Ptr;
1230 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1231 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1232 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1233 " has incorrect cmdsize");
1234 return;
1235 }
1236 if (RoutinesLoadCmd) {
1237 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1238 "command");
1239 return;
1240 }
1241 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001242 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1243 if ((Err = checkThreadCommand(this, Load, I, "LC_UNIXTHREAD")))
1244 return;
1245 if (UnixThreadLoadCmd) {
1246 Err = malformedError("more than one LC_UNIXTHREAD command");
1247 return;
1248 }
1249 UnixThreadLoadCmd = Load.Ptr;
1250 } else if (Load.C.cmd == MachO::LC_THREAD) {
1251 if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD")))
1252 return;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001253 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1254 if ((Err = checkTwoLevelHintsCommand(this, Load, I,
1255 &TwoLevelHintsLoadCmd)))
1256 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001257 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001258 if (I < LoadCommandCount - 1) {
Kevin Enderby368e7142016-05-03 17:16:08 +00001259 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001260 Load = *LoadOrErr;
1261 else {
1262 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001263 return;
1264 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001265 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001266 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001267 if (!SymtabLoadCmd) {
1268 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001269 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001270 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001271 return;
1272 }
1273 } else if (DysymtabLoadCmd) {
1274 MachO::symtab_command Symtab =
1275 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1276 MachO::dysymtab_command Dysymtab =
1277 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1278 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001279 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001280 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001281 return;
1282 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001283 uint64_t BigSize = Dysymtab.ilocalsym;
1284 BigSize += Dysymtab.nlocalsym;
1285 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001286 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001287 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001288 return;
1289 }
1290 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001291 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001292 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001293 return;
1294 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001295 BigSize = Dysymtab.iextdefsym;
1296 BigSize += Dysymtab.nextdefsym;
1297 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001298 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001299 "load command extends past the end of the symbol "
1300 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001301 return;
1302 }
1303 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001304 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001305 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001306 return;
1307 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001308 BigSize = Dysymtab.iundefsym;
1309 BigSize += Dysymtab.nundefsym;
1310 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001311 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001312 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001313 return;
1314 }
1315 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001316 if ((getHeader().filetype == MachO::MH_DYLIB ||
1317 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1318 DyldIdLoadCmd == nullptr) {
1319 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1320 "filetype");
1321 return;
1322 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001323 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001324
1325 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001326}
1327
Rafael Espindola5e812af2014-01-30 02:49:50 +00001328void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001329 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001330 sizeof(MachO::nlist_64) :
1331 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001332 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001333}
1334
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001335Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001336 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001337 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001338 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001339 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001340 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001341 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001342 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001343 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001344}
1345
Rafael Espindola0e77a942014-12-10 20:46:55 +00001346unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1347 DataRefImpl DRI = Sec.getRawDataRefImpl();
1348 uint32_t Flags = getSectionFlags(this, DRI);
1349 return Flags & MachO::SECTION_TYPE;
1350}
1351
Rafael Espindola59128922015-06-24 18:14:41 +00001352uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1353 if (is64Bit()) {
1354 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1355 return Entry.n_value;
1356 }
1357 MachO::nlist Entry = getSymbolTableEntry(Sym);
1358 return Entry.n_value;
1359}
1360
Kevin Enderby980b2582014-06-05 21:21:57 +00001361// getIndirectName() returns the name of the alias'ed symbol who's string table
1362// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001363std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1364 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001365 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +00001366 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
1367 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1368 return object_error::parse_failed;
1369 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001370 if (NValue >= StringTable.size())
1371 return object_error::parse_failed;
1372 const char *Start = &StringTable.data()[NValue];
1373 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001374 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001375}
1376
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001377uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001378 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001379}
1380
Kevin Enderby931cb652016-06-24 18:24:42 +00001381Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001382 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001383}
1384
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001385uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001386 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001387 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001388 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001389 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001390 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001391 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001392}
1393
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001394uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001395 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001396}
1397
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001398Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001399MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001400 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001401 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001402
Rafael Espindola56f976f2013-04-18 18:08:55 +00001403 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001404 if (n_type & MachO::N_STAB)
1405 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001406
Charles Davis74ec8b02013-08-27 05:00:13 +00001407 switch (n_type & MachO::N_TYPE) {
1408 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001409 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001410 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001411 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001412 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001413 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001414 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001415 if (Sec->isData() || Sec->isBSS())
1416 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001417 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001418 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001419 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001420}
1421
Rafael Espindola20122a42014-01-31 20:57:12 +00001422uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001423 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001424
Charles Davis8bdfafd2013-09-01 04:28:48 +00001425 uint8_t MachOType = Entry.n_type;
1426 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001427
Rafael Espindola20122a42014-01-31 20:57:12 +00001428 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001429
Tim Northovereaef0742014-05-30 13:22:59 +00001430 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1431 Result |= SymbolRef::SF_Indirect;
1432
Rafael Espindolaa1356322013-11-02 05:03:24 +00001433 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001434 Result |= SymbolRef::SF_FormatSpecific;
1435
Charles Davis74ec8b02013-08-27 05:00:13 +00001436 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001437 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001438 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001439 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001440 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001441 else
1442 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001443 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001444
1445 if (!(MachOType & MachO::N_PEXT))
1446 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001447 }
1448
Charles Davis74ec8b02013-08-27 05:00:13 +00001449 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001450 Result |= SymbolRef::SF_Weak;
1451
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001452 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1453 Result |= SymbolRef::SF_Thumb;
1454
Charles Davis74ec8b02013-08-27 05:00:13 +00001455 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001456 Result |= SymbolRef::SF_Absolute;
1457
Rafael Espindola20122a42014-01-31 20:57:12 +00001458 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001459}
1460
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001461Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001462MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +00001463 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001464 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001465
Rafael Espindola8bab8892015-08-07 23:27:14 +00001466 if (index == 0)
1467 return section_end();
1468 DataRefImpl DRI;
1469 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001470 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001471 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001472 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001473 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001474 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001475}
1476
Rafael Espindola6bf32212015-06-24 19:57:32 +00001477unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1478 MachO::nlist_base Entry =
1479 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
1480 return Entry.n_sect - 1;
1481}
1482
Rafael Espindola5e812af2014-01-30 02:49:50 +00001483void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001484 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001485}
1486
Rafael Espindola3acea392014-06-12 21:46:39 +00001487std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1488 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001489 ArrayRef<char> Raw = getSectionRawName(Sec);
1490 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001491 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001492}
1493
Rafael Espindola80291272014-10-08 15:28:58 +00001494uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1495 if (is64Bit())
1496 return getSection64(Sec).addr;
1497 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001498}
1499
Rafael Espindola80291272014-10-08 15:28:58 +00001500uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001501 // In the case if a malformed Mach-O file where the section offset is past
1502 // the end of the file or some part of the section size is past the end of
1503 // the file return a size of zero or a size that covers the rest of the file
1504 // but does not extend past the end of the file.
1505 uint32_t SectOffset, SectType;
1506 uint64_t SectSize;
1507
1508 if (is64Bit()) {
1509 MachO::section_64 Sect = getSection64(Sec);
1510 SectOffset = Sect.offset;
1511 SectSize = Sect.size;
1512 SectType = Sect.flags & MachO::SECTION_TYPE;
1513 } else {
1514 MachO::section Sect = getSection(Sec);
1515 SectOffset = Sect.offset;
1516 SectSize = Sect.size;
1517 SectType = Sect.flags & MachO::SECTION_TYPE;
1518 }
1519 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1520 return SectSize;
1521 uint64_t FileSize = getData().size();
1522 if (SectOffset > FileSize)
1523 return 0;
1524 if (FileSize - SectOffset < SectSize)
1525 return FileSize - SectOffset;
1526 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001527}
1528
Rafael Espindola3acea392014-06-12 21:46:39 +00001529std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1530 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001531 uint32_t Offset;
1532 uint64_t Size;
1533
1534 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001535 MachO::section_64 Sect = getSection64(Sec);
1536 Offset = Sect.offset;
1537 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001538 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001539 MachO::section Sect = getSection(Sec);
1540 Offset = Sect.offset;
1541 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001542 }
1543
1544 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001545 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001546}
1547
Rafael Espindola80291272014-10-08 15:28:58 +00001548uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001549 uint32_t Align;
1550 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001551 MachO::section_64 Sect = getSection64(Sec);
1552 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001553 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001554 MachO::section Sect = getSection(Sec);
1555 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001556 }
1557
Rafael Espindola80291272014-10-08 15:28:58 +00001558 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001559}
1560
George Rimar401e4e52016-05-24 12:48:46 +00001561bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1562 return false;
1563}
1564
Rafael Espindola80291272014-10-08 15:28:58 +00001565bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001566 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001567 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001568}
1569
Rafael Espindola80291272014-10-08 15:28:58 +00001570bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +00001571 uint32_t Flags = getSectionFlags(this, Sec);
1572 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001573 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1574 !(SectionType == MachO::S_ZEROFILL ||
1575 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001576}
1577
Rafael Espindola80291272014-10-08 15:28:58 +00001578bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +00001579 uint32_t Flags = getSectionFlags(this, Sec);
1580 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001581 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1582 (SectionType == MachO::S_ZEROFILL ||
1583 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001584}
1585
Rafael Espindola6bf32212015-06-24 19:57:32 +00001586unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1587 return Sec.getRawDataRefImpl().d.a;
1588}
1589
Rafael Espindola80291272014-10-08 15:28:58 +00001590bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +00001591 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +00001592 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001593}
1594
Steven Wuf2fe0142016-02-29 19:40:10 +00001595bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1596 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1597 StringRef SectName;
1598 if (!getSectionName(Sec, SectName))
1599 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1600 return false;
1601}
1602
Rui Ueyamabc654b12013-09-27 21:47:05 +00001603relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001604 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001605 Ret.d.a = Sec.d.a;
1606 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001607 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001608}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001609
Rafael Espindola56f976f2013-04-18 18:08:55 +00001610relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00001611MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001612 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001613 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001614 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001615 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001616 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001617 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001618 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001619 }
Eric Christopher7b015c72011-04-22 03:19:48 +00001620
Rafael Espindola56f976f2013-04-18 18:08:55 +00001621 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001622 Ret.d.a = Sec.d.a;
1623 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001624 return relocation_iterator(RelocationRef(Ret, this));
1625}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001626
Rafael Espindola5e812af2014-01-30 02:49:50 +00001627void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001628 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001629}
Owen Anderson171f4852011-10-24 23:20:07 +00001630
Rafael Espindola96d071c2015-06-29 23:29:12 +00001631uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +00001632 assert(getHeader().filetype == MachO::MH_OBJECT &&
1633 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001634 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00001635 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00001636}
1637
Rafael Espindola806f0062013-06-05 01:33:53 +00001638symbol_iterator
1639MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001640 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00001641 if (isRelocationScattered(RE))
1642 return symbol_end();
1643
Rafael Espindola56f976f2013-04-18 18:08:55 +00001644 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1645 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00001646 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00001647 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00001648
Charles Davis8bdfafd2013-09-01 04:28:48 +00001649 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001650 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001651 sizeof(MachO::nlist_64) :
1652 sizeof(MachO::nlist);
1653 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001654 DataRefImpl Sym;
1655 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00001656 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001657}
1658
Keno Fischerc780e8e2015-05-21 21:24:32 +00001659section_iterator
1660MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
1661 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
1662}
1663
Rafael Espindola99c041b2015-06-30 01:53:01 +00001664uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001665 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00001666 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001667}
1668
Rafael Espindola41bb4322015-06-30 04:08:37 +00001669void MachOObjectFile::getRelocationTypeName(
1670 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001671 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00001672 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001673
1674 unsigned Arch = this->getArch();
1675
1676 switch (Arch) {
1677 case Triple::x86: {
1678 static const char *const Table[] = {
1679 "GENERIC_RELOC_VANILLA",
1680 "GENERIC_RELOC_PAIR",
1681 "GENERIC_RELOC_SECTDIFF",
1682 "GENERIC_RELOC_PB_LA_PTR",
1683 "GENERIC_RELOC_LOCAL_SECTDIFF",
1684 "GENERIC_RELOC_TLV" };
1685
Eric Christopher13250cb2013-12-06 02:33:38 +00001686 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001687 res = "Unknown";
1688 else
1689 res = Table[RType];
1690 break;
1691 }
1692 case Triple::x86_64: {
1693 static const char *const Table[] = {
1694 "X86_64_RELOC_UNSIGNED",
1695 "X86_64_RELOC_SIGNED",
1696 "X86_64_RELOC_BRANCH",
1697 "X86_64_RELOC_GOT_LOAD",
1698 "X86_64_RELOC_GOT",
1699 "X86_64_RELOC_SUBTRACTOR",
1700 "X86_64_RELOC_SIGNED_1",
1701 "X86_64_RELOC_SIGNED_2",
1702 "X86_64_RELOC_SIGNED_4",
1703 "X86_64_RELOC_TLV" };
1704
1705 if (RType > 9)
1706 res = "Unknown";
1707 else
1708 res = Table[RType];
1709 break;
1710 }
1711 case Triple::arm: {
1712 static const char *const Table[] = {
1713 "ARM_RELOC_VANILLA",
1714 "ARM_RELOC_PAIR",
1715 "ARM_RELOC_SECTDIFF",
1716 "ARM_RELOC_LOCAL_SECTDIFF",
1717 "ARM_RELOC_PB_LA_PTR",
1718 "ARM_RELOC_BR24",
1719 "ARM_THUMB_RELOC_BR22",
1720 "ARM_THUMB_32BIT_BRANCH",
1721 "ARM_RELOC_HALF",
1722 "ARM_RELOC_HALF_SECTDIFF" };
1723
1724 if (RType > 9)
1725 res = "Unknown";
1726 else
1727 res = Table[RType];
1728 break;
1729 }
Tim Northover00ed9962014-03-29 10:18:08 +00001730 case Triple::aarch64: {
1731 static const char *const Table[] = {
1732 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
1733 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
1734 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
1735 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
1736 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
1737 "ARM64_RELOC_ADDEND"
1738 };
1739
1740 if (RType >= array_lengthof(Table))
1741 res = "Unknown";
1742 else
1743 res = Table[RType];
1744 break;
1745 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001746 case Triple::ppc: {
1747 static const char *const Table[] = {
1748 "PPC_RELOC_VANILLA",
1749 "PPC_RELOC_PAIR",
1750 "PPC_RELOC_BR14",
1751 "PPC_RELOC_BR24",
1752 "PPC_RELOC_HI16",
1753 "PPC_RELOC_LO16",
1754 "PPC_RELOC_HA16",
1755 "PPC_RELOC_LO14",
1756 "PPC_RELOC_SECTDIFF",
1757 "PPC_RELOC_PB_LA_PTR",
1758 "PPC_RELOC_HI16_SECTDIFF",
1759 "PPC_RELOC_LO16_SECTDIFF",
1760 "PPC_RELOC_HA16_SECTDIFF",
1761 "PPC_RELOC_JBSR",
1762 "PPC_RELOC_LO14_SECTDIFF",
1763 "PPC_RELOC_LOCAL_SECTDIFF" };
1764
Eric Christopher13250cb2013-12-06 02:33:38 +00001765 if (RType > 15)
1766 res = "Unknown";
1767 else
1768 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00001769 break;
1770 }
1771 case Triple::UnknownArch:
1772 res = "Unknown";
1773 break;
1774 }
1775 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00001776}
1777
Keno Fischer281b6942015-05-30 19:44:53 +00001778uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
1779 MachO::any_relocation_info RE = getRelocation(Rel);
1780 return getAnyRelocationLength(RE);
1781}
1782
Kevin Enderby980b2582014-06-05 21:21:57 +00001783//
1784// guessLibraryShortName() is passed a name of a dynamic library and returns a
1785// guess on what the short name is. Then name is returned as a substring of the
1786// StringRef Name passed in. The name of the dynamic library is recognized as
1787// a framework if it has one of the two following forms:
1788// Foo.framework/Versions/A/Foo
1789// Foo.framework/Foo
1790// Where A and Foo can be any string. And may contain a trailing suffix
1791// starting with an underbar. If the Name is recognized as a framework then
1792// isFramework is set to true else it is set to false. If the Name has a
1793// suffix then Suffix is set to the substring in Name that contains the suffix
1794// else it is set to a NULL StringRef.
1795//
1796// The Name of the dynamic library is recognized as a library name if it has
1797// one of the two following forms:
1798// libFoo.A.dylib
1799// libFoo.dylib
1800// The library may have a suffix trailing the name Foo of the form:
1801// libFoo_profile.A.dylib
1802// libFoo_profile.dylib
1803//
1804// The Name of the dynamic library is also recognized as a library name if it
1805// has the following form:
1806// Foo.qtx
1807//
1808// If the Name of the dynamic library is none of the forms above then a NULL
1809// StringRef is returned.
1810//
1811StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1812 bool &isFramework,
1813 StringRef &Suffix) {
1814 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1815 size_t a, b, c, d, Idx;
1816
1817 isFramework = false;
1818 Suffix = StringRef();
1819
1820 // Pull off the last component and make Foo point to it
1821 a = Name.rfind('/');
1822 if (a == Name.npos || a == 0)
1823 goto guess_library;
1824 Foo = Name.slice(a+1, Name.npos);
1825
1826 // Look for a suffix starting with a '_'
1827 Idx = Foo.rfind('_');
1828 if (Idx != Foo.npos && Foo.size() >= 2) {
1829 Suffix = Foo.slice(Idx, Foo.npos);
1830 Foo = Foo.slice(0, Idx);
1831 }
1832
1833 // First look for the form Foo.framework/Foo
1834 b = Name.rfind('/', a);
1835 if (b == Name.npos)
1836 Idx = 0;
1837 else
1838 Idx = b+1;
1839 F = Name.slice(Idx, Idx + Foo.size());
1840 DotFramework = Name.slice(Idx + Foo.size(),
1841 Idx + Foo.size() + sizeof(".framework/")-1);
1842 if (F == Foo && DotFramework == ".framework/") {
1843 isFramework = true;
1844 return Foo;
1845 }
1846
1847 // Next look for the form Foo.framework/Versions/A/Foo
1848 if (b == Name.npos)
1849 goto guess_library;
1850 c = Name.rfind('/', b);
1851 if (c == Name.npos || c == 0)
1852 goto guess_library;
1853 V = Name.slice(c+1, Name.npos);
1854 if (!V.startswith("Versions/"))
1855 goto guess_library;
1856 d = Name.rfind('/', c);
1857 if (d == Name.npos)
1858 Idx = 0;
1859 else
1860 Idx = d+1;
1861 F = Name.slice(Idx, Idx + Foo.size());
1862 DotFramework = Name.slice(Idx + Foo.size(),
1863 Idx + Foo.size() + sizeof(".framework/")-1);
1864 if (F == Foo && DotFramework == ".framework/") {
1865 isFramework = true;
1866 return Foo;
1867 }
1868
1869guess_library:
1870 // pull off the suffix after the "." and make a point to it
1871 a = Name.rfind('.');
1872 if (a == Name.npos || a == 0)
1873 return StringRef();
1874 Dylib = Name.slice(a, Name.npos);
1875 if (Dylib != ".dylib")
1876 goto guess_qtx;
1877
1878 // First pull off the version letter for the form Foo.A.dylib if any.
1879 if (a >= 3) {
1880 Dot = Name.slice(a-2, a-1);
1881 if (Dot == ".")
1882 a = a - 2;
1883 }
1884
1885 b = Name.rfind('/', a);
1886 if (b == Name.npos)
1887 b = 0;
1888 else
1889 b = b+1;
1890 // ignore any suffix after an underbar like Foo_profile.A.dylib
1891 Idx = Name.find('_', b);
1892 if (Idx != Name.npos && Idx != b) {
1893 Lib = Name.slice(b, Idx);
1894 Suffix = Name.slice(Idx, a);
1895 }
1896 else
1897 Lib = Name.slice(b, a);
1898 // There are incorrect library names of the form:
1899 // libATS.A_profile.dylib so check for these.
1900 if (Lib.size() >= 3) {
1901 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1902 if (Dot == ".")
1903 Lib = Lib.slice(0, Lib.size()-2);
1904 }
1905 return Lib;
1906
1907guess_qtx:
1908 Qtx = Name.slice(a, Name.npos);
1909 if (Qtx != ".qtx")
1910 return StringRef();
1911 b = Name.rfind('/', a);
1912 if (b == Name.npos)
1913 Lib = Name.slice(0, a);
1914 else
1915 Lib = Name.slice(b+1, a);
1916 // There are library names of the form: QT.A.qtx so check for these.
1917 if (Lib.size() >= 3) {
1918 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1919 if (Dot == ".")
1920 Lib = Lib.slice(0, Lib.size()-2);
1921 }
1922 return Lib;
1923}
1924
1925// getLibraryShortNameByIndex() is used to get the short name of the library
1926// for an undefined symbol in a linked Mach-O binary that was linked with the
1927// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1928// It is passed the index (0 - based) of the library as translated from
1929// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001930std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001931 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001932 if (Index >= Libraries.size())
1933 return object_error::parse_failed;
1934
Kevin Enderby980b2582014-06-05 21:21:57 +00001935 // If the cache of LibrariesShortNames is not built up do that first for
1936 // all the Libraries.
1937 if (LibrariesShortNames.size() == 0) {
1938 for (unsigned i = 0; i < Libraries.size(); i++) {
1939 MachO::dylib_command D =
1940 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001941 if (D.dylib.name >= D.cmdsize)
1942 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001943 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001944 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001945 if (D.dylib.name+Name.size() >= D.cmdsize)
1946 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001947 StringRef Suffix;
1948 bool isFramework;
1949 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001950 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001951 LibrariesShortNames.push_back(Name);
1952 else
1953 LibrariesShortNames.push_back(shortName);
1954 }
1955 }
1956
1957 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001958 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001959}
1960
Rafael Espindola76ad2322015-07-06 14:55:37 +00001961section_iterator
1962MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1963 DataRefImpl Sec;
1964 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1965 return section_iterator(SectionRef(Sec, this));
1966}
1967
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001968basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001969 DataRefImpl DRI;
1970 MachO::symtab_command Symtab = getSymtabLoadCommand();
1971 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1972 return basic_symbol_iterator(SymbolRef(DRI, this));
1973
Lang Hames36072da2014-05-12 21:39:59 +00001974 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001975}
1976
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001977basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001978 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001979 MachO::symtab_command Symtab = getSymtabLoadCommand();
1980 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001981 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001982
Rafael Espindola75c30362013-04-24 19:47:55 +00001983 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001984 sizeof(MachO::nlist_64) :
1985 sizeof(MachO::nlist);
1986 unsigned Offset = Symtab.symoff +
1987 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001988 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001989 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001990}
1991
Lang Hames36072da2014-05-12 21:39:59 +00001992basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001993 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001994 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001995 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001996 unsigned SymbolTableEntrySize =
1997 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001998 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001999 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
2000 DRI.p += Index * SymbolTableEntrySize;
2001 return basic_symbol_iterator(SymbolRef(DRI, this));
2002}
2003
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002004uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2005 MachO::symtab_command Symtab = getSymtabLoadCommand();
2006 if (!SymtabLoadCmd)
2007 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2008 unsigned SymbolTableEntrySize =
2009 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2010 DataRefImpl DRIstart;
2011 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
2012 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2013 return Index;
2014}
2015
Rafael Espindolab5155a52014-02-10 20:24:04 +00002016section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002017 DataRefImpl DRI;
2018 return section_iterator(SectionRef(DRI, this));
2019}
2020
Rafael Espindolab5155a52014-02-10 20:24:04 +00002021section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002022 DataRefImpl DRI;
2023 DRI.d.a = Sections.size();
2024 return section_iterator(SectionRef(DRI, this));
2025}
2026
Rafael Espindola56f976f2013-04-18 18:08:55 +00002027uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002028 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002029}
2030
Rafael Espindola56f976f2013-04-18 18:08:55 +00002031StringRef MachOObjectFile::getFileFormatName() const {
2032 unsigned CPUType = getCPUType(this);
2033 if (!is64Bit()) {
2034 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002035 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002036 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00002037 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002038 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00002039 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002040 return "Mach-O 32-bit ppc";
2041 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002042 return "Mach-O 32-bit unknown";
2043 }
2044 }
2045
Rafael Espindola56f976f2013-04-18 18:08:55 +00002046 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002047 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002048 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00002049 case llvm::MachO::CPU_TYPE_ARM64:
2050 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00002051 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002052 return "Mach-O 64-bit ppc64";
2053 default:
2054 return "Mach-O 64-bit unknown";
2055 }
2056}
2057
Alexey Samsonove6388e62013-06-18 15:03:28 +00002058Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2059 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002060 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002061 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00002062 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002063 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002064 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002065 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00002066 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002067 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002068 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002069 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00002070 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002071 return Triple::ppc64;
2072 default:
2073 return Triple::UnknownArch;
2074 }
2075}
2076
Tim Northover9e8eb412016-04-22 23:21:13 +00002077Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2078 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002079 if (McpuDefault)
2080 *McpuDefault = nullptr;
2081
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002082 switch (CPUType) {
2083 case MachO::CPU_TYPE_I386:
2084 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2085 case MachO::CPU_SUBTYPE_I386_ALL:
2086 return Triple("i386-apple-darwin");
2087 default:
2088 return Triple();
2089 }
2090 case MachO::CPU_TYPE_X86_64:
2091 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2092 case MachO::CPU_SUBTYPE_X86_64_ALL:
2093 return Triple("x86_64-apple-darwin");
2094 case MachO::CPU_SUBTYPE_X86_64_H:
2095 return Triple("x86_64h-apple-darwin");
2096 default:
2097 return Triple();
2098 }
2099 case MachO::CPU_TYPE_ARM:
2100 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2101 case MachO::CPU_SUBTYPE_ARM_V4T:
2102 return Triple("armv4t-apple-darwin");
2103 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2104 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002105 case MachO::CPU_SUBTYPE_ARM_XSCALE:
2106 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002107 case MachO::CPU_SUBTYPE_ARM_V6:
2108 return Triple("armv6-apple-darwin");
2109 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002110 if (McpuDefault)
2111 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002112 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002113 case MachO::CPU_SUBTYPE_ARM_V7:
2114 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002115 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002116 if (McpuDefault)
2117 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00002118 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002119 case MachO::CPU_SUBTYPE_ARM_V7K:
2120 return Triple("armv7k-apple-darwin");
2121 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002122 if (McpuDefault)
2123 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00002124 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002125 case MachO::CPU_SUBTYPE_ARM_V7S:
2126 return Triple("armv7s-apple-darwin");
2127 default:
2128 return Triple();
2129 }
2130 case MachO::CPU_TYPE_ARM64:
2131 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2132 case MachO::CPU_SUBTYPE_ARM64_ALL:
2133 return Triple("arm64-apple-darwin");
2134 default:
2135 return Triple();
2136 }
2137 case MachO::CPU_TYPE_POWERPC:
2138 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2139 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2140 return Triple("ppc-apple-darwin");
2141 default:
2142 return Triple();
2143 }
2144 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002145 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002146 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2147 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002148 default:
2149 return Triple();
2150 }
2151 default:
2152 return Triple();
2153 }
2154}
2155
2156Triple MachOObjectFile::getHostArch() {
2157 return Triple(sys::getDefaultTargetTriple());
2158}
2159
Rafael Espindola72318b42014-08-08 16:30:17 +00002160bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2161 return StringSwitch<bool>(ArchFlag)
2162 .Case("i386", true)
2163 .Case("x86_64", true)
2164 .Case("x86_64h", true)
2165 .Case("armv4t", true)
2166 .Case("arm", true)
2167 .Case("armv5e", true)
2168 .Case("armv6", true)
2169 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002170 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002171 .Case("armv7em", true)
2172 .Case("armv7k", true)
2173 .Case("armv7m", true)
2174 .Case("armv7s", true)
2175 .Case("arm64", true)
2176 .Case("ppc", true)
2177 .Case("ppc64", true)
2178 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002179}
2180
Alexey Samsonove6388e62013-06-18 15:03:28 +00002181unsigned MachOObjectFile::getArch() const {
2182 return getArch(getCPUType(this));
2183}
2184
Tim Northover9e8eb412016-04-22 23:21:13 +00002185Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2186 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002187}
2188
Rui Ueyamabc654b12013-09-27 21:47:05 +00002189relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002190 DataRefImpl DRI;
2191 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002192 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002193}
2194
Rui Ueyamabc654b12013-09-27 21:47:05 +00002195relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002196 DataRefImpl DRI;
2197 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002198 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002199}
2200
Kevin Enderby273ae012013-06-06 17:20:50 +00002201dice_iterator MachOObjectFile::begin_dices() const {
2202 DataRefImpl DRI;
2203 if (!DataInCodeLoadCmd)
2204 return dice_iterator(DiceRef(DRI, this));
2205
Charles Davis8bdfafd2013-09-01 04:28:48 +00002206 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2207 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002208 return dice_iterator(DiceRef(DRI, this));
2209}
2210
2211dice_iterator MachOObjectFile::end_dices() const {
2212 DataRefImpl DRI;
2213 if (!DataInCodeLoadCmd)
2214 return dice_iterator(DiceRef(DRI, this));
2215
Charles Davis8bdfafd2013-09-01 04:28:48 +00002216 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2217 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00002218 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
2219 return dice_iterator(DiceRef(DRI, this));
2220}
2221
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002222ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
2223 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002224
2225void ExportEntry::moveToFirst() {
2226 pushNode(0);
2227 pushDownUntilBottom();
2228}
2229
2230void ExportEntry::moveToEnd() {
2231 Stack.clear();
2232 Done = true;
2233}
2234
2235bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002236 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002237 if (Done || Other.Done)
2238 return (Done == Other.Done);
2239 // Not equal if different stack sizes.
2240 if (Stack.size() != Other.Stack.size())
2241 return false;
2242 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002243 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002244 return false;
2245 // Equal if all nodes in both stacks match.
2246 for (unsigned i=0; i < Stack.size(); ++i) {
2247 if (Stack[i].Start != Other.Stack[i].Start)
2248 return false;
2249 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002250 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002251}
2252
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002253uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
2254 unsigned Count;
2255 uint64_t Result = decodeULEB128(Ptr, &Count);
2256 Ptr += Count;
2257 if (Ptr > Trie.end()) {
2258 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002259 Malformed = true;
2260 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002261 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002262}
2263
2264StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002265 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002266}
2267
2268uint64_t ExportEntry::flags() const {
2269 return Stack.back().Flags;
2270}
2271
2272uint64_t ExportEntry::address() const {
2273 return Stack.back().Address;
2274}
2275
2276uint64_t ExportEntry::other() const {
2277 return Stack.back().Other;
2278}
2279
2280StringRef ExportEntry::otherName() const {
2281 const char* ImportName = Stack.back().ImportName;
2282 if (ImportName)
2283 return StringRef(ImportName);
2284 return StringRef();
2285}
2286
2287uint32_t ExportEntry::nodeOffset() const {
2288 return Stack.back().Start - Trie.begin();
2289}
2290
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002291ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2292 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
2293 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
2294 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002295
2296void ExportEntry::pushNode(uint64_t offset) {
2297 const uint8_t *Ptr = Trie.begin() + offset;
2298 NodeState State(Ptr);
2299 uint64_t ExportInfoSize = readULEB128(State.Current);
2300 State.IsExportNode = (ExportInfoSize != 0);
2301 const uint8_t* Children = State.Current + ExportInfoSize;
2302 if (State.IsExportNode) {
2303 State.Flags = readULEB128(State.Current);
2304 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2305 State.Address = 0;
2306 State.Other = readULEB128(State.Current); // dylib ordinal
2307 State.ImportName = reinterpret_cast<const char*>(State.Current);
2308 } else {
2309 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00002310 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002311 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002312 }
2313 }
2314 State.ChildCount = *Children;
2315 State.Current = Children + 1;
2316 State.NextChildIndex = 0;
2317 State.ParentStringLength = CumulativeString.size();
2318 Stack.push_back(State);
2319}
2320
2321void ExportEntry::pushDownUntilBottom() {
2322 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2323 NodeState &Top = Stack.back();
2324 CumulativeString.resize(Top.ParentStringLength);
2325 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002326 char C = *Top.Current;
2327 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002328 }
2329 Top.Current += 1;
2330 uint64_t childNodeIndex = readULEB128(Top.Current);
2331 Top.NextChildIndex += 1;
2332 pushNode(childNodeIndex);
2333 }
2334 if (!Stack.back().IsExportNode) {
2335 Malformed = true;
2336 moveToEnd();
2337 }
2338}
2339
2340// We have a trie data structure and need a way to walk it that is compatible
2341// with the C++ iterator model. The solution is a non-recursive depth first
2342// traversal where the iterator contains a stack of parent nodes along with a
2343// string that is the accumulation of all edge strings along the parent chain
2344// to this point.
2345//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002346// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002347// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002348// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002349//
2350// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2351// child until hitting a node with no children (which is an export node or
2352// else the trie is malformed). On the way down, each node is pushed on the
2353// stack ivar. If there is no more ways down, it pops up one and tries to go
2354// down a sibling path until a childless node is reached.
2355void ExportEntry::moveNext() {
2356 if (Stack.empty() || !Stack.back().IsExportNode) {
2357 Malformed = true;
2358 moveToEnd();
2359 return;
2360 }
2361
2362 Stack.pop_back();
2363 while (!Stack.empty()) {
2364 NodeState &Top = Stack.back();
2365 if (Top.NextChildIndex < Top.ChildCount) {
2366 pushDownUntilBottom();
2367 // Now at the next export node.
2368 return;
2369 } else {
2370 if (Top.IsExportNode) {
2371 // This node has no children but is itself an export node.
2372 CumulativeString.resize(Top.ParentStringLength);
2373 return;
2374 }
2375 Stack.pop_back();
2376 }
2377 }
2378 Done = true;
2379}
2380
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002381iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00002382MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
2383 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002384 if (Trie.size() == 0)
2385 Start.moveToEnd();
2386 else
2387 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002388
2389 ExportEntry Finish(Trie);
2390 Finish.moveToEnd();
2391
Craig Topper15576e12015-12-06 05:08:07 +00002392 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002393}
2394
2395iterator_range<export_iterator> MachOObjectFile::exports() const {
2396 return exports(getDyldInfoExportsTrie());
2397}
2398
Nick Kledzikac431442014-09-12 21:34:15 +00002399MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
2400 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2401 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2402 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
2403
2404void MachORebaseEntry::moveToFirst() {
2405 Ptr = Opcodes.begin();
2406 moveNext();
2407}
2408
2409void MachORebaseEntry::moveToEnd() {
2410 Ptr = Opcodes.end();
2411 RemainingLoopCount = 0;
2412 Done = true;
2413}
2414
2415void MachORebaseEntry::moveNext() {
2416 // If in the middle of some loop, move to next rebasing in loop.
2417 SegmentOffset += AdvanceAmount;
2418 if (RemainingLoopCount) {
2419 --RemainingLoopCount;
2420 return;
2421 }
2422 if (Ptr == Opcodes.end()) {
2423 Done = true;
2424 return;
2425 }
2426 bool More = true;
2427 while (More && !Malformed) {
2428 // Parse next opcode and set up next loop.
2429 uint8_t Byte = *Ptr++;
2430 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2431 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
2432 switch (Opcode) {
2433 case MachO::REBASE_OPCODE_DONE:
2434 More = false;
2435 Done = true;
2436 moveToEnd();
2437 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
2438 break;
2439 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2440 RebaseType = ImmValue;
2441 DEBUG_WITH_TYPE(
2442 "mach-o-rebase",
2443 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2444 << "RebaseType=" << (int) RebaseType << "\n");
2445 break;
2446 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2447 SegmentIndex = ImmValue;
2448 SegmentOffset = readULEB128();
2449 DEBUG_WITH_TYPE(
2450 "mach-o-rebase",
2451 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2452 << "SegmentIndex=" << SegmentIndex << ", "
2453 << format("SegmentOffset=0x%06X", SegmentOffset)
2454 << "\n");
2455 break;
2456 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
2457 SegmentOffset += readULEB128();
2458 DEBUG_WITH_TYPE("mach-o-rebase",
2459 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
2460 << format("SegmentOffset=0x%06X",
2461 SegmentOffset) << "\n");
2462 break;
2463 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
2464 SegmentOffset += ImmValue * PointerSize;
2465 DEBUG_WITH_TYPE("mach-o-rebase",
2466 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
2467 << format("SegmentOffset=0x%06X",
2468 SegmentOffset) << "\n");
2469 break;
2470 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
2471 AdvanceAmount = PointerSize;
2472 RemainingLoopCount = ImmValue - 1;
2473 DEBUG_WITH_TYPE(
2474 "mach-o-rebase",
2475 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
2476 << format("SegmentOffset=0x%06X", SegmentOffset)
2477 << ", AdvanceAmount=" << AdvanceAmount
2478 << ", RemainingLoopCount=" << RemainingLoopCount
2479 << "\n");
2480 return;
2481 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
2482 AdvanceAmount = PointerSize;
2483 RemainingLoopCount = readULEB128() - 1;
2484 DEBUG_WITH_TYPE(
2485 "mach-o-rebase",
2486 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
2487 << format("SegmentOffset=0x%06X", SegmentOffset)
2488 << ", AdvanceAmount=" << AdvanceAmount
2489 << ", RemainingLoopCount=" << RemainingLoopCount
2490 << "\n");
2491 return;
2492 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
2493 AdvanceAmount = readULEB128() + PointerSize;
2494 RemainingLoopCount = 0;
2495 DEBUG_WITH_TYPE(
2496 "mach-o-rebase",
2497 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
2498 << format("SegmentOffset=0x%06X", SegmentOffset)
2499 << ", AdvanceAmount=" << AdvanceAmount
2500 << ", RemainingLoopCount=" << RemainingLoopCount
2501 << "\n");
2502 return;
2503 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
2504 RemainingLoopCount = readULEB128() - 1;
2505 AdvanceAmount = readULEB128() + PointerSize;
2506 DEBUG_WITH_TYPE(
2507 "mach-o-rebase",
2508 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
2509 << format("SegmentOffset=0x%06X", SegmentOffset)
2510 << ", AdvanceAmount=" << AdvanceAmount
2511 << ", RemainingLoopCount=" << RemainingLoopCount
2512 << "\n");
2513 return;
2514 default:
2515 Malformed = true;
2516 }
2517 }
2518}
2519
2520uint64_t MachORebaseEntry::readULEB128() {
2521 unsigned Count;
2522 uint64_t Result = decodeULEB128(Ptr, &Count);
2523 Ptr += Count;
2524 if (Ptr > Opcodes.end()) {
2525 Ptr = Opcodes.end();
2526 Malformed = true;
2527 }
2528 return Result;
2529}
2530
2531uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
2532
2533uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
2534
2535StringRef MachORebaseEntry::typeName() const {
2536 switch (RebaseType) {
2537 case MachO::REBASE_TYPE_POINTER:
2538 return "pointer";
2539 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
2540 return "text abs32";
2541 case MachO::REBASE_TYPE_TEXT_PCREL32:
2542 return "text rel32";
2543 }
2544 return "unknown";
2545}
2546
2547bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
2548 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2549 return (Ptr == Other.Ptr) &&
2550 (RemainingLoopCount == Other.RemainingLoopCount) &&
2551 (Done == Other.Done);
2552}
2553
2554iterator_range<rebase_iterator>
2555MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
2556 MachORebaseEntry Start(Opcodes, is64);
2557 Start.moveToFirst();
2558
2559 MachORebaseEntry Finish(Opcodes, is64);
2560 Finish.moveToEnd();
2561
Craig Topper15576e12015-12-06 05:08:07 +00002562 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00002563}
2564
2565iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
2566 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
2567}
2568
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002569MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00002570 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2571 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
2572 BindType(0), PointerSize(is64Bit ? 8 : 4),
2573 TableKind(BK), Malformed(false), Done(false) {}
2574
2575void MachOBindEntry::moveToFirst() {
2576 Ptr = Opcodes.begin();
2577 moveNext();
2578}
2579
2580void MachOBindEntry::moveToEnd() {
2581 Ptr = Opcodes.end();
2582 RemainingLoopCount = 0;
2583 Done = true;
2584}
2585
2586void MachOBindEntry::moveNext() {
2587 // If in the middle of some loop, move to next binding in loop.
2588 SegmentOffset += AdvanceAmount;
2589 if (RemainingLoopCount) {
2590 --RemainingLoopCount;
2591 return;
2592 }
2593 if (Ptr == Opcodes.end()) {
2594 Done = true;
2595 return;
2596 }
2597 bool More = true;
2598 while (More && !Malformed) {
2599 // Parse next opcode and set up next loop.
2600 uint8_t Byte = *Ptr++;
2601 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
2602 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
2603 int8_t SignExtended;
2604 const uint8_t *SymStart;
2605 switch (Opcode) {
2606 case MachO::BIND_OPCODE_DONE:
2607 if (TableKind == Kind::Lazy) {
2608 // Lazying bindings have a DONE opcode between entries. Need to ignore
2609 // it to advance to next entry. But need not if this is last entry.
2610 bool NotLastEntry = false;
2611 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
2612 if (*P) {
2613 NotLastEntry = true;
2614 }
2615 }
2616 if (NotLastEntry)
2617 break;
2618 }
2619 More = false;
2620 Done = true;
2621 moveToEnd();
2622 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
2623 break;
2624 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
2625 Ordinal = ImmValue;
2626 DEBUG_WITH_TYPE(
2627 "mach-o-bind",
2628 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
2629 << "Ordinal=" << Ordinal << "\n");
2630 break;
2631 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
2632 Ordinal = readULEB128();
2633 DEBUG_WITH_TYPE(
2634 "mach-o-bind",
2635 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
2636 << "Ordinal=" << Ordinal << "\n");
2637 break;
2638 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
2639 if (ImmValue) {
2640 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
2641 Ordinal = SignExtended;
2642 } else
2643 Ordinal = 0;
2644 DEBUG_WITH_TYPE(
2645 "mach-o-bind",
2646 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
2647 << "Ordinal=" << Ordinal << "\n");
2648 break;
2649 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
2650 Flags = ImmValue;
2651 SymStart = Ptr;
2652 while (*Ptr) {
2653 ++Ptr;
2654 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00002655 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
2656 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00002657 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002658 DEBUG_WITH_TYPE(
2659 "mach-o-bind",
2660 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
2661 << "SymbolName=" << SymbolName << "\n");
2662 if (TableKind == Kind::Weak) {
2663 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
2664 return;
2665 }
2666 break;
2667 case MachO::BIND_OPCODE_SET_TYPE_IMM:
2668 BindType = ImmValue;
2669 DEBUG_WITH_TYPE(
2670 "mach-o-bind",
2671 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
2672 << "BindType=" << (int)BindType << "\n");
2673 break;
2674 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
2675 Addend = readSLEB128();
2676 if (TableKind == Kind::Lazy)
2677 Malformed = true;
2678 DEBUG_WITH_TYPE(
2679 "mach-o-bind",
2680 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
2681 << "Addend=" << Addend << "\n");
2682 break;
2683 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2684 SegmentIndex = ImmValue;
2685 SegmentOffset = readULEB128();
2686 DEBUG_WITH_TYPE(
2687 "mach-o-bind",
2688 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2689 << "SegmentIndex=" << SegmentIndex << ", "
2690 << format("SegmentOffset=0x%06X", SegmentOffset)
2691 << "\n");
2692 break;
2693 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2694 SegmentOffset += readULEB128();
2695 DEBUG_WITH_TYPE("mach-o-bind",
2696 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2697 << format("SegmentOffset=0x%06X",
2698 SegmentOffset) << "\n");
2699 break;
2700 case MachO::BIND_OPCODE_DO_BIND:
2701 AdvanceAmount = PointerSize;
2702 RemainingLoopCount = 0;
2703 DEBUG_WITH_TYPE("mach-o-bind",
2704 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2705 << format("SegmentOffset=0x%06X",
2706 SegmentOffset) << "\n");
2707 return;
2708 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002709 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002710 RemainingLoopCount = 0;
2711 if (TableKind == Kind::Lazy)
2712 Malformed = true;
2713 DEBUG_WITH_TYPE(
2714 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002715 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00002716 << format("SegmentOffset=0x%06X", SegmentOffset)
2717 << ", AdvanceAmount=" << AdvanceAmount
2718 << ", RemainingLoopCount=" << RemainingLoopCount
2719 << "\n");
2720 return;
2721 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002722 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002723 RemainingLoopCount = 0;
2724 if (TableKind == Kind::Lazy)
2725 Malformed = true;
2726 DEBUG_WITH_TYPE("mach-o-bind",
2727 llvm::dbgs()
2728 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2729 << format("SegmentOffset=0x%06X",
2730 SegmentOffset) << "\n");
2731 return;
2732 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2733 RemainingLoopCount = readULEB128() - 1;
2734 AdvanceAmount = readULEB128() + PointerSize;
2735 if (TableKind == Kind::Lazy)
2736 Malformed = true;
2737 DEBUG_WITH_TYPE(
2738 "mach-o-bind",
2739 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2740 << format("SegmentOffset=0x%06X", SegmentOffset)
2741 << ", AdvanceAmount=" << AdvanceAmount
2742 << ", RemainingLoopCount=" << RemainingLoopCount
2743 << "\n");
2744 return;
2745 default:
2746 Malformed = true;
2747 }
2748 }
2749}
2750
2751uint64_t MachOBindEntry::readULEB128() {
2752 unsigned Count;
2753 uint64_t Result = decodeULEB128(Ptr, &Count);
2754 Ptr += Count;
2755 if (Ptr > Opcodes.end()) {
2756 Ptr = Opcodes.end();
2757 Malformed = true;
2758 }
2759 return Result;
2760}
2761
2762int64_t MachOBindEntry::readSLEB128() {
2763 unsigned Count;
2764 int64_t Result = decodeSLEB128(Ptr, &Count);
2765 Ptr += Count;
2766 if (Ptr > Opcodes.end()) {
2767 Ptr = Opcodes.end();
2768 Malformed = true;
2769 }
2770 return Result;
2771}
2772
Nick Kledzik56ebef42014-09-16 01:41:51 +00002773uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2774
2775uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2776
2777StringRef MachOBindEntry::typeName() const {
2778 switch (BindType) {
2779 case MachO::BIND_TYPE_POINTER:
2780 return "pointer";
2781 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2782 return "text abs32";
2783 case MachO::BIND_TYPE_TEXT_PCREL32:
2784 return "text rel32";
2785 }
2786 return "unknown";
2787}
2788
2789StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2790
2791int64_t MachOBindEntry::addend() const { return Addend; }
2792
2793uint32_t MachOBindEntry::flags() const { return Flags; }
2794
2795int MachOBindEntry::ordinal() const { return Ordinal; }
2796
2797bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2798 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2799 return (Ptr == Other.Ptr) &&
2800 (RemainingLoopCount == Other.RemainingLoopCount) &&
2801 (Done == Other.Done);
2802}
2803
2804iterator_range<bind_iterator>
2805MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2806 MachOBindEntry::Kind BKind) {
2807 MachOBindEntry Start(Opcodes, is64, BKind);
2808 Start.moveToFirst();
2809
2810 MachOBindEntry Finish(Opcodes, is64, BKind);
2811 Finish.moveToEnd();
2812
Craig Topper15576e12015-12-06 05:08:07 +00002813 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00002814}
2815
2816iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2817 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2818 MachOBindEntry::Kind::Regular);
2819}
2820
2821iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2822 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2823 MachOBindEntry::Kind::Lazy);
2824}
2825
2826iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2827 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2828 MachOBindEntry::Kind::Weak);
2829}
2830
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00002831MachOObjectFile::load_command_iterator
2832MachOObjectFile::begin_load_commands() const {
2833 return LoadCommands.begin();
2834}
2835
2836MachOObjectFile::load_command_iterator
2837MachOObjectFile::end_load_commands() const {
2838 return LoadCommands.end();
2839}
2840
2841iterator_range<MachOObjectFile::load_command_iterator>
2842MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00002843 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00002844}
2845
Rafael Espindola56f976f2013-04-18 18:08:55 +00002846StringRef
2847MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2848 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2849 return parseSegmentOrSectionName(Raw.data());
2850}
2851
2852ArrayRef<char>
2853MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002854 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002855 const section_base *Base =
2856 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002857 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002858}
2859
2860ArrayRef<char>
2861MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002862 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002863 const section_base *Base =
2864 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002865 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002866}
2867
2868bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002869MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002870 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002871 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002872 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002873 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002874}
2875
Eric Christopher1d62c252013-07-22 22:25:07 +00002876unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002877 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002878 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002879 return RE.r_word1 & 0xffffff;
2880 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002881}
2882
Eric Christopher1d62c252013-07-22 22:25:07 +00002883bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002884 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002885 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002886 return (RE.r_word1 >> 27) & 1;
2887 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002888}
2889
Eric Christopher1d62c252013-07-22 22:25:07 +00002890bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002891 const MachO::any_relocation_info &RE) const {
2892 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002893}
2894
Eric Christopher1d62c252013-07-22 22:25:07 +00002895uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002896 const MachO::any_relocation_info &RE) const {
2897 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002898}
2899
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002900uint32_t MachOObjectFile::getScatteredRelocationType(
2901 const MachO::any_relocation_info &RE) const {
2902 return (RE.r_word0 >> 24) & 0xf;
2903}
2904
Eric Christopher1d62c252013-07-22 22:25:07 +00002905unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002906 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002907 if (isRelocationScattered(RE))
2908 return getScatteredRelocationAddress(RE);
2909 return getPlainRelocationAddress(RE);
2910}
2911
Charles Davis8bdfafd2013-09-01 04:28:48 +00002912unsigned MachOObjectFile::getAnyRelocationPCRel(
2913 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002914 if (isRelocationScattered(RE))
2915 return getScatteredRelocationPCRel(this, RE);
2916 return getPlainRelocationPCRel(this, RE);
2917}
2918
Eric Christopher1d62c252013-07-22 22:25:07 +00002919unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002920 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002921 if (isRelocationScattered(RE))
2922 return getScatteredRelocationLength(RE);
2923 return getPlainRelocationLength(this, RE);
2924}
2925
2926unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002927MachOObjectFile::getAnyRelocationType(
2928 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002929 if (isRelocationScattered(RE))
2930 return getScatteredRelocationType(RE);
2931 return getPlainRelocationType(this, RE);
2932}
2933
Rafael Espindola52501032013-04-30 15:40:54 +00002934SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002935MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002936 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002937 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002938 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002939 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2940 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2941 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002942 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002943 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002944 return SectionRef(DRI, this);
2945}
2946
Charles Davis8bdfafd2013-09-01 04:28:48 +00002947MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002948 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002949 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002950}
2951
Charles Davis8bdfafd2013-09-01 04:28:48 +00002952MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002953 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002954 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002955}
2956
Charles Davis8bdfafd2013-09-01 04:28:48 +00002957MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002958 unsigned Index) const {
2959 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002960 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002961}
2962
Charles Davis8bdfafd2013-09-01 04:28:48 +00002963MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2964 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002965 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002966 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002967}
2968
Charles Davis8bdfafd2013-09-01 04:28:48 +00002969MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002970MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002971 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002972 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002973}
2974
Charles Davis8bdfafd2013-09-01 04:28:48 +00002975MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002976MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002977 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002978 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002979}
2980
Charles Davis8bdfafd2013-09-01 04:28:48 +00002981MachO::linkedit_data_command
2982MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2983 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002984}
2985
Charles Davis8bdfafd2013-09-01 04:28:48 +00002986MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002987MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002988 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002989}
2990
Charles Davis8bdfafd2013-09-01 04:28:48 +00002991MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002992MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002993 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002994}
2995
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002996MachO::linker_option_command
2997MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2998 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002999}
3000
Jim Grosbach448334a2014-03-18 22:09:05 +00003001MachO::version_min_command
3002MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
3003 return getStruct<MachO::version_min_command>(this, L.Ptr);
3004}
3005
Tim Northover8f9590b2014-06-30 14:40:57 +00003006MachO::dylib_command
3007MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
3008 return getStruct<MachO::dylib_command>(this, L.Ptr);
3009}
3010
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003011MachO::dyld_info_command
3012MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
3013 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
3014}
3015
3016MachO::dylinker_command
3017MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
3018 return getStruct<MachO::dylinker_command>(this, L.Ptr);
3019}
3020
3021MachO::uuid_command
3022MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
3023 return getStruct<MachO::uuid_command>(this, L.Ptr);
3024}
3025
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00003026MachO::rpath_command
3027MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
3028 return getStruct<MachO::rpath_command>(this, L.Ptr);
3029}
3030
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003031MachO::source_version_command
3032MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
3033 return getStruct<MachO::source_version_command>(this, L.Ptr);
3034}
3035
3036MachO::entry_point_command
3037MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
3038 return getStruct<MachO::entry_point_command>(this, L.Ptr);
3039}
3040
Kevin Enderby0804f4672014-12-16 23:25:52 +00003041MachO::encryption_info_command
3042MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
3043 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
3044}
3045
Kevin Enderby57538292014-12-17 01:01:30 +00003046MachO::encryption_info_command_64
3047MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
3048 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
3049}
3050
Kevin Enderbyb4b79312014-12-18 19:24:35 +00003051MachO::sub_framework_command
3052MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
3053 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
3054}
Tim Northover8f9590b2014-06-30 14:40:57 +00003055
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00003056MachO::sub_umbrella_command
3057MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
3058 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
3059}
3060
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00003061MachO::sub_library_command
3062MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
3063 return getStruct<MachO::sub_library_command>(this, L.Ptr);
3064}
3065
Kevin Enderby186eac32014-12-19 21:06:24 +00003066MachO::sub_client_command
3067MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
3068 return getStruct<MachO::sub_client_command>(this, L.Ptr);
3069}
3070
Kevin Enderby52e4ce42014-12-19 22:25:22 +00003071MachO::routines_command
3072MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
3073 return getStruct<MachO::routines_command>(this, L.Ptr);
3074}
3075
3076MachO::routines_command_64
3077MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
3078 return getStruct<MachO::routines_command_64>(this, L.Ptr);
3079}
3080
Kevin Enderby48ef5342014-12-23 22:56:39 +00003081MachO::thread_command
3082MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
3083 return getStruct<MachO::thread_command>(this, L.Ptr);
3084}
3085
Charles Davis8bdfafd2013-09-01 04:28:48 +00003086MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00003087MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00003088 DataRefImpl Sec;
3089 Sec.d.a = Rel.d.a;
3090 uint32_t Offset;
3091 if (is64Bit()) {
3092 MachO::section_64 Sect = getSection64(Sec);
3093 Offset = Sect.reloff;
3094 } else {
3095 MachO::section Sect = getSection(Sec);
3096 Offset = Sect.reloff;
3097 }
3098
3099 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
3100 getPtr(this, Offset)) + Rel.d.b;
3101 return getStruct<MachO::any_relocation_info>(
3102 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00003103}
3104
Charles Davis8bdfafd2013-09-01 04:28:48 +00003105MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00003106MachOObjectFile::getDice(DataRefImpl Rel) const {
3107 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00003108 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00003109}
3110
Alexey Samsonov13415ed2015-06-04 19:22:03 +00003111const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00003112 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003113}
3114
Alexey Samsonov13415ed2015-06-04 19:22:03 +00003115const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
3116 assert(is64Bit());
3117 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00003118}
3119
Charles Davis8bdfafd2013-09-01 04:28:48 +00003120uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
3121 const MachO::dysymtab_command &DLC,
3122 unsigned Index) const {
3123 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
3124 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00003125}
3126
Charles Davis8bdfafd2013-09-01 04:28:48 +00003127MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00003128MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
3129 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003130 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
3131 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00003132}
3133
Charles Davis8bdfafd2013-09-01 04:28:48 +00003134MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003135 if (SymtabLoadCmd)
3136 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
3137
3138 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
3139 MachO::symtab_command Cmd;
3140 Cmd.cmd = MachO::LC_SYMTAB;
3141 Cmd.cmdsize = sizeof(MachO::symtab_command);
3142 Cmd.symoff = 0;
3143 Cmd.nsyms = 0;
3144 Cmd.stroff = 0;
3145 Cmd.strsize = 0;
3146 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003147}
3148
Charles Davis8bdfafd2013-09-01 04:28:48 +00003149MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003150 if (DysymtabLoadCmd)
3151 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
3152
3153 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
3154 MachO::dysymtab_command Cmd;
3155 Cmd.cmd = MachO::LC_DYSYMTAB;
3156 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
3157 Cmd.ilocalsym = 0;
3158 Cmd.nlocalsym = 0;
3159 Cmd.iextdefsym = 0;
3160 Cmd.nextdefsym = 0;
3161 Cmd.iundefsym = 0;
3162 Cmd.nundefsym = 0;
3163 Cmd.tocoff = 0;
3164 Cmd.ntoc = 0;
3165 Cmd.modtaboff = 0;
3166 Cmd.nmodtab = 0;
3167 Cmd.extrefsymoff = 0;
3168 Cmd.nextrefsyms = 0;
3169 Cmd.indirectsymoff = 0;
3170 Cmd.nindirectsyms = 0;
3171 Cmd.extreloff = 0;
3172 Cmd.nextrel = 0;
3173 Cmd.locreloff = 0;
3174 Cmd.nlocrel = 0;
3175 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00003176}
3177
Charles Davis8bdfafd2013-09-01 04:28:48 +00003178MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00003179MachOObjectFile::getDataInCodeLoadCommand() const {
3180 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00003181 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00003182
3183 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00003184 MachO::linkedit_data_command Cmd;
3185 Cmd.cmd = MachO::LC_DATA_IN_CODE;
3186 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3187 Cmd.dataoff = 0;
3188 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00003189 return Cmd;
3190}
3191
Kevin Enderby9a509442015-01-27 21:28:24 +00003192MachO::linkedit_data_command
3193MachOObjectFile::getLinkOptHintsLoadCommand() const {
3194 if (LinkOptHintsLoadCmd)
3195 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
3196
3197 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
3198 // fields.
3199 MachO::linkedit_data_command Cmd;
3200 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
3201 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3202 Cmd.dataoff = 0;
3203 Cmd.datasize = 0;
3204 return Cmd;
3205}
3206
Nick Kledzikd04bc352014-08-30 00:20:14 +00003207ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003208 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003209 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003210
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003211 MachO::dyld_info_command DyldInfo =
3212 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3213 const uint8_t *Ptr =
3214 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00003215 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003216}
3217
3218ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003219 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003220 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003221
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003222 MachO::dyld_info_command DyldInfo =
3223 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3224 const uint8_t *Ptr =
3225 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003226 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003227}
3228
3229ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003230 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003231 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003232
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003233 MachO::dyld_info_command DyldInfo =
3234 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3235 const uint8_t *Ptr =
3236 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003237 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003238}
3239
3240ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003241 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003242 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003243
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003244 MachO::dyld_info_command DyldInfo =
3245 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3246 const uint8_t *Ptr =
3247 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003248 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003249}
3250
3251ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003252 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003253 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003254
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003255 MachO::dyld_info_command DyldInfo =
3256 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
3257 const uint8_t *Ptr =
3258 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00003259 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003260}
3261
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00003262ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
3263 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003264 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00003265 // Returning a pointer is fine as uuid doesn't need endian swapping.
3266 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00003267 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00003268}
Nick Kledzikd04bc352014-08-30 00:20:14 +00003269
Rafael Espindola6e040c02013-04-26 20:07:33 +00003270StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003271 MachO::symtab_command S = getSymtabLoadCommand();
3272 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003273}
3274
Rafael Espindola56f976f2013-04-18 18:08:55 +00003275bool MachOObjectFile::is64Bit() const {
3276 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00003277 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003278}
3279
3280void MachOObjectFile::ReadULEB128s(uint64_t Index,
3281 SmallVectorImpl<uint64_t> &Out) const {
3282 DataExtractor extractor(ObjectFile::getData(), true, 0);
3283
3284 uint32_t offset = Index;
3285 uint64_t data = 0;
3286 while (uint64_t delta = extractor.getULEB128(&offset)) {
3287 data += delta;
3288 Out.push_back(data);
3289 }
3290}
3291
Rafael Espindolac66d7612014-08-17 19:09:37 +00003292bool MachOObjectFile::isRelocatableObject() const {
3293 return getHeader().filetype == MachO::MH_OBJECT;
3294}
3295
Lang Hamesff044b12016-03-25 23:11:52 +00003296Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00003297ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
3298 uint32_t UniversalCputype,
3299 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00003300 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00003301 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003302 return MachOObjectFile::create(Buffer, false, false,
3303 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003304 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003305 return MachOObjectFile::create(Buffer, true, false,
3306 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003307 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003308 return MachOObjectFile::create(Buffer, false, true,
3309 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003310 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003311 return MachOObjectFile::create(Buffer, true, true,
3312 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00003313 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00003314 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003315}