blob: 863081fbd4ce6e8de4a69d08c7c9cc9617a8b7b3 [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.
222template <typename SegmentCmd>
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,
226 uint32_t LoadCommandIndex, const char *CmdName) {
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000227 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
228 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");
Lang Hames9e964f32016-03-25 17:25:34 +0000231 if (auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr)) {
232 SegmentCmd S = SegOrErr.get();
233 const unsigned SectionSize =
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000234 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
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) +
Kevin Enderby89134962016-05-05 23:41:05 +0000238 " inconsistent cmdsize in " + CmdName +
239 " 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);
243 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000244 uint64_t FileSize = Obj->getData().size();
245 if (S.fileoff > FileSize)
246 return malformedError("load command " + Twine(LoadCommandIndex) +
247 " fileoff field in " + CmdName +
248 " extends past the end of the file");
Lang Hames9e964f32016-03-25 17:25:34 +0000249 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
250 } else
251 return SegOrErr.takeError();
252
253 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000254}
255
Lang Hames82627642016-03-25 21:59:14 +0000256Expected<std::unique_ptr<MachOObjectFile>>
257MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
258 bool Is64Bits) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000259 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000260 std::unique_ptr<MachOObjectFile> Obj(
261 new MachOObjectFile(std::move(Object), IsLittleEndian,
262 Is64Bits, Err));
263 if (Err)
264 return std::move(Err);
265 return std::move(Obj);
266}
267
Rafael Espindola48af1c22014-08-19 18:44:46 +0000268MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Lang Hames9e964f32016-03-25 17:25:34 +0000269 bool Is64bits, Error &Err)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000270 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000271 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000272 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
273 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
274 HasPageZeroSegment(false) {
Lang Hames5e51a2e2016-07-22 16:11:25 +0000275 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000276 uint64_t BigSize;
Kevin Enderby87025742016-04-13 21:17:58 +0000277 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +0000278 parseHeader(this, Header64, Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000279 BigSize = sizeof(MachO::mach_header_64);
Kevin Enderby87025742016-04-13 21:17:58 +0000280 } else {
Lang Hames9e964f32016-03-25 17:25:34 +0000281 parseHeader(this, Header, Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000282 BigSize = sizeof(MachO::mach_header);
Kevin Enderby87025742016-04-13 21:17:58 +0000283 }
Lang Hames9e964f32016-03-25 17:25:34 +0000284 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000285 return;
Kevin Enderby5e55d172016-04-21 20:29:49 +0000286 BigSize += getHeader().sizeofcmds;
287 if (getData().data() + BigSize > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000288 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +0000289 return;
290 }
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000291
292 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000293 if (LoadCommandCount == 0)
294 return;
295
Lang Hames9e964f32016-03-25 17:25:34 +0000296 LoadCommandInfo Load;
297 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
298 Load = *LoadOrErr;
299 else {
300 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000301 return;
302 }
Lang Hames9e964f32016-03-25 17:25:34 +0000303
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000304 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +0000305 if (is64Bit()) {
306 if (Load.C.cmdsize % 8 != 0) {
307 // We have a hack here to allow 64-bit Mach-O core files to have
308 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
309 // allowed since the macOS kernel produces them.
310 if (getHeader().filetype != MachO::MH_CORE ||
311 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
312 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
313 "multiple of 8");
314 return;
315 }
316 }
317 } else {
318 if (Load.C.cmdsize % 4 != 0) {
319 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
320 "multiple of 4");
321 return;
322 }
323 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000324 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000325 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000326 // Multiple symbol tables
327 if (SymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000328 Err = malformedError("Multiple symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000329 return;
330 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000331 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000332 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000333 // Multiple dynamic symbol tables
334 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000335 Err = malformedError("Multiple dynamic symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000336 return;
337 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000338 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000339 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000340 // Multiple data in code tables
341 if (DataInCodeLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000342 Err = malformedError("Multiple data-in-code tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000343 return;
344 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000345 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000346 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
347 // Multiple linker optimization hint tables
348 if (LinkOptHintsLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000349 Err = malformedError("Multiple linker optimization hint tables");
Kevin Enderby9a509442015-01-27 21:28:24 +0000350 return;
351 }
352 LinkOptHintsLoadCmd = Load.Ptr;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000353 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000354 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000355 // Multiple dyldinfo load commands
356 if (DyldInfoLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000357 Err = malformedError("Multiple dyldinfo load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000358 return;
359 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000360 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000361 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000362 // Multiple UUID load commands
363 if (UuidLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000364 Err = malformedError("Multiple UUID load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000365 return;
366 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000367 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000368 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Lang Hames9e964f32016-03-25 17:25:34 +0000369 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000370 this, Load, Sections, HasPageZeroSegment, I,
371 "LC_SEGMENT_64")))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000372 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000373 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Lang Hames9e964f32016-03-25 17:25:34 +0000374 if ((Err = parseSegmentLoadCommand<MachO::segment_command>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000375 this, Load, Sections, HasPageZeroSegment, I, "LC_SEGMENT")))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000376 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000377 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
378 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
379 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
380 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
381 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
382 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000383 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000384 if (I < LoadCommandCount - 1) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000385 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +0000386 Load = *LoadOrErr;
387 else {
388 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000389 return;
390 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000391 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000392 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000393 if (!SymtabLoadCmd) {
394 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000395 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +0000396 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +0000397 return;
398 }
399 } else if (DysymtabLoadCmd) {
400 MachO::symtab_command Symtab =
401 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
402 MachO::dysymtab_command Dysymtab =
403 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
404 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000405 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000406 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000407 return;
408 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000409 uint64_t BigSize = Dysymtab.ilocalsym;
410 BigSize += Dysymtab.nlocalsym;
411 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000412 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +0000413 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000414 return;
415 }
416 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000417 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000418 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000419 return;
420 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000421 BigSize = Dysymtab.iextdefsym;
422 BigSize += Dysymtab.nextdefsym;
423 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000424 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +0000425 "load command extends past the end of the symbol "
426 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000427 return;
428 }
429 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000430 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +0000431 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000432 return;
433 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000434 BigSize = Dysymtab.iundefsym;
435 BigSize += Dysymtab.nundefsym;
436 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000437 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +0000438 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000439 return;
440 }
441 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000442 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +0000443
444 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000445}
446
Rafael Espindola5e812af2014-01-30 02:49:50 +0000447void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000448 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000449 sizeof(MachO::nlist_64) :
450 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000451 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000452}
453
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000454Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000455 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000456 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000457 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000458 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000459 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +0000460 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000461 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000462 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000463}
464
Rafael Espindola0e77a942014-12-10 20:46:55 +0000465unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
466 DataRefImpl DRI = Sec.getRawDataRefImpl();
467 uint32_t Flags = getSectionFlags(this, DRI);
468 return Flags & MachO::SECTION_TYPE;
469}
470
Rafael Espindola59128922015-06-24 18:14:41 +0000471uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
472 if (is64Bit()) {
473 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
474 return Entry.n_value;
475 }
476 MachO::nlist Entry = getSymbolTableEntry(Sym);
477 return Entry.n_value;
478}
479
Kevin Enderby980b2582014-06-05 21:21:57 +0000480// getIndirectName() returns the name of the alias'ed symbol who's string table
481// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000482std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
483 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000484 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000485 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
486 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
487 return object_error::parse_failed;
488 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000489 if (NValue >= StringTable.size())
490 return object_error::parse_failed;
491 const char *Start = &StringTable.data()[NValue];
492 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000493 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000494}
495
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000496uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000497 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000498}
499
Kevin Enderby931cb652016-06-24 18:24:42 +0000500Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +0000501 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000502}
503
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000504uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000505 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000506 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000507 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000508 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000509 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000510 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000511}
512
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000513uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000514 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000515}
516
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000517Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000518MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000519 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000520 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000521
Rafael Espindola56f976f2013-04-18 18:08:55 +0000522 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000523 if (n_type & MachO::N_STAB)
524 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000525
Charles Davis74ec8b02013-08-27 05:00:13 +0000526 switch (n_type & MachO::N_TYPE) {
527 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000528 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000529 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000530 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000531 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000532 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000533 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000534 if (Sec->isData() || Sec->isBSS())
535 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000536 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000538 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000539}
540
Rafael Espindola20122a42014-01-31 20:57:12 +0000541uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000542 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000543
Charles Davis8bdfafd2013-09-01 04:28:48 +0000544 uint8_t MachOType = Entry.n_type;
545 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000546
Rafael Espindola20122a42014-01-31 20:57:12 +0000547 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000548
Tim Northovereaef0742014-05-30 13:22:59 +0000549 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
550 Result |= SymbolRef::SF_Indirect;
551
Rafael Espindolaa1356322013-11-02 05:03:24 +0000552 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000553 Result |= SymbolRef::SF_FormatSpecific;
554
Charles Davis74ec8b02013-08-27 05:00:13 +0000555 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000556 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000557 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000558 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000559 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000560 else
561 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000562 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000563
564 if (!(MachOType & MachO::N_PEXT))
565 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000566 }
567
Charles Davis74ec8b02013-08-27 05:00:13 +0000568 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000569 Result |= SymbolRef::SF_Weak;
570
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000571 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
572 Result |= SymbolRef::SF_Thumb;
573
Charles Davis74ec8b02013-08-27 05:00:13 +0000574 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000575 Result |= SymbolRef::SF_Absolute;
576
Rafael Espindola20122a42014-01-31 20:57:12 +0000577 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000578}
579
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000580Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +0000581MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000582 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000583 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000584
Rafael Espindola8bab8892015-08-07 23:27:14 +0000585 if (index == 0)
586 return section_end();
587 DataRefImpl DRI;
588 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000589 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000590 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +0000591 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000592 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000593 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000594}
595
Rafael Espindola6bf32212015-06-24 19:57:32 +0000596unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
597 MachO::nlist_base Entry =
598 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
599 return Entry.n_sect - 1;
600}
601
Rafael Espindola5e812af2014-01-30 02:49:50 +0000602void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000603 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000604}
605
Rafael Espindola3acea392014-06-12 21:46:39 +0000606std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
607 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000608 ArrayRef<char> Raw = getSectionRawName(Sec);
609 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000610 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000611}
612
Rafael Espindola80291272014-10-08 15:28:58 +0000613uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
614 if (is64Bit())
615 return getSection64(Sec).addr;
616 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000617}
618
Rafael Espindola80291272014-10-08 15:28:58 +0000619uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000620 // In the case if a malformed Mach-O file where the section offset is past
621 // the end of the file or some part of the section size is past the end of
622 // the file return a size of zero or a size that covers the rest of the file
623 // but does not extend past the end of the file.
624 uint32_t SectOffset, SectType;
625 uint64_t SectSize;
626
627 if (is64Bit()) {
628 MachO::section_64 Sect = getSection64(Sec);
629 SectOffset = Sect.offset;
630 SectSize = Sect.size;
631 SectType = Sect.flags & MachO::SECTION_TYPE;
632 } else {
633 MachO::section Sect = getSection(Sec);
634 SectOffset = Sect.offset;
635 SectSize = Sect.size;
636 SectType = Sect.flags & MachO::SECTION_TYPE;
637 }
638 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
639 return SectSize;
640 uint64_t FileSize = getData().size();
641 if (SectOffset > FileSize)
642 return 0;
643 if (FileSize - SectOffset < SectSize)
644 return FileSize - SectOffset;
645 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000646}
647
Rafael Espindola3acea392014-06-12 21:46:39 +0000648std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
649 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000650 uint32_t Offset;
651 uint64_t Size;
652
653 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000654 MachO::section_64 Sect = getSection64(Sec);
655 Offset = Sect.offset;
656 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000657 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000658 MachO::section Sect = getSection(Sec);
659 Offset = Sect.offset;
660 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000661 }
662
663 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000664 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000665}
666
Rafael Espindola80291272014-10-08 15:28:58 +0000667uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000668 uint32_t Align;
669 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000670 MachO::section_64 Sect = getSection64(Sec);
671 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000672 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000673 MachO::section Sect = getSection(Sec);
674 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000675 }
676
Rafael Espindola80291272014-10-08 15:28:58 +0000677 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000678}
679
George Rimar401e4e52016-05-24 12:48:46 +0000680bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
681 return false;
682}
683
Rafael Espindola80291272014-10-08 15:28:58 +0000684bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000685 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000686 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000687}
688
Rafael Espindola80291272014-10-08 15:28:58 +0000689bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000690 uint32_t Flags = getSectionFlags(this, Sec);
691 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000692 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
693 !(SectionType == MachO::S_ZEROFILL ||
694 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000695}
696
Rafael Espindola80291272014-10-08 15:28:58 +0000697bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000698 uint32_t Flags = getSectionFlags(this, Sec);
699 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000700 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
701 (SectionType == MachO::S_ZEROFILL ||
702 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000703}
704
Rafael Espindola6bf32212015-06-24 19:57:32 +0000705unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
706 return Sec.getRawDataRefImpl().d.a;
707}
708
Rafael Espindola80291272014-10-08 15:28:58 +0000709bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000710 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000711 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000712}
713
Steven Wuf2fe0142016-02-29 19:40:10 +0000714bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
715 StringRef SegmentName = getSectionFinalSegmentName(Sec);
716 StringRef SectName;
717 if (!getSectionName(Sec, SectName))
718 return (SegmentName == "__LLVM" && SectName == "__bitcode");
719 return false;
720}
721
Rui Ueyamabc654b12013-09-27 21:47:05 +0000722relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000723 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000724 Ret.d.a = Sec.d.a;
725 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000726 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000727}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000728
Rafael Espindola56f976f2013-04-18 18:08:55 +0000729relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000730MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000731 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000732 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000733 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000734 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000735 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000736 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000737 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000738 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000739
Rafael Espindola56f976f2013-04-18 18:08:55 +0000740 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000741 Ret.d.a = Sec.d.a;
742 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000743 return relocation_iterator(RelocationRef(Ret, this));
744}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000745
Rafael Espindola5e812af2014-01-30 02:49:50 +0000746void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000747 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000748}
Owen Anderson171f4852011-10-24 23:20:07 +0000749
Rafael Espindola96d071c2015-06-29 23:29:12 +0000750uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000751 assert(getHeader().filetype == MachO::MH_OBJECT &&
752 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000753 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000754 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000755}
756
Rafael Espindola806f0062013-06-05 01:33:53 +0000757symbol_iterator
758MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000759 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000760 if (isRelocationScattered(RE))
761 return symbol_end();
762
Rafael Espindola56f976f2013-04-18 18:08:55 +0000763 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
764 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000765 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000766 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000767
Charles Davis8bdfafd2013-09-01 04:28:48 +0000768 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000769 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000770 sizeof(MachO::nlist_64) :
771 sizeof(MachO::nlist);
772 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000773 DataRefImpl Sym;
774 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000775 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000776}
777
Keno Fischerc780e8e2015-05-21 21:24:32 +0000778section_iterator
779MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
780 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
781}
782
Rafael Espindola99c041b2015-06-30 01:53:01 +0000783uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000784 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000785 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000786}
787
Rafael Espindola41bb4322015-06-30 04:08:37 +0000788void MachOObjectFile::getRelocationTypeName(
789 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000790 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000791 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000792
793 unsigned Arch = this->getArch();
794
795 switch (Arch) {
796 case Triple::x86: {
797 static const char *const Table[] = {
798 "GENERIC_RELOC_VANILLA",
799 "GENERIC_RELOC_PAIR",
800 "GENERIC_RELOC_SECTDIFF",
801 "GENERIC_RELOC_PB_LA_PTR",
802 "GENERIC_RELOC_LOCAL_SECTDIFF",
803 "GENERIC_RELOC_TLV" };
804
Eric Christopher13250cb2013-12-06 02:33:38 +0000805 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000806 res = "Unknown";
807 else
808 res = Table[RType];
809 break;
810 }
811 case Triple::x86_64: {
812 static const char *const Table[] = {
813 "X86_64_RELOC_UNSIGNED",
814 "X86_64_RELOC_SIGNED",
815 "X86_64_RELOC_BRANCH",
816 "X86_64_RELOC_GOT_LOAD",
817 "X86_64_RELOC_GOT",
818 "X86_64_RELOC_SUBTRACTOR",
819 "X86_64_RELOC_SIGNED_1",
820 "X86_64_RELOC_SIGNED_2",
821 "X86_64_RELOC_SIGNED_4",
822 "X86_64_RELOC_TLV" };
823
824 if (RType > 9)
825 res = "Unknown";
826 else
827 res = Table[RType];
828 break;
829 }
830 case Triple::arm: {
831 static const char *const Table[] = {
832 "ARM_RELOC_VANILLA",
833 "ARM_RELOC_PAIR",
834 "ARM_RELOC_SECTDIFF",
835 "ARM_RELOC_LOCAL_SECTDIFF",
836 "ARM_RELOC_PB_LA_PTR",
837 "ARM_RELOC_BR24",
838 "ARM_THUMB_RELOC_BR22",
839 "ARM_THUMB_32BIT_BRANCH",
840 "ARM_RELOC_HALF",
841 "ARM_RELOC_HALF_SECTDIFF" };
842
843 if (RType > 9)
844 res = "Unknown";
845 else
846 res = Table[RType];
847 break;
848 }
Tim Northover00ed9962014-03-29 10:18:08 +0000849 case Triple::aarch64: {
850 static const char *const Table[] = {
851 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
852 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
853 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
854 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
855 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
856 "ARM64_RELOC_ADDEND"
857 };
858
859 if (RType >= array_lengthof(Table))
860 res = "Unknown";
861 else
862 res = Table[RType];
863 break;
864 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000865 case Triple::ppc: {
866 static const char *const Table[] = {
867 "PPC_RELOC_VANILLA",
868 "PPC_RELOC_PAIR",
869 "PPC_RELOC_BR14",
870 "PPC_RELOC_BR24",
871 "PPC_RELOC_HI16",
872 "PPC_RELOC_LO16",
873 "PPC_RELOC_HA16",
874 "PPC_RELOC_LO14",
875 "PPC_RELOC_SECTDIFF",
876 "PPC_RELOC_PB_LA_PTR",
877 "PPC_RELOC_HI16_SECTDIFF",
878 "PPC_RELOC_LO16_SECTDIFF",
879 "PPC_RELOC_HA16_SECTDIFF",
880 "PPC_RELOC_JBSR",
881 "PPC_RELOC_LO14_SECTDIFF",
882 "PPC_RELOC_LOCAL_SECTDIFF" };
883
Eric Christopher13250cb2013-12-06 02:33:38 +0000884 if (RType > 15)
885 res = "Unknown";
886 else
887 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000888 break;
889 }
890 case Triple::UnknownArch:
891 res = "Unknown";
892 break;
893 }
894 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000895}
896
Keno Fischer281b6942015-05-30 19:44:53 +0000897uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
898 MachO::any_relocation_info RE = getRelocation(Rel);
899 return getAnyRelocationLength(RE);
900}
901
Kevin Enderby980b2582014-06-05 21:21:57 +0000902//
903// guessLibraryShortName() is passed a name of a dynamic library and returns a
904// guess on what the short name is. Then name is returned as a substring of the
905// StringRef Name passed in. The name of the dynamic library is recognized as
906// a framework if it has one of the two following forms:
907// Foo.framework/Versions/A/Foo
908// Foo.framework/Foo
909// Where A and Foo can be any string. And may contain a trailing suffix
910// starting with an underbar. If the Name is recognized as a framework then
911// isFramework is set to true else it is set to false. If the Name has a
912// suffix then Suffix is set to the substring in Name that contains the suffix
913// else it is set to a NULL StringRef.
914//
915// The Name of the dynamic library is recognized as a library name if it has
916// one of the two following forms:
917// libFoo.A.dylib
918// libFoo.dylib
919// The library may have a suffix trailing the name Foo of the form:
920// libFoo_profile.A.dylib
921// libFoo_profile.dylib
922//
923// The Name of the dynamic library is also recognized as a library name if it
924// has the following form:
925// Foo.qtx
926//
927// If the Name of the dynamic library is none of the forms above then a NULL
928// StringRef is returned.
929//
930StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
931 bool &isFramework,
932 StringRef &Suffix) {
933 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
934 size_t a, b, c, d, Idx;
935
936 isFramework = false;
937 Suffix = StringRef();
938
939 // Pull off the last component and make Foo point to it
940 a = Name.rfind('/');
941 if (a == Name.npos || a == 0)
942 goto guess_library;
943 Foo = Name.slice(a+1, Name.npos);
944
945 // Look for a suffix starting with a '_'
946 Idx = Foo.rfind('_');
947 if (Idx != Foo.npos && Foo.size() >= 2) {
948 Suffix = Foo.slice(Idx, Foo.npos);
949 Foo = Foo.slice(0, Idx);
950 }
951
952 // First look for the form Foo.framework/Foo
953 b = Name.rfind('/', a);
954 if (b == Name.npos)
955 Idx = 0;
956 else
957 Idx = b+1;
958 F = Name.slice(Idx, Idx + Foo.size());
959 DotFramework = Name.slice(Idx + Foo.size(),
960 Idx + Foo.size() + sizeof(".framework/")-1);
961 if (F == Foo && DotFramework == ".framework/") {
962 isFramework = true;
963 return Foo;
964 }
965
966 // Next look for the form Foo.framework/Versions/A/Foo
967 if (b == Name.npos)
968 goto guess_library;
969 c = Name.rfind('/', b);
970 if (c == Name.npos || c == 0)
971 goto guess_library;
972 V = Name.slice(c+1, Name.npos);
973 if (!V.startswith("Versions/"))
974 goto guess_library;
975 d = Name.rfind('/', c);
976 if (d == Name.npos)
977 Idx = 0;
978 else
979 Idx = d+1;
980 F = Name.slice(Idx, Idx + Foo.size());
981 DotFramework = Name.slice(Idx + Foo.size(),
982 Idx + Foo.size() + sizeof(".framework/")-1);
983 if (F == Foo && DotFramework == ".framework/") {
984 isFramework = true;
985 return Foo;
986 }
987
988guess_library:
989 // pull off the suffix after the "." and make a point to it
990 a = Name.rfind('.');
991 if (a == Name.npos || a == 0)
992 return StringRef();
993 Dylib = Name.slice(a, Name.npos);
994 if (Dylib != ".dylib")
995 goto guess_qtx;
996
997 // First pull off the version letter for the form Foo.A.dylib if any.
998 if (a >= 3) {
999 Dot = Name.slice(a-2, a-1);
1000 if (Dot == ".")
1001 a = a - 2;
1002 }
1003
1004 b = Name.rfind('/', a);
1005 if (b == Name.npos)
1006 b = 0;
1007 else
1008 b = b+1;
1009 // ignore any suffix after an underbar like Foo_profile.A.dylib
1010 Idx = Name.find('_', b);
1011 if (Idx != Name.npos && Idx != b) {
1012 Lib = Name.slice(b, Idx);
1013 Suffix = Name.slice(Idx, a);
1014 }
1015 else
1016 Lib = Name.slice(b, a);
1017 // There are incorrect library names of the form:
1018 // libATS.A_profile.dylib so check for these.
1019 if (Lib.size() >= 3) {
1020 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1021 if (Dot == ".")
1022 Lib = Lib.slice(0, Lib.size()-2);
1023 }
1024 return Lib;
1025
1026guess_qtx:
1027 Qtx = Name.slice(a, Name.npos);
1028 if (Qtx != ".qtx")
1029 return StringRef();
1030 b = Name.rfind('/', a);
1031 if (b == Name.npos)
1032 Lib = Name.slice(0, a);
1033 else
1034 Lib = Name.slice(b+1, a);
1035 // There are library names of the form: QT.A.qtx so check for these.
1036 if (Lib.size() >= 3) {
1037 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1038 if (Dot == ".")
1039 Lib = Lib.slice(0, Lib.size()-2);
1040 }
1041 return Lib;
1042}
1043
1044// getLibraryShortNameByIndex() is used to get the short name of the library
1045// for an undefined symbol in a linked Mach-O binary that was linked with the
1046// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1047// It is passed the index (0 - based) of the library as translated from
1048// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001049std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001050 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001051 if (Index >= Libraries.size())
1052 return object_error::parse_failed;
1053
Kevin Enderby980b2582014-06-05 21:21:57 +00001054 // If the cache of LibrariesShortNames is not built up do that first for
1055 // all the Libraries.
1056 if (LibrariesShortNames.size() == 0) {
1057 for (unsigned i = 0; i < Libraries.size(); i++) {
1058 MachO::dylib_command D =
1059 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001060 if (D.dylib.name >= D.cmdsize)
1061 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001062 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001063 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001064 if (D.dylib.name+Name.size() >= D.cmdsize)
1065 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001066 StringRef Suffix;
1067 bool isFramework;
1068 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001069 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001070 LibrariesShortNames.push_back(Name);
1071 else
1072 LibrariesShortNames.push_back(shortName);
1073 }
1074 }
1075
1076 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001077 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001078}
1079
Rafael Espindola76ad2322015-07-06 14:55:37 +00001080section_iterator
1081MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1082 DataRefImpl Sec;
1083 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1084 return section_iterator(SectionRef(Sec, this));
1085}
1086
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001087basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001088 DataRefImpl DRI;
1089 MachO::symtab_command Symtab = getSymtabLoadCommand();
1090 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1091 return basic_symbol_iterator(SymbolRef(DRI, this));
1092
Lang Hames36072da2014-05-12 21:39:59 +00001093 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001094}
1095
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001096basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001097 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001098 MachO::symtab_command Symtab = getSymtabLoadCommand();
1099 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001100 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001101
Rafael Espindola75c30362013-04-24 19:47:55 +00001102 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001103 sizeof(MachO::nlist_64) :
1104 sizeof(MachO::nlist);
1105 unsigned Offset = Symtab.symoff +
1106 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001107 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001108 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001109}
1110
Lang Hames36072da2014-05-12 21:39:59 +00001111basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001112 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001113 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001114 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001115 unsigned SymbolTableEntrySize =
1116 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001117 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001118 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1119 DRI.p += Index * SymbolTableEntrySize;
1120 return basic_symbol_iterator(SymbolRef(DRI, this));
1121}
1122
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001123uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
1124 MachO::symtab_command Symtab = getSymtabLoadCommand();
1125 if (!SymtabLoadCmd)
1126 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
1127 unsigned SymbolTableEntrySize =
1128 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1129 DataRefImpl DRIstart;
1130 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1131 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
1132 return Index;
1133}
1134
Rafael Espindolab5155a52014-02-10 20:24:04 +00001135section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001136 DataRefImpl DRI;
1137 return section_iterator(SectionRef(DRI, this));
1138}
1139
Rafael Espindolab5155a52014-02-10 20:24:04 +00001140section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001141 DataRefImpl DRI;
1142 DRI.d.a = Sections.size();
1143 return section_iterator(SectionRef(DRI, this));
1144}
1145
Rafael Espindola56f976f2013-04-18 18:08:55 +00001146uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001147 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001148}
1149
Rafael Espindola56f976f2013-04-18 18:08:55 +00001150StringRef MachOObjectFile::getFileFormatName() const {
1151 unsigned CPUType = getCPUType(this);
1152 if (!is64Bit()) {
1153 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001154 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001155 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001156 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001157 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001158 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001159 return "Mach-O 32-bit ppc";
1160 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001161 return "Mach-O 32-bit unknown";
1162 }
1163 }
1164
Rafael Espindola56f976f2013-04-18 18:08:55 +00001165 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001166 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001167 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001168 case llvm::MachO::CPU_TYPE_ARM64:
1169 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001170 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001171 return "Mach-O 64-bit ppc64";
1172 default:
1173 return "Mach-O 64-bit unknown";
1174 }
1175}
1176
Alexey Samsonove6388e62013-06-18 15:03:28 +00001177Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1178 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001179 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001180 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001181 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001182 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001183 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001184 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001185 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001186 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001187 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001188 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001189 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001190 return Triple::ppc64;
1191 default:
1192 return Triple::UnknownArch;
1193 }
1194}
1195
Tim Northover9e8eb412016-04-22 23:21:13 +00001196Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
1197 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001198 if (McpuDefault)
1199 *McpuDefault = nullptr;
1200
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001201 switch (CPUType) {
1202 case MachO::CPU_TYPE_I386:
1203 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1204 case MachO::CPU_SUBTYPE_I386_ALL:
1205 return Triple("i386-apple-darwin");
1206 default:
1207 return Triple();
1208 }
1209 case MachO::CPU_TYPE_X86_64:
1210 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1211 case MachO::CPU_SUBTYPE_X86_64_ALL:
1212 return Triple("x86_64-apple-darwin");
1213 case MachO::CPU_SUBTYPE_X86_64_H:
1214 return Triple("x86_64h-apple-darwin");
1215 default:
1216 return Triple();
1217 }
1218 case MachO::CPU_TYPE_ARM:
1219 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1220 case MachO::CPU_SUBTYPE_ARM_V4T:
1221 return Triple("armv4t-apple-darwin");
1222 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1223 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001224 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1225 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001226 case MachO::CPU_SUBTYPE_ARM_V6:
1227 return Triple("armv6-apple-darwin");
1228 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001229 if (McpuDefault)
1230 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001231 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001232 case MachO::CPU_SUBTYPE_ARM_V7:
1233 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001234 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001235 if (McpuDefault)
1236 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00001237 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001238 case MachO::CPU_SUBTYPE_ARM_V7K:
1239 return Triple("armv7k-apple-darwin");
1240 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001241 if (McpuDefault)
1242 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00001243 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001244 case MachO::CPU_SUBTYPE_ARM_V7S:
1245 return Triple("armv7s-apple-darwin");
1246 default:
1247 return Triple();
1248 }
1249 case MachO::CPU_TYPE_ARM64:
1250 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1251 case MachO::CPU_SUBTYPE_ARM64_ALL:
1252 return Triple("arm64-apple-darwin");
1253 default:
1254 return Triple();
1255 }
1256 case MachO::CPU_TYPE_POWERPC:
1257 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1258 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1259 return Triple("ppc-apple-darwin");
1260 default:
1261 return Triple();
1262 }
1263 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001264 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001265 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1266 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001267 default:
1268 return Triple();
1269 }
1270 default:
1271 return Triple();
1272 }
1273}
1274
1275Triple MachOObjectFile::getHostArch() {
1276 return Triple(sys::getDefaultTargetTriple());
1277}
1278
Rafael Espindola72318b42014-08-08 16:30:17 +00001279bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1280 return StringSwitch<bool>(ArchFlag)
1281 .Case("i386", true)
1282 .Case("x86_64", true)
1283 .Case("x86_64h", true)
1284 .Case("armv4t", true)
1285 .Case("arm", true)
1286 .Case("armv5e", true)
1287 .Case("armv6", true)
1288 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001289 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001290 .Case("armv7em", true)
1291 .Case("armv7k", true)
1292 .Case("armv7m", true)
1293 .Case("armv7s", true)
1294 .Case("arm64", true)
1295 .Case("ppc", true)
1296 .Case("ppc64", true)
1297 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001298}
1299
Alexey Samsonove6388e62013-06-18 15:03:28 +00001300unsigned MachOObjectFile::getArch() const {
1301 return getArch(getCPUType(this));
1302}
1303
Tim Northover9e8eb412016-04-22 23:21:13 +00001304Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
1305 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001306}
1307
Rui Ueyamabc654b12013-09-27 21:47:05 +00001308relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001309 DataRefImpl DRI;
1310 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001311 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001312}
1313
Rui Ueyamabc654b12013-09-27 21:47:05 +00001314relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001315 DataRefImpl DRI;
1316 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001317 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001318}
1319
Kevin Enderby273ae012013-06-06 17:20:50 +00001320dice_iterator MachOObjectFile::begin_dices() const {
1321 DataRefImpl DRI;
1322 if (!DataInCodeLoadCmd)
1323 return dice_iterator(DiceRef(DRI, this));
1324
Charles Davis8bdfafd2013-09-01 04:28:48 +00001325 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1326 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001327 return dice_iterator(DiceRef(DRI, this));
1328}
1329
1330dice_iterator MachOObjectFile::end_dices() const {
1331 DataRefImpl DRI;
1332 if (!DataInCodeLoadCmd)
1333 return dice_iterator(DiceRef(DRI, this));
1334
Charles Davis8bdfafd2013-09-01 04:28:48 +00001335 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1336 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001337 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1338 return dice_iterator(DiceRef(DRI, this));
1339}
1340
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001341ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1342 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001343
1344void ExportEntry::moveToFirst() {
1345 pushNode(0);
1346 pushDownUntilBottom();
1347}
1348
1349void ExportEntry::moveToEnd() {
1350 Stack.clear();
1351 Done = true;
1352}
1353
1354bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001355 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001356 if (Done || Other.Done)
1357 return (Done == Other.Done);
1358 // Not equal if different stack sizes.
1359 if (Stack.size() != Other.Stack.size())
1360 return false;
1361 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001362 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001363 return false;
1364 // Equal if all nodes in both stacks match.
1365 for (unsigned i=0; i < Stack.size(); ++i) {
1366 if (Stack[i].Start != Other.Stack[i].Start)
1367 return false;
1368 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001369 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001370}
1371
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001372uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1373 unsigned Count;
1374 uint64_t Result = decodeULEB128(Ptr, &Count);
1375 Ptr += Count;
1376 if (Ptr > Trie.end()) {
1377 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001378 Malformed = true;
1379 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001380 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001381}
1382
1383StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001384 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001385}
1386
1387uint64_t ExportEntry::flags() const {
1388 return Stack.back().Flags;
1389}
1390
1391uint64_t ExportEntry::address() const {
1392 return Stack.back().Address;
1393}
1394
1395uint64_t ExportEntry::other() const {
1396 return Stack.back().Other;
1397}
1398
1399StringRef ExportEntry::otherName() const {
1400 const char* ImportName = Stack.back().ImportName;
1401 if (ImportName)
1402 return StringRef(ImportName);
1403 return StringRef();
1404}
1405
1406uint32_t ExportEntry::nodeOffset() const {
1407 return Stack.back().Start - Trie.begin();
1408}
1409
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001410ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1411 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1412 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1413 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001414
1415void ExportEntry::pushNode(uint64_t offset) {
1416 const uint8_t *Ptr = Trie.begin() + offset;
1417 NodeState State(Ptr);
1418 uint64_t ExportInfoSize = readULEB128(State.Current);
1419 State.IsExportNode = (ExportInfoSize != 0);
1420 const uint8_t* Children = State.Current + ExportInfoSize;
1421 if (State.IsExportNode) {
1422 State.Flags = readULEB128(State.Current);
1423 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1424 State.Address = 0;
1425 State.Other = readULEB128(State.Current); // dylib ordinal
1426 State.ImportName = reinterpret_cast<const char*>(State.Current);
1427 } else {
1428 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001429 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001430 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001431 }
1432 }
1433 State.ChildCount = *Children;
1434 State.Current = Children + 1;
1435 State.NextChildIndex = 0;
1436 State.ParentStringLength = CumulativeString.size();
1437 Stack.push_back(State);
1438}
1439
1440void ExportEntry::pushDownUntilBottom() {
1441 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1442 NodeState &Top = Stack.back();
1443 CumulativeString.resize(Top.ParentStringLength);
1444 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001445 char C = *Top.Current;
1446 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001447 }
1448 Top.Current += 1;
1449 uint64_t childNodeIndex = readULEB128(Top.Current);
1450 Top.NextChildIndex += 1;
1451 pushNode(childNodeIndex);
1452 }
1453 if (!Stack.back().IsExportNode) {
1454 Malformed = true;
1455 moveToEnd();
1456 }
1457}
1458
1459// We have a trie data structure and need a way to walk it that is compatible
1460// with the C++ iterator model. The solution is a non-recursive depth first
1461// traversal where the iterator contains a stack of parent nodes along with a
1462// string that is the accumulation of all edge strings along the parent chain
1463// to this point.
1464//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001465// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001466// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001467// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001468//
1469// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1470// child until hitting a node with no children (which is an export node or
1471// else the trie is malformed). On the way down, each node is pushed on the
1472// stack ivar. If there is no more ways down, it pops up one and tries to go
1473// down a sibling path until a childless node is reached.
1474void ExportEntry::moveNext() {
1475 if (Stack.empty() || !Stack.back().IsExportNode) {
1476 Malformed = true;
1477 moveToEnd();
1478 return;
1479 }
1480
1481 Stack.pop_back();
1482 while (!Stack.empty()) {
1483 NodeState &Top = Stack.back();
1484 if (Top.NextChildIndex < Top.ChildCount) {
1485 pushDownUntilBottom();
1486 // Now at the next export node.
1487 return;
1488 } else {
1489 if (Top.IsExportNode) {
1490 // This node has no children but is itself an export node.
1491 CumulativeString.resize(Top.ParentStringLength);
1492 return;
1493 }
1494 Stack.pop_back();
1495 }
1496 }
1497 Done = true;
1498}
1499
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001500iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001501MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1502 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001503 if (Trie.size() == 0)
1504 Start.moveToEnd();
1505 else
1506 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001507
1508 ExportEntry Finish(Trie);
1509 Finish.moveToEnd();
1510
Craig Topper15576e12015-12-06 05:08:07 +00001511 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001512}
1513
1514iterator_range<export_iterator> MachOObjectFile::exports() const {
1515 return exports(getDyldInfoExportsTrie());
1516}
1517
Nick Kledzikac431442014-09-12 21:34:15 +00001518MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1519 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1520 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1521 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1522
1523void MachORebaseEntry::moveToFirst() {
1524 Ptr = Opcodes.begin();
1525 moveNext();
1526}
1527
1528void MachORebaseEntry::moveToEnd() {
1529 Ptr = Opcodes.end();
1530 RemainingLoopCount = 0;
1531 Done = true;
1532}
1533
1534void MachORebaseEntry::moveNext() {
1535 // If in the middle of some loop, move to next rebasing in loop.
1536 SegmentOffset += AdvanceAmount;
1537 if (RemainingLoopCount) {
1538 --RemainingLoopCount;
1539 return;
1540 }
1541 if (Ptr == Opcodes.end()) {
1542 Done = true;
1543 return;
1544 }
1545 bool More = true;
1546 while (More && !Malformed) {
1547 // Parse next opcode and set up next loop.
1548 uint8_t Byte = *Ptr++;
1549 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1550 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1551 switch (Opcode) {
1552 case MachO::REBASE_OPCODE_DONE:
1553 More = false;
1554 Done = true;
1555 moveToEnd();
1556 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1557 break;
1558 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1559 RebaseType = ImmValue;
1560 DEBUG_WITH_TYPE(
1561 "mach-o-rebase",
1562 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1563 << "RebaseType=" << (int) RebaseType << "\n");
1564 break;
1565 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1566 SegmentIndex = ImmValue;
1567 SegmentOffset = readULEB128();
1568 DEBUG_WITH_TYPE(
1569 "mach-o-rebase",
1570 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1571 << "SegmentIndex=" << SegmentIndex << ", "
1572 << format("SegmentOffset=0x%06X", SegmentOffset)
1573 << "\n");
1574 break;
1575 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1576 SegmentOffset += readULEB128();
1577 DEBUG_WITH_TYPE("mach-o-rebase",
1578 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1579 << format("SegmentOffset=0x%06X",
1580 SegmentOffset) << "\n");
1581 break;
1582 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1583 SegmentOffset += ImmValue * PointerSize;
1584 DEBUG_WITH_TYPE("mach-o-rebase",
1585 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1586 << format("SegmentOffset=0x%06X",
1587 SegmentOffset) << "\n");
1588 break;
1589 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1590 AdvanceAmount = PointerSize;
1591 RemainingLoopCount = ImmValue - 1;
1592 DEBUG_WITH_TYPE(
1593 "mach-o-rebase",
1594 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1595 << format("SegmentOffset=0x%06X", SegmentOffset)
1596 << ", AdvanceAmount=" << AdvanceAmount
1597 << ", RemainingLoopCount=" << RemainingLoopCount
1598 << "\n");
1599 return;
1600 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1601 AdvanceAmount = PointerSize;
1602 RemainingLoopCount = readULEB128() - 1;
1603 DEBUG_WITH_TYPE(
1604 "mach-o-rebase",
1605 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1606 << format("SegmentOffset=0x%06X", SegmentOffset)
1607 << ", AdvanceAmount=" << AdvanceAmount
1608 << ", RemainingLoopCount=" << RemainingLoopCount
1609 << "\n");
1610 return;
1611 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1612 AdvanceAmount = readULEB128() + PointerSize;
1613 RemainingLoopCount = 0;
1614 DEBUG_WITH_TYPE(
1615 "mach-o-rebase",
1616 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1617 << format("SegmentOffset=0x%06X", SegmentOffset)
1618 << ", AdvanceAmount=" << AdvanceAmount
1619 << ", RemainingLoopCount=" << RemainingLoopCount
1620 << "\n");
1621 return;
1622 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1623 RemainingLoopCount = readULEB128() - 1;
1624 AdvanceAmount = readULEB128() + PointerSize;
1625 DEBUG_WITH_TYPE(
1626 "mach-o-rebase",
1627 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1628 << format("SegmentOffset=0x%06X", SegmentOffset)
1629 << ", AdvanceAmount=" << AdvanceAmount
1630 << ", RemainingLoopCount=" << RemainingLoopCount
1631 << "\n");
1632 return;
1633 default:
1634 Malformed = true;
1635 }
1636 }
1637}
1638
1639uint64_t MachORebaseEntry::readULEB128() {
1640 unsigned Count;
1641 uint64_t Result = decodeULEB128(Ptr, &Count);
1642 Ptr += Count;
1643 if (Ptr > Opcodes.end()) {
1644 Ptr = Opcodes.end();
1645 Malformed = true;
1646 }
1647 return Result;
1648}
1649
1650uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1651
1652uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1653
1654StringRef MachORebaseEntry::typeName() const {
1655 switch (RebaseType) {
1656 case MachO::REBASE_TYPE_POINTER:
1657 return "pointer";
1658 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1659 return "text abs32";
1660 case MachO::REBASE_TYPE_TEXT_PCREL32:
1661 return "text rel32";
1662 }
1663 return "unknown";
1664}
1665
1666bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1667 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1668 return (Ptr == Other.Ptr) &&
1669 (RemainingLoopCount == Other.RemainingLoopCount) &&
1670 (Done == Other.Done);
1671}
1672
1673iterator_range<rebase_iterator>
1674MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1675 MachORebaseEntry Start(Opcodes, is64);
1676 Start.moveToFirst();
1677
1678 MachORebaseEntry Finish(Opcodes, is64);
1679 Finish.moveToEnd();
1680
Craig Topper15576e12015-12-06 05:08:07 +00001681 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001682}
1683
1684iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1685 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1686}
1687
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001688MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001689 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1690 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1691 BindType(0), PointerSize(is64Bit ? 8 : 4),
1692 TableKind(BK), Malformed(false), Done(false) {}
1693
1694void MachOBindEntry::moveToFirst() {
1695 Ptr = Opcodes.begin();
1696 moveNext();
1697}
1698
1699void MachOBindEntry::moveToEnd() {
1700 Ptr = Opcodes.end();
1701 RemainingLoopCount = 0;
1702 Done = true;
1703}
1704
1705void MachOBindEntry::moveNext() {
1706 // If in the middle of some loop, move to next binding in loop.
1707 SegmentOffset += AdvanceAmount;
1708 if (RemainingLoopCount) {
1709 --RemainingLoopCount;
1710 return;
1711 }
1712 if (Ptr == Opcodes.end()) {
1713 Done = true;
1714 return;
1715 }
1716 bool More = true;
1717 while (More && !Malformed) {
1718 // Parse next opcode and set up next loop.
1719 uint8_t Byte = *Ptr++;
1720 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1721 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1722 int8_t SignExtended;
1723 const uint8_t *SymStart;
1724 switch (Opcode) {
1725 case MachO::BIND_OPCODE_DONE:
1726 if (TableKind == Kind::Lazy) {
1727 // Lazying bindings have a DONE opcode between entries. Need to ignore
1728 // it to advance to next entry. But need not if this is last entry.
1729 bool NotLastEntry = false;
1730 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1731 if (*P) {
1732 NotLastEntry = true;
1733 }
1734 }
1735 if (NotLastEntry)
1736 break;
1737 }
1738 More = false;
1739 Done = true;
1740 moveToEnd();
1741 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1742 break;
1743 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1744 Ordinal = ImmValue;
1745 DEBUG_WITH_TYPE(
1746 "mach-o-bind",
1747 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1748 << "Ordinal=" << Ordinal << "\n");
1749 break;
1750 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1751 Ordinal = readULEB128();
1752 DEBUG_WITH_TYPE(
1753 "mach-o-bind",
1754 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1755 << "Ordinal=" << Ordinal << "\n");
1756 break;
1757 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1758 if (ImmValue) {
1759 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1760 Ordinal = SignExtended;
1761 } else
1762 Ordinal = 0;
1763 DEBUG_WITH_TYPE(
1764 "mach-o-bind",
1765 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1766 << "Ordinal=" << Ordinal << "\n");
1767 break;
1768 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1769 Flags = ImmValue;
1770 SymStart = Ptr;
1771 while (*Ptr) {
1772 ++Ptr;
1773 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001774 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1775 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001776 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001777 DEBUG_WITH_TYPE(
1778 "mach-o-bind",
1779 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1780 << "SymbolName=" << SymbolName << "\n");
1781 if (TableKind == Kind::Weak) {
1782 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1783 return;
1784 }
1785 break;
1786 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1787 BindType = ImmValue;
1788 DEBUG_WITH_TYPE(
1789 "mach-o-bind",
1790 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1791 << "BindType=" << (int)BindType << "\n");
1792 break;
1793 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1794 Addend = readSLEB128();
1795 if (TableKind == Kind::Lazy)
1796 Malformed = true;
1797 DEBUG_WITH_TYPE(
1798 "mach-o-bind",
1799 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1800 << "Addend=" << Addend << "\n");
1801 break;
1802 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1803 SegmentIndex = ImmValue;
1804 SegmentOffset = readULEB128();
1805 DEBUG_WITH_TYPE(
1806 "mach-o-bind",
1807 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1808 << "SegmentIndex=" << SegmentIndex << ", "
1809 << format("SegmentOffset=0x%06X", SegmentOffset)
1810 << "\n");
1811 break;
1812 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1813 SegmentOffset += readULEB128();
1814 DEBUG_WITH_TYPE("mach-o-bind",
1815 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1816 << format("SegmentOffset=0x%06X",
1817 SegmentOffset) << "\n");
1818 break;
1819 case MachO::BIND_OPCODE_DO_BIND:
1820 AdvanceAmount = PointerSize;
1821 RemainingLoopCount = 0;
1822 DEBUG_WITH_TYPE("mach-o-bind",
1823 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1824 << format("SegmentOffset=0x%06X",
1825 SegmentOffset) << "\n");
1826 return;
1827 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001828 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001829 RemainingLoopCount = 0;
1830 if (TableKind == Kind::Lazy)
1831 Malformed = true;
1832 DEBUG_WITH_TYPE(
1833 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001834 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001835 << format("SegmentOffset=0x%06X", SegmentOffset)
1836 << ", AdvanceAmount=" << AdvanceAmount
1837 << ", RemainingLoopCount=" << RemainingLoopCount
1838 << "\n");
1839 return;
1840 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001841 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001842 RemainingLoopCount = 0;
1843 if (TableKind == Kind::Lazy)
1844 Malformed = true;
1845 DEBUG_WITH_TYPE("mach-o-bind",
1846 llvm::dbgs()
1847 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1848 << format("SegmentOffset=0x%06X",
1849 SegmentOffset) << "\n");
1850 return;
1851 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1852 RemainingLoopCount = readULEB128() - 1;
1853 AdvanceAmount = readULEB128() + PointerSize;
1854 if (TableKind == Kind::Lazy)
1855 Malformed = true;
1856 DEBUG_WITH_TYPE(
1857 "mach-o-bind",
1858 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1859 << format("SegmentOffset=0x%06X", SegmentOffset)
1860 << ", AdvanceAmount=" << AdvanceAmount
1861 << ", RemainingLoopCount=" << RemainingLoopCount
1862 << "\n");
1863 return;
1864 default:
1865 Malformed = true;
1866 }
1867 }
1868}
1869
1870uint64_t MachOBindEntry::readULEB128() {
1871 unsigned Count;
1872 uint64_t Result = decodeULEB128(Ptr, &Count);
1873 Ptr += Count;
1874 if (Ptr > Opcodes.end()) {
1875 Ptr = Opcodes.end();
1876 Malformed = true;
1877 }
1878 return Result;
1879}
1880
1881int64_t MachOBindEntry::readSLEB128() {
1882 unsigned Count;
1883 int64_t Result = decodeSLEB128(Ptr, &Count);
1884 Ptr += Count;
1885 if (Ptr > Opcodes.end()) {
1886 Ptr = Opcodes.end();
1887 Malformed = true;
1888 }
1889 return Result;
1890}
1891
Nick Kledzik56ebef42014-09-16 01:41:51 +00001892uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1893
1894uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1895
1896StringRef MachOBindEntry::typeName() const {
1897 switch (BindType) {
1898 case MachO::BIND_TYPE_POINTER:
1899 return "pointer";
1900 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1901 return "text abs32";
1902 case MachO::BIND_TYPE_TEXT_PCREL32:
1903 return "text rel32";
1904 }
1905 return "unknown";
1906}
1907
1908StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1909
1910int64_t MachOBindEntry::addend() const { return Addend; }
1911
1912uint32_t MachOBindEntry::flags() const { return Flags; }
1913
1914int MachOBindEntry::ordinal() const { return Ordinal; }
1915
1916bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1917 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1918 return (Ptr == Other.Ptr) &&
1919 (RemainingLoopCount == Other.RemainingLoopCount) &&
1920 (Done == Other.Done);
1921}
1922
1923iterator_range<bind_iterator>
1924MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1925 MachOBindEntry::Kind BKind) {
1926 MachOBindEntry Start(Opcodes, is64, BKind);
1927 Start.moveToFirst();
1928
1929 MachOBindEntry Finish(Opcodes, is64, BKind);
1930 Finish.moveToEnd();
1931
Craig Topper15576e12015-12-06 05:08:07 +00001932 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00001933}
1934
1935iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1936 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1937 MachOBindEntry::Kind::Regular);
1938}
1939
1940iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1941 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1942 MachOBindEntry::Kind::Lazy);
1943}
1944
1945iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1946 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1947 MachOBindEntry::Kind::Weak);
1948}
1949
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001950MachOObjectFile::load_command_iterator
1951MachOObjectFile::begin_load_commands() const {
1952 return LoadCommands.begin();
1953}
1954
1955MachOObjectFile::load_command_iterator
1956MachOObjectFile::end_load_commands() const {
1957 return LoadCommands.end();
1958}
1959
1960iterator_range<MachOObjectFile::load_command_iterator>
1961MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00001962 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001963}
1964
Rafael Espindola56f976f2013-04-18 18:08:55 +00001965StringRef
1966MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1967 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1968 return parseSegmentOrSectionName(Raw.data());
1969}
1970
1971ArrayRef<char>
1972MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001973 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001974 const section_base *Base =
1975 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001976 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001977}
1978
1979ArrayRef<char>
1980MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001981 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001982 const section_base *Base =
1983 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001984 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001985}
1986
1987bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001988MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001989 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001990 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001991 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001992 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001993}
1994
Eric Christopher1d62c252013-07-22 22:25:07 +00001995unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001996 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001997 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001998 return RE.r_word1 & 0xffffff;
1999 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002000}
2001
Eric Christopher1d62c252013-07-22 22:25:07 +00002002bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002003 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002004 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002005 return (RE.r_word1 >> 27) & 1;
2006 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002007}
2008
Eric Christopher1d62c252013-07-22 22:25:07 +00002009bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002010 const MachO::any_relocation_info &RE) const {
2011 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002012}
2013
Eric Christopher1d62c252013-07-22 22:25:07 +00002014uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002015 const MachO::any_relocation_info &RE) const {
2016 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002017}
2018
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002019uint32_t MachOObjectFile::getScatteredRelocationType(
2020 const MachO::any_relocation_info &RE) const {
2021 return (RE.r_word0 >> 24) & 0xf;
2022}
2023
Eric Christopher1d62c252013-07-22 22:25:07 +00002024unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002025 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002026 if (isRelocationScattered(RE))
2027 return getScatteredRelocationAddress(RE);
2028 return getPlainRelocationAddress(RE);
2029}
2030
Charles Davis8bdfafd2013-09-01 04:28:48 +00002031unsigned MachOObjectFile::getAnyRelocationPCRel(
2032 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002033 if (isRelocationScattered(RE))
2034 return getScatteredRelocationPCRel(this, RE);
2035 return getPlainRelocationPCRel(this, RE);
2036}
2037
Eric Christopher1d62c252013-07-22 22:25:07 +00002038unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002039 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002040 if (isRelocationScattered(RE))
2041 return getScatteredRelocationLength(RE);
2042 return getPlainRelocationLength(this, RE);
2043}
2044
2045unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002046MachOObjectFile::getAnyRelocationType(
2047 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002048 if (isRelocationScattered(RE))
2049 return getScatteredRelocationType(RE);
2050 return getPlainRelocationType(this, RE);
2051}
2052
Rafael Espindola52501032013-04-30 15:40:54 +00002053SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002054MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002055 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002056 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002057 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002058 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2059 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2060 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002061 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002062 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002063 return SectionRef(DRI, this);
2064}
2065
Charles Davis8bdfafd2013-09-01 04:28:48 +00002066MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002067 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002068 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002069}
2070
Charles Davis8bdfafd2013-09-01 04:28:48 +00002071MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002072 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002073 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002074}
2075
Charles Davis8bdfafd2013-09-01 04:28:48 +00002076MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002077 unsigned Index) const {
2078 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002079 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002080}
2081
Charles Davis8bdfafd2013-09-01 04:28:48 +00002082MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2083 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002084 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002085 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002086}
2087
Charles Davis8bdfafd2013-09-01 04:28:48 +00002088MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002089MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002090 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002091 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002092}
2093
Charles Davis8bdfafd2013-09-01 04:28:48 +00002094MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002095MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002096 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002097 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002098}
2099
Charles Davis8bdfafd2013-09-01 04:28:48 +00002100MachO::linkedit_data_command
2101MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2102 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002103}
2104
Charles Davis8bdfafd2013-09-01 04:28:48 +00002105MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002106MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002107 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002108}
2109
Charles Davis8bdfafd2013-09-01 04:28:48 +00002110MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002111MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002112 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002113}
2114
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002115MachO::linker_option_command
2116MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2117 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002118}
2119
Jim Grosbach448334a2014-03-18 22:09:05 +00002120MachO::version_min_command
2121MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2122 return getStruct<MachO::version_min_command>(this, L.Ptr);
2123}
2124
Tim Northover8f9590b2014-06-30 14:40:57 +00002125MachO::dylib_command
2126MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2127 return getStruct<MachO::dylib_command>(this, L.Ptr);
2128}
2129
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002130MachO::dyld_info_command
2131MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2132 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2133}
2134
2135MachO::dylinker_command
2136MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2137 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2138}
2139
2140MachO::uuid_command
2141MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2142 return getStruct<MachO::uuid_command>(this, L.Ptr);
2143}
2144
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002145MachO::rpath_command
2146MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2147 return getStruct<MachO::rpath_command>(this, L.Ptr);
2148}
2149
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002150MachO::source_version_command
2151MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2152 return getStruct<MachO::source_version_command>(this, L.Ptr);
2153}
2154
2155MachO::entry_point_command
2156MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2157 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2158}
2159
Kevin Enderby0804f4672014-12-16 23:25:52 +00002160MachO::encryption_info_command
2161MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2162 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2163}
2164
Kevin Enderby57538292014-12-17 01:01:30 +00002165MachO::encryption_info_command_64
2166MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2167 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2168}
2169
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002170MachO::sub_framework_command
2171MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2172 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2173}
Tim Northover8f9590b2014-06-30 14:40:57 +00002174
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002175MachO::sub_umbrella_command
2176MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2177 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2178}
2179
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002180MachO::sub_library_command
2181MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2182 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2183}
2184
Kevin Enderby186eac32014-12-19 21:06:24 +00002185MachO::sub_client_command
2186MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2187 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2188}
2189
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002190MachO::routines_command
2191MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2192 return getStruct<MachO::routines_command>(this, L.Ptr);
2193}
2194
2195MachO::routines_command_64
2196MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2197 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2198}
2199
Kevin Enderby48ef5342014-12-23 22:56:39 +00002200MachO::thread_command
2201MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2202 return getStruct<MachO::thread_command>(this, L.Ptr);
2203}
2204
Charles Davis8bdfafd2013-09-01 04:28:48 +00002205MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002206MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002207 DataRefImpl Sec;
2208 Sec.d.a = Rel.d.a;
2209 uint32_t Offset;
2210 if (is64Bit()) {
2211 MachO::section_64 Sect = getSection64(Sec);
2212 Offset = Sect.reloff;
2213 } else {
2214 MachO::section Sect = getSection(Sec);
2215 Offset = Sect.reloff;
2216 }
2217
2218 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2219 getPtr(this, Offset)) + Rel.d.b;
2220 return getStruct<MachO::any_relocation_info>(
2221 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002222}
2223
Charles Davis8bdfafd2013-09-01 04:28:48 +00002224MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002225MachOObjectFile::getDice(DataRefImpl Rel) const {
2226 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002227 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002228}
2229
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002230const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002231 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002232}
2233
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002234const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2235 assert(is64Bit());
2236 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002237}
2238
Charles Davis8bdfafd2013-09-01 04:28:48 +00002239uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2240 const MachO::dysymtab_command &DLC,
2241 unsigned Index) const {
2242 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2243 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002244}
2245
Charles Davis8bdfafd2013-09-01 04:28:48 +00002246MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002247MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2248 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002249 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2250 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002251}
2252
Charles Davis8bdfafd2013-09-01 04:28:48 +00002253MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002254 if (SymtabLoadCmd)
2255 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2256
2257 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2258 MachO::symtab_command Cmd;
2259 Cmd.cmd = MachO::LC_SYMTAB;
2260 Cmd.cmdsize = sizeof(MachO::symtab_command);
2261 Cmd.symoff = 0;
2262 Cmd.nsyms = 0;
2263 Cmd.stroff = 0;
2264 Cmd.strsize = 0;
2265 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002266}
2267
Charles Davis8bdfafd2013-09-01 04:28:48 +00002268MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002269 if (DysymtabLoadCmd)
2270 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2271
2272 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2273 MachO::dysymtab_command Cmd;
2274 Cmd.cmd = MachO::LC_DYSYMTAB;
2275 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2276 Cmd.ilocalsym = 0;
2277 Cmd.nlocalsym = 0;
2278 Cmd.iextdefsym = 0;
2279 Cmd.nextdefsym = 0;
2280 Cmd.iundefsym = 0;
2281 Cmd.nundefsym = 0;
2282 Cmd.tocoff = 0;
2283 Cmd.ntoc = 0;
2284 Cmd.modtaboff = 0;
2285 Cmd.nmodtab = 0;
2286 Cmd.extrefsymoff = 0;
2287 Cmd.nextrefsyms = 0;
2288 Cmd.indirectsymoff = 0;
2289 Cmd.nindirectsyms = 0;
2290 Cmd.extreloff = 0;
2291 Cmd.nextrel = 0;
2292 Cmd.locreloff = 0;
2293 Cmd.nlocrel = 0;
2294 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002295}
2296
Charles Davis8bdfafd2013-09-01 04:28:48 +00002297MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002298MachOObjectFile::getDataInCodeLoadCommand() const {
2299 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002300 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002301
2302 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002303 MachO::linkedit_data_command Cmd;
2304 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2305 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2306 Cmd.dataoff = 0;
2307 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002308 return Cmd;
2309}
2310
Kevin Enderby9a509442015-01-27 21:28:24 +00002311MachO::linkedit_data_command
2312MachOObjectFile::getLinkOptHintsLoadCommand() const {
2313 if (LinkOptHintsLoadCmd)
2314 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2315
2316 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2317 // fields.
2318 MachO::linkedit_data_command Cmd;
2319 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2320 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2321 Cmd.dataoff = 0;
2322 Cmd.datasize = 0;
2323 return Cmd;
2324}
2325
Nick Kledzikd04bc352014-08-30 00:20:14 +00002326ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002327 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002328 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002329
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002330 MachO::dyld_info_command DyldInfo =
2331 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2332 const uint8_t *Ptr =
2333 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002334 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002335}
2336
2337ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002338 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002339 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002340
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002341 MachO::dyld_info_command DyldInfo =
2342 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2343 const uint8_t *Ptr =
2344 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002345 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002346}
2347
2348ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002349 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002350 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002351
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002352 MachO::dyld_info_command DyldInfo =
2353 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2354 const uint8_t *Ptr =
2355 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002356 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002357}
2358
2359ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002360 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002361 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002362
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002363 MachO::dyld_info_command DyldInfo =
2364 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2365 const uint8_t *Ptr =
2366 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002367 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002368}
2369
2370ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002371 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002372 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002373
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002374 MachO::dyld_info_command DyldInfo =
2375 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2376 const uint8_t *Ptr =
2377 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002378 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002379}
2380
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002381ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2382 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002383 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002384 // Returning a pointer is fine as uuid doesn't need endian swapping.
2385 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002386 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002387}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002388
Rafael Espindola6e040c02013-04-26 20:07:33 +00002389StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002390 MachO::symtab_command S = getSymtabLoadCommand();
2391 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002392}
2393
Rafael Espindola56f976f2013-04-18 18:08:55 +00002394bool MachOObjectFile::is64Bit() const {
2395 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002396 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002397}
2398
2399void MachOObjectFile::ReadULEB128s(uint64_t Index,
2400 SmallVectorImpl<uint64_t> &Out) const {
2401 DataExtractor extractor(ObjectFile::getData(), true, 0);
2402
2403 uint32_t offset = Index;
2404 uint64_t data = 0;
2405 while (uint64_t delta = extractor.getULEB128(&offset)) {
2406 data += delta;
2407 Out.push_back(data);
2408 }
2409}
2410
Rafael Espindolac66d7612014-08-17 19:09:37 +00002411bool MachOObjectFile::isRelocatableObject() const {
2412 return getHeader().filetype == MachO::MH_OBJECT;
2413}
2414
Lang Hamesff044b12016-03-25 23:11:52 +00002415Expected<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002416ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2417 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00002418 if (Magic == "\xFE\xED\xFA\xCE")
Lang Hamesff044b12016-03-25 23:11:52 +00002419 return MachOObjectFile::create(Buffer, false, false);
David Blaikieb805f732016-03-28 17:45:48 +00002420 if (Magic == "\xCE\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002421 return MachOObjectFile::create(Buffer, true, false);
David Blaikieb805f732016-03-28 17:45:48 +00002422 if (Magic == "\xFE\xED\xFA\xCF")
Lang Hamesff044b12016-03-25 23:11:52 +00002423 return MachOObjectFile::create(Buffer, false, true);
David Blaikieb805f732016-03-28 17:45:48 +00002424 if (Magic == "\xCF\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002425 return MachOObjectFile::create(Buffer, true, true);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00002426 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00002427 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002428}