blob: 43e76a9b4042dd3c77992c699a1a212470bc4534 [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 Enderby3fcdf6a2016-04-06 22:14:09 +0000187 if (sizeof(MachOObjectFile::LoadCommandInfo) > 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);
198 if (L.Ptr + L.C.cmdsize + sizeof(MachOObjectFile::LoadCommandInfo) >
199 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
Lang Hames82627642016-03-25 21:59:14 +0000331Expected<std::unique_ptr<MachOObjectFile>>
332MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
333 bool Is64Bits) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000334 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000335 std::unique_ptr<MachOObjectFile> Obj(
336 new MachOObjectFile(std::move(Object), IsLittleEndian,
337 Is64Bits, Err));
338 if (Err)
339 return std::move(Err);
340 return std::move(Obj);
341}
342
Rafael Espindola48af1c22014-08-19 18:44:46 +0000343MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Lang Hames9e964f32016-03-25 17:25:34 +0000344 bool Is64bits, Error &Err)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000345 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000346 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000347 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
348 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
349 HasPageZeroSegment(false) {
Lang Hames5e51a2e2016-07-22 16:11:25 +0000350 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000351 uint64_t SizeOfHeaders;
Kevin Enderby87025742016-04-13 21:17:58 +0000352 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +0000353 parseHeader(this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000354 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby87025742016-04-13 21:17:58 +0000355 } else {
Lang Hames9e964f32016-03-25 17:25:34 +0000356 parseHeader(this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000357 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby87025742016-04-13 21:17:58 +0000358 }
Lang Hames9e964f32016-03-25 17:25:34 +0000359 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000360 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000361 SizeOfHeaders += getHeader().sizeofcmds;
362 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000363 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +0000364 return;
365 }
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000366
367 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000368 if (LoadCommandCount == 0)
369 return;
370
Lang Hames9e964f32016-03-25 17:25:34 +0000371 LoadCommandInfo Load;
372 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
373 Load = *LoadOrErr;
374 else {
375 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000376 return;
377 }
Lang Hames9e964f32016-03-25 17:25:34 +0000378
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000379 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +0000380 if (is64Bit()) {
381 if (Load.C.cmdsize % 8 != 0) {
382 // We have a hack here to allow 64-bit Mach-O core files to have
383 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
384 // allowed since the macOS kernel produces them.
385 if (getHeader().filetype != MachO::MH_CORE ||
386 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
387 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
388 "multiple of 8");
389 return;
390 }
391 }
392 } else {
393 if (Load.C.cmdsize % 4 != 0) {
394 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
395 "multiple of 4");
396 return;
397 }
398 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000399 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000400 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000401 // Multiple symbol tables
402 if (SymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000403 Err = malformedError("Multiple symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000404 return;
405 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000406 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000407 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000408 // Multiple dynamic symbol tables
409 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000410 Err = malformedError("Multiple dynamic symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000411 return;
412 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000413 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000414 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000415 // Multiple data in code tables
416 if (DataInCodeLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000417 Err = malformedError("Multiple data-in-code tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000418 return;
419 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000420 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000421 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
422 // Multiple linker optimization hint tables
423 if (LinkOptHintsLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000424 Err = malformedError("Multiple linker optimization hint tables");
Kevin Enderby9a509442015-01-27 21:28:24 +0000425 return;
426 }
427 LinkOptHintsLoadCmd = Load.Ptr;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000428 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000429 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000430 // Multiple dyldinfo load commands
431 if (DyldInfoLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000432 Err = malformedError("Multiple dyldinfo load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000433 return;
434 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000435 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000436 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000437 // Multiple UUID load commands
438 if (UuidLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000439 Err = malformedError("Multiple UUID load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000440 return;
441 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000442 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000443 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000444 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
445 MachO::section_64>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000446 this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyc614d282016-08-12 20:10:25 +0000447 "LC_SEGMENT_64", SizeOfHeaders)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000448 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000449 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000450 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
451 MachO::section>(
452 this, Load, Sections, HasPageZeroSegment, I,
453 "LC_SEGMENT", SizeOfHeaders)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000454 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000455 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
456 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
457 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
458 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
459 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
460 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000461 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000462 if (I < LoadCommandCount - 1) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000463 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +0000464 Load = *LoadOrErr;
465 else {
466 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000467 return;
468 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000469 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000470 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000471 if (!SymtabLoadCmd) {
472 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000473 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +0000474 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +0000475 return;
476 }
477 } else if (DysymtabLoadCmd) {
478 MachO::symtab_command Symtab =
479 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
480 MachO::dysymtab_command Dysymtab =
481 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
482 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000483 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000484 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000485 return;
486 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000487 uint64_t BigSize = Dysymtab.ilocalsym;
488 BigSize += Dysymtab.nlocalsym;
489 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000490 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +0000491 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000492 return;
493 }
494 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000495 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000496 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000497 return;
498 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000499 BigSize = Dysymtab.iextdefsym;
500 BigSize += Dysymtab.nextdefsym;
501 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000502 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +0000503 "load command extends past the end of the symbol "
504 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000505 return;
506 }
507 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000508 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000509 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000510 return;
511 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000512 BigSize = Dysymtab.iundefsym;
513 BigSize += Dysymtab.nundefsym;
514 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000515 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +0000516 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000517 return;
518 }
519 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000520 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +0000521
522 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000523}
524
Rafael Espindola5e812af2014-01-30 02:49:50 +0000525void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000526 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000527 sizeof(MachO::nlist_64) :
528 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000529 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000530}
531
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000532Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000533 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000534 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000535 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000536 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000537 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +0000538 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000539 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000540 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000541}
542
Rafael Espindola0e77a942014-12-10 20:46:55 +0000543unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
544 DataRefImpl DRI = Sec.getRawDataRefImpl();
545 uint32_t Flags = getSectionFlags(this, DRI);
546 return Flags & MachO::SECTION_TYPE;
547}
548
Rafael Espindola59128922015-06-24 18:14:41 +0000549uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
550 if (is64Bit()) {
551 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
552 return Entry.n_value;
553 }
554 MachO::nlist Entry = getSymbolTableEntry(Sym);
555 return Entry.n_value;
556}
557
Kevin Enderby980b2582014-06-05 21:21:57 +0000558// getIndirectName() returns the name of the alias'ed symbol who's string table
559// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000560std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
561 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000562 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000563 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
564 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
565 return object_error::parse_failed;
566 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000567 if (NValue >= StringTable.size())
568 return object_error::parse_failed;
569 const char *Start = &StringTable.data()[NValue];
570 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000571 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000572}
573
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000574uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000575 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000576}
577
Kevin Enderby931cb652016-06-24 18:24:42 +0000578Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +0000579 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000580}
581
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000582uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000583 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000584 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000585 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000586 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000587 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000588 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000589}
590
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000591uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000592 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000593}
594
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000595Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000596MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000597 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000598 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000599
Rafael Espindola56f976f2013-04-18 18:08:55 +0000600 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000601 if (n_type & MachO::N_STAB)
602 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000603
Charles Davis74ec8b02013-08-27 05:00:13 +0000604 switch (n_type & MachO::N_TYPE) {
605 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000606 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000607 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000608 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000609 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000610 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000611 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000612 if (Sec->isData() || Sec->isBSS())
613 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000614 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000615 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000616 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000617}
618
Rafael Espindola20122a42014-01-31 20:57:12 +0000619uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000620 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000621
Charles Davis8bdfafd2013-09-01 04:28:48 +0000622 uint8_t MachOType = Entry.n_type;
623 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000624
Rafael Espindola20122a42014-01-31 20:57:12 +0000625 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000626
Tim Northovereaef0742014-05-30 13:22:59 +0000627 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
628 Result |= SymbolRef::SF_Indirect;
629
Rafael Espindolaa1356322013-11-02 05:03:24 +0000630 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000631 Result |= SymbolRef::SF_FormatSpecific;
632
Charles Davis74ec8b02013-08-27 05:00:13 +0000633 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000634 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000635 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000636 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000637 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000638 else
639 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000640 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000641
642 if (!(MachOType & MachO::N_PEXT))
643 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000644 }
645
Charles Davis74ec8b02013-08-27 05:00:13 +0000646 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000647 Result |= SymbolRef::SF_Weak;
648
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000649 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
650 Result |= SymbolRef::SF_Thumb;
651
Charles Davis74ec8b02013-08-27 05:00:13 +0000652 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000653 Result |= SymbolRef::SF_Absolute;
654
Rafael Espindola20122a42014-01-31 20:57:12 +0000655 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000656}
657
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000658Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +0000659MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000660 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000661 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000662
Rafael Espindola8bab8892015-08-07 23:27:14 +0000663 if (index == 0)
664 return section_end();
665 DataRefImpl DRI;
666 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000667 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000668 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +0000669 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000670 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000671 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000672}
673
Rafael Espindola6bf32212015-06-24 19:57:32 +0000674unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
675 MachO::nlist_base Entry =
676 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
677 return Entry.n_sect - 1;
678}
679
Rafael Espindola5e812af2014-01-30 02:49:50 +0000680void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000681 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000682}
683
Rafael Espindola3acea392014-06-12 21:46:39 +0000684std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
685 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000686 ArrayRef<char> Raw = getSectionRawName(Sec);
687 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000688 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000689}
690
Rafael Espindola80291272014-10-08 15:28:58 +0000691uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
692 if (is64Bit())
693 return getSection64(Sec).addr;
694 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000695}
696
Rafael Espindola80291272014-10-08 15:28:58 +0000697uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000698 // In the case if a malformed Mach-O file where the section offset is past
699 // the end of the file or some part of the section size is past the end of
700 // the file return a size of zero or a size that covers the rest of the file
701 // but does not extend past the end of the file.
702 uint32_t SectOffset, SectType;
703 uint64_t SectSize;
704
705 if (is64Bit()) {
706 MachO::section_64 Sect = getSection64(Sec);
707 SectOffset = Sect.offset;
708 SectSize = Sect.size;
709 SectType = Sect.flags & MachO::SECTION_TYPE;
710 } else {
711 MachO::section Sect = getSection(Sec);
712 SectOffset = Sect.offset;
713 SectSize = Sect.size;
714 SectType = Sect.flags & MachO::SECTION_TYPE;
715 }
716 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
717 return SectSize;
718 uint64_t FileSize = getData().size();
719 if (SectOffset > FileSize)
720 return 0;
721 if (FileSize - SectOffset < SectSize)
722 return FileSize - SectOffset;
723 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000724}
725
Rafael Espindola3acea392014-06-12 21:46:39 +0000726std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
727 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000728 uint32_t Offset;
729 uint64_t Size;
730
731 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000732 MachO::section_64 Sect = getSection64(Sec);
733 Offset = Sect.offset;
734 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000735 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000736 MachO::section Sect = getSection(Sec);
737 Offset = Sect.offset;
738 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000739 }
740
741 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000742 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000743}
744
Rafael Espindola80291272014-10-08 15:28:58 +0000745uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000746 uint32_t Align;
747 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000748 MachO::section_64 Sect = getSection64(Sec);
749 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000750 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000751 MachO::section Sect = getSection(Sec);
752 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000753 }
754
Rafael Espindola80291272014-10-08 15:28:58 +0000755 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000756}
757
George Rimar401e4e52016-05-24 12:48:46 +0000758bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
759 return false;
760}
761
Rafael Espindola80291272014-10-08 15:28:58 +0000762bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000763 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000764 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000765}
766
Rafael Espindola80291272014-10-08 15:28:58 +0000767bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000768 uint32_t Flags = getSectionFlags(this, Sec);
769 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000770 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
771 !(SectionType == MachO::S_ZEROFILL ||
772 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000773}
774
Rafael Espindola80291272014-10-08 15:28:58 +0000775bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000776 uint32_t Flags = getSectionFlags(this, Sec);
777 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000778 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
779 (SectionType == MachO::S_ZEROFILL ||
780 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000781}
782
Rafael Espindola6bf32212015-06-24 19:57:32 +0000783unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
784 return Sec.getRawDataRefImpl().d.a;
785}
786
Rafael Espindola80291272014-10-08 15:28:58 +0000787bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000788 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000789 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000790}
791
Steven Wuf2fe0142016-02-29 19:40:10 +0000792bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
793 StringRef SegmentName = getSectionFinalSegmentName(Sec);
794 StringRef SectName;
795 if (!getSectionName(Sec, SectName))
796 return (SegmentName == "__LLVM" && SectName == "__bitcode");
797 return false;
798}
799
Rui Ueyamabc654b12013-09-27 21:47:05 +0000800relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000801 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000802 Ret.d.a = Sec.d.a;
803 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000804 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000805}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000806
Rafael Espindola56f976f2013-04-18 18:08:55 +0000807relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000808MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000809 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000810 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000811 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000812 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000813 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000814 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000815 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000816 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000817
Rafael Espindola56f976f2013-04-18 18:08:55 +0000818 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000819 Ret.d.a = Sec.d.a;
820 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000821 return relocation_iterator(RelocationRef(Ret, this));
822}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000823
Rafael Espindola5e812af2014-01-30 02:49:50 +0000824void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000825 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000826}
Owen Anderson171f4852011-10-24 23:20:07 +0000827
Rafael Espindola96d071c2015-06-29 23:29:12 +0000828uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000829 assert(getHeader().filetype == MachO::MH_OBJECT &&
830 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000831 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000832 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000833}
834
Rafael Espindola806f0062013-06-05 01:33:53 +0000835symbol_iterator
836MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000837 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000838 if (isRelocationScattered(RE))
839 return symbol_end();
840
Rafael Espindola56f976f2013-04-18 18:08:55 +0000841 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
842 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000843 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000844 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000845
Charles Davis8bdfafd2013-09-01 04:28:48 +0000846 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000847 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000848 sizeof(MachO::nlist_64) :
849 sizeof(MachO::nlist);
850 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000851 DataRefImpl Sym;
852 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000853 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000854}
855
Keno Fischerc780e8e2015-05-21 21:24:32 +0000856section_iterator
857MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
858 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
859}
860
Rafael Espindola99c041b2015-06-30 01:53:01 +0000861uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000862 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000863 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000864}
865
Rafael Espindola41bb4322015-06-30 04:08:37 +0000866void MachOObjectFile::getRelocationTypeName(
867 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000868 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000869 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000870
871 unsigned Arch = this->getArch();
872
873 switch (Arch) {
874 case Triple::x86: {
875 static const char *const Table[] = {
876 "GENERIC_RELOC_VANILLA",
877 "GENERIC_RELOC_PAIR",
878 "GENERIC_RELOC_SECTDIFF",
879 "GENERIC_RELOC_PB_LA_PTR",
880 "GENERIC_RELOC_LOCAL_SECTDIFF",
881 "GENERIC_RELOC_TLV" };
882
Eric Christopher13250cb2013-12-06 02:33:38 +0000883 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000884 res = "Unknown";
885 else
886 res = Table[RType];
887 break;
888 }
889 case Triple::x86_64: {
890 static const char *const Table[] = {
891 "X86_64_RELOC_UNSIGNED",
892 "X86_64_RELOC_SIGNED",
893 "X86_64_RELOC_BRANCH",
894 "X86_64_RELOC_GOT_LOAD",
895 "X86_64_RELOC_GOT",
896 "X86_64_RELOC_SUBTRACTOR",
897 "X86_64_RELOC_SIGNED_1",
898 "X86_64_RELOC_SIGNED_2",
899 "X86_64_RELOC_SIGNED_4",
900 "X86_64_RELOC_TLV" };
901
902 if (RType > 9)
903 res = "Unknown";
904 else
905 res = Table[RType];
906 break;
907 }
908 case Triple::arm: {
909 static const char *const Table[] = {
910 "ARM_RELOC_VANILLA",
911 "ARM_RELOC_PAIR",
912 "ARM_RELOC_SECTDIFF",
913 "ARM_RELOC_LOCAL_SECTDIFF",
914 "ARM_RELOC_PB_LA_PTR",
915 "ARM_RELOC_BR24",
916 "ARM_THUMB_RELOC_BR22",
917 "ARM_THUMB_32BIT_BRANCH",
918 "ARM_RELOC_HALF",
919 "ARM_RELOC_HALF_SECTDIFF" };
920
921 if (RType > 9)
922 res = "Unknown";
923 else
924 res = Table[RType];
925 break;
926 }
Tim Northover00ed9962014-03-29 10:18:08 +0000927 case Triple::aarch64: {
928 static const char *const Table[] = {
929 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
930 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
931 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
932 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
933 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
934 "ARM64_RELOC_ADDEND"
935 };
936
937 if (RType >= array_lengthof(Table))
938 res = "Unknown";
939 else
940 res = Table[RType];
941 break;
942 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000943 case Triple::ppc: {
944 static const char *const Table[] = {
945 "PPC_RELOC_VANILLA",
946 "PPC_RELOC_PAIR",
947 "PPC_RELOC_BR14",
948 "PPC_RELOC_BR24",
949 "PPC_RELOC_HI16",
950 "PPC_RELOC_LO16",
951 "PPC_RELOC_HA16",
952 "PPC_RELOC_LO14",
953 "PPC_RELOC_SECTDIFF",
954 "PPC_RELOC_PB_LA_PTR",
955 "PPC_RELOC_HI16_SECTDIFF",
956 "PPC_RELOC_LO16_SECTDIFF",
957 "PPC_RELOC_HA16_SECTDIFF",
958 "PPC_RELOC_JBSR",
959 "PPC_RELOC_LO14_SECTDIFF",
960 "PPC_RELOC_LOCAL_SECTDIFF" };
961
Eric Christopher13250cb2013-12-06 02:33:38 +0000962 if (RType > 15)
963 res = "Unknown";
964 else
965 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000966 break;
967 }
968 case Triple::UnknownArch:
969 res = "Unknown";
970 break;
971 }
972 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000973}
974
Keno Fischer281b6942015-05-30 19:44:53 +0000975uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
976 MachO::any_relocation_info RE = getRelocation(Rel);
977 return getAnyRelocationLength(RE);
978}
979
Kevin Enderby980b2582014-06-05 21:21:57 +0000980//
981// guessLibraryShortName() is passed a name of a dynamic library and returns a
982// guess on what the short name is. Then name is returned as a substring of the
983// StringRef Name passed in. The name of the dynamic library is recognized as
984// a framework if it has one of the two following forms:
985// Foo.framework/Versions/A/Foo
986// Foo.framework/Foo
987// Where A and Foo can be any string. And may contain a trailing suffix
988// starting with an underbar. If the Name is recognized as a framework then
989// isFramework is set to true else it is set to false. If the Name has a
990// suffix then Suffix is set to the substring in Name that contains the suffix
991// else it is set to a NULL StringRef.
992//
993// The Name of the dynamic library is recognized as a library name if it has
994// one of the two following forms:
995// libFoo.A.dylib
996// libFoo.dylib
997// The library may have a suffix trailing the name Foo of the form:
998// libFoo_profile.A.dylib
999// libFoo_profile.dylib
1000//
1001// The Name of the dynamic library is also recognized as a library name if it
1002// has the following form:
1003// Foo.qtx
1004//
1005// If the Name of the dynamic library is none of the forms above then a NULL
1006// StringRef is returned.
1007//
1008StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1009 bool &isFramework,
1010 StringRef &Suffix) {
1011 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1012 size_t a, b, c, d, Idx;
1013
1014 isFramework = false;
1015 Suffix = StringRef();
1016
1017 // Pull off the last component and make Foo point to it
1018 a = Name.rfind('/');
1019 if (a == Name.npos || a == 0)
1020 goto guess_library;
1021 Foo = Name.slice(a+1, Name.npos);
1022
1023 // Look for a suffix starting with a '_'
1024 Idx = Foo.rfind('_');
1025 if (Idx != Foo.npos && Foo.size() >= 2) {
1026 Suffix = Foo.slice(Idx, Foo.npos);
1027 Foo = Foo.slice(0, Idx);
1028 }
1029
1030 // First look for the form Foo.framework/Foo
1031 b = Name.rfind('/', a);
1032 if (b == Name.npos)
1033 Idx = 0;
1034 else
1035 Idx = b+1;
1036 F = Name.slice(Idx, Idx + Foo.size());
1037 DotFramework = Name.slice(Idx + Foo.size(),
1038 Idx + Foo.size() + sizeof(".framework/")-1);
1039 if (F == Foo && DotFramework == ".framework/") {
1040 isFramework = true;
1041 return Foo;
1042 }
1043
1044 // Next look for the form Foo.framework/Versions/A/Foo
1045 if (b == Name.npos)
1046 goto guess_library;
1047 c = Name.rfind('/', b);
1048 if (c == Name.npos || c == 0)
1049 goto guess_library;
1050 V = Name.slice(c+1, Name.npos);
1051 if (!V.startswith("Versions/"))
1052 goto guess_library;
1053 d = Name.rfind('/', c);
1054 if (d == Name.npos)
1055 Idx = 0;
1056 else
1057 Idx = d+1;
1058 F = Name.slice(Idx, Idx + Foo.size());
1059 DotFramework = Name.slice(Idx + Foo.size(),
1060 Idx + Foo.size() + sizeof(".framework/")-1);
1061 if (F == Foo && DotFramework == ".framework/") {
1062 isFramework = true;
1063 return Foo;
1064 }
1065
1066guess_library:
1067 // pull off the suffix after the "." and make a point to it
1068 a = Name.rfind('.');
1069 if (a == Name.npos || a == 0)
1070 return StringRef();
1071 Dylib = Name.slice(a, Name.npos);
1072 if (Dylib != ".dylib")
1073 goto guess_qtx;
1074
1075 // First pull off the version letter for the form Foo.A.dylib if any.
1076 if (a >= 3) {
1077 Dot = Name.slice(a-2, a-1);
1078 if (Dot == ".")
1079 a = a - 2;
1080 }
1081
1082 b = Name.rfind('/', a);
1083 if (b == Name.npos)
1084 b = 0;
1085 else
1086 b = b+1;
1087 // ignore any suffix after an underbar like Foo_profile.A.dylib
1088 Idx = Name.find('_', b);
1089 if (Idx != Name.npos && Idx != b) {
1090 Lib = Name.slice(b, Idx);
1091 Suffix = Name.slice(Idx, a);
1092 }
1093 else
1094 Lib = Name.slice(b, a);
1095 // There are incorrect library names of the form:
1096 // libATS.A_profile.dylib so check for these.
1097 if (Lib.size() >= 3) {
1098 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1099 if (Dot == ".")
1100 Lib = Lib.slice(0, Lib.size()-2);
1101 }
1102 return Lib;
1103
1104guess_qtx:
1105 Qtx = Name.slice(a, Name.npos);
1106 if (Qtx != ".qtx")
1107 return StringRef();
1108 b = Name.rfind('/', a);
1109 if (b == Name.npos)
1110 Lib = Name.slice(0, a);
1111 else
1112 Lib = Name.slice(b+1, a);
1113 // There are library names of the form: QT.A.qtx so check for these.
1114 if (Lib.size() >= 3) {
1115 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1116 if (Dot == ".")
1117 Lib = Lib.slice(0, Lib.size()-2);
1118 }
1119 return Lib;
1120}
1121
1122// getLibraryShortNameByIndex() is used to get the short name of the library
1123// for an undefined symbol in a linked Mach-O binary that was linked with the
1124// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1125// It is passed the index (0 - based) of the library as translated from
1126// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001127std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001128 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001129 if (Index >= Libraries.size())
1130 return object_error::parse_failed;
1131
Kevin Enderby980b2582014-06-05 21:21:57 +00001132 // If the cache of LibrariesShortNames is not built up do that first for
1133 // all the Libraries.
1134 if (LibrariesShortNames.size() == 0) {
1135 for (unsigned i = 0; i < Libraries.size(); i++) {
1136 MachO::dylib_command D =
1137 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001138 if (D.dylib.name >= D.cmdsize)
1139 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001140 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001141 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001142 if (D.dylib.name+Name.size() >= D.cmdsize)
1143 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001144 StringRef Suffix;
1145 bool isFramework;
1146 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001147 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001148 LibrariesShortNames.push_back(Name);
1149 else
1150 LibrariesShortNames.push_back(shortName);
1151 }
1152 }
1153
1154 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001155 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001156}
1157
Rafael Espindola76ad2322015-07-06 14:55:37 +00001158section_iterator
1159MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1160 DataRefImpl Sec;
1161 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1162 return section_iterator(SectionRef(Sec, this));
1163}
1164
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001165basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001166 DataRefImpl DRI;
1167 MachO::symtab_command Symtab = getSymtabLoadCommand();
1168 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1169 return basic_symbol_iterator(SymbolRef(DRI, this));
1170
Lang Hames36072da2014-05-12 21:39:59 +00001171 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001172}
1173
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001174basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001175 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001176 MachO::symtab_command Symtab = getSymtabLoadCommand();
1177 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001178 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001179
Rafael Espindola75c30362013-04-24 19:47:55 +00001180 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001181 sizeof(MachO::nlist_64) :
1182 sizeof(MachO::nlist);
1183 unsigned Offset = Symtab.symoff +
1184 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001185 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001186 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001187}
1188
Lang Hames36072da2014-05-12 21:39:59 +00001189basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001190 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001191 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001192 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001193 unsigned SymbolTableEntrySize =
1194 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001195 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001196 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1197 DRI.p += Index * SymbolTableEntrySize;
1198 return basic_symbol_iterator(SymbolRef(DRI, this));
1199}
1200
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001201uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
1202 MachO::symtab_command Symtab = getSymtabLoadCommand();
1203 if (!SymtabLoadCmd)
1204 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
1205 unsigned SymbolTableEntrySize =
1206 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1207 DataRefImpl DRIstart;
1208 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1209 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
1210 return Index;
1211}
1212
Rafael Espindolab5155a52014-02-10 20:24:04 +00001213section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001214 DataRefImpl DRI;
1215 return section_iterator(SectionRef(DRI, this));
1216}
1217
Rafael Espindolab5155a52014-02-10 20:24:04 +00001218section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001219 DataRefImpl DRI;
1220 DRI.d.a = Sections.size();
1221 return section_iterator(SectionRef(DRI, this));
1222}
1223
Rafael Espindola56f976f2013-04-18 18:08:55 +00001224uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001225 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001226}
1227
Rafael Espindola56f976f2013-04-18 18:08:55 +00001228StringRef MachOObjectFile::getFileFormatName() const {
1229 unsigned CPUType = getCPUType(this);
1230 if (!is64Bit()) {
1231 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001232 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001233 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001234 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001235 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001236 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001237 return "Mach-O 32-bit ppc";
1238 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001239 return "Mach-O 32-bit unknown";
1240 }
1241 }
1242
Rafael Espindola56f976f2013-04-18 18:08:55 +00001243 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001244 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001245 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001246 case llvm::MachO::CPU_TYPE_ARM64:
1247 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001248 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001249 return "Mach-O 64-bit ppc64";
1250 default:
1251 return "Mach-O 64-bit unknown";
1252 }
1253}
1254
Alexey Samsonove6388e62013-06-18 15:03:28 +00001255Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1256 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001257 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001258 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001259 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001260 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001261 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001262 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001263 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001264 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001265 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001266 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001267 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001268 return Triple::ppc64;
1269 default:
1270 return Triple::UnknownArch;
1271 }
1272}
1273
Tim Northover9e8eb412016-04-22 23:21:13 +00001274Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
1275 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001276 if (McpuDefault)
1277 *McpuDefault = nullptr;
1278
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001279 switch (CPUType) {
1280 case MachO::CPU_TYPE_I386:
1281 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1282 case MachO::CPU_SUBTYPE_I386_ALL:
1283 return Triple("i386-apple-darwin");
1284 default:
1285 return Triple();
1286 }
1287 case MachO::CPU_TYPE_X86_64:
1288 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1289 case MachO::CPU_SUBTYPE_X86_64_ALL:
1290 return Triple("x86_64-apple-darwin");
1291 case MachO::CPU_SUBTYPE_X86_64_H:
1292 return Triple("x86_64h-apple-darwin");
1293 default:
1294 return Triple();
1295 }
1296 case MachO::CPU_TYPE_ARM:
1297 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1298 case MachO::CPU_SUBTYPE_ARM_V4T:
1299 return Triple("armv4t-apple-darwin");
1300 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1301 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001302 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1303 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001304 case MachO::CPU_SUBTYPE_ARM_V6:
1305 return Triple("armv6-apple-darwin");
1306 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001307 if (McpuDefault)
1308 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001309 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001310 case MachO::CPU_SUBTYPE_ARM_V7:
1311 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001312 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001313 if (McpuDefault)
1314 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00001315 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001316 case MachO::CPU_SUBTYPE_ARM_V7K:
1317 return Triple("armv7k-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001319 if (McpuDefault)
1320 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00001321 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001322 case MachO::CPU_SUBTYPE_ARM_V7S:
1323 return Triple("armv7s-apple-darwin");
1324 default:
1325 return Triple();
1326 }
1327 case MachO::CPU_TYPE_ARM64:
1328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1329 case MachO::CPU_SUBTYPE_ARM64_ALL:
1330 return Triple("arm64-apple-darwin");
1331 default:
1332 return Triple();
1333 }
1334 case MachO::CPU_TYPE_POWERPC:
1335 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1336 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1337 return Triple("ppc-apple-darwin");
1338 default:
1339 return Triple();
1340 }
1341 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001342 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001343 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1344 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001345 default:
1346 return Triple();
1347 }
1348 default:
1349 return Triple();
1350 }
1351}
1352
1353Triple MachOObjectFile::getHostArch() {
1354 return Triple(sys::getDefaultTargetTriple());
1355}
1356
Rafael Espindola72318b42014-08-08 16:30:17 +00001357bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1358 return StringSwitch<bool>(ArchFlag)
1359 .Case("i386", true)
1360 .Case("x86_64", true)
1361 .Case("x86_64h", true)
1362 .Case("armv4t", true)
1363 .Case("arm", true)
1364 .Case("armv5e", true)
1365 .Case("armv6", true)
1366 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001367 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001368 .Case("armv7em", true)
1369 .Case("armv7k", true)
1370 .Case("armv7m", true)
1371 .Case("armv7s", true)
1372 .Case("arm64", true)
1373 .Case("ppc", true)
1374 .Case("ppc64", true)
1375 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001376}
1377
Alexey Samsonove6388e62013-06-18 15:03:28 +00001378unsigned MachOObjectFile::getArch() const {
1379 return getArch(getCPUType(this));
1380}
1381
Tim Northover9e8eb412016-04-22 23:21:13 +00001382Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
1383 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001384}
1385
Rui Ueyamabc654b12013-09-27 21:47:05 +00001386relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001387 DataRefImpl DRI;
1388 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001389 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001390}
1391
Rui Ueyamabc654b12013-09-27 21:47:05 +00001392relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001393 DataRefImpl DRI;
1394 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001395 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001396}
1397
Kevin Enderby273ae012013-06-06 17:20:50 +00001398dice_iterator MachOObjectFile::begin_dices() const {
1399 DataRefImpl DRI;
1400 if (!DataInCodeLoadCmd)
1401 return dice_iterator(DiceRef(DRI, this));
1402
Charles Davis8bdfafd2013-09-01 04:28:48 +00001403 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1404 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001405 return dice_iterator(DiceRef(DRI, this));
1406}
1407
1408dice_iterator MachOObjectFile::end_dices() const {
1409 DataRefImpl DRI;
1410 if (!DataInCodeLoadCmd)
1411 return dice_iterator(DiceRef(DRI, this));
1412
Charles Davis8bdfafd2013-09-01 04:28:48 +00001413 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1414 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001415 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1416 return dice_iterator(DiceRef(DRI, this));
1417}
1418
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001419ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1420 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001421
1422void ExportEntry::moveToFirst() {
1423 pushNode(0);
1424 pushDownUntilBottom();
1425}
1426
1427void ExportEntry::moveToEnd() {
1428 Stack.clear();
1429 Done = true;
1430}
1431
1432bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001433 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001434 if (Done || Other.Done)
1435 return (Done == Other.Done);
1436 // Not equal if different stack sizes.
1437 if (Stack.size() != Other.Stack.size())
1438 return false;
1439 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001440 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001441 return false;
1442 // Equal if all nodes in both stacks match.
1443 for (unsigned i=0; i < Stack.size(); ++i) {
1444 if (Stack[i].Start != Other.Stack[i].Start)
1445 return false;
1446 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001447 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001448}
1449
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001450uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1451 unsigned Count;
1452 uint64_t Result = decodeULEB128(Ptr, &Count);
1453 Ptr += Count;
1454 if (Ptr > Trie.end()) {
1455 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001456 Malformed = true;
1457 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001458 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001459}
1460
1461StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001462 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001463}
1464
1465uint64_t ExportEntry::flags() const {
1466 return Stack.back().Flags;
1467}
1468
1469uint64_t ExportEntry::address() const {
1470 return Stack.back().Address;
1471}
1472
1473uint64_t ExportEntry::other() const {
1474 return Stack.back().Other;
1475}
1476
1477StringRef ExportEntry::otherName() const {
1478 const char* ImportName = Stack.back().ImportName;
1479 if (ImportName)
1480 return StringRef(ImportName);
1481 return StringRef();
1482}
1483
1484uint32_t ExportEntry::nodeOffset() const {
1485 return Stack.back().Start - Trie.begin();
1486}
1487
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001488ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1489 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1490 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1491 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001492
1493void ExportEntry::pushNode(uint64_t offset) {
1494 const uint8_t *Ptr = Trie.begin() + offset;
1495 NodeState State(Ptr);
1496 uint64_t ExportInfoSize = readULEB128(State.Current);
1497 State.IsExportNode = (ExportInfoSize != 0);
1498 const uint8_t* Children = State.Current + ExportInfoSize;
1499 if (State.IsExportNode) {
1500 State.Flags = readULEB128(State.Current);
1501 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1502 State.Address = 0;
1503 State.Other = readULEB128(State.Current); // dylib ordinal
1504 State.ImportName = reinterpret_cast<const char*>(State.Current);
1505 } else {
1506 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001507 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001508 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001509 }
1510 }
1511 State.ChildCount = *Children;
1512 State.Current = Children + 1;
1513 State.NextChildIndex = 0;
1514 State.ParentStringLength = CumulativeString.size();
1515 Stack.push_back(State);
1516}
1517
1518void ExportEntry::pushDownUntilBottom() {
1519 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1520 NodeState &Top = Stack.back();
1521 CumulativeString.resize(Top.ParentStringLength);
1522 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001523 char C = *Top.Current;
1524 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001525 }
1526 Top.Current += 1;
1527 uint64_t childNodeIndex = readULEB128(Top.Current);
1528 Top.NextChildIndex += 1;
1529 pushNode(childNodeIndex);
1530 }
1531 if (!Stack.back().IsExportNode) {
1532 Malformed = true;
1533 moveToEnd();
1534 }
1535}
1536
1537// We have a trie data structure and need a way to walk it that is compatible
1538// with the C++ iterator model. The solution is a non-recursive depth first
1539// traversal where the iterator contains a stack of parent nodes along with a
1540// string that is the accumulation of all edge strings along the parent chain
1541// to this point.
1542//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001543// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001544// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001545// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001546//
1547// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1548// child until hitting a node with no children (which is an export node or
1549// else the trie is malformed). On the way down, each node is pushed on the
1550// stack ivar. If there is no more ways down, it pops up one and tries to go
1551// down a sibling path until a childless node is reached.
1552void ExportEntry::moveNext() {
1553 if (Stack.empty() || !Stack.back().IsExportNode) {
1554 Malformed = true;
1555 moveToEnd();
1556 return;
1557 }
1558
1559 Stack.pop_back();
1560 while (!Stack.empty()) {
1561 NodeState &Top = Stack.back();
1562 if (Top.NextChildIndex < Top.ChildCount) {
1563 pushDownUntilBottom();
1564 // Now at the next export node.
1565 return;
1566 } else {
1567 if (Top.IsExportNode) {
1568 // This node has no children but is itself an export node.
1569 CumulativeString.resize(Top.ParentStringLength);
1570 return;
1571 }
1572 Stack.pop_back();
1573 }
1574 }
1575 Done = true;
1576}
1577
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001578iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001579MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1580 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001581 if (Trie.size() == 0)
1582 Start.moveToEnd();
1583 else
1584 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001585
1586 ExportEntry Finish(Trie);
1587 Finish.moveToEnd();
1588
Craig Topper15576e12015-12-06 05:08:07 +00001589 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001590}
1591
1592iterator_range<export_iterator> MachOObjectFile::exports() const {
1593 return exports(getDyldInfoExportsTrie());
1594}
1595
Nick Kledzikac431442014-09-12 21:34:15 +00001596MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1597 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1598 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1599 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1600
1601void MachORebaseEntry::moveToFirst() {
1602 Ptr = Opcodes.begin();
1603 moveNext();
1604}
1605
1606void MachORebaseEntry::moveToEnd() {
1607 Ptr = Opcodes.end();
1608 RemainingLoopCount = 0;
1609 Done = true;
1610}
1611
1612void MachORebaseEntry::moveNext() {
1613 // If in the middle of some loop, move to next rebasing in loop.
1614 SegmentOffset += AdvanceAmount;
1615 if (RemainingLoopCount) {
1616 --RemainingLoopCount;
1617 return;
1618 }
1619 if (Ptr == Opcodes.end()) {
1620 Done = true;
1621 return;
1622 }
1623 bool More = true;
1624 while (More && !Malformed) {
1625 // Parse next opcode and set up next loop.
1626 uint8_t Byte = *Ptr++;
1627 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1628 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1629 switch (Opcode) {
1630 case MachO::REBASE_OPCODE_DONE:
1631 More = false;
1632 Done = true;
1633 moveToEnd();
1634 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1635 break;
1636 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1637 RebaseType = ImmValue;
1638 DEBUG_WITH_TYPE(
1639 "mach-o-rebase",
1640 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1641 << "RebaseType=" << (int) RebaseType << "\n");
1642 break;
1643 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1644 SegmentIndex = ImmValue;
1645 SegmentOffset = readULEB128();
1646 DEBUG_WITH_TYPE(
1647 "mach-o-rebase",
1648 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1649 << "SegmentIndex=" << SegmentIndex << ", "
1650 << format("SegmentOffset=0x%06X", SegmentOffset)
1651 << "\n");
1652 break;
1653 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1654 SegmentOffset += readULEB128();
1655 DEBUG_WITH_TYPE("mach-o-rebase",
1656 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1657 << format("SegmentOffset=0x%06X",
1658 SegmentOffset) << "\n");
1659 break;
1660 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1661 SegmentOffset += ImmValue * PointerSize;
1662 DEBUG_WITH_TYPE("mach-o-rebase",
1663 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1664 << format("SegmentOffset=0x%06X",
1665 SegmentOffset) << "\n");
1666 break;
1667 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1668 AdvanceAmount = PointerSize;
1669 RemainingLoopCount = ImmValue - 1;
1670 DEBUG_WITH_TYPE(
1671 "mach-o-rebase",
1672 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1673 << format("SegmentOffset=0x%06X", SegmentOffset)
1674 << ", AdvanceAmount=" << AdvanceAmount
1675 << ", RemainingLoopCount=" << RemainingLoopCount
1676 << "\n");
1677 return;
1678 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1679 AdvanceAmount = PointerSize;
1680 RemainingLoopCount = readULEB128() - 1;
1681 DEBUG_WITH_TYPE(
1682 "mach-o-rebase",
1683 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1684 << format("SegmentOffset=0x%06X", SegmentOffset)
1685 << ", AdvanceAmount=" << AdvanceAmount
1686 << ", RemainingLoopCount=" << RemainingLoopCount
1687 << "\n");
1688 return;
1689 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1690 AdvanceAmount = readULEB128() + PointerSize;
1691 RemainingLoopCount = 0;
1692 DEBUG_WITH_TYPE(
1693 "mach-o-rebase",
1694 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1695 << format("SegmentOffset=0x%06X", SegmentOffset)
1696 << ", AdvanceAmount=" << AdvanceAmount
1697 << ", RemainingLoopCount=" << RemainingLoopCount
1698 << "\n");
1699 return;
1700 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1701 RemainingLoopCount = readULEB128() - 1;
1702 AdvanceAmount = readULEB128() + PointerSize;
1703 DEBUG_WITH_TYPE(
1704 "mach-o-rebase",
1705 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1706 << format("SegmentOffset=0x%06X", SegmentOffset)
1707 << ", AdvanceAmount=" << AdvanceAmount
1708 << ", RemainingLoopCount=" << RemainingLoopCount
1709 << "\n");
1710 return;
1711 default:
1712 Malformed = true;
1713 }
1714 }
1715}
1716
1717uint64_t MachORebaseEntry::readULEB128() {
1718 unsigned Count;
1719 uint64_t Result = decodeULEB128(Ptr, &Count);
1720 Ptr += Count;
1721 if (Ptr > Opcodes.end()) {
1722 Ptr = Opcodes.end();
1723 Malformed = true;
1724 }
1725 return Result;
1726}
1727
1728uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1729
1730uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1731
1732StringRef MachORebaseEntry::typeName() const {
1733 switch (RebaseType) {
1734 case MachO::REBASE_TYPE_POINTER:
1735 return "pointer";
1736 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1737 return "text abs32";
1738 case MachO::REBASE_TYPE_TEXT_PCREL32:
1739 return "text rel32";
1740 }
1741 return "unknown";
1742}
1743
1744bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1745 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1746 return (Ptr == Other.Ptr) &&
1747 (RemainingLoopCount == Other.RemainingLoopCount) &&
1748 (Done == Other.Done);
1749}
1750
1751iterator_range<rebase_iterator>
1752MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1753 MachORebaseEntry Start(Opcodes, is64);
1754 Start.moveToFirst();
1755
1756 MachORebaseEntry Finish(Opcodes, is64);
1757 Finish.moveToEnd();
1758
Craig Topper15576e12015-12-06 05:08:07 +00001759 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001760}
1761
1762iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1763 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1764}
1765
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001766MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001767 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1768 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1769 BindType(0), PointerSize(is64Bit ? 8 : 4),
1770 TableKind(BK), Malformed(false), Done(false) {}
1771
1772void MachOBindEntry::moveToFirst() {
1773 Ptr = Opcodes.begin();
1774 moveNext();
1775}
1776
1777void MachOBindEntry::moveToEnd() {
1778 Ptr = Opcodes.end();
1779 RemainingLoopCount = 0;
1780 Done = true;
1781}
1782
1783void MachOBindEntry::moveNext() {
1784 // If in the middle of some loop, move to next binding in loop.
1785 SegmentOffset += AdvanceAmount;
1786 if (RemainingLoopCount) {
1787 --RemainingLoopCount;
1788 return;
1789 }
1790 if (Ptr == Opcodes.end()) {
1791 Done = true;
1792 return;
1793 }
1794 bool More = true;
1795 while (More && !Malformed) {
1796 // Parse next opcode and set up next loop.
1797 uint8_t Byte = *Ptr++;
1798 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1799 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1800 int8_t SignExtended;
1801 const uint8_t *SymStart;
1802 switch (Opcode) {
1803 case MachO::BIND_OPCODE_DONE:
1804 if (TableKind == Kind::Lazy) {
1805 // Lazying bindings have a DONE opcode between entries. Need to ignore
1806 // it to advance to next entry. But need not if this is last entry.
1807 bool NotLastEntry = false;
1808 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1809 if (*P) {
1810 NotLastEntry = true;
1811 }
1812 }
1813 if (NotLastEntry)
1814 break;
1815 }
1816 More = false;
1817 Done = true;
1818 moveToEnd();
1819 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1820 break;
1821 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1822 Ordinal = ImmValue;
1823 DEBUG_WITH_TYPE(
1824 "mach-o-bind",
1825 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1826 << "Ordinal=" << Ordinal << "\n");
1827 break;
1828 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1829 Ordinal = readULEB128();
1830 DEBUG_WITH_TYPE(
1831 "mach-o-bind",
1832 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1833 << "Ordinal=" << Ordinal << "\n");
1834 break;
1835 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1836 if (ImmValue) {
1837 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1838 Ordinal = SignExtended;
1839 } else
1840 Ordinal = 0;
1841 DEBUG_WITH_TYPE(
1842 "mach-o-bind",
1843 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1844 << "Ordinal=" << Ordinal << "\n");
1845 break;
1846 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1847 Flags = ImmValue;
1848 SymStart = Ptr;
1849 while (*Ptr) {
1850 ++Ptr;
1851 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001852 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1853 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001854 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001855 DEBUG_WITH_TYPE(
1856 "mach-o-bind",
1857 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1858 << "SymbolName=" << SymbolName << "\n");
1859 if (TableKind == Kind::Weak) {
1860 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1861 return;
1862 }
1863 break;
1864 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1865 BindType = ImmValue;
1866 DEBUG_WITH_TYPE(
1867 "mach-o-bind",
1868 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1869 << "BindType=" << (int)BindType << "\n");
1870 break;
1871 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1872 Addend = readSLEB128();
1873 if (TableKind == Kind::Lazy)
1874 Malformed = true;
1875 DEBUG_WITH_TYPE(
1876 "mach-o-bind",
1877 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1878 << "Addend=" << Addend << "\n");
1879 break;
1880 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1881 SegmentIndex = ImmValue;
1882 SegmentOffset = readULEB128();
1883 DEBUG_WITH_TYPE(
1884 "mach-o-bind",
1885 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1886 << "SegmentIndex=" << SegmentIndex << ", "
1887 << format("SegmentOffset=0x%06X", SegmentOffset)
1888 << "\n");
1889 break;
1890 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1891 SegmentOffset += readULEB128();
1892 DEBUG_WITH_TYPE("mach-o-bind",
1893 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1894 << format("SegmentOffset=0x%06X",
1895 SegmentOffset) << "\n");
1896 break;
1897 case MachO::BIND_OPCODE_DO_BIND:
1898 AdvanceAmount = PointerSize;
1899 RemainingLoopCount = 0;
1900 DEBUG_WITH_TYPE("mach-o-bind",
1901 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1902 << format("SegmentOffset=0x%06X",
1903 SegmentOffset) << "\n");
1904 return;
1905 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001906 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001907 RemainingLoopCount = 0;
1908 if (TableKind == Kind::Lazy)
1909 Malformed = true;
1910 DEBUG_WITH_TYPE(
1911 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001912 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001913 << format("SegmentOffset=0x%06X", SegmentOffset)
1914 << ", AdvanceAmount=" << AdvanceAmount
1915 << ", RemainingLoopCount=" << RemainingLoopCount
1916 << "\n");
1917 return;
1918 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001919 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001920 RemainingLoopCount = 0;
1921 if (TableKind == Kind::Lazy)
1922 Malformed = true;
1923 DEBUG_WITH_TYPE("mach-o-bind",
1924 llvm::dbgs()
1925 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1926 << format("SegmentOffset=0x%06X",
1927 SegmentOffset) << "\n");
1928 return;
1929 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1930 RemainingLoopCount = readULEB128() - 1;
1931 AdvanceAmount = readULEB128() + PointerSize;
1932 if (TableKind == Kind::Lazy)
1933 Malformed = true;
1934 DEBUG_WITH_TYPE(
1935 "mach-o-bind",
1936 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1937 << format("SegmentOffset=0x%06X", SegmentOffset)
1938 << ", AdvanceAmount=" << AdvanceAmount
1939 << ", RemainingLoopCount=" << RemainingLoopCount
1940 << "\n");
1941 return;
1942 default:
1943 Malformed = true;
1944 }
1945 }
1946}
1947
1948uint64_t MachOBindEntry::readULEB128() {
1949 unsigned Count;
1950 uint64_t Result = decodeULEB128(Ptr, &Count);
1951 Ptr += Count;
1952 if (Ptr > Opcodes.end()) {
1953 Ptr = Opcodes.end();
1954 Malformed = true;
1955 }
1956 return Result;
1957}
1958
1959int64_t MachOBindEntry::readSLEB128() {
1960 unsigned Count;
1961 int64_t Result = decodeSLEB128(Ptr, &Count);
1962 Ptr += Count;
1963 if (Ptr > Opcodes.end()) {
1964 Ptr = Opcodes.end();
1965 Malformed = true;
1966 }
1967 return Result;
1968}
1969
Nick Kledzik56ebef42014-09-16 01:41:51 +00001970uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1971
1972uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1973
1974StringRef MachOBindEntry::typeName() const {
1975 switch (BindType) {
1976 case MachO::BIND_TYPE_POINTER:
1977 return "pointer";
1978 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1979 return "text abs32";
1980 case MachO::BIND_TYPE_TEXT_PCREL32:
1981 return "text rel32";
1982 }
1983 return "unknown";
1984}
1985
1986StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1987
1988int64_t MachOBindEntry::addend() const { return Addend; }
1989
1990uint32_t MachOBindEntry::flags() const { return Flags; }
1991
1992int MachOBindEntry::ordinal() const { return Ordinal; }
1993
1994bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1995 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1996 return (Ptr == Other.Ptr) &&
1997 (RemainingLoopCount == Other.RemainingLoopCount) &&
1998 (Done == Other.Done);
1999}
2000
2001iterator_range<bind_iterator>
2002MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2003 MachOBindEntry::Kind BKind) {
2004 MachOBindEntry Start(Opcodes, is64, BKind);
2005 Start.moveToFirst();
2006
2007 MachOBindEntry Finish(Opcodes, is64, BKind);
2008 Finish.moveToEnd();
2009
Craig Topper15576e12015-12-06 05:08:07 +00002010 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00002011}
2012
2013iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2014 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2015 MachOBindEntry::Kind::Regular);
2016}
2017
2018iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2019 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2020 MachOBindEntry::Kind::Lazy);
2021}
2022
2023iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2024 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2025 MachOBindEntry::Kind::Weak);
2026}
2027
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00002028MachOObjectFile::load_command_iterator
2029MachOObjectFile::begin_load_commands() const {
2030 return LoadCommands.begin();
2031}
2032
2033MachOObjectFile::load_command_iterator
2034MachOObjectFile::end_load_commands() const {
2035 return LoadCommands.end();
2036}
2037
2038iterator_range<MachOObjectFile::load_command_iterator>
2039MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00002040 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00002041}
2042
Rafael Espindola56f976f2013-04-18 18:08:55 +00002043StringRef
2044MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2045 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2046 return parseSegmentOrSectionName(Raw.data());
2047}
2048
2049ArrayRef<char>
2050MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002051 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002052 const section_base *Base =
2053 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002054 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002055}
2056
2057ArrayRef<char>
2058MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002059 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002060 const section_base *Base =
2061 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002062 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002063}
2064
2065bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002066MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002067 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002068 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002069 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002070 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002071}
2072
Eric Christopher1d62c252013-07-22 22:25:07 +00002073unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002074 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002075 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002076 return RE.r_word1 & 0xffffff;
2077 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002078}
2079
Eric Christopher1d62c252013-07-22 22:25:07 +00002080bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002081 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002082 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002083 return (RE.r_word1 >> 27) & 1;
2084 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002085}
2086
Eric Christopher1d62c252013-07-22 22:25:07 +00002087bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002088 const MachO::any_relocation_info &RE) const {
2089 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002090}
2091
Eric Christopher1d62c252013-07-22 22:25:07 +00002092uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002093 const MachO::any_relocation_info &RE) const {
2094 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002095}
2096
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002097uint32_t MachOObjectFile::getScatteredRelocationType(
2098 const MachO::any_relocation_info &RE) const {
2099 return (RE.r_word0 >> 24) & 0xf;
2100}
2101
Eric Christopher1d62c252013-07-22 22:25:07 +00002102unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002103 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002104 if (isRelocationScattered(RE))
2105 return getScatteredRelocationAddress(RE);
2106 return getPlainRelocationAddress(RE);
2107}
2108
Charles Davis8bdfafd2013-09-01 04:28:48 +00002109unsigned MachOObjectFile::getAnyRelocationPCRel(
2110 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002111 if (isRelocationScattered(RE))
2112 return getScatteredRelocationPCRel(this, RE);
2113 return getPlainRelocationPCRel(this, RE);
2114}
2115
Eric Christopher1d62c252013-07-22 22:25:07 +00002116unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002117 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002118 if (isRelocationScattered(RE))
2119 return getScatteredRelocationLength(RE);
2120 return getPlainRelocationLength(this, RE);
2121}
2122
2123unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002124MachOObjectFile::getAnyRelocationType(
2125 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002126 if (isRelocationScattered(RE))
2127 return getScatteredRelocationType(RE);
2128 return getPlainRelocationType(this, RE);
2129}
2130
Rafael Espindola52501032013-04-30 15:40:54 +00002131SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002132MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002133 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002134 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002135 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002136 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2137 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2138 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002139 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002140 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002141 return SectionRef(DRI, this);
2142}
2143
Charles Davis8bdfafd2013-09-01 04:28:48 +00002144MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002145 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002146 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002147}
2148
Charles Davis8bdfafd2013-09-01 04:28:48 +00002149MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002150 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002151 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002152}
2153
Charles Davis8bdfafd2013-09-01 04:28:48 +00002154MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002155 unsigned Index) const {
2156 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002157 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002158}
2159
Charles Davis8bdfafd2013-09-01 04:28:48 +00002160MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2161 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002162 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002163 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002164}
2165
Charles Davis8bdfafd2013-09-01 04:28:48 +00002166MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002167MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002168 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002169 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002170}
2171
Charles Davis8bdfafd2013-09-01 04:28:48 +00002172MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002173MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002174 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002175 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002176}
2177
Charles Davis8bdfafd2013-09-01 04:28:48 +00002178MachO::linkedit_data_command
2179MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2180 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002181}
2182
Charles Davis8bdfafd2013-09-01 04:28:48 +00002183MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002184MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002185 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002186}
2187
Charles Davis8bdfafd2013-09-01 04:28:48 +00002188MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002189MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002190 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002191}
2192
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002193MachO::linker_option_command
2194MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2195 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002196}
2197
Jim Grosbach448334a2014-03-18 22:09:05 +00002198MachO::version_min_command
2199MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2200 return getStruct<MachO::version_min_command>(this, L.Ptr);
2201}
2202
Tim Northover8f9590b2014-06-30 14:40:57 +00002203MachO::dylib_command
2204MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2205 return getStruct<MachO::dylib_command>(this, L.Ptr);
2206}
2207
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002208MachO::dyld_info_command
2209MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2210 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2211}
2212
2213MachO::dylinker_command
2214MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2215 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2216}
2217
2218MachO::uuid_command
2219MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2220 return getStruct<MachO::uuid_command>(this, L.Ptr);
2221}
2222
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002223MachO::rpath_command
2224MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2225 return getStruct<MachO::rpath_command>(this, L.Ptr);
2226}
2227
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002228MachO::source_version_command
2229MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2230 return getStruct<MachO::source_version_command>(this, L.Ptr);
2231}
2232
2233MachO::entry_point_command
2234MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2235 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2236}
2237
Kevin Enderby0804f4672014-12-16 23:25:52 +00002238MachO::encryption_info_command
2239MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2240 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2241}
2242
Kevin Enderby57538292014-12-17 01:01:30 +00002243MachO::encryption_info_command_64
2244MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2245 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2246}
2247
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002248MachO::sub_framework_command
2249MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2250 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2251}
Tim Northover8f9590b2014-06-30 14:40:57 +00002252
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002253MachO::sub_umbrella_command
2254MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2255 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2256}
2257
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002258MachO::sub_library_command
2259MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2260 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2261}
2262
Kevin Enderby186eac32014-12-19 21:06:24 +00002263MachO::sub_client_command
2264MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2265 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2266}
2267
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002268MachO::routines_command
2269MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2270 return getStruct<MachO::routines_command>(this, L.Ptr);
2271}
2272
2273MachO::routines_command_64
2274MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2275 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2276}
2277
Kevin Enderby48ef5342014-12-23 22:56:39 +00002278MachO::thread_command
2279MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2280 return getStruct<MachO::thread_command>(this, L.Ptr);
2281}
2282
Charles Davis8bdfafd2013-09-01 04:28:48 +00002283MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002284MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002285 DataRefImpl Sec;
2286 Sec.d.a = Rel.d.a;
2287 uint32_t Offset;
2288 if (is64Bit()) {
2289 MachO::section_64 Sect = getSection64(Sec);
2290 Offset = Sect.reloff;
2291 } else {
2292 MachO::section Sect = getSection(Sec);
2293 Offset = Sect.reloff;
2294 }
2295
2296 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2297 getPtr(this, Offset)) + Rel.d.b;
2298 return getStruct<MachO::any_relocation_info>(
2299 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002300}
2301
Charles Davis8bdfafd2013-09-01 04:28:48 +00002302MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002303MachOObjectFile::getDice(DataRefImpl Rel) const {
2304 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002305 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002306}
2307
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002308const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002309 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002310}
2311
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002312const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2313 assert(is64Bit());
2314 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002315}
2316
Charles Davis8bdfafd2013-09-01 04:28:48 +00002317uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2318 const MachO::dysymtab_command &DLC,
2319 unsigned Index) const {
2320 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2321 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002322}
2323
Charles Davis8bdfafd2013-09-01 04:28:48 +00002324MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002325MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2326 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002327 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2328 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002329}
2330
Charles Davis8bdfafd2013-09-01 04:28:48 +00002331MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002332 if (SymtabLoadCmd)
2333 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2334
2335 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2336 MachO::symtab_command Cmd;
2337 Cmd.cmd = MachO::LC_SYMTAB;
2338 Cmd.cmdsize = sizeof(MachO::symtab_command);
2339 Cmd.symoff = 0;
2340 Cmd.nsyms = 0;
2341 Cmd.stroff = 0;
2342 Cmd.strsize = 0;
2343 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002344}
2345
Charles Davis8bdfafd2013-09-01 04:28:48 +00002346MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002347 if (DysymtabLoadCmd)
2348 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2349
2350 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2351 MachO::dysymtab_command Cmd;
2352 Cmd.cmd = MachO::LC_DYSYMTAB;
2353 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2354 Cmd.ilocalsym = 0;
2355 Cmd.nlocalsym = 0;
2356 Cmd.iextdefsym = 0;
2357 Cmd.nextdefsym = 0;
2358 Cmd.iundefsym = 0;
2359 Cmd.nundefsym = 0;
2360 Cmd.tocoff = 0;
2361 Cmd.ntoc = 0;
2362 Cmd.modtaboff = 0;
2363 Cmd.nmodtab = 0;
2364 Cmd.extrefsymoff = 0;
2365 Cmd.nextrefsyms = 0;
2366 Cmd.indirectsymoff = 0;
2367 Cmd.nindirectsyms = 0;
2368 Cmd.extreloff = 0;
2369 Cmd.nextrel = 0;
2370 Cmd.locreloff = 0;
2371 Cmd.nlocrel = 0;
2372 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002373}
2374
Charles Davis8bdfafd2013-09-01 04:28:48 +00002375MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002376MachOObjectFile::getDataInCodeLoadCommand() const {
2377 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002378 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002379
2380 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002381 MachO::linkedit_data_command Cmd;
2382 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2383 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2384 Cmd.dataoff = 0;
2385 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002386 return Cmd;
2387}
2388
Kevin Enderby9a509442015-01-27 21:28:24 +00002389MachO::linkedit_data_command
2390MachOObjectFile::getLinkOptHintsLoadCommand() const {
2391 if (LinkOptHintsLoadCmd)
2392 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2393
2394 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2395 // fields.
2396 MachO::linkedit_data_command Cmd;
2397 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2398 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2399 Cmd.dataoff = 0;
2400 Cmd.datasize = 0;
2401 return Cmd;
2402}
2403
Nick Kledzikd04bc352014-08-30 00:20:14 +00002404ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002405 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002406 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002407
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002408 MachO::dyld_info_command DyldInfo =
2409 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2410 const uint8_t *Ptr =
2411 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002412 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002413}
2414
2415ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002416 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002417 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002418
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002419 MachO::dyld_info_command DyldInfo =
2420 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2421 const uint8_t *Ptr =
2422 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002423 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002424}
2425
2426ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002427 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002428 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002429
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002430 MachO::dyld_info_command DyldInfo =
2431 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2432 const uint8_t *Ptr =
2433 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002434 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002435}
2436
2437ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002438 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002439 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002440
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002441 MachO::dyld_info_command DyldInfo =
2442 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2443 const uint8_t *Ptr =
2444 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002445 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002446}
2447
2448ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002449 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002450 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002451
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002452 MachO::dyld_info_command DyldInfo =
2453 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2454 const uint8_t *Ptr =
2455 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002456 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002457}
2458
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002459ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2460 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002461 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002462 // Returning a pointer is fine as uuid doesn't need endian swapping.
2463 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002464 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002465}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002466
Rafael Espindola6e040c02013-04-26 20:07:33 +00002467StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002468 MachO::symtab_command S = getSymtabLoadCommand();
2469 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002470}
2471
Rafael Espindola56f976f2013-04-18 18:08:55 +00002472bool MachOObjectFile::is64Bit() const {
2473 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002474 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002475}
2476
2477void MachOObjectFile::ReadULEB128s(uint64_t Index,
2478 SmallVectorImpl<uint64_t> &Out) const {
2479 DataExtractor extractor(ObjectFile::getData(), true, 0);
2480
2481 uint32_t offset = Index;
2482 uint64_t data = 0;
2483 while (uint64_t delta = extractor.getULEB128(&offset)) {
2484 data += delta;
2485 Out.push_back(data);
2486 }
2487}
2488
Rafael Espindolac66d7612014-08-17 19:09:37 +00002489bool MachOObjectFile::isRelocatableObject() const {
2490 return getHeader().filetype == MachO::MH_OBJECT;
2491}
2492
Lang Hamesff044b12016-03-25 23:11:52 +00002493Expected<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002494ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2495 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00002496 if (Magic == "\xFE\xED\xFA\xCE")
Lang Hamesff044b12016-03-25 23:11:52 +00002497 return MachOObjectFile::create(Buffer, false, false);
David Blaikieb805f732016-03-28 17:45:48 +00002498 if (Magic == "\xCE\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002499 return MachOObjectFile::create(Buffer, true, false);
David Blaikieb805f732016-03-28 17:45:48 +00002500 if (Magic == "\xFE\xED\xFA\xCF")
Lang Hamesff044b12016-03-25 23:11:52 +00002501 return MachOObjectFile::create(Buffer, false, true);
David Blaikieb805f732016-03-28 17:45:48 +00002502 if (Magic == "\xCF\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002503 return MachOObjectFile::create(Buffer, true, true);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00002504 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00002505 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002506}