blob: 2435340b66edcc19176a57f6aa224ac3b84822c2 [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
Lang Hames82627642016-03-25 21:59:14 +0000507Expected<std::unique_ptr<MachOObjectFile>>
508MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
509 bool Is64Bits) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000510 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000511 std::unique_ptr<MachOObjectFile> Obj(
512 new MachOObjectFile(std::move(Object), IsLittleEndian,
513 Is64Bits, Err));
514 if (Err)
515 return std::move(Err);
516 return std::move(Obj);
517}
518
Rafael Espindola48af1c22014-08-19 18:44:46 +0000519MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Lang Hames9e964f32016-03-25 17:25:34 +0000520 bool Is64bits, Error &Err)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000521 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000522 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000523 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
524 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
525 HasPageZeroSegment(false) {
Lang Hames5e51a2e2016-07-22 16:11:25 +0000526 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000527 uint64_t SizeOfHeaders;
Kevin Enderby87025742016-04-13 21:17:58 +0000528 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +0000529 parseHeader(this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000530 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby87025742016-04-13 21:17:58 +0000531 } else {
Lang Hames9e964f32016-03-25 17:25:34 +0000532 parseHeader(this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000533 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby87025742016-04-13 21:17:58 +0000534 }
Lang Hames9e964f32016-03-25 17:25:34 +0000535 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000536 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000537 SizeOfHeaders += getHeader().sizeofcmds;
538 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000539 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +0000540 return;
541 }
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000542
543 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000544 if (LoadCommandCount == 0)
545 return;
546
Lang Hames9e964f32016-03-25 17:25:34 +0000547 LoadCommandInfo Load;
548 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
549 Load = *LoadOrErr;
550 else {
551 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000552 return;
553 }
Lang Hames9e964f32016-03-25 17:25:34 +0000554
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000555 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +0000556 if (is64Bit()) {
557 if (Load.C.cmdsize % 8 != 0) {
558 // We have a hack here to allow 64-bit Mach-O core files to have
559 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
560 // allowed since the macOS kernel produces them.
561 if (getHeader().filetype != MachO::MH_CORE ||
562 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
563 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
564 "multiple of 8");
565 return;
566 }
567 }
568 } else {
569 if (Load.C.cmdsize % 4 != 0) {
570 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
571 "multiple of 4");
572 return;
573 }
574 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000575 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000576 if (Load.C.cmd == MachO::LC_SYMTAB) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000577 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd)))
David Majnemer73cc6ff2014-11-13 19:48:56 +0000578 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000579 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000580 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd)))
David Majnemer73cc6ff2014-11-13 19:48:56 +0000581 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000582 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000583 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd,
584 "LC_DATA_IN_CODE")))
David Majnemer73cc6ff2014-11-13 19:48:56 +0000585 return;
Kevin Enderby9a509442015-01-27 21:28:24 +0000586 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000587 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd,
588 "LC_LINKER_OPTIMIZATION_HINT")))
Kevin Enderby9a509442015-01-27 21:28:24 +0000589 return;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000590 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000591 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000592 // Multiple dyldinfo load commands
593 if (DyldInfoLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000594 Err = malformedError("Multiple dyldinfo load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000595 return;
596 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000597 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000598 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000599 // Multiple UUID load commands
600 if (UuidLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000601 Err = malformedError("Multiple UUID load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000602 return;
603 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000604 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000605 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000606 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
607 MachO::section_64>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000608 this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyc614d282016-08-12 20:10:25 +0000609 "LC_SEGMENT_64", SizeOfHeaders)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000610 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000611 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000612 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
613 MachO::section>(
614 this, Load, Sections, HasPageZeroSegment, I,
615 "LC_SEGMENT", SizeOfHeaders)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000616 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000617 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
618 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
619 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
620 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
621 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
622 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000623 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000624 if (I < LoadCommandCount - 1) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000625 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +0000626 Load = *LoadOrErr;
627 else {
628 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000629 return;
630 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000631 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000632 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000633 if (!SymtabLoadCmd) {
634 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000635 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +0000636 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +0000637 return;
638 }
639 } else if (DysymtabLoadCmd) {
640 MachO::symtab_command Symtab =
641 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
642 MachO::dysymtab_command Dysymtab =
643 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
644 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000645 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000646 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000647 return;
648 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000649 uint64_t BigSize = Dysymtab.ilocalsym;
650 BigSize += Dysymtab.nlocalsym;
651 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000652 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +0000653 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000654 return;
655 }
656 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000657 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000658 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000659 return;
660 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000661 BigSize = Dysymtab.iextdefsym;
662 BigSize += Dysymtab.nextdefsym;
663 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000664 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +0000665 "load command extends past the end of the symbol "
666 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000667 return;
668 }
669 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000670 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000671 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000672 return;
673 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000674 BigSize = Dysymtab.iundefsym;
675 BigSize += Dysymtab.nundefsym;
676 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000677 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +0000678 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000679 return;
680 }
681 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000682 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +0000683
684 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000685}
686
Rafael Espindola5e812af2014-01-30 02:49:50 +0000687void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000688 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000689 sizeof(MachO::nlist_64) :
690 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000691 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000692}
693
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000694Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000695 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000696 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000697 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000698 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000699 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +0000700 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000701 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000702 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000703}
704
Rafael Espindola0e77a942014-12-10 20:46:55 +0000705unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
706 DataRefImpl DRI = Sec.getRawDataRefImpl();
707 uint32_t Flags = getSectionFlags(this, DRI);
708 return Flags & MachO::SECTION_TYPE;
709}
710
Rafael Espindola59128922015-06-24 18:14:41 +0000711uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
712 if (is64Bit()) {
713 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
714 return Entry.n_value;
715 }
716 MachO::nlist Entry = getSymbolTableEntry(Sym);
717 return Entry.n_value;
718}
719
Kevin Enderby980b2582014-06-05 21:21:57 +0000720// getIndirectName() returns the name of the alias'ed symbol who's string table
721// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000722std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
723 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000724 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000725 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
726 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
727 return object_error::parse_failed;
728 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000729 if (NValue >= StringTable.size())
730 return object_error::parse_failed;
731 const char *Start = &StringTable.data()[NValue];
732 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000733 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000734}
735
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000736uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000737 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000738}
739
Kevin Enderby931cb652016-06-24 18:24:42 +0000740Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +0000741 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000742}
743
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000744uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000745 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000746 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000747 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000748 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000749 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000750 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000751}
752
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000753uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000754 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000755}
756
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000757Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000758MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000759 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000760 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000761
Rafael Espindola56f976f2013-04-18 18:08:55 +0000762 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000763 if (n_type & MachO::N_STAB)
764 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000765
Charles Davis74ec8b02013-08-27 05:00:13 +0000766 switch (n_type & MachO::N_TYPE) {
767 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000768 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000769 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000770 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000771 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000772 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000773 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000774 if (Sec->isData() || Sec->isBSS())
775 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000776 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000777 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000778 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000779}
780
Rafael Espindola20122a42014-01-31 20:57:12 +0000781uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000782 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000783
Charles Davis8bdfafd2013-09-01 04:28:48 +0000784 uint8_t MachOType = Entry.n_type;
785 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000786
Rafael Espindola20122a42014-01-31 20:57:12 +0000787 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000788
Tim Northovereaef0742014-05-30 13:22:59 +0000789 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
790 Result |= SymbolRef::SF_Indirect;
791
Rafael Espindolaa1356322013-11-02 05:03:24 +0000792 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000793 Result |= SymbolRef::SF_FormatSpecific;
794
Charles Davis74ec8b02013-08-27 05:00:13 +0000795 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000796 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000797 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000798 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000799 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000800 else
801 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000802 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000803
804 if (!(MachOType & MachO::N_PEXT))
805 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000806 }
807
Charles Davis74ec8b02013-08-27 05:00:13 +0000808 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000809 Result |= SymbolRef::SF_Weak;
810
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000811 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
812 Result |= SymbolRef::SF_Thumb;
813
Charles Davis74ec8b02013-08-27 05:00:13 +0000814 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000815 Result |= SymbolRef::SF_Absolute;
816
Rafael Espindola20122a42014-01-31 20:57:12 +0000817 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000818}
819
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000820Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +0000821MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000822 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000823 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000824
Rafael Espindola8bab8892015-08-07 23:27:14 +0000825 if (index == 0)
826 return section_end();
827 DataRefImpl DRI;
828 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000829 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000830 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +0000831 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000832 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000833 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000834}
835
Rafael Espindola6bf32212015-06-24 19:57:32 +0000836unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
837 MachO::nlist_base Entry =
838 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
839 return Entry.n_sect - 1;
840}
841
Rafael Espindola5e812af2014-01-30 02:49:50 +0000842void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000843 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000844}
845
Rafael Espindola3acea392014-06-12 21:46:39 +0000846std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
847 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000848 ArrayRef<char> Raw = getSectionRawName(Sec);
849 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000850 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000851}
852
Rafael Espindola80291272014-10-08 15:28:58 +0000853uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
854 if (is64Bit())
855 return getSection64(Sec).addr;
856 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000857}
858
Rafael Espindola80291272014-10-08 15:28:58 +0000859uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000860 // In the case if a malformed Mach-O file where the section offset is past
861 // the end of the file or some part of the section size is past the end of
862 // the file return a size of zero or a size that covers the rest of the file
863 // but does not extend past the end of the file.
864 uint32_t SectOffset, SectType;
865 uint64_t SectSize;
866
867 if (is64Bit()) {
868 MachO::section_64 Sect = getSection64(Sec);
869 SectOffset = Sect.offset;
870 SectSize = Sect.size;
871 SectType = Sect.flags & MachO::SECTION_TYPE;
872 } else {
873 MachO::section Sect = getSection(Sec);
874 SectOffset = Sect.offset;
875 SectSize = Sect.size;
876 SectType = Sect.flags & MachO::SECTION_TYPE;
877 }
878 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
879 return SectSize;
880 uint64_t FileSize = getData().size();
881 if (SectOffset > FileSize)
882 return 0;
883 if (FileSize - SectOffset < SectSize)
884 return FileSize - SectOffset;
885 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000886}
887
Rafael Espindola3acea392014-06-12 21:46:39 +0000888std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
889 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000890 uint32_t Offset;
891 uint64_t Size;
892
893 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000894 MachO::section_64 Sect = getSection64(Sec);
895 Offset = Sect.offset;
896 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000897 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000898 MachO::section Sect = getSection(Sec);
899 Offset = Sect.offset;
900 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000901 }
902
903 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000904 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000905}
906
Rafael Espindola80291272014-10-08 15:28:58 +0000907uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000908 uint32_t Align;
909 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000910 MachO::section_64 Sect = getSection64(Sec);
911 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000912 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000913 MachO::section Sect = getSection(Sec);
914 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000915 }
916
Rafael Espindola80291272014-10-08 15:28:58 +0000917 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000918}
919
George Rimar401e4e52016-05-24 12:48:46 +0000920bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
921 return false;
922}
923
Rafael Espindola80291272014-10-08 15:28:58 +0000924bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000925 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000926 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000927}
928
Rafael Espindola80291272014-10-08 15:28:58 +0000929bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000930 uint32_t Flags = getSectionFlags(this, Sec);
931 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000932 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
933 !(SectionType == MachO::S_ZEROFILL ||
934 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000935}
936
Rafael Espindola80291272014-10-08 15:28:58 +0000937bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000938 uint32_t Flags = getSectionFlags(this, Sec);
939 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000940 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
941 (SectionType == MachO::S_ZEROFILL ||
942 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000943}
944
Rafael Espindola6bf32212015-06-24 19:57:32 +0000945unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
946 return Sec.getRawDataRefImpl().d.a;
947}
948
Rafael Espindola80291272014-10-08 15:28:58 +0000949bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000950 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000951 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000952}
953
Steven Wuf2fe0142016-02-29 19:40:10 +0000954bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
955 StringRef SegmentName = getSectionFinalSegmentName(Sec);
956 StringRef SectName;
957 if (!getSectionName(Sec, SectName))
958 return (SegmentName == "__LLVM" && SectName == "__bitcode");
959 return false;
960}
961
Rui Ueyamabc654b12013-09-27 21:47:05 +0000962relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000963 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000964 Ret.d.a = Sec.d.a;
965 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000966 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000967}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000968
Rafael Espindola56f976f2013-04-18 18:08:55 +0000969relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000970MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000971 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000972 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000973 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000974 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000975 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000976 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000977 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000978 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000979
Rafael Espindola56f976f2013-04-18 18:08:55 +0000980 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000981 Ret.d.a = Sec.d.a;
982 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000983 return relocation_iterator(RelocationRef(Ret, this));
984}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000985
Rafael Espindola5e812af2014-01-30 02:49:50 +0000986void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000987 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000988}
Owen Anderson171f4852011-10-24 23:20:07 +0000989
Rafael Espindola96d071c2015-06-29 23:29:12 +0000990uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000991 assert(getHeader().filetype == MachO::MH_OBJECT &&
992 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000993 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000994 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000995}
996
Rafael Espindola806f0062013-06-05 01:33:53 +0000997symbol_iterator
998MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000999 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00001000 if (isRelocationScattered(RE))
1001 return symbol_end();
1002
Rafael Espindola56f976f2013-04-18 18:08:55 +00001003 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1004 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00001005 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00001006 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00001007
Charles Davis8bdfafd2013-09-01 04:28:48 +00001008 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001009 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001010 sizeof(MachO::nlist_64) :
1011 sizeof(MachO::nlist);
1012 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001013 DataRefImpl Sym;
1014 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00001015 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001016}
1017
Keno Fischerc780e8e2015-05-21 21:24:32 +00001018section_iterator
1019MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
1020 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
1021}
1022
Rafael Espindola99c041b2015-06-30 01:53:01 +00001023uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001024 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00001025 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001026}
1027
Rafael Espindola41bb4322015-06-30 04:08:37 +00001028void MachOObjectFile::getRelocationTypeName(
1029 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001030 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00001031 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001032
1033 unsigned Arch = this->getArch();
1034
1035 switch (Arch) {
1036 case Triple::x86: {
1037 static const char *const Table[] = {
1038 "GENERIC_RELOC_VANILLA",
1039 "GENERIC_RELOC_PAIR",
1040 "GENERIC_RELOC_SECTDIFF",
1041 "GENERIC_RELOC_PB_LA_PTR",
1042 "GENERIC_RELOC_LOCAL_SECTDIFF",
1043 "GENERIC_RELOC_TLV" };
1044
Eric Christopher13250cb2013-12-06 02:33:38 +00001045 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001046 res = "Unknown";
1047 else
1048 res = Table[RType];
1049 break;
1050 }
1051 case Triple::x86_64: {
1052 static const char *const Table[] = {
1053 "X86_64_RELOC_UNSIGNED",
1054 "X86_64_RELOC_SIGNED",
1055 "X86_64_RELOC_BRANCH",
1056 "X86_64_RELOC_GOT_LOAD",
1057 "X86_64_RELOC_GOT",
1058 "X86_64_RELOC_SUBTRACTOR",
1059 "X86_64_RELOC_SIGNED_1",
1060 "X86_64_RELOC_SIGNED_2",
1061 "X86_64_RELOC_SIGNED_4",
1062 "X86_64_RELOC_TLV" };
1063
1064 if (RType > 9)
1065 res = "Unknown";
1066 else
1067 res = Table[RType];
1068 break;
1069 }
1070 case Triple::arm: {
1071 static const char *const Table[] = {
1072 "ARM_RELOC_VANILLA",
1073 "ARM_RELOC_PAIR",
1074 "ARM_RELOC_SECTDIFF",
1075 "ARM_RELOC_LOCAL_SECTDIFF",
1076 "ARM_RELOC_PB_LA_PTR",
1077 "ARM_RELOC_BR24",
1078 "ARM_THUMB_RELOC_BR22",
1079 "ARM_THUMB_32BIT_BRANCH",
1080 "ARM_RELOC_HALF",
1081 "ARM_RELOC_HALF_SECTDIFF" };
1082
1083 if (RType > 9)
1084 res = "Unknown";
1085 else
1086 res = Table[RType];
1087 break;
1088 }
Tim Northover00ed9962014-03-29 10:18:08 +00001089 case Triple::aarch64: {
1090 static const char *const Table[] = {
1091 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
1092 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
1093 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
1094 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
1095 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
1096 "ARM64_RELOC_ADDEND"
1097 };
1098
1099 if (RType >= array_lengthof(Table))
1100 res = "Unknown";
1101 else
1102 res = Table[RType];
1103 break;
1104 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001105 case Triple::ppc: {
1106 static const char *const Table[] = {
1107 "PPC_RELOC_VANILLA",
1108 "PPC_RELOC_PAIR",
1109 "PPC_RELOC_BR14",
1110 "PPC_RELOC_BR24",
1111 "PPC_RELOC_HI16",
1112 "PPC_RELOC_LO16",
1113 "PPC_RELOC_HA16",
1114 "PPC_RELOC_LO14",
1115 "PPC_RELOC_SECTDIFF",
1116 "PPC_RELOC_PB_LA_PTR",
1117 "PPC_RELOC_HI16_SECTDIFF",
1118 "PPC_RELOC_LO16_SECTDIFF",
1119 "PPC_RELOC_HA16_SECTDIFF",
1120 "PPC_RELOC_JBSR",
1121 "PPC_RELOC_LO14_SECTDIFF",
1122 "PPC_RELOC_LOCAL_SECTDIFF" };
1123
Eric Christopher13250cb2013-12-06 02:33:38 +00001124 if (RType > 15)
1125 res = "Unknown";
1126 else
1127 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00001128 break;
1129 }
1130 case Triple::UnknownArch:
1131 res = "Unknown";
1132 break;
1133 }
1134 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00001135}
1136
Keno Fischer281b6942015-05-30 19:44:53 +00001137uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
1138 MachO::any_relocation_info RE = getRelocation(Rel);
1139 return getAnyRelocationLength(RE);
1140}
1141
Kevin Enderby980b2582014-06-05 21:21:57 +00001142//
1143// guessLibraryShortName() is passed a name of a dynamic library and returns a
1144// guess on what the short name is. Then name is returned as a substring of the
1145// StringRef Name passed in. The name of the dynamic library is recognized as
1146// a framework if it has one of the two following forms:
1147// Foo.framework/Versions/A/Foo
1148// Foo.framework/Foo
1149// Where A and Foo can be any string. And may contain a trailing suffix
1150// starting with an underbar. If the Name is recognized as a framework then
1151// isFramework is set to true else it is set to false. If the Name has a
1152// suffix then Suffix is set to the substring in Name that contains the suffix
1153// else it is set to a NULL StringRef.
1154//
1155// The Name of the dynamic library is recognized as a library name if it has
1156// one of the two following forms:
1157// libFoo.A.dylib
1158// libFoo.dylib
1159// The library may have a suffix trailing the name Foo of the form:
1160// libFoo_profile.A.dylib
1161// libFoo_profile.dylib
1162//
1163// The Name of the dynamic library is also recognized as a library name if it
1164// has the following form:
1165// Foo.qtx
1166//
1167// If the Name of the dynamic library is none of the forms above then a NULL
1168// StringRef is returned.
1169//
1170StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1171 bool &isFramework,
1172 StringRef &Suffix) {
1173 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1174 size_t a, b, c, d, Idx;
1175
1176 isFramework = false;
1177 Suffix = StringRef();
1178
1179 // Pull off the last component and make Foo point to it
1180 a = Name.rfind('/');
1181 if (a == Name.npos || a == 0)
1182 goto guess_library;
1183 Foo = Name.slice(a+1, Name.npos);
1184
1185 // Look for a suffix starting with a '_'
1186 Idx = Foo.rfind('_');
1187 if (Idx != Foo.npos && Foo.size() >= 2) {
1188 Suffix = Foo.slice(Idx, Foo.npos);
1189 Foo = Foo.slice(0, Idx);
1190 }
1191
1192 // First look for the form Foo.framework/Foo
1193 b = Name.rfind('/', a);
1194 if (b == Name.npos)
1195 Idx = 0;
1196 else
1197 Idx = b+1;
1198 F = Name.slice(Idx, Idx + Foo.size());
1199 DotFramework = Name.slice(Idx + Foo.size(),
1200 Idx + Foo.size() + sizeof(".framework/")-1);
1201 if (F == Foo && DotFramework == ".framework/") {
1202 isFramework = true;
1203 return Foo;
1204 }
1205
1206 // Next look for the form Foo.framework/Versions/A/Foo
1207 if (b == Name.npos)
1208 goto guess_library;
1209 c = Name.rfind('/', b);
1210 if (c == Name.npos || c == 0)
1211 goto guess_library;
1212 V = Name.slice(c+1, Name.npos);
1213 if (!V.startswith("Versions/"))
1214 goto guess_library;
1215 d = Name.rfind('/', c);
1216 if (d == Name.npos)
1217 Idx = 0;
1218 else
1219 Idx = d+1;
1220 F = Name.slice(Idx, Idx + Foo.size());
1221 DotFramework = Name.slice(Idx + Foo.size(),
1222 Idx + Foo.size() + sizeof(".framework/")-1);
1223 if (F == Foo && DotFramework == ".framework/") {
1224 isFramework = true;
1225 return Foo;
1226 }
1227
1228guess_library:
1229 // pull off the suffix after the "." and make a point to it
1230 a = Name.rfind('.');
1231 if (a == Name.npos || a == 0)
1232 return StringRef();
1233 Dylib = Name.slice(a, Name.npos);
1234 if (Dylib != ".dylib")
1235 goto guess_qtx;
1236
1237 // First pull off the version letter for the form Foo.A.dylib if any.
1238 if (a >= 3) {
1239 Dot = Name.slice(a-2, a-1);
1240 if (Dot == ".")
1241 a = a - 2;
1242 }
1243
1244 b = Name.rfind('/', a);
1245 if (b == Name.npos)
1246 b = 0;
1247 else
1248 b = b+1;
1249 // ignore any suffix after an underbar like Foo_profile.A.dylib
1250 Idx = Name.find('_', b);
1251 if (Idx != Name.npos && Idx != b) {
1252 Lib = Name.slice(b, Idx);
1253 Suffix = Name.slice(Idx, a);
1254 }
1255 else
1256 Lib = Name.slice(b, a);
1257 // There are incorrect library names of the form:
1258 // libATS.A_profile.dylib so check for these.
1259 if (Lib.size() >= 3) {
1260 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1261 if (Dot == ".")
1262 Lib = Lib.slice(0, Lib.size()-2);
1263 }
1264 return Lib;
1265
1266guess_qtx:
1267 Qtx = Name.slice(a, Name.npos);
1268 if (Qtx != ".qtx")
1269 return StringRef();
1270 b = Name.rfind('/', a);
1271 if (b == Name.npos)
1272 Lib = Name.slice(0, a);
1273 else
1274 Lib = Name.slice(b+1, a);
1275 // There are library names of the form: QT.A.qtx so check for these.
1276 if (Lib.size() >= 3) {
1277 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1278 if (Dot == ".")
1279 Lib = Lib.slice(0, Lib.size()-2);
1280 }
1281 return Lib;
1282}
1283
1284// getLibraryShortNameByIndex() is used to get the short name of the library
1285// for an undefined symbol in a linked Mach-O binary that was linked with the
1286// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1287// It is passed the index (0 - based) of the library as translated from
1288// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001289std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001290 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001291 if (Index >= Libraries.size())
1292 return object_error::parse_failed;
1293
Kevin Enderby980b2582014-06-05 21:21:57 +00001294 // If the cache of LibrariesShortNames is not built up do that first for
1295 // all the Libraries.
1296 if (LibrariesShortNames.size() == 0) {
1297 for (unsigned i = 0; i < Libraries.size(); i++) {
1298 MachO::dylib_command D =
1299 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001300 if (D.dylib.name >= D.cmdsize)
1301 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001302 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001303 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001304 if (D.dylib.name+Name.size() >= D.cmdsize)
1305 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001306 StringRef Suffix;
1307 bool isFramework;
1308 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001309 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001310 LibrariesShortNames.push_back(Name);
1311 else
1312 LibrariesShortNames.push_back(shortName);
1313 }
1314 }
1315
1316 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001317 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001318}
1319
Rafael Espindola76ad2322015-07-06 14:55:37 +00001320section_iterator
1321MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1322 DataRefImpl Sec;
1323 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1324 return section_iterator(SectionRef(Sec, this));
1325}
1326
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001327basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001328 DataRefImpl DRI;
1329 MachO::symtab_command Symtab = getSymtabLoadCommand();
1330 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1331 return basic_symbol_iterator(SymbolRef(DRI, this));
1332
Lang Hames36072da2014-05-12 21:39:59 +00001333 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001334}
1335
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001336basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001337 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001338 MachO::symtab_command Symtab = getSymtabLoadCommand();
1339 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001340 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001341
Rafael Espindola75c30362013-04-24 19:47:55 +00001342 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001343 sizeof(MachO::nlist_64) :
1344 sizeof(MachO::nlist);
1345 unsigned Offset = Symtab.symoff +
1346 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001347 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001348 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001349}
1350
Lang Hames36072da2014-05-12 21:39:59 +00001351basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001352 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001353 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001354 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001355 unsigned SymbolTableEntrySize =
1356 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001357 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001358 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1359 DRI.p += Index * SymbolTableEntrySize;
1360 return basic_symbol_iterator(SymbolRef(DRI, this));
1361}
1362
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001363uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
1364 MachO::symtab_command Symtab = getSymtabLoadCommand();
1365 if (!SymtabLoadCmd)
1366 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
1367 unsigned SymbolTableEntrySize =
1368 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1369 DataRefImpl DRIstart;
1370 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1371 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
1372 return Index;
1373}
1374
Rafael Espindolab5155a52014-02-10 20:24:04 +00001375section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001376 DataRefImpl DRI;
1377 return section_iterator(SectionRef(DRI, this));
1378}
1379
Rafael Espindolab5155a52014-02-10 20:24:04 +00001380section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001381 DataRefImpl DRI;
1382 DRI.d.a = Sections.size();
1383 return section_iterator(SectionRef(DRI, this));
1384}
1385
Rafael Espindola56f976f2013-04-18 18:08:55 +00001386uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001387 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001388}
1389
Rafael Espindola56f976f2013-04-18 18:08:55 +00001390StringRef MachOObjectFile::getFileFormatName() const {
1391 unsigned CPUType = getCPUType(this);
1392 if (!is64Bit()) {
1393 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001394 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001395 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001396 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001397 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001398 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001399 return "Mach-O 32-bit ppc";
1400 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001401 return "Mach-O 32-bit unknown";
1402 }
1403 }
1404
Rafael Espindola56f976f2013-04-18 18:08:55 +00001405 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001406 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001407 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001408 case llvm::MachO::CPU_TYPE_ARM64:
1409 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001410 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001411 return "Mach-O 64-bit ppc64";
1412 default:
1413 return "Mach-O 64-bit unknown";
1414 }
1415}
1416
Alexey Samsonove6388e62013-06-18 15:03:28 +00001417Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1418 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001419 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001420 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001421 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001422 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001423 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001424 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001425 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001426 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001427 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001428 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001429 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001430 return Triple::ppc64;
1431 default:
1432 return Triple::UnknownArch;
1433 }
1434}
1435
Tim Northover9e8eb412016-04-22 23:21:13 +00001436Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
1437 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001438 if (McpuDefault)
1439 *McpuDefault = nullptr;
1440
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001441 switch (CPUType) {
1442 case MachO::CPU_TYPE_I386:
1443 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1444 case MachO::CPU_SUBTYPE_I386_ALL:
1445 return Triple("i386-apple-darwin");
1446 default:
1447 return Triple();
1448 }
1449 case MachO::CPU_TYPE_X86_64:
1450 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1451 case MachO::CPU_SUBTYPE_X86_64_ALL:
1452 return Triple("x86_64-apple-darwin");
1453 case MachO::CPU_SUBTYPE_X86_64_H:
1454 return Triple("x86_64h-apple-darwin");
1455 default:
1456 return Triple();
1457 }
1458 case MachO::CPU_TYPE_ARM:
1459 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1460 case MachO::CPU_SUBTYPE_ARM_V4T:
1461 return Triple("armv4t-apple-darwin");
1462 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1463 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001464 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1465 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001466 case MachO::CPU_SUBTYPE_ARM_V6:
1467 return Triple("armv6-apple-darwin");
1468 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001469 if (McpuDefault)
1470 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001471 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001472 case MachO::CPU_SUBTYPE_ARM_V7:
1473 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001474 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001475 if (McpuDefault)
1476 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00001477 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001478 case MachO::CPU_SUBTYPE_ARM_V7K:
1479 return Triple("armv7k-apple-darwin");
1480 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001481 if (McpuDefault)
1482 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00001483 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001484 case MachO::CPU_SUBTYPE_ARM_V7S:
1485 return Triple("armv7s-apple-darwin");
1486 default:
1487 return Triple();
1488 }
1489 case MachO::CPU_TYPE_ARM64:
1490 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1491 case MachO::CPU_SUBTYPE_ARM64_ALL:
1492 return Triple("arm64-apple-darwin");
1493 default:
1494 return Triple();
1495 }
1496 case MachO::CPU_TYPE_POWERPC:
1497 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1498 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1499 return Triple("ppc-apple-darwin");
1500 default:
1501 return Triple();
1502 }
1503 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001504 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001505 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1506 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001507 default:
1508 return Triple();
1509 }
1510 default:
1511 return Triple();
1512 }
1513}
1514
1515Triple MachOObjectFile::getHostArch() {
1516 return Triple(sys::getDefaultTargetTriple());
1517}
1518
Rafael Espindola72318b42014-08-08 16:30:17 +00001519bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1520 return StringSwitch<bool>(ArchFlag)
1521 .Case("i386", true)
1522 .Case("x86_64", true)
1523 .Case("x86_64h", true)
1524 .Case("armv4t", true)
1525 .Case("arm", true)
1526 .Case("armv5e", true)
1527 .Case("armv6", true)
1528 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001529 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001530 .Case("armv7em", true)
1531 .Case("armv7k", true)
1532 .Case("armv7m", true)
1533 .Case("armv7s", true)
1534 .Case("arm64", true)
1535 .Case("ppc", true)
1536 .Case("ppc64", true)
1537 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001538}
1539
Alexey Samsonove6388e62013-06-18 15:03:28 +00001540unsigned MachOObjectFile::getArch() const {
1541 return getArch(getCPUType(this));
1542}
1543
Tim Northover9e8eb412016-04-22 23:21:13 +00001544Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
1545 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001546}
1547
Rui Ueyamabc654b12013-09-27 21:47:05 +00001548relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001549 DataRefImpl DRI;
1550 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001551 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001552}
1553
Rui Ueyamabc654b12013-09-27 21:47:05 +00001554relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001555 DataRefImpl DRI;
1556 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001557 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001558}
1559
Kevin Enderby273ae012013-06-06 17:20:50 +00001560dice_iterator MachOObjectFile::begin_dices() const {
1561 DataRefImpl DRI;
1562 if (!DataInCodeLoadCmd)
1563 return dice_iterator(DiceRef(DRI, this));
1564
Charles Davis8bdfafd2013-09-01 04:28:48 +00001565 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1566 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001567 return dice_iterator(DiceRef(DRI, this));
1568}
1569
1570dice_iterator MachOObjectFile::end_dices() const {
1571 DataRefImpl DRI;
1572 if (!DataInCodeLoadCmd)
1573 return dice_iterator(DiceRef(DRI, this));
1574
Charles Davis8bdfafd2013-09-01 04:28:48 +00001575 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1576 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001577 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1578 return dice_iterator(DiceRef(DRI, this));
1579}
1580
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001581ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1582 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001583
1584void ExportEntry::moveToFirst() {
1585 pushNode(0);
1586 pushDownUntilBottom();
1587}
1588
1589void ExportEntry::moveToEnd() {
1590 Stack.clear();
1591 Done = true;
1592}
1593
1594bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001595 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001596 if (Done || Other.Done)
1597 return (Done == Other.Done);
1598 // Not equal if different stack sizes.
1599 if (Stack.size() != Other.Stack.size())
1600 return false;
1601 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001602 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001603 return false;
1604 // Equal if all nodes in both stacks match.
1605 for (unsigned i=0; i < Stack.size(); ++i) {
1606 if (Stack[i].Start != Other.Stack[i].Start)
1607 return false;
1608 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001609 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001610}
1611
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001612uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1613 unsigned Count;
1614 uint64_t Result = decodeULEB128(Ptr, &Count);
1615 Ptr += Count;
1616 if (Ptr > Trie.end()) {
1617 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001618 Malformed = true;
1619 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001620 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001621}
1622
1623StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001624 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001625}
1626
1627uint64_t ExportEntry::flags() const {
1628 return Stack.back().Flags;
1629}
1630
1631uint64_t ExportEntry::address() const {
1632 return Stack.back().Address;
1633}
1634
1635uint64_t ExportEntry::other() const {
1636 return Stack.back().Other;
1637}
1638
1639StringRef ExportEntry::otherName() const {
1640 const char* ImportName = Stack.back().ImportName;
1641 if (ImportName)
1642 return StringRef(ImportName);
1643 return StringRef();
1644}
1645
1646uint32_t ExportEntry::nodeOffset() const {
1647 return Stack.back().Start - Trie.begin();
1648}
1649
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001650ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1651 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1652 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1653 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001654
1655void ExportEntry::pushNode(uint64_t offset) {
1656 const uint8_t *Ptr = Trie.begin() + offset;
1657 NodeState State(Ptr);
1658 uint64_t ExportInfoSize = readULEB128(State.Current);
1659 State.IsExportNode = (ExportInfoSize != 0);
1660 const uint8_t* Children = State.Current + ExportInfoSize;
1661 if (State.IsExportNode) {
1662 State.Flags = readULEB128(State.Current);
1663 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1664 State.Address = 0;
1665 State.Other = readULEB128(State.Current); // dylib ordinal
1666 State.ImportName = reinterpret_cast<const char*>(State.Current);
1667 } else {
1668 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001669 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001670 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001671 }
1672 }
1673 State.ChildCount = *Children;
1674 State.Current = Children + 1;
1675 State.NextChildIndex = 0;
1676 State.ParentStringLength = CumulativeString.size();
1677 Stack.push_back(State);
1678}
1679
1680void ExportEntry::pushDownUntilBottom() {
1681 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1682 NodeState &Top = Stack.back();
1683 CumulativeString.resize(Top.ParentStringLength);
1684 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001685 char C = *Top.Current;
1686 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001687 }
1688 Top.Current += 1;
1689 uint64_t childNodeIndex = readULEB128(Top.Current);
1690 Top.NextChildIndex += 1;
1691 pushNode(childNodeIndex);
1692 }
1693 if (!Stack.back().IsExportNode) {
1694 Malformed = true;
1695 moveToEnd();
1696 }
1697}
1698
1699// We have a trie data structure and need a way to walk it that is compatible
1700// with the C++ iterator model. The solution is a non-recursive depth first
1701// traversal where the iterator contains a stack of parent nodes along with a
1702// string that is the accumulation of all edge strings along the parent chain
1703// to this point.
1704//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001705// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001706// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001707// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001708//
1709// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1710// child until hitting a node with no children (which is an export node or
1711// else the trie is malformed). On the way down, each node is pushed on the
1712// stack ivar. If there is no more ways down, it pops up one and tries to go
1713// down a sibling path until a childless node is reached.
1714void ExportEntry::moveNext() {
1715 if (Stack.empty() || !Stack.back().IsExportNode) {
1716 Malformed = true;
1717 moveToEnd();
1718 return;
1719 }
1720
1721 Stack.pop_back();
1722 while (!Stack.empty()) {
1723 NodeState &Top = Stack.back();
1724 if (Top.NextChildIndex < Top.ChildCount) {
1725 pushDownUntilBottom();
1726 // Now at the next export node.
1727 return;
1728 } else {
1729 if (Top.IsExportNode) {
1730 // This node has no children but is itself an export node.
1731 CumulativeString.resize(Top.ParentStringLength);
1732 return;
1733 }
1734 Stack.pop_back();
1735 }
1736 }
1737 Done = true;
1738}
1739
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001740iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001741MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1742 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001743 if (Trie.size() == 0)
1744 Start.moveToEnd();
1745 else
1746 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001747
1748 ExportEntry Finish(Trie);
1749 Finish.moveToEnd();
1750
Craig Topper15576e12015-12-06 05:08:07 +00001751 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001752}
1753
1754iterator_range<export_iterator> MachOObjectFile::exports() const {
1755 return exports(getDyldInfoExportsTrie());
1756}
1757
Nick Kledzikac431442014-09-12 21:34:15 +00001758MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1759 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1760 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1761 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1762
1763void MachORebaseEntry::moveToFirst() {
1764 Ptr = Opcodes.begin();
1765 moveNext();
1766}
1767
1768void MachORebaseEntry::moveToEnd() {
1769 Ptr = Opcodes.end();
1770 RemainingLoopCount = 0;
1771 Done = true;
1772}
1773
1774void MachORebaseEntry::moveNext() {
1775 // If in the middle of some loop, move to next rebasing in loop.
1776 SegmentOffset += AdvanceAmount;
1777 if (RemainingLoopCount) {
1778 --RemainingLoopCount;
1779 return;
1780 }
1781 if (Ptr == Opcodes.end()) {
1782 Done = true;
1783 return;
1784 }
1785 bool More = true;
1786 while (More && !Malformed) {
1787 // Parse next opcode and set up next loop.
1788 uint8_t Byte = *Ptr++;
1789 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1790 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1791 switch (Opcode) {
1792 case MachO::REBASE_OPCODE_DONE:
1793 More = false;
1794 Done = true;
1795 moveToEnd();
1796 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1797 break;
1798 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1799 RebaseType = ImmValue;
1800 DEBUG_WITH_TYPE(
1801 "mach-o-rebase",
1802 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1803 << "RebaseType=" << (int) RebaseType << "\n");
1804 break;
1805 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1806 SegmentIndex = ImmValue;
1807 SegmentOffset = readULEB128();
1808 DEBUG_WITH_TYPE(
1809 "mach-o-rebase",
1810 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1811 << "SegmentIndex=" << SegmentIndex << ", "
1812 << format("SegmentOffset=0x%06X", SegmentOffset)
1813 << "\n");
1814 break;
1815 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1816 SegmentOffset += readULEB128();
1817 DEBUG_WITH_TYPE("mach-o-rebase",
1818 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1819 << format("SegmentOffset=0x%06X",
1820 SegmentOffset) << "\n");
1821 break;
1822 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1823 SegmentOffset += ImmValue * PointerSize;
1824 DEBUG_WITH_TYPE("mach-o-rebase",
1825 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1826 << format("SegmentOffset=0x%06X",
1827 SegmentOffset) << "\n");
1828 break;
1829 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1830 AdvanceAmount = PointerSize;
1831 RemainingLoopCount = ImmValue - 1;
1832 DEBUG_WITH_TYPE(
1833 "mach-o-rebase",
1834 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1835 << format("SegmentOffset=0x%06X", SegmentOffset)
1836 << ", AdvanceAmount=" << AdvanceAmount
1837 << ", RemainingLoopCount=" << RemainingLoopCount
1838 << "\n");
1839 return;
1840 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1841 AdvanceAmount = PointerSize;
1842 RemainingLoopCount = readULEB128() - 1;
1843 DEBUG_WITH_TYPE(
1844 "mach-o-rebase",
1845 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1846 << format("SegmentOffset=0x%06X", SegmentOffset)
1847 << ", AdvanceAmount=" << AdvanceAmount
1848 << ", RemainingLoopCount=" << RemainingLoopCount
1849 << "\n");
1850 return;
1851 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1852 AdvanceAmount = readULEB128() + PointerSize;
1853 RemainingLoopCount = 0;
1854 DEBUG_WITH_TYPE(
1855 "mach-o-rebase",
1856 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1857 << format("SegmentOffset=0x%06X", SegmentOffset)
1858 << ", AdvanceAmount=" << AdvanceAmount
1859 << ", RemainingLoopCount=" << RemainingLoopCount
1860 << "\n");
1861 return;
1862 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1863 RemainingLoopCount = readULEB128() - 1;
1864 AdvanceAmount = readULEB128() + PointerSize;
1865 DEBUG_WITH_TYPE(
1866 "mach-o-rebase",
1867 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1868 << format("SegmentOffset=0x%06X", SegmentOffset)
1869 << ", AdvanceAmount=" << AdvanceAmount
1870 << ", RemainingLoopCount=" << RemainingLoopCount
1871 << "\n");
1872 return;
1873 default:
1874 Malformed = true;
1875 }
1876 }
1877}
1878
1879uint64_t MachORebaseEntry::readULEB128() {
1880 unsigned Count;
1881 uint64_t Result = decodeULEB128(Ptr, &Count);
1882 Ptr += Count;
1883 if (Ptr > Opcodes.end()) {
1884 Ptr = Opcodes.end();
1885 Malformed = true;
1886 }
1887 return Result;
1888}
1889
1890uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1891
1892uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1893
1894StringRef MachORebaseEntry::typeName() const {
1895 switch (RebaseType) {
1896 case MachO::REBASE_TYPE_POINTER:
1897 return "pointer";
1898 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1899 return "text abs32";
1900 case MachO::REBASE_TYPE_TEXT_PCREL32:
1901 return "text rel32";
1902 }
1903 return "unknown";
1904}
1905
1906bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1907 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1908 return (Ptr == Other.Ptr) &&
1909 (RemainingLoopCount == Other.RemainingLoopCount) &&
1910 (Done == Other.Done);
1911}
1912
1913iterator_range<rebase_iterator>
1914MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1915 MachORebaseEntry Start(Opcodes, is64);
1916 Start.moveToFirst();
1917
1918 MachORebaseEntry Finish(Opcodes, is64);
1919 Finish.moveToEnd();
1920
Craig Topper15576e12015-12-06 05:08:07 +00001921 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001922}
1923
1924iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1925 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1926}
1927
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001928MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001929 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1930 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1931 BindType(0), PointerSize(is64Bit ? 8 : 4),
1932 TableKind(BK), Malformed(false), Done(false) {}
1933
1934void MachOBindEntry::moveToFirst() {
1935 Ptr = Opcodes.begin();
1936 moveNext();
1937}
1938
1939void MachOBindEntry::moveToEnd() {
1940 Ptr = Opcodes.end();
1941 RemainingLoopCount = 0;
1942 Done = true;
1943}
1944
1945void MachOBindEntry::moveNext() {
1946 // If in the middle of some loop, move to next binding in loop.
1947 SegmentOffset += AdvanceAmount;
1948 if (RemainingLoopCount) {
1949 --RemainingLoopCount;
1950 return;
1951 }
1952 if (Ptr == Opcodes.end()) {
1953 Done = true;
1954 return;
1955 }
1956 bool More = true;
1957 while (More && !Malformed) {
1958 // Parse next opcode and set up next loop.
1959 uint8_t Byte = *Ptr++;
1960 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1961 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1962 int8_t SignExtended;
1963 const uint8_t *SymStart;
1964 switch (Opcode) {
1965 case MachO::BIND_OPCODE_DONE:
1966 if (TableKind == Kind::Lazy) {
1967 // Lazying bindings have a DONE opcode between entries. Need to ignore
1968 // it to advance to next entry. But need not if this is last entry.
1969 bool NotLastEntry = false;
1970 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1971 if (*P) {
1972 NotLastEntry = true;
1973 }
1974 }
1975 if (NotLastEntry)
1976 break;
1977 }
1978 More = false;
1979 Done = true;
1980 moveToEnd();
1981 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1982 break;
1983 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1984 Ordinal = ImmValue;
1985 DEBUG_WITH_TYPE(
1986 "mach-o-bind",
1987 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1988 << "Ordinal=" << Ordinal << "\n");
1989 break;
1990 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1991 Ordinal = readULEB128();
1992 DEBUG_WITH_TYPE(
1993 "mach-o-bind",
1994 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1995 << "Ordinal=" << Ordinal << "\n");
1996 break;
1997 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1998 if (ImmValue) {
1999 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
2000 Ordinal = SignExtended;
2001 } else
2002 Ordinal = 0;
2003 DEBUG_WITH_TYPE(
2004 "mach-o-bind",
2005 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
2006 << "Ordinal=" << Ordinal << "\n");
2007 break;
2008 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
2009 Flags = ImmValue;
2010 SymStart = Ptr;
2011 while (*Ptr) {
2012 ++Ptr;
2013 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00002014 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
2015 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00002016 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002017 DEBUG_WITH_TYPE(
2018 "mach-o-bind",
2019 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
2020 << "SymbolName=" << SymbolName << "\n");
2021 if (TableKind == Kind::Weak) {
2022 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
2023 return;
2024 }
2025 break;
2026 case MachO::BIND_OPCODE_SET_TYPE_IMM:
2027 BindType = ImmValue;
2028 DEBUG_WITH_TYPE(
2029 "mach-o-bind",
2030 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
2031 << "BindType=" << (int)BindType << "\n");
2032 break;
2033 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
2034 Addend = readSLEB128();
2035 if (TableKind == Kind::Lazy)
2036 Malformed = true;
2037 DEBUG_WITH_TYPE(
2038 "mach-o-bind",
2039 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
2040 << "Addend=" << Addend << "\n");
2041 break;
2042 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2043 SegmentIndex = ImmValue;
2044 SegmentOffset = readULEB128();
2045 DEBUG_WITH_TYPE(
2046 "mach-o-bind",
2047 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2048 << "SegmentIndex=" << SegmentIndex << ", "
2049 << format("SegmentOffset=0x%06X", SegmentOffset)
2050 << "\n");
2051 break;
2052 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2053 SegmentOffset += readULEB128();
2054 DEBUG_WITH_TYPE("mach-o-bind",
2055 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2056 << format("SegmentOffset=0x%06X",
2057 SegmentOffset) << "\n");
2058 break;
2059 case MachO::BIND_OPCODE_DO_BIND:
2060 AdvanceAmount = PointerSize;
2061 RemainingLoopCount = 0;
2062 DEBUG_WITH_TYPE("mach-o-bind",
2063 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2064 << format("SegmentOffset=0x%06X",
2065 SegmentOffset) << "\n");
2066 return;
2067 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002068 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002069 RemainingLoopCount = 0;
2070 if (TableKind == Kind::Lazy)
2071 Malformed = true;
2072 DEBUG_WITH_TYPE(
2073 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002074 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00002075 << format("SegmentOffset=0x%06X", SegmentOffset)
2076 << ", AdvanceAmount=" << AdvanceAmount
2077 << ", RemainingLoopCount=" << RemainingLoopCount
2078 << "\n");
2079 return;
2080 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002081 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002082 RemainingLoopCount = 0;
2083 if (TableKind == Kind::Lazy)
2084 Malformed = true;
2085 DEBUG_WITH_TYPE("mach-o-bind",
2086 llvm::dbgs()
2087 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2088 << format("SegmentOffset=0x%06X",
2089 SegmentOffset) << "\n");
2090 return;
2091 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2092 RemainingLoopCount = readULEB128() - 1;
2093 AdvanceAmount = readULEB128() + PointerSize;
2094 if (TableKind == Kind::Lazy)
2095 Malformed = true;
2096 DEBUG_WITH_TYPE(
2097 "mach-o-bind",
2098 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2099 << format("SegmentOffset=0x%06X", SegmentOffset)
2100 << ", AdvanceAmount=" << AdvanceAmount
2101 << ", RemainingLoopCount=" << RemainingLoopCount
2102 << "\n");
2103 return;
2104 default:
2105 Malformed = true;
2106 }
2107 }
2108}
2109
2110uint64_t MachOBindEntry::readULEB128() {
2111 unsigned Count;
2112 uint64_t Result = decodeULEB128(Ptr, &Count);
2113 Ptr += Count;
2114 if (Ptr > Opcodes.end()) {
2115 Ptr = Opcodes.end();
2116 Malformed = true;
2117 }
2118 return Result;
2119}
2120
2121int64_t MachOBindEntry::readSLEB128() {
2122 unsigned Count;
2123 int64_t Result = decodeSLEB128(Ptr, &Count);
2124 Ptr += Count;
2125 if (Ptr > Opcodes.end()) {
2126 Ptr = Opcodes.end();
2127 Malformed = true;
2128 }
2129 return Result;
2130}
2131
Nick Kledzik56ebef42014-09-16 01:41:51 +00002132uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2133
2134uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2135
2136StringRef MachOBindEntry::typeName() const {
2137 switch (BindType) {
2138 case MachO::BIND_TYPE_POINTER:
2139 return "pointer";
2140 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2141 return "text abs32";
2142 case MachO::BIND_TYPE_TEXT_PCREL32:
2143 return "text rel32";
2144 }
2145 return "unknown";
2146}
2147
2148StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2149
2150int64_t MachOBindEntry::addend() const { return Addend; }
2151
2152uint32_t MachOBindEntry::flags() const { return Flags; }
2153
2154int MachOBindEntry::ordinal() const { return Ordinal; }
2155
2156bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2157 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2158 return (Ptr == Other.Ptr) &&
2159 (RemainingLoopCount == Other.RemainingLoopCount) &&
2160 (Done == Other.Done);
2161}
2162
2163iterator_range<bind_iterator>
2164MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2165 MachOBindEntry::Kind BKind) {
2166 MachOBindEntry Start(Opcodes, is64, BKind);
2167 Start.moveToFirst();
2168
2169 MachOBindEntry Finish(Opcodes, is64, BKind);
2170 Finish.moveToEnd();
2171
Craig Topper15576e12015-12-06 05:08:07 +00002172 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00002173}
2174
2175iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2176 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2177 MachOBindEntry::Kind::Regular);
2178}
2179
2180iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2181 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2182 MachOBindEntry::Kind::Lazy);
2183}
2184
2185iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2186 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2187 MachOBindEntry::Kind::Weak);
2188}
2189
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00002190MachOObjectFile::load_command_iterator
2191MachOObjectFile::begin_load_commands() const {
2192 return LoadCommands.begin();
2193}
2194
2195MachOObjectFile::load_command_iterator
2196MachOObjectFile::end_load_commands() const {
2197 return LoadCommands.end();
2198}
2199
2200iterator_range<MachOObjectFile::load_command_iterator>
2201MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00002202 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00002203}
2204
Rafael Espindola56f976f2013-04-18 18:08:55 +00002205StringRef
2206MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2207 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2208 return parseSegmentOrSectionName(Raw.data());
2209}
2210
2211ArrayRef<char>
2212MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002213 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002214 const section_base *Base =
2215 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002216 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002217}
2218
2219ArrayRef<char>
2220MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002221 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002222 const section_base *Base =
2223 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002224 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002225}
2226
2227bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002228MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002229 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002230 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002231 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002232 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002233}
2234
Eric Christopher1d62c252013-07-22 22:25:07 +00002235unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002236 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002237 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002238 return RE.r_word1 & 0xffffff;
2239 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002240}
2241
Eric Christopher1d62c252013-07-22 22:25:07 +00002242bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002243 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002244 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002245 return (RE.r_word1 >> 27) & 1;
2246 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002247}
2248
Eric Christopher1d62c252013-07-22 22:25:07 +00002249bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002250 const MachO::any_relocation_info &RE) const {
2251 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002252}
2253
Eric Christopher1d62c252013-07-22 22:25:07 +00002254uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002255 const MachO::any_relocation_info &RE) const {
2256 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002257}
2258
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002259uint32_t MachOObjectFile::getScatteredRelocationType(
2260 const MachO::any_relocation_info &RE) const {
2261 return (RE.r_word0 >> 24) & 0xf;
2262}
2263
Eric Christopher1d62c252013-07-22 22:25:07 +00002264unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002265 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002266 if (isRelocationScattered(RE))
2267 return getScatteredRelocationAddress(RE);
2268 return getPlainRelocationAddress(RE);
2269}
2270
Charles Davis8bdfafd2013-09-01 04:28:48 +00002271unsigned MachOObjectFile::getAnyRelocationPCRel(
2272 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002273 if (isRelocationScattered(RE))
2274 return getScatteredRelocationPCRel(this, RE);
2275 return getPlainRelocationPCRel(this, RE);
2276}
2277
Eric Christopher1d62c252013-07-22 22:25:07 +00002278unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002279 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002280 if (isRelocationScattered(RE))
2281 return getScatteredRelocationLength(RE);
2282 return getPlainRelocationLength(this, RE);
2283}
2284
2285unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002286MachOObjectFile::getAnyRelocationType(
2287 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002288 if (isRelocationScattered(RE))
2289 return getScatteredRelocationType(RE);
2290 return getPlainRelocationType(this, RE);
2291}
2292
Rafael Espindola52501032013-04-30 15:40:54 +00002293SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002294MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002295 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002296 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002297 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002298 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2299 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2300 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002301 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002302 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002303 return SectionRef(DRI, this);
2304}
2305
Charles Davis8bdfafd2013-09-01 04:28:48 +00002306MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002307 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002308 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002309}
2310
Charles Davis8bdfafd2013-09-01 04:28:48 +00002311MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002312 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002313 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002314}
2315
Charles Davis8bdfafd2013-09-01 04:28:48 +00002316MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002317 unsigned Index) const {
2318 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002319 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002320}
2321
Charles Davis8bdfafd2013-09-01 04:28:48 +00002322MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2323 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002324 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002325 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002326}
2327
Charles Davis8bdfafd2013-09-01 04:28:48 +00002328MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002329MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002330 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002331 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002332}
2333
Charles Davis8bdfafd2013-09-01 04:28:48 +00002334MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002335MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002336 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002337 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002338}
2339
Charles Davis8bdfafd2013-09-01 04:28:48 +00002340MachO::linkedit_data_command
2341MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2342 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002343}
2344
Charles Davis8bdfafd2013-09-01 04:28:48 +00002345MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002346MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002347 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002348}
2349
Charles Davis8bdfafd2013-09-01 04:28:48 +00002350MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002351MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002352 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002353}
2354
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002355MachO::linker_option_command
2356MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2357 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002358}
2359
Jim Grosbach448334a2014-03-18 22:09:05 +00002360MachO::version_min_command
2361MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2362 return getStruct<MachO::version_min_command>(this, L.Ptr);
2363}
2364
Tim Northover8f9590b2014-06-30 14:40:57 +00002365MachO::dylib_command
2366MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2367 return getStruct<MachO::dylib_command>(this, L.Ptr);
2368}
2369
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002370MachO::dyld_info_command
2371MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2372 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2373}
2374
2375MachO::dylinker_command
2376MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2377 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2378}
2379
2380MachO::uuid_command
2381MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2382 return getStruct<MachO::uuid_command>(this, L.Ptr);
2383}
2384
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002385MachO::rpath_command
2386MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2387 return getStruct<MachO::rpath_command>(this, L.Ptr);
2388}
2389
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002390MachO::source_version_command
2391MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2392 return getStruct<MachO::source_version_command>(this, L.Ptr);
2393}
2394
2395MachO::entry_point_command
2396MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2397 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2398}
2399
Kevin Enderby0804f4672014-12-16 23:25:52 +00002400MachO::encryption_info_command
2401MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2402 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2403}
2404
Kevin Enderby57538292014-12-17 01:01:30 +00002405MachO::encryption_info_command_64
2406MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2407 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2408}
2409
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002410MachO::sub_framework_command
2411MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2412 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2413}
Tim Northover8f9590b2014-06-30 14:40:57 +00002414
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002415MachO::sub_umbrella_command
2416MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2417 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2418}
2419
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002420MachO::sub_library_command
2421MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2422 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2423}
2424
Kevin Enderby186eac32014-12-19 21:06:24 +00002425MachO::sub_client_command
2426MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2427 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2428}
2429
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002430MachO::routines_command
2431MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2432 return getStruct<MachO::routines_command>(this, L.Ptr);
2433}
2434
2435MachO::routines_command_64
2436MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2437 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2438}
2439
Kevin Enderby48ef5342014-12-23 22:56:39 +00002440MachO::thread_command
2441MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2442 return getStruct<MachO::thread_command>(this, L.Ptr);
2443}
2444
Charles Davis8bdfafd2013-09-01 04:28:48 +00002445MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002446MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002447 DataRefImpl Sec;
2448 Sec.d.a = Rel.d.a;
2449 uint32_t Offset;
2450 if (is64Bit()) {
2451 MachO::section_64 Sect = getSection64(Sec);
2452 Offset = Sect.reloff;
2453 } else {
2454 MachO::section Sect = getSection(Sec);
2455 Offset = Sect.reloff;
2456 }
2457
2458 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2459 getPtr(this, Offset)) + Rel.d.b;
2460 return getStruct<MachO::any_relocation_info>(
2461 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002462}
2463
Charles Davis8bdfafd2013-09-01 04:28:48 +00002464MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002465MachOObjectFile::getDice(DataRefImpl Rel) const {
2466 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002467 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002468}
2469
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002470const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002471 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002472}
2473
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002474const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2475 assert(is64Bit());
2476 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002477}
2478
Charles Davis8bdfafd2013-09-01 04:28:48 +00002479uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2480 const MachO::dysymtab_command &DLC,
2481 unsigned Index) const {
2482 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2483 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002484}
2485
Charles Davis8bdfafd2013-09-01 04:28:48 +00002486MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002487MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2488 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002489 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2490 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002491}
2492
Charles Davis8bdfafd2013-09-01 04:28:48 +00002493MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002494 if (SymtabLoadCmd)
2495 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2496
2497 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2498 MachO::symtab_command Cmd;
2499 Cmd.cmd = MachO::LC_SYMTAB;
2500 Cmd.cmdsize = sizeof(MachO::symtab_command);
2501 Cmd.symoff = 0;
2502 Cmd.nsyms = 0;
2503 Cmd.stroff = 0;
2504 Cmd.strsize = 0;
2505 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002506}
2507
Charles Davis8bdfafd2013-09-01 04:28:48 +00002508MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002509 if (DysymtabLoadCmd)
2510 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2511
2512 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2513 MachO::dysymtab_command Cmd;
2514 Cmd.cmd = MachO::LC_DYSYMTAB;
2515 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2516 Cmd.ilocalsym = 0;
2517 Cmd.nlocalsym = 0;
2518 Cmd.iextdefsym = 0;
2519 Cmd.nextdefsym = 0;
2520 Cmd.iundefsym = 0;
2521 Cmd.nundefsym = 0;
2522 Cmd.tocoff = 0;
2523 Cmd.ntoc = 0;
2524 Cmd.modtaboff = 0;
2525 Cmd.nmodtab = 0;
2526 Cmd.extrefsymoff = 0;
2527 Cmd.nextrefsyms = 0;
2528 Cmd.indirectsymoff = 0;
2529 Cmd.nindirectsyms = 0;
2530 Cmd.extreloff = 0;
2531 Cmd.nextrel = 0;
2532 Cmd.locreloff = 0;
2533 Cmd.nlocrel = 0;
2534 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002535}
2536
Charles Davis8bdfafd2013-09-01 04:28:48 +00002537MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002538MachOObjectFile::getDataInCodeLoadCommand() const {
2539 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002540 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002541
2542 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002543 MachO::linkedit_data_command Cmd;
2544 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2545 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2546 Cmd.dataoff = 0;
2547 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002548 return Cmd;
2549}
2550
Kevin Enderby9a509442015-01-27 21:28:24 +00002551MachO::linkedit_data_command
2552MachOObjectFile::getLinkOptHintsLoadCommand() const {
2553 if (LinkOptHintsLoadCmd)
2554 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2555
2556 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2557 // fields.
2558 MachO::linkedit_data_command Cmd;
2559 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2560 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2561 Cmd.dataoff = 0;
2562 Cmd.datasize = 0;
2563 return Cmd;
2564}
2565
Nick Kledzikd04bc352014-08-30 00:20:14 +00002566ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002567 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002568 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002569
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002570 MachO::dyld_info_command DyldInfo =
2571 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2572 const uint8_t *Ptr =
2573 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002574 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002575}
2576
2577ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002578 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002579 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002580
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002581 MachO::dyld_info_command DyldInfo =
2582 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2583 const uint8_t *Ptr =
2584 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002585 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002586}
2587
2588ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002589 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002590 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002591
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002592 MachO::dyld_info_command DyldInfo =
2593 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2594 const uint8_t *Ptr =
2595 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002596 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002597}
2598
2599ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002600 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002601 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002602
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002603 MachO::dyld_info_command DyldInfo =
2604 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2605 const uint8_t *Ptr =
2606 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002607 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002608}
2609
2610ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002611 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002612 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002613
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002614 MachO::dyld_info_command DyldInfo =
2615 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2616 const uint8_t *Ptr =
2617 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002618 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002619}
2620
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002621ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2622 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002623 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002624 // Returning a pointer is fine as uuid doesn't need endian swapping.
2625 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002626 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002627}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002628
Rafael Espindola6e040c02013-04-26 20:07:33 +00002629StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002630 MachO::symtab_command S = getSymtabLoadCommand();
2631 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002632}
2633
Rafael Espindola56f976f2013-04-18 18:08:55 +00002634bool MachOObjectFile::is64Bit() const {
2635 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002636 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002637}
2638
2639void MachOObjectFile::ReadULEB128s(uint64_t Index,
2640 SmallVectorImpl<uint64_t> &Out) const {
2641 DataExtractor extractor(ObjectFile::getData(), true, 0);
2642
2643 uint32_t offset = Index;
2644 uint64_t data = 0;
2645 while (uint64_t delta = extractor.getULEB128(&offset)) {
2646 data += delta;
2647 Out.push_back(data);
2648 }
2649}
2650
Rafael Espindolac66d7612014-08-17 19:09:37 +00002651bool MachOObjectFile::isRelocatableObject() const {
2652 return getHeader().filetype == MachO::MH_OBJECT;
2653}
2654
Lang Hamesff044b12016-03-25 23:11:52 +00002655Expected<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002656ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2657 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00002658 if (Magic == "\xFE\xED\xFA\xCE")
Lang Hamesff044b12016-03-25 23:11:52 +00002659 return MachOObjectFile::create(Buffer, false, false);
David Blaikieb805f732016-03-28 17:45:48 +00002660 if (Magic == "\xCE\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002661 return MachOObjectFile::create(Buffer, true, false);
David Blaikieb805f732016-03-28 17:45:48 +00002662 if (Magic == "\xFE\xED\xFA\xCF")
Lang Hamesff044b12016-03-25 23:11:52 +00002663 return MachOObjectFile::create(Buffer, false, true);
David Blaikieb805f732016-03-28 17:45:48 +00002664 if (Magic == "\xCF\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002665 return MachOObjectFile::create(Buffer, true, true);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00002666 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00002667 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002668}