blob: 3262c6c26ab9ac60251b473a95ce5a12c16ea1ad [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
Alexey Samsonov9f336632015-06-04 19:45:22 +000041// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000042template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000043static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000044 // Don't read before the beginning or past the end of the file
45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46 report_fatal_error("Malformed MachO file.");
47
Rafael Espindola3cdeb172013-04-19 13:45:05 +000048 T Cmd;
49 memcpy(&Cmd, P, sizeof(T));
50 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000051 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000052 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000053}
54
Alexey Samsonov9f336632015-06-04 19:45:22 +000055template <typename T>
56static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57 // Don't read before the beginning or past the end of the file
58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59 return object_error::parse_failed;
60
61 T Cmd;
62 memcpy(&Cmd, P, sizeof(T));
63 if (O->isLittleEndian() != sys::IsLittleEndianHost)
64 MachO::swapStruct(Cmd);
65 return Cmd;
66}
67
Filipe Cabecinhas40139502015-01-15 22:52:38 +000068template <typename SegmentCmd>
69static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
70 uint32_t Cmdsize) {
71 const unsigned SectionSize = sizeof(SegmentCmd);
72 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
73 S.nsects * SectionSize > Cmdsize - sizeof(S))
74 report_fatal_error(
75 "Number of sections too large for size of load command.");
76 return S.nsects;
77}
78
Rafael Espindola56f976f2013-04-18 18:08:55 +000079static uint32_t
80getSegmentLoadCommandNumSections(const MachOObjectFile *O,
81 const MachOObjectFile::LoadCommandInfo &L) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000082 if (O->is64Bit())
83 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
84 L.C.cmdsize);
85
86 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
87 L.C.cmdsize);
Rafael Espindola5ffc0792013-04-07 16:07:35 +000088}
89
Nick Kledzik56ebef42014-09-16 01:41:51 +000090static bool isPageZeroSegment(const MachOObjectFile *O,
91 const MachOObjectFile::LoadCommandInfo &L) {
92 if (O->is64Bit()) {
93 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
94 return StringRef("__PAGEZERO").equals(S.segname);
95 }
96 MachO::segment_command S = O->getSegmentLoadCommand(L);
97 return StringRef("__PAGEZERO").equals(S.segname);
98}
99
100
Rafael Espindola6e040c02013-04-26 20:07:33 +0000101static const char *
102getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
103 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000104 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
105
106 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +0000107 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
108 sizeof(MachO::segment_command);
109 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
110 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000111
112 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +0000113 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +0000114}
115
Rafael Espindola56f976f2013-04-18 18:08:55 +0000116static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
117 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000118}
119
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000120static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +0000121getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000122 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000123 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000124}
125
Rafael Espindola56f976f2013-04-18 18:08:55 +0000126static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000127 if (P[15] == 0)
128 // Null terminated.
129 return P;
130 // Not null terminated, so this is a 16 char string.
131 return StringRef(P, 16);
132}
133
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134// Helper to advance a section or symbol iterator multiple increments at a time.
135template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000136static void advance(T &it, size_t Val) {
137 while (Val--)
138 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000139}
140
141static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000142 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000143}
144
Charles Davis8bdfafd2013-09-01 04:28:48 +0000145static uint32_t
146getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
147 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000148}
149
150static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000151getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
152 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000153}
154
155static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000156 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000157 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000158 return (RE.r_word1 >> 24) & 1;
159 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000160}
161
162static bool
163getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000164 const MachO::any_relocation_info &RE) {
165 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000166}
167
168static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000169 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000170 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000171 return (RE.r_word1 >> 25) & 3;
172 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000173}
174
175static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000176getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
177 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000178}
179
180static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000181 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000182 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000183 return RE.r_word1 >> 28;
184 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000185}
186
Rafael Espindola56f976f2013-04-18 18:08:55 +0000187static uint32_t getSectionFlags(const MachOObjectFile *O,
188 DataRefImpl Sec) {
189 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000190 MachO::section_64 Sect = O->getSection64(Sec);
191 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000192 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000193 MachO::section Sect = O->getSection(Sec);
194 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000195}
196
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000197static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000198getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000199 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
200 if (!CmdOrErr)
201 return CmdOrErr.getError();
202 if (CmdOrErr->cmdsize < 8)
203 return object_error::macho_small_load_command;
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000204 MachOObjectFile::LoadCommandInfo Load;
205 Load.Ptr = Ptr;
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000206 Load.C = CmdOrErr.get();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000207 return Load;
208}
209
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000210static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000211getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
212 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
213 : sizeof(MachO::mach_header);
214 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
215}
216
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000217static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000218getNextLoadCommandInfo(const MachOObjectFile *Obj,
219 const MachOObjectFile::LoadCommandInfo &L) {
220 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
221}
222
Alexey Samsonov9f336632015-06-04 19:45:22 +0000223template <typename T>
224static void parseHeader(const MachOObjectFile *Obj, T &Header,
225 std::error_code &EC) {
226 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
227 if (HeaderOrErr)
228 Header = HeaderOrErr.get();
229 else
230 EC = HeaderOrErr.getError();
231}
232
Rafael Espindola48af1c22014-08-19 18:44:46 +0000233MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
234 bool Is64bits, std::error_code &EC)
235 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000236 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000237 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
238 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
239 HasPageZeroSegment(false) {
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000240 if (is64Bit())
Alexey Samsonov9f336632015-06-04 19:45:22 +0000241 parseHeader(this, Header64, EC);
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000242 else
243 // First fields of MachO::mach_header_64 are the same as
244 // in MachO::mach_header.
Alexey Samsonov9f336632015-06-04 19:45:22 +0000245 parseHeader(this, *reinterpret_cast<MachO::mach_header *>(&this->Header64),
246 EC);
247 if (EC)
248 return;
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000249
250 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000251 if (LoadCommandCount == 0)
252 return;
253
Charles Davis8bdfafd2013-09-01 04:28:48 +0000254 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
255 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000256
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000257 auto LoadOrErr = getFirstLoadCommandInfo(this);
258 if (!LoadOrErr) {
259 EC = LoadOrErr.getError();
260 return;
261 }
262 LoadCommandInfo Load = LoadOrErr.get();
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000263 for (unsigned I = 0; I < LoadCommandCount; ++I) {
264 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000265 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000266 // Multiple symbol tables
267 if (SymtabLoadCmd) {
268 EC = object_error::parse_failed;
269 return;
270 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000271 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000272 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000273 // Multiple dynamic symbol tables
274 if (DysymtabLoadCmd) {
275 EC = object_error::parse_failed;
276 return;
277 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000278 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000279 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000280 // Multiple data in code tables
281 if (DataInCodeLoadCmd) {
282 EC = object_error::parse_failed;
283 return;
284 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000285 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000286 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
287 // Multiple linker optimization hint tables
288 if (LinkOptHintsLoadCmd) {
289 EC = object_error::parse_failed;
290 return;
291 }
292 LinkOptHintsLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000293 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
294 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000295 // Multiple dyldinfo load commands
296 if (DyldInfoLoadCmd) {
297 EC = object_error::parse_failed;
298 return;
299 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000300 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000301 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000302 // Multiple UUID load commands
303 if (UuidLoadCmd) {
304 EC = object_error::parse_failed;
305 return;
306 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000307 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000308 } else if (Load.C.cmd == SegmentLoadType) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +0000309 const unsigned SegmentLoadSize = this->is64Bit()
310 ? sizeof(MachO::segment_command_64)
311 : sizeof(MachO::segment_command);
312 if (Load.C.cmdsize < SegmentLoadSize)
313 report_fatal_error("Segment load command size is too small.");
314
Rafael Espindola56f976f2013-04-18 18:08:55 +0000315 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
316 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000317 const char *Sec = getSectionPtr(this, Load, J);
318 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000319 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000320 if (isPageZeroSegment(this, Load))
321 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000322 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
323 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
324 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
325 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
326 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
327 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000328 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000329 if (I < LoadCommandCount - 1) {
330 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
331 if (!LoadOrErr) {
332 EC = LoadOrErr.getError();
333 return;
334 }
335 Load = LoadOrErr.get();
336 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000337 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000338 assert(LoadCommands.size() == LoadCommandCount);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000339}
340
Rafael Espindola5e812af2014-01-30 02:49:50 +0000341void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000342 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000343 sizeof(MachO::nlist_64) :
344 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000345 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000346}
347
Rafael Espindola3acea392014-06-12 21:46:39 +0000348std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
349 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000350 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000351 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000352 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000353 if (Start < getData().begin() || Start >= getData().end())
354 report_fatal_error(
355 "Symbol name entry points before beginning or past end of file.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000356 Res = StringRef(Start);
357 return object_error::success;
358}
359
Rafael Espindola0e77a942014-12-10 20:46:55 +0000360unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
361 DataRefImpl DRI = Sec.getRawDataRefImpl();
362 uint32_t Flags = getSectionFlags(this, DRI);
363 return Flags & MachO::SECTION_TYPE;
364}
365
Kevin Enderby980b2582014-06-05 21:21:57 +0000366// getIndirectName() returns the name of the alias'ed symbol who's string table
367// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000368std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
369 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000370 StringRef StringTable = getStringTableData();
371 uint64_t NValue;
372 if (is64Bit()) {
373 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
374 NValue = Entry.n_value;
375 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
376 return object_error::parse_failed;
377 } else {
378 MachO::nlist Entry = getSymbolTableEntry(Symb);
379 NValue = Entry.n_value;
380 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
381 return object_error::parse_failed;
382 }
383 if (NValue >= StringTable.size())
384 return object_error::parse_failed;
385 const char *Start = &StringTable.data()[NValue];
386 Res = StringRef(Start);
387 return object_error::success;
388}
389
Rafael Espindola3acea392014-06-12 21:46:39 +0000390std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
391 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000392 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000393 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000394 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
395 Entry.n_value == 0)
396 Res = UnknownAddressOrSize;
397 else
398 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000399 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000400 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000401 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
402 Entry.n_value == 0)
403 Res = UnknownAddressOrSize;
404 else
405 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000406 }
407 return object_error::success;
408}
409
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000410uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000411 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000412 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000414 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000415 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000416 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000417}
418
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000419uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000420 uint64_t Value;
421 getSymbolAddress(DRI, Value);
Rafael Espindola62a07cb2015-05-22 15:43:00 +0000422 uint32_t flags = getSymbolFlags(DRI);
423 if (flags & SymbolRef::SF_Common)
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000424 return Value;
425 return UnknownAddressOrSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000426}
427
Rafael Espindola3acea392014-06-12 21:46:39 +0000428std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
429 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000430 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000431 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000432
433 Res = SymbolRef::ST_Other;
434
435 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000436 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437 Res = SymbolRef::ST_Debug;
438 return object_error::success;
439 }
440
Charles Davis74ec8b02013-08-27 05:00:13 +0000441 switch (n_type & MachO::N_TYPE) {
442 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000443 Res = SymbolRef::ST_Unknown;
444 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000445 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000446 Res = SymbolRef::ST_Function;
447 break;
448 }
449 return object_error::success;
450}
451
Rafael Espindola20122a42014-01-31 20:57:12 +0000452uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000453 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000454
Charles Davis8bdfafd2013-09-01 04:28:48 +0000455 uint8_t MachOType = Entry.n_type;
456 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000457
Rafael Espindola20122a42014-01-31 20:57:12 +0000458 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000459
Charles Davis74ec8b02013-08-27 05:00:13 +0000460 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000461 Result |= SymbolRef::SF_Undefined;
462
Tim Northovereaef0742014-05-30 13:22:59 +0000463 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
464 Result |= SymbolRef::SF_Indirect;
465
Rafael Espindolaa1356322013-11-02 05:03:24 +0000466 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000467 Result |= SymbolRef::SF_FormatSpecific;
468
Charles Davis74ec8b02013-08-27 05:00:13 +0000469 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000470 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000471 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000472 uint64_t Value;
473 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000474 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000475 Result |= SymbolRef::SF_Common;
476 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000477
478 if (!(MachOType & MachO::N_PEXT))
479 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000480 }
481
Charles Davis74ec8b02013-08-27 05:00:13 +0000482 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000483 Result |= SymbolRef::SF_Weak;
484
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000485 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
486 Result |= SymbolRef::SF_Thumb;
487
Charles Davis74ec8b02013-08-27 05:00:13 +0000488 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000489 Result |= SymbolRef::SF_Absolute;
490
Rafael Espindola20122a42014-01-31 20:57:12 +0000491 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000492}
493
Rafael Espindola3acea392014-06-12 21:46:39 +0000494std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
495 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000496 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000497 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000498
499 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000500 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000501 } else {
502 DataRefImpl DRI;
503 DRI.d.a = index - 1;
Rafael Espindola0d85d102015-05-22 14:59:27 +0000504 if (DRI.d.a >= Sections.size())
505 report_fatal_error("getSymbolSection: Invalid section index.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000506 Res = section_iterator(SectionRef(DRI, this));
507 }
508
509 return object_error::success;
510}
511
Rafael Espindola5e812af2014-01-30 02:49:50 +0000512void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000513 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000514}
515
Rafael Espindola3acea392014-06-12 21:46:39 +0000516std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
517 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000518 ArrayRef<char> Raw = getSectionRawName(Sec);
519 Result = parseSegmentOrSectionName(Raw.data());
520 return object_error::success;
521}
522
Rafael Espindola80291272014-10-08 15:28:58 +0000523uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
524 if (is64Bit())
525 return getSection64(Sec).addr;
526 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000527}
528
Rafael Espindola80291272014-10-08 15:28:58 +0000529uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
530 if (is64Bit())
531 return getSection64(Sec).size;
532 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000533}
534
Rafael Espindola3acea392014-06-12 21:46:39 +0000535std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
536 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537 uint32_t Offset;
538 uint64_t Size;
539
540 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000541 MachO::section_64 Sect = getSection64(Sec);
542 Offset = Sect.offset;
543 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000544 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000545 MachO::section Sect = getSection(Sec);
546 Offset = Sect.offset;
547 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000548 }
549
550 Res = this->getData().substr(Offset, Size);
551 return object_error::success;
552}
553
Rafael Espindola80291272014-10-08 15:28:58 +0000554uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000555 uint32_t Align;
556 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000557 MachO::section_64 Sect = getSection64(Sec);
558 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000559 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000560 MachO::section Sect = getSection(Sec);
561 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000562 }
563
Rafael Espindola80291272014-10-08 15:28:58 +0000564 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000565}
566
Rafael Espindola80291272014-10-08 15:28:58 +0000567bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000568 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000569 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000570}
571
Rafael Espindola80291272014-10-08 15:28:58 +0000572bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000573 uint32_t Flags = getSectionFlags(this, Sec);
574 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000575 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
576 !(SectionType == MachO::S_ZEROFILL ||
577 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000578}
579
Rafael Espindola80291272014-10-08 15:28:58 +0000580bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000581 uint32_t Flags = getSectionFlags(this, Sec);
582 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000583 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
584 (SectionType == MachO::S_ZEROFILL ||
585 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000586}
587
Rafael Espindola80291272014-10-08 15:28:58 +0000588bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000589 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000590 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000591}
592
Rafael Espindola80291272014-10-08 15:28:58 +0000593bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
594 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000595 SymbolRef::Type ST;
596 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000597 if (ST == SymbolRef::ST_Unknown)
598 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000599
Rafael Espindola80291272014-10-08 15:28:58 +0000600 uint64_t SectBegin = getSectionAddress(Sec);
601 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000602 SectEnd += SectBegin;
603
604 uint64_t SymAddr;
605 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000606 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000607}
608
Rui Ueyamabc654b12013-09-27 21:47:05 +0000609relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000610 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000611 Ret.d.a = Sec.d.a;
612 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000613 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000614}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000615
Rafael Espindola56f976f2013-04-18 18:08:55 +0000616relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000617MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000618 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000619 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000620 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000621 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000622 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000623 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000624 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000625 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000626
Rafael Espindola56f976f2013-04-18 18:08:55 +0000627 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000628 Ret.d.a = Sec.d.a;
629 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000630 return relocation_iterator(RelocationRef(Ret, this));
631}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000632
Rafael Espindola5e812af2014-01-30 02:49:50 +0000633void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000634 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000635}
Owen Anderson171f4852011-10-24 23:20:07 +0000636
Rafael Espindola3acea392014-06-12 21:46:39 +0000637std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
638 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000639 uint64_t Offset;
640 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000641
642 DataRefImpl Sec;
643 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000644 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000645 Res = SecAddress + Offset;
646 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000647}
648
Rafael Espindola3acea392014-06-12 21:46:39 +0000649std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
650 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000651 assert(getHeader().filetype == MachO::MH_OBJECT &&
652 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000653 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000654 Res = getAnyRelocationAddress(RE);
655 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000656}
657
Rafael Espindola806f0062013-06-05 01:33:53 +0000658symbol_iterator
659MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000660 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000661 if (isRelocationScattered(RE))
662 return symbol_end();
663
Rafael Espindola56f976f2013-04-18 18:08:55 +0000664 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
665 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000666 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000667 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000668
Charles Davis8bdfafd2013-09-01 04:28:48 +0000669 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000670 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000671 sizeof(MachO::nlist_64) :
672 sizeof(MachO::nlist);
673 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000674 DataRefImpl Sym;
675 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000676 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000677}
678
Keno Fischerc780e8e2015-05-21 21:24:32 +0000679section_iterator
680MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
681 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
682}
683
Rafael Espindola3acea392014-06-12 21:46:39 +0000684std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
685 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000686 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000687 Res = getAnyRelocationType(RE);
688 return object_error::success;
689}
690
Rafael Espindola3acea392014-06-12 21:46:39 +0000691std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000692MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
693 SmallVectorImpl<char> &Result) const {
694 StringRef res;
695 uint64_t RType;
696 getRelocationType(Rel, RType);
697
698 unsigned Arch = this->getArch();
699
700 switch (Arch) {
701 case Triple::x86: {
702 static const char *const Table[] = {
703 "GENERIC_RELOC_VANILLA",
704 "GENERIC_RELOC_PAIR",
705 "GENERIC_RELOC_SECTDIFF",
706 "GENERIC_RELOC_PB_LA_PTR",
707 "GENERIC_RELOC_LOCAL_SECTDIFF",
708 "GENERIC_RELOC_TLV" };
709
Eric Christopher13250cb2013-12-06 02:33:38 +0000710 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000711 res = "Unknown";
712 else
713 res = Table[RType];
714 break;
715 }
716 case Triple::x86_64: {
717 static const char *const Table[] = {
718 "X86_64_RELOC_UNSIGNED",
719 "X86_64_RELOC_SIGNED",
720 "X86_64_RELOC_BRANCH",
721 "X86_64_RELOC_GOT_LOAD",
722 "X86_64_RELOC_GOT",
723 "X86_64_RELOC_SUBTRACTOR",
724 "X86_64_RELOC_SIGNED_1",
725 "X86_64_RELOC_SIGNED_2",
726 "X86_64_RELOC_SIGNED_4",
727 "X86_64_RELOC_TLV" };
728
729 if (RType > 9)
730 res = "Unknown";
731 else
732 res = Table[RType];
733 break;
734 }
735 case Triple::arm: {
736 static const char *const Table[] = {
737 "ARM_RELOC_VANILLA",
738 "ARM_RELOC_PAIR",
739 "ARM_RELOC_SECTDIFF",
740 "ARM_RELOC_LOCAL_SECTDIFF",
741 "ARM_RELOC_PB_LA_PTR",
742 "ARM_RELOC_BR24",
743 "ARM_THUMB_RELOC_BR22",
744 "ARM_THUMB_32BIT_BRANCH",
745 "ARM_RELOC_HALF",
746 "ARM_RELOC_HALF_SECTDIFF" };
747
748 if (RType > 9)
749 res = "Unknown";
750 else
751 res = Table[RType];
752 break;
753 }
Tim Northover00ed9962014-03-29 10:18:08 +0000754 case Triple::aarch64: {
755 static const char *const Table[] = {
756 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
757 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
758 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
759 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
760 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
761 "ARM64_RELOC_ADDEND"
762 };
763
764 if (RType >= array_lengthof(Table))
765 res = "Unknown";
766 else
767 res = Table[RType];
768 break;
769 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000770 case Triple::ppc: {
771 static const char *const Table[] = {
772 "PPC_RELOC_VANILLA",
773 "PPC_RELOC_PAIR",
774 "PPC_RELOC_BR14",
775 "PPC_RELOC_BR24",
776 "PPC_RELOC_HI16",
777 "PPC_RELOC_LO16",
778 "PPC_RELOC_HA16",
779 "PPC_RELOC_LO14",
780 "PPC_RELOC_SECTDIFF",
781 "PPC_RELOC_PB_LA_PTR",
782 "PPC_RELOC_HI16_SECTDIFF",
783 "PPC_RELOC_LO16_SECTDIFF",
784 "PPC_RELOC_HA16_SECTDIFF",
785 "PPC_RELOC_JBSR",
786 "PPC_RELOC_LO14_SECTDIFF",
787 "PPC_RELOC_LOCAL_SECTDIFF" };
788
Eric Christopher13250cb2013-12-06 02:33:38 +0000789 if (RType > 15)
790 res = "Unknown";
791 else
792 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000793 break;
794 }
795 case Triple::UnknownArch:
796 res = "Unknown";
797 break;
798 }
799 Result.append(res.begin(), res.end());
800 return object_error::success;
801}
802
Rafael Espindola3acea392014-06-12 21:46:39 +0000803std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
804 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000805 unsigned Arch = getArch();
806 uint64_t Type;
807 getRelocationType(Rel, Type);
808
809 Result = false;
810
811 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
812 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000813 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000814 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000815 } else if (Arch == Triple::x86_64) {
816 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000817 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000818 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000819 DataRefImpl RelPrev = Rel;
820 RelPrev.d.a--;
821 uint64_t PrevType;
822 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000823 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000824 Result = true;
825 }
826 }
827
828 return object_error::success;
829}
830
Keno Fischer281b6942015-05-30 19:44:53 +0000831uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
832 MachO::any_relocation_info RE = getRelocation(Rel);
833 return getAnyRelocationLength(RE);
834}
835
Kevin Enderby980b2582014-06-05 21:21:57 +0000836//
837// guessLibraryShortName() is passed a name of a dynamic library and returns a
838// guess on what the short name is. Then name is returned as a substring of the
839// StringRef Name passed in. The name of the dynamic library is recognized as
840// a framework if it has one of the two following forms:
841// Foo.framework/Versions/A/Foo
842// Foo.framework/Foo
843// Where A and Foo can be any string. And may contain a trailing suffix
844// starting with an underbar. If the Name is recognized as a framework then
845// isFramework is set to true else it is set to false. If the Name has a
846// suffix then Suffix is set to the substring in Name that contains the suffix
847// else it is set to a NULL StringRef.
848//
849// The Name of the dynamic library is recognized as a library name if it has
850// one of the two following forms:
851// libFoo.A.dylib
852// libFoo.dylib
853// The library may have a suffix trailing the name Foo of the form:
854// libFoo_profile.A.dylib
855// libFoo_profile.dylib
856//
857// The Name of the dynamic library is also recognized as a library name if it
858// has the following form:
859// Foo.qtx
860//
861// If the Name of the dynamic library is none of the forms above then a NULL
862// StringRef is returned.
863//
864StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
865 bool &isFramework,
866 StringRef &Suffix) {
867 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
868 size_t a, b, c, d, Idx;
869
870 isFramework = false;
871 Suffix = StringRef();
872
873 // Pull off the last component and make Foo point to it
874 a = Name.rfind('/');
875 if (a == Name.npos || a == 0)
876 goto guess_library;
877 Foo = Name.slice(a+1, Name.npos);
878
879 // Look for a suffix starting with a '_'
880 Idx = Foo.rfind('_');
881 if (Idx != Foo.npos && Foo.size() >= 2) {
882 Suffix = Foo.slice(Idx, Foo.npos);
883 Foo = Foo.slice(0, Idx);
884 }
885
886 // First look for the form Foo.framework/Foo
887 b = Name.rfind('/', a);
888 if (b == Name.npos)
889 Idx = 0;
890 else
891 Idx = b+1;
892 F = Name.slice(Idx, Idx + Foo.size());
893 DotFramework = Name.slice(Idx + Foo.size(),
894 Idx + Foo.size() + sizeof(".framework/")-1);
895 if (F == Foo && DotFramework == ".framework/") {
896 isFramework = true;
897 return Foo;
898 }
899
900 // Next look for the form Foo.framework/Versions/A/Foo
901 if (b == Name.npos)
902 goto guess_library;
903 c = Name.rfind('/', b);
904 if (c == Name.npos || c == 0)
905 goto guess_library;
906 V = Name.slice(c+1, Name.npos);
907 if (!V.startswith("Versions/"))
908 goto guess_library;
909 d = Name.rfind('/', c);
910 if (d == Name.npos)
911 Idx = 0;
912 else
913 Idx = d+1;
914 F = Name.slice(Idx, Idx + Foo.size());
915 DotFramework = Name.slice(Idx + Foo.size(),
916 Idx + Foo.size() + sizeof(".framework/")-1);
917 if (F == Foo && DotFramework == ".framework/") {
918 isFramework = true;
919 return Foo;
920 }
921
922guess_library:
923 // pull off the suffix after the "." and make a point to it
924 a = Name.rfind('.');
925 if (a == Name.npos || a == 0)
926 return StringRef();
927 Dylib = Name.slice(a, Name.npos);
928 if (Dylib != ".dylib")
929 goto guess_qtx;
930
931 // First pull off the version letter for the form Foo.A.dylib if any.
932 if (a >= 3) {
933 Dot = Name.slice(a-2, a-1);
934 if (Dot == ".")
935 a = a - 2;
936 }
937
938 b = Name.rfind('/', a);
939 if (b == Name.npos)
940 b = 0;
941 else
942 b = b+1;
943 // ignore any suffix after an underbar like Foo_profile.A.dylib
944 Idx = Name.find('_', b);
945 if (Idx != Name.npos && Idx != b) {
946 Lib = Name.slice(b, Idx);
947 Suffix = Name.slice(Idx, a);
948 }
949 else
950 Lib = Name.slice(b, a);
951 // There are incorrect library names of the form:
952 // libATS.A_profile.dylib so check for these.
953 if (Lib.size() >= 3) {
954 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
955 if (Dot == ".")
956 Lib = Lib.slice(0, Lib.size()-2);
957 }
958 return Lib;
959
960guess_qtx:
961 Qtx = Name.slice(a, Name.npos);
962 if (Qtx != ".qtx")
963 return StringRef();
964 b = Name.rfind('/', a);
965 if (b == Name.npos)
966 Lib = Name.slice(0, a);
967 else
968 Lib = Name.slice(b+1, a);
969 // There are library names of the form: QT.A.qtx so check for these.
970 if (Lib.size() >= 3) {
971 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
972 if (Dot == ".")
973 Lib = Lib.slice(0, Lib.size()-2);
974 }
975 return Lib;
976}
977
978// getLibraryShortNameByIndex() is used to get the short name of the library
979// for an undefined symbol in a linked Mach-O binary that was linked with the
980// normal two-level namespace default (that is MH_TWOLEVEL in the header).
981// It is passed the index (0 - based) of the library as translated from
982// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +0000983std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +0000984 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000985 if (Index >= Libraries.size())
986 return object_error::parse_failed;
987
Kevin Enderby980b2582014-06-05 21:21:57 +0000988 // If the cache of LibrariesShortNames is not built up do that first for
989 // all the Libraries.
990 if (LibrariesShortNames.size() == 0) {
991 for (unsigned i = 0; i < Libraries.size(); i++) {
992 MachO::dylib_command D =
993 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +0000994 if (D.dylib.name >= D.cmdsize)
995 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +0000996 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +0000997 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +0000998 if (D.dylib.name+Name.size() >= D.cmdsize)
999 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001000 StringRef Suffix;
1001 bool isFramework;
1002 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001003 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001004 LibrariesShortNames.push_back(Name);
1005 else
1006 LibrariesShortNames.push_back(shortName);
1007 }
1008 }
1009
1010 Res = LibrariesShortNames[Index];
1011 return object_error::success;
1012}
1013
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001014basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001015 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001016}
1017
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001018basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001019 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001020 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001021 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001022
Charles Davis8bdfafd2013-09-01 04:28:48 +00001023 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001024 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001025 sizeof(MachO::nlist_64) :
1026 sizeof(MachO::nlist);
1027 unsigned Offset = Symtab.symoff +
1028 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001029 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001030 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001031}
1032
Lang Hames36072da2014-05-12 21:39:59 +00001033basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1034 DataRefImpl DRI;
1035 if (!SymtabLoadCmd)
1036 return basic_symbol_iterator(SymbolRef(DRI, this));
1037
1038 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001039 if (Index >= Symtab.nsyms)
1040 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001041 unsigned SymbolTableEntrySize =
1042 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1043 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1044 DRI.p += Index * SymbolTableEntrySize;
1045 return basic_symbol_iterator(SymbolRef(DRI, this));
1046}
1047
Rafael Espindolab5155a52014-02-10 20:24:04 +00001048section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001049 DataRefImpl DRI;
1050 return section_iterator(SectionRef(DRI, this));
1051}
1052
Rafael Espindolab5155a52014-02-10 20:24:04 +00001053section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001054 DataRefImpl DRI;
1055 DRI.d.a = Sections.size();
1056 return section_iterator(SectionRef(DRI, this));
1057}
1058
Rafael Espindola56f976f2013-04-18 18:08:55 +00001059uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001060 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001061}
1062
Rafael Espindola56f976f2013-04-18 18:08:55 +00001063StringRef MachOObjectFile::getFileFormatName() const {
1064 unsigned CPUType = getCPUType(this);
1065 if (!is64Bit()) {
1066 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001067 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001068 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001069 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001070 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001071 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001072 return "Mach-O 32-bit ppc";
1073 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001074 return "Mach-O 32-bit unknown";
1075 }
1076 }
1077
Rafael Espindola56f976f2013-04-18 18:08:55 +00001078 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001079 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001080 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001081 case llvm::MachO::CPU_TYPE_ARM64:
1082 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001083 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001084 return "Mach-O 64-bit ppc64";
1085 default:
1086 return "Mach-O 64-bit unknown";
1087 }
1088}
1089
Alexey Samsonove6388e62013-06-18 15:03:28 +00001090Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1091 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001092 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001093 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001094 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001095 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001096 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001097 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001098 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001099 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001100 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001101 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001102 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001103 return Triple::ppc64;
1104 default:
1105 return Triple::UnknownArch;
1106 }
1107}
1108
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001109Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1110 const char **McpuDefault) {
1111 if (McpuDefault)
1112 *McpuDefault = nullptr;
1113
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001114 switch (CPUType) {
1115 case MachO::CPU_TYPE_I386:
1116 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1117 case MachO::CPU_SUBTYPE_I386_ALL:
1118 return Triple("i386-apple-darwin");
1119 default:
1120 return Triple();
1121 }
1122 case MachO::CPU_TYPE_X86_64:
1123 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1124 case MachO::CPU_SUBTYPE_X86_64_ALL:
1125 return Triple("x86_64-apple-darwin");
1126 case MachO::CPU_SUBTYPE_X86_64_H:
1127 return Triple("x86_64h-apple-darwin");
1128 default:
1129 return Triple();
1130 }
1131 case MachO::CPU_TYPE_ARM:
1132 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1133 case MachO::CPU_SUBTYPE_ARM_V4T:
1134 return Triple("armv4t-apple-darwin");
1135 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1136 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001137 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1138 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001139 case MachO::CPU_SUBTYPE_ARM_V6:
1140 return Triple("armv6-apple-darwin");
1141 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001142 if (McpuDefault)
1143 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001144 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001145 case MachO::CPU_SUBTYPE_ARM_V7:
1146 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001147 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001148 if (McpuDefault)
1149 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001150 return Triple("armv7em-apple-darwin");
1151 case MachO::CPU_SUBTYPE_ARM_V7K:
1152 return Triple("armv7k-apple-darwin");
1153 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001154 if (McpuDefault)
1155 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001156 return Triple("armv7m-apple-darwin");
1157 case MachO::CPU_SUBTYPE_ARM_V7S:
1158 return Triple("armv7s-apple-darwin");
1159 default:
1160 return Triple();
1161 }
1162 case MachO::CPU_TYPE_ARM64:
1163 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1164 case MachO::CPU_SUBTYPE_ARM64_ALL:
1165 return Triple("arm64-apple-darwin");
1166 default:
1167 return Triple();
1168 }
1169 case MachO::CPU_TYPE_POWERPC:
1170 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1171 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1172 return Triple("ppc-apple-darwin");
1173 default:
1174 return Triple();
1175 }
1176 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001177 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001178 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1179 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001180 default:
1181 return Triple();
1182 }
1183 default:
1184 return Triple();
1185 }
1186}
1187
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001188Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1189 const char **McpuDefault) {
1190 if (McpuDefault)
1191 *McpuDefault = nullptr;
1192
1193 switch (CPUType) {
1194 case MachO::CPU_TYPE_ARM:
1195 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1196 case MachO::CPU_SUBTYPE_ARM_V4T:
1197 return Triple("thumbv4t-apple-darwin");
1198 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1199 return Triple("thumbv5e-apple-darwin");
1200 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1201 return Triple("xscale-apple-darwin");
1202 case MachO::CPU_SUBTYPE_ARM_V6:
1203 return Triple("thumbv6-apple-darwin");
1204 case MachO::CPU_SUBTYPE_ARM_V6M:
1205 if (McpuDefault)
1206 *McpuDefault = "cortex-m0";
1207 return Triple("thumbv6m-apple-darwin");
1208 case MachO::CPU_SUBTYPE_ARM_V7:
1209 return Triple("thumbv7-apple-darwin");
1210 case MachO::CPU_SUBTYPE_ARM_V7EM:
1211 if (McpuDefault)
1212 *McpuDefault = "cortex-m4";
1213 return Triple("thumbv7em-apple-darwin");
1214 case MachO::CPU_SUBTYPE_ARM_V7K:
1215 return Triple("thumbv7k-apple-darwin");
1216 case MachO::CPU_SUBTYPE_ARM_V7M:
1217 if (McpuDefault)
1218 *McpuDefault = "cortex-m3";
1219 return Triple("thumbv7m-apple-darwin");
1220 case MachO::CPU_SUBTYPE_ARM_V7S:
1221 return Triple("thumbv7s-apple-darwin");
1222 default:
1223 return Triple();
1224 }
1225 default:
1226 return Triple();
1227 }
1228}
1229
1230Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1231 const char **McpuDefault,
1232 Triple *ThumbTriple) {
1233 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1234 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1235 McpuDefault);
1236 return T;
1237}
1238
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001239Triple MachOObjectFile::getHostArch() {
1240 return Triple(sys::getDefaultTargetTriple());
1241}
1242
Rafael Espindola72318b42014-08-08 16:30:17 +00001243bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1244 return StringSwitch<bool>(ArchFlag)
1245 .Case("i386", true)
1246 .Case("x86_64", true)
1247 .Case("x86_64h", true)
1248 .Case("armv4t", true)
1249 .Case("arm", true)
1250 .Case("armv5e", true)
1251 .Case("armv6", true)
1252 .Case("armv6m", true)
1253 .Case("armv7em", true)
1254 .Case("armv7k", true)
1255 .Case("armv7m", true)
1256 .Case("armv7s", true)
1257 .Case("arm64", true)
1258 .Case("ppc", true)
1259 .Case("ppc64", true)
1260 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001261}
1262
Alexey Samsonove6388e62013-06-18 15:03:28 +00001263unsigned MachOObjectFile::getArch() const {
1264 return getArch(getCPUType(this));
1265}
1266
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001267Triple MachOObjectFile::getArch(const char **McpuDefault,
1268 Triple *ThumbTriple) const {
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001269 const auto &Header = getHeader();
1270 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1271 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001272}
1273
Rui Ueyamabc654b12013-09-27 21:47:05 +00001274relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001275 DataRefImpl DRI;
1276 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001277 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001278}
1279
Rui Ueyamabc654b12013-09-27 21:47:05 +00001280relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001281 DataRefImpl DRI;
1282 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001283 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001284}
1285
Kevin Enderby273ae012013-06-06 17:20:50 +00001286dice_iterator MachOObjectFile::begin_dices() const {
1287 DataRefImpl DRI;
1288 if (!DataInCodeLoadCmd)
1289 return dice_iterator(DiceRef(DRI, this));
1290
Charles Davis8bdfafd2013-09-01 04:28:48 +00001291 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1292 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001293 return dice_iterator(DiceRef(DRI, this));
1294}
1295
1296dice_iterator MachOObjectFile::end_dices() const {
1297 DataRefImpl DRI;
1298 if (!DataInCodeLoadCmd)
1299 return dice_iterator(DiceRef(DRI, this));
1300
Charles Davis8bdfafd2013-09-01 04:28:48 +00001301 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1302 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001303 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1304 return dice_iterator(DiceRef(DRI, this));
1305}
1306
Nick Kledzikd04bc352014-08-30 00:20:14 +00001307ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1308 : Trie(T), Malformed(false), Done(false) { }
1309
1310void ExportEntry::moveToFirst() {
1311 pushNode(0);
1312 pushDownUntilBottom();
1313}
1314
1315void ExportEntry::moveToEnd() {
1316 Stack.clear();
1317 Done = true;
1318}
1319
1320bool ExportEntry::operator==(const ExportEntry &Other) const {
1321 // Common case, one at end, other iterating from begin.
1322 if (Done || Other.Done)
1323 return (Done == Other.Done);
1324 // Not equal if different stack sizes.
1325 if (Stack.size() != Other.Stack.size())
1326 return false;
1327 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001328 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001329 return false;
1330 // Equal if all nodes in both stacks match.
1331 for (unsigned i=0; i < Stack.size(); ++i) {
1332 if (Stack[i].Start != Other.Stack[i].Start)
1333 return false;
1334 }
1335 return true;
1336}
1337
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001338uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1339 unsigned Count;
1340 uint64_t Result = decodeULEB128(Ptr, &Count);
1341 Ptr += Count;
1342 if (Ptr > Trie.end()) {
1343 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001344 Malformed = true;
1345 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001346 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001347}
1348
1349StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001350 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001351}
1352
1353uint64_t ExportEntry::flags() const {
1354 return Stack.back().Flags;
1355}
1356
1357uint64_t ExportEntry::address() const {
1358 return Stack.back().Address;
1359}
1360
1361uint64_t ExportEntry::other() const {
1362 return Stack.back().Other;
1363}
1364
1365StringRef ExportEntry::otherName() const {
1366 const char* ImportName = Stack.back().ImportName;
1367 if (ImportName)
1368 return StringRef(ImportName);
1369 return StringRef();
1370}
1371
1372uint32_t ExportEntry::nodeOffset() const {
1373 return Stack.back().Start - Trie.begin();
1374}
1375
1376ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1377 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1378 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1379 ParentStringLength(0), IsExportNode(false) {
1380}
1381
1382void ExportEntry::pushNode(uint64_t offset) {
1383 const uint8_t *Ptr = Trie.begin() + offset;
1384 NodeState State(Ptr);
1385 uint64_t ExportInfoSize = readULEB128(State.Current);
1386 State.IsExportNode = (ExportInfoSize != 0);
1387 const uint8_t* Children = State.Current + ExportInfoSize;
1388 if (State.IsExportNode) {
1389 State.Flags = readULEB128(State.Current);
1390 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1391 State.Address = 0;
1392 State.Other = readULEB128(State.Current); // dylib ordinal
1393 State.ImportName = reinterpret_cast<const char*>(State.Current);
1394 } else {
1395 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001396 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1397 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001398 }
1399 }
1400 State.ChildCount = *Children;
1401 State.Current = Children + 1;
1402 State.NextChildIndex = 0;
1403 State.ParentStringLength = CumulativeString.size();
1404 Stack.push_back(State);
1405}
1406
1407void ExportEntry::pushDownUntilBottom() {
1408 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1409 NodeState &Top = Stack.back();
1410 CumulativeString.resize(Top.ParentStringLength);
1411 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001412 char C = *Top.Current;
1413 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001414 }
1415 Top.Current += 1;
1416 uint64_t childNodeIndex = readULEB128(Top.Current);
1417 Top.NextChildIndex += 1;
1418 pushNode(childNodeIndex);
1419 }
1420 if (!Stack.back().IsExportNode) {
1421 Malformed = true;
1422 moveToEnd();
1423 }
1424}
1425
1426// We have a trie data structure and need a way to walk it that is compatible
1427// with the C++ iterator model. The solution is a non-recursive depth first
1428// traversal where the iterator contains a stack of parent nodes along with a
1429// string that is the accumulation of all edge strings along the parent chain
1430// to this point.
1431//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001432// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001433// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1434// node may have child nodes too.
1435//
1436// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1437// child until hitting a node with no children (which is an export node or
1438// else the trie is malformed). On the way down, each node is pushed on the
1439// stack ivar. If there is no more ways down, it pops up one and tries to go
1440// down a sibling path until a childless node is reached.
1441void ExportEntry::moveNext() {
1442 if (Stack.empty() || !Stack.back().IsExportNode) {
1443 Malformed = true;
1444 moveToEnd();
1445 return;
1446 }
1447
1448 Stack.pop_back();
1449 while (!Stack.empty()) {
1450 NodeState &Top = Stack.back();
1451 if (Top.NextChildIndex < Top.ChildCount) {
1452 pushDownUntilBottom();
1453 // Now at the next export node.
1454 return;
1455 } else {
1456 if (Top.IsExportNode) {
1457 // This node has no children but is itself an export node.
1458 CumulativeString.resize(Top.ParentStringLength);
1459 return;
1460 }
1461 Stack.pop_back();
1462 }
1463 }
1464 Done = true;
1465}
1466
1467iterator_range<export_iterator>
1468MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1469 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001470 if (Trie.size() == 0)
1471 Start.moveToEnd();
1472 else
1473 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001474
1475 ExportEntry Finish(Trie);
1476 Finish.moveToEnd();
1477
1478 return iterator_range<export_iterator>(export_iterator(Start),
1479 export_iterator(Finish));
1480}
1481
1482iterator_range<export_iterator> MachOObjectFile::exports() const {
1483 return exports(getDyldInfoExportsTrie());
1484}
1485
1486
Nick Kledzikac431442014-09-12 21:34:15 +00001487MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1488 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1489 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1490 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1491
1492void MachORebaseEntry::moveToFirst() {
1493 Ptr = Opcodes.begin();
1494 moveNext();
1495}
1496
1497void MachORebaseEntry::moveToEnd() {
1498 Ptr = Opcodes.end();
1499 RemainingLoopCount = 0;
1500 Done = true;
1501}
1502
1503void MachORebaseEntry::moveNext() {
1504 // If in the middle of some loop, move to next rebasing in loop.
1505 SegmentOffset += AdvanceAmount;
1506 if (RemainingLoopCount) {
1507 --RemainingLoopCount;
1508 return;
1509 }
1510 if (Ptr == Opcodes.end()) {
1511 Done = true;
1512 return;
1513 }
1514 bool More = true;
1515 while (More && !Malformed) {
1516 // Parse next opcode and set up next loop.
1517 uint8_t Byte = *Ptr++;
1518 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1519 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1520 switch (Opcode) {
1521 case MachO::REBASE_OPCODE_DONE:
1522 More = false;
1523 Done = true;
1524 moveToEnd();
1525 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1526 break;
1527 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1528 RebaseType = ImmValue;
1529 DEBUG_WITH_TYPE(
1530 "mach-o-rebase",
1531 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1532 << "RebaseType=" << (int) RebaseType << "\n");
1533 break;
1534 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1535 SegmentIndex = ImmValue;
1536 SegmentOffset = readULEB128();
1537 DEBUG_WITH_TYPE(
1538 "mach-o-rebase",
1539 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1540 << "SegmentIndex=" << SegmentIndex << ", "
1541 << format("SegmentOffset=0x%06X", SegmentOffset)
1542 << "\n");
1543 break;
1544 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1545 SegmentOffset += readULEB128();
1546 DEBUG_WITH_TYPE("mach-o-rebase",
1547 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1548 << format("SegmentOffset=0x%06X",
1549 SegmentOffset) << "\n");
1550 break;
1551 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1552 SegmentOffset += ImmValue * PointerSize;
1553 DEBUG_WITH_TYPE("mach-o-rebase",
1554 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1555 << format("SegmentOffset=0x%06X",
1556 SegmentOffset) << "\n");
1557 break;
1558 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1559 AdvanceAmount = PointerSize;
1560 RemainingLoopCount = ImmValue - 1;
1561 DEBUG_WITH_TYPE(
1562 "mach-o-rebase",
1563 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1564 << format("SegmentOffset=0x%06X", SegmentOffset)
1565 << ", AdvanceAmount=" << AdvanceAmount
1566 << ", RemainingLoopCount=" << RemainingLoopCount
1567 << "\n");
1568 return;
1569 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1570 AdvanceAmount = PointerSize;
1571 RemainingLoopCount = readULEB128() - 1;
1572 DEBUG_WITH_TYPE(
1573 "mach-o-rebase",
1574 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1575 << format("SegmentOffset=0x%06X", SegmentOffset)
1576 << ", AdvanceAmount=" << AdvanceAmount
1577 << ", RemainingLoopCount=" << RemainingLoopCount
1578 << "\n");
1579 return;
1580 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1581 AdvanceAmount = readULEB128() + PointerSize;
1582 RemainingLoopCount = 0;
1583 DEBUG_WITH_TYPE(
1584 "mach-o-rebase",
1585 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1586 << format("SegmentOffset=0x%06X", SegmentOffset)
1587 << ", AdvanceAmount=" << AdvanceAmount
1588 << ", RemainingLoopCount=" << RemainingLoopCount
1589 << "\n");
1590 return;
1591 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1592 RemainingLoopCount = readULEB128() - 1;
1593 AdvanceAmount = readULEB128() + PointerSize;
1594 DEBUG_WITH_TYPE(
1595 "mach-o-rebase",
1596 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1597 << format("SegmentOffset=0x%06X", SegmentOffset)
1598 << ", AdvanceAmount=" << AdvanceAmount
1599 << ", RemainingLoopCount=" << RemainingLoopCount
1600 << "\n");
1601 return;
1602 default:
1603 Malformed = true;
1604 }
1605 }
1606}
1607
1608uint64_t MachORebaseEntry::readULEB128() {
1609 unsigned Count;
1610 uint64_t Result = decodeULEB128(Ptr, &Count);
1611 Ptr += Count;
1612 if (Ptr > Opcodes.end()) {
1613 Ptr = Opcodes.end();
1614 Malformed = true;
1615 }
1616 return Result;
1617}
1618
1619uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1620
1621uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1622
1623StringRef MachORebaseEntry::typeName() const {
1624 switch (RebaseType) {
1625 case MachO::REBASE_TYPE_POINTER:
1626 return "pointer";
1627 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1628 return "text abs32";
1629 case MachO::REBASE_TYPE_TEXT_PCREL32:
1630 return "text rel32";
1631 }
1632 return "unknown";
1633}
1634
1635bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1636 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1637 return (Ptr == Other.Ptr) &&
1638 (RemainingLoopCount == Other.RemainingLoopCount) &&
1639 (Done == Other.Done);
1640}
1641
1642iterator_range<rebase_iterator>
1643MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1644 MachORebaseEntry Start(Opcodes, is64);
1645 Start.moveToFirst();
1646
1647 MachORebaseEntry Finish(Opcodes, is64);
1648 Finish.moveToEnd();
1649
1650 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1651 rebase_iterator(Finish));
1652}
1653
1654iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1655 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1656}
1657
Nick Kledzik56ebef42014-09-16 01:41:51 +00001658
1659MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1660 Kind BK)
1661 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1662 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1663 BindType(0), PointerSize(is64Bit ? 8 : 4),
1664 TableKind(BK), Malformed(false), Done(false) {}
1665
1666void MachOBindEntry::moveToFirst() {
1667 Ptr = Opcodes.begin();
1668 moveNext();
1669}
1670
1671void MachOBindEntry::moveToEnd() {
1672 Ptr = Opcodes.end();
1673 RemainingLoopCount = 0;
1674 Done = true;
1675}
1676
1677void MachOBindEntry::moveNext() {
1678 // If in the middle of some loop, move to next binding in loop.
1679 SegmentOffset += AdvanceAmount;
1680 if (RemainingLoopCount) {
1681 --RemainingLoopCount;
1682 return;
1683 }
1684 if (Ptr == Opcodes.end()) {
1685 Done = true;
1686 return;
1687 }
1688 bool More = true;
1689 while (More && !Malformed) {
1690 // Parse next opcode and set up next loop.
1691 uint8_t Byte = *Ptr++;
1692 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1693 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1694 int8_t SignExtended;
1695 const uint8_t *SymStart;
1696 switch (Opcode) {
1697 case MachO::BIND_OPCODE_DONE:
1698 if (TableKind == Kind::Lazy) {
1699 // Lazying bindings have a DONE opcode between entries. Need to ignore
1700 // it to advance to next entry. But need not if this is last entry.
1701 bool NotLastEntry = false;
1702 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1703 if (*P) {
1704 NotLastEntry = true;
1705 }
1706 }
1707 if (NotLastEntry)
1708 break;
1709 }
1710 More = false;
1711 Done = true;
1712 moveToEnd();
1713 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1714 break;
1715 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1716 Ordinal = ImmValue;
1717 DEBUG_WITH_TYPE(
1718 "mach-o-bind",
1719 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1720 << "Ordinal=" << Ordinal << "\n");
1721 break;
1722 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1723 Ordinal = readULEB128();
1724 DEBUG_WITH_TYPE(
1725 "mach-o-bind",
1726 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1727 << "Ordinal=" << Ordinal << "\n");
1728 break;
1729 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1730 if (ImmValue) {
1731 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1732 Ordinal = SignExtended;
1733 } else
1734 Ordinal = 0;
1735 DEBUG_WITH_TYPE(
1736 "mach-o-bind",
1737 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1738 << "Ordinal=" << Ordinal << "\n");
1739 break;
1740 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1741 Flags = ImmValue;
1742 SymStart = Ptr;
1743 while (*Ptr) {
1744 ++Ptr;
1745 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001746 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1747 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001748 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001749 DEBUG_WITH_TYPE(
1750 "mach-o-bind",
1751 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1752 << "SymbolName=" << SymbolName << "\n");
1753 if (TableKind == Kind::Weak) {
1754 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1755 return;
1756 }
1757 break;
1758 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1759 BindType = ImmValue;
1760 DEBUG_WITH_TYPE(
1761 "mach-o-bind",
1762 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1763 << "BindType=" << (int)BindType << "\n");
1764 break;
1765 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1766 Addend = readSLEB128();
1767 if (TableKind == Kind::Lazy)
1768 Malformed = true;
1769 DEBUG_WITH_TYPE(
1770 "mach-o-bind",
1771 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1772 << "Addend=" << Addend << "\n");
1773 break;
1774 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1775 SegmentIndex = ImmValue;
1776 SegmentOffset = readULEB128();
1777 DEBUG_WITH_TYPE(
1778 "mach-o-bind",
1779 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1780 << "SegmentIndex=" << SegmentIndex << ", "
1781 << format("SegmentOffset=0x%06X", SegmentOffset)
1782 << "\n");
1783 break;
1784 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1785 SegmentOffset += readULEB128();
1786 DEBUG_WITH_TYPE("mach-o-bind",
1787 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1788 << format("SegmentOffset=0x%06X",
1789 SegmentOffset) << "\n");
1790 break;
1791 case MachO::BIND_OPCODE_DO_BIND:
1792 AdvanceAmount = PointerSize;
1793 RemainingLoopCount = 0;
1794 DEBUG_WITH_TYPE("mach-o-bind",
1795 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1796 << format("SegmentOffset=0x%06X",
1797 SegmentOffset) << "\n");
1798 return;
1799 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001800 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001801 RemainingLoopCount = 0;
1802 if (TableKind == Kind::Lazy)
1803 Malformed = true;
1804 DEBUG_WITH_TYPE(
1805 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001806 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001807 << format("SegmentOffset=0x%06X", SegmentOffset)
1808 << ", AdvanceAmount=" << AdvanceAmount
1809 << ", RemainingLoopCount=" << RemainingLoopCount
1810 << "\n");
1811 return;
1812 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001813 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001814 RemainingLoopCount = 0;
1815 if (TableKind == Kind::Lazy)
1816 Malformed = true;
1817 DEBUG_WITH_TYPE("mach-o-bind",
1818 llvm::dbgs()
1819 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1820 << format("SegmentOffset=0x%06X",
1821 SegmentOffset) << "\n");
1822 return;
1823 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1824 RemainingLoopCount = readULEB128() - 1;
1825 AdvanceAmount = readULEB128() + PointerSize;
1826 if (TableKind == Kind::Lazy)
1827 Malformed = true;
1828 DEBUG_WITH_TYPE(
1829 "mach-o-bind",
1830 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1831 << format("SegmentOffset=0x%06X", SegmentOffset)
1832 << ", AdvanceAmount=" << AdvanceAmount
1833 << ", RemainingLoopCount=" << RemainingLoopCount
1834 << "\n");
1835 return;
1836 default:
1837 Malformed = true;
1838 }
1839 }
1840}
1841
1842uint64_t MachOBindEntry::readULEB128() {
1843 unsigned Count;
1844 uint64_t Result = decodeULEB128(Ptr, &Count);
1845 Ptr += Count;
1846 if (Ptr > Opcodes.end()) {
1847 Ptr = Opcodes.end();
1848 Malformed = true;
1849 }
1850 return Result;
1851}
1852
1853int64_t MachOBindEntry::readSLEB128() {
1854 unsigned Count;
1855 int64_t Result = decodeSLEB128(Ptr, &Count);
1856 Ptr += Count;
1857 if (Ptr > Opcodes.end()) {
1858 Ptr = Opcodes.end();
1859 Malformed = true;
1860 }
1861 return Result;
1862}
1863
1864
1865uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1866
1867uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1868
1869StringRef MachOBindEntry::typeName() const {
1870 switch (BindType) {
1871 case MachO::BIND_TYPE_POINTER:
1872 return "pointer";
1873 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1874 return "text abs32";
1875 case MachO::BIND_TYPE_TEXT_PCREL32:
1876 return "text rel32";
1877 }
1878 return "unknown";
1879}
1880
1881StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1882
1883int64_t MachOBindEntry::addend() const { return Addend; }
1884
1885uint32_t MachOBindEntry::flags() const { return Flags; }
1886
1887int MachOBindEntry::ordinal() const { return Ordinal; }
1888
1889bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1890 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1891 return (Ptr == Other.Ptr) &&
1892 (RemainingLoopCount == Other.RemainingLoopCount) &&
1893 (Done == Other.Done);
1894}
1895
1896iterator_range<bind_iterator>
1897MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1898 MachOBindEntry::Kind BKind) {
1899 MachOBindEntry Start(Opcodes, is64, BKind);
1900 Start.moveToFirst();
1901
1902 MachOBindEntry Finish(Opcodes, is64, BKind);
1903 Finish.moveToEnd();
1904
1905 return iterator_range<bind_iterator>(bind_iterator(Start),
1906 bind_iterator(Finish));
1907}
1908
1909iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1910 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1911 MachOBindEntry::Kind::Regular);
1912}
1913
1914iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1915 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1916 MachOBindEntry::Kind::Lazy);
1917}
1918
1919iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1920 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1921 MachOBindEntry::Kind::Weak);
1922}
1923
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001924MachOObjectFile::load_command_iterator
1925MachOObjectFile::begin_load_commands() const {
1926 return LoadCommands.begin();
1927}
1928
1929MachOObjectFile::load_command_iterator
1930MachOObjectFile::end_load_commands() const {
1931 return LoadCommands.end();
1932}
1933
1934iterator_range<MachOObjectFile::load_command_iterator>
1935MachOObjectFile::load_commands() const {
1936 return iterator_range<load_command_iterator>(begin_load_commands(),
1937 end_load_commands());
1938}
1939
Rafael Espindola56f976f2013-04-18 18:08:55 +00001940StringRef
1941MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1942 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1943 return parseSegmentOrSectionName(Raw.data());
1944}
1945
1946ArrayRef<char>
1947MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001948 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001949 const section_base *Base =
1950 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001951 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001952}
1953
1954ArrayRef<char>
1955MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001956 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001957 const section_base *Base =
1958 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001959 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001960}
1961
1962bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001963MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001964 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001965 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001966 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001967 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001968}
1969
Eric Christopher1d62c252013-07-22 22:25:07 +00001970unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001971 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001972 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001973 return RE.r_word1 & 0xffffff;
1974 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001975}
1976
Eric Christopher1d62c252013-07-22 22:25:07 +00001977bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001978 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001979 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001980 return (RE.r_word1 >> 27) & 1;
1981 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001982}
1983
Eric Christopher1d62c252013-07-22 22:25:07 +00001984bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001985 const MachO::any_relocation_info &RE) const {
1986 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001987}
1988
Eric Christopher1d62c252013-07-22 22:25:07 +00001989uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001990 const MachO::any_relocation_info &RE) const {
1991 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001992}
1993
Kevin Enderby9907d0a2014-11-04 00:43:16 +00001994uint32_t MachOObjectFile::getScatteredRelocationType(
1995 const MachO::any_relocation_info &RE) const {
1996 return (RE.r_word0 >> 24) & 0xf;
1997}
1998
Eric Christopher1d62c252013-07-22 22:25:07 +00001999unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002000 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002001 if (isRelocationScattered(RE))
2002 return getScatteredRelocationAddress(RE);
2003 return getPlainRelocationAddress(RE);
2004}
2005
Charles Davis8bdfafd2013-09-01 04:28:48 +00002006unsigned MachOObjectFile::getAnyRelocationPCRel(
2007 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002008 if (isRelocationScattered(RE))
2009 return getScatteredRelocationPCRel(this, RE);
2010 return getPlainRelocationPCRel(this, RE);
2011}
2012
Eric Christopher1d62c252013-07-22 22:25:07 +00002013unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002014 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002015 if (isRelocationScattered(RE))
2016 return getScatteredRelocationLength(RE);
2017 return getPlainRelocationLength(this, RE);
2018}
2019
2020unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002021MachOObjectFile::getAnyRelocationType(
2022 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002023 if (isRelocationScattered(RE))
2024 return getScatteredRelocationType(RE);
2025 return getPlainRelocationType(this, RE);
2026}
2027
Rafael Espindola52501032013-04-30 15:40:54 +00002028SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002029MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002030 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002031 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002032 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002033 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2034 DataRefImpl DRI;
2035 DRI.d.a = SecNum;
2036 return SectionRef(DRI, this);
2037}
2038
Charles Davis8bdfafd2013-09-01 04:28:48 +00002039MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002040 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002041 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002042}
2043
Charles Davis8bdfafd2013-09-01 04:28:48 +00002044MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002045 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002046 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002047}
2048
Charles Davis8bdfafd2013-09-01 04:28:48 +00002049MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002050 unsigned Index) const {
2051 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002052 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002053}
2054
Charles Davis8bdfafd2013-09-01 04:28:48 +00002055MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2056 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002057 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002058 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002059}
2060
Charles Davis8bdfafd2013-09-01 04:28:48 +00002061MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002062MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002063 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002064 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002065}
2066
Charles Davis8bdfafd2013-09-01 04:28:48 +00002067MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002068MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002069 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002070 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002071}
2072
Charles Davis8bdfafd2013-09-01 04:28:48 +00002073MachO::linkedit_data_command
2074MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2075 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002076}
2077
Charles Davis8bdfafd2013-09-01 04:28:48 +00002078MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002079MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002080 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002081}
2082
Charles Davis8bdfafd2013-09-01 04:28:48 +00002083MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002084MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002085 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002086}
2087
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002088MachO::linker_option_command
2089MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2090 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002091}
2092
Jim Grosbach448334a2014-03-18 22:09:05 +00002093MachO::version_min_command
2094MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2095 return getStruct<MachO::version_min_command>(this, L.Ptr);
2096}
2097
Tim Northover8f9590b2014-06-30 14:40:57 +00002098MachO::dylib_command
2099MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2100 return getStruct<MachO::dylib_command>(this, L.Ptr);
2101}
2102
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002103MachO::dyld_info_command
2104MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2105 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2106}
2107
2108MachO::dylinker_command
2109MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2110 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2111}
2112
2113MachO::uuid_command
2114MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2115 return getStruct<MachO::uuid_command>(this, L.Ptr);
2116}
2117
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002118MachO::rpath_command
2119MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2120 return getStruct<MachO::rpath_command>(this, L.Ptr);
2121}
2122
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002123MachO::source_version_command
2124MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2125 return getStruct<MachO::source_version_command>(this, L.Ptr);
2126}
2127
2128MachO::entry_point_command
2129MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2130 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2131}
2132
Kevin Enderby0804f4672014-12-16 23:25:52 +00002133MachO::encryption_info_command
2134MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2135 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2136}
2137
Kevin Enderby57538292014-12-17 01:01:30 +00002138MachO::encryption_info_command_64
2139MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2140 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2141}
2142
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002143MachO::sub_framework_command
2144MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2145 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2146}
Tim Northover8f9590b2014-06-30 14:40:57 +00002147
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002148MachO::sub_umbrella_command
2149MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2150 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2151}
2152
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002153MachO::sub_library_command
2154MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2155 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2156}
2157
Kevin Enderby186eac32014-12-19 21:06:24 +00002158MachO::sub_client_command
2159MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2160 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2161}
2162
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002163MachO::routines_command
2164MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2165 return getStruct<MachO::routines_command>(this, L.Ptr);
2166}
2167
2168MachO::routines_command_64
2169MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2170 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2171}
2172
Kevin Enderby48ef5342014-12-23 22:56:39 +00002173MachO::thread_command
2174MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2175 return getStruct<MachO::thread_command>(this, L.Ptr);
2176}
2177
Charles Davis8bdfafd2013-09-01 04:28:48 +00002178MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002179MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002180 DataRefImpl Sec;
2181 Sec.d.a = Rel.d.a;
2182 uint32_t Offset;
2183 if (is64Bit()) {
2184 MachO::section_64 Sect = getSection64(Sec);
2185 Offset = Sect.reloff;
2186 } else {
2187 MachO::section Sect = getSection(Sec);
2188 Offset = Sect.reloff;
2189 }
2190
2191 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2192 getPtr(this, Offset)) + Rel.d.b;
2193 return getStruct<MachO::any_relocation_info>(
2194 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002195}
2196
Charles Davis8bdfafd2013-09-01 04:28:48 +00002197MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002198MachOObjectFile::getDice(DataRefImpl Rel) const {
2199 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002200 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002201}
2202
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002203const MachO::mach_header &MachOObjectFile::getHeader() const {
2204 // First fields of MachO::mach_header_64 are the same as
2205 // in MachO::mach_header.
2206 return *reinterpret_cast<const MachO::mach_header *>(&this->Header64);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002207}
2208
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002209const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2210 assert(is64Bit());
2211 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002212}
2213
Charles Davis8bdfafd2013-09-01 04:28:48 +00002214uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2215 const MachO::dysymtab_command &DLC,
2216 unsigned Index) const {
2217 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2218 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002219}
2220
Charles Davis8bdfafd2013-09-01 04:28:48 +00002221MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002222MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2223 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002224 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2225 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002226}
2227
Charles Davis8bdfafd2013-09-01 04:28:48 +00002228MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002229 if (SymtabLoadCmd)
2230 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2231
2232 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2233 MachO::symtab_command Cmd;
2234 Cmd.cmd = MachO::LC_SYMTAB;
2235 Cmd.cmdsize = sizeof(MachO::symtab_command);
2236 Cmd.symoff = 0;
2237 Cmd.nsyms = 0;
2238 Cmd.stroff = 0;
2239 Cmd.strsize = 0;
2240 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002241}
2242
Charles Davis8bdfafd2013-09-01 04:28:48 +00002243MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002244 if (DysymtabLoadCmd)
2245 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2246
2247 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2248 MachO::dysymtab_command Cmd;
2249 Cmd.cmd = MachO::LC_DYSYMTAB;
2250 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2251 Cmd.ilocalsym = 0;
2252 Cmd.nlocalsym = 0;
2253 Cmd.iextdefsym = 0;
2254 Cmd.nextdefsym = 0;
2255 Cmd.iundefsym = 0;
2256 Cmd.nundefsym = 0;
2257 Cmd.tocoff = 0;
2258 Cmd.ntoc = 0;
2259 Cmd.modtaboff = 0;
2260 Cmd.nmodtab = 0;
2261 Cmd.extrefsymoff = 0;
2262 Cmd.nextrefsyms = 0;
2263 Cmd.indirectsymoff = 0;
2264 Cmd.nindirectsyms = 0;
2265 Cmd.extreloff = 0;
2266 Cmd.nextrel = 0;
2267 Cmd.locreloff = 0;
2268 Cmd.nlocrel = 0;
2269 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002270}
2271
Charles Davis8bdfafd2013-09-01 04:28:48 +00002272MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002273MachOObjectFile::getDataInCodeLoadCommand() const {
2274 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002275 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002276
2277 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002278 MachO::linkedit_data_command Cmd;
2279 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2280 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2281 Cmd.dataoff = 0;
2282 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002283 return Cmd;
2284}
2285
Kevin Enderby9a509442015-01-27 21:28:24 +00002286MachO::linkedit_data_command
2287MachOObjectFile::getLinkOptHintsLoadCommand() const {
2288 if (LinkOptHintsLoadCmd)
2289 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2290
2291 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2292 // fields.
2293 MachO::linkedit_data_command Cmd;
2294 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2295 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2296 Cmd.dataoff = 0;
2297 Cmd.datasize = 0;
2298 return Cmd;
2299}
2300
Nick Kledzikd04bc352014-08-30 00:20:14 +00002301ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2302 if (!DyldInfoLoadCmd)
2303 return ArrayRef<uint8_t>();
2304
2305 MachO::dyld_info_command DyldInfo
2306 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2307 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2308 getPtr(this, DyldInfo.rebase_off));
2309 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2310}
2311
2312ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2313 if (!DyldInfoLoadCmd)
2314 return ArrayRef<uint8_t>();
2315
2316 MachO::dyld_info_command DyldInfo
2317 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2318 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2319 getPtr(this, DyldInfo.bind_off));
2320 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2321}
2322
2323ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2324 if (!DyldInfoLoadCmd)
2325 return ArrayRef<uint8_t>();
2326
2327 MachO::dyld_info_command DyldInfo
2328 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2329 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2330 getPtr(this, DyldInfo.weak_bind_off));
2331 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2332}
2333
2334ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2335 if (!DyldInfoLoadCmd)
2336 return ArrayRef<uint8_t>();
2337
2338 MachO::dyld_info_command DyldInfo
2339 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2340 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2341 getPtr(this, DyldInfo.lazy_bind_off));
2342 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2343}
2344
2345ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2346 if (!DyldInfoLoadCmd)
2347 return ArrayRef<uint8_t>();
2348
2349 MachO::dyld_info_command DyldInfo
2350 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2351 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2352 getPtr(this, DyldInfo.export_off));
2353 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2354}
2355
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002356ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2357 if (!UuidLoadCmd)
2358 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002359 // Returning a pointer is fine as uuid doesn't need endian swapping.
2360 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2361 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002362}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002363
Rafael Espindola6e040c02013-04-26 20:07:33 +00002364StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002365 MachO::symtab_command S = getSymtabLoadCommand();
2366 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002367}
2368
Rafael Espindola56f976f2013-04-18 18:08:55 +00002369bool MachOObjectFile::is64Bit() const {
2370 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002371 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002372}
2373
2374void MachOObjectFile::ReadULEB128s(uint64_t Index,
2375 SmallVectorImpl<uint64_t> &Out) const {
2376 DataExtractor extractor(ObjectFile::getData(), true, 0);
2377
2378 uint32_t offset = Index;
2379 uint64_t data = 0;
2380 while (uint64_t delta = extractor.getULEB128(&offset)) {
2381 data += delta;
2382 Out.push_back(data);
2383 }
2384}
2385
Rafael Espindolac66d7612014-08-17 19:09:37 +00002386bool MachOObjectFile::isRelocatableObject() const {
2387 return getHeader().filetype == MachO::MH_OBJECT;
2388}
2389
Rafael Espindola437b0d52014-07-31 03:12:45 +00002390ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002391ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2392 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002393 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002394 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002395 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002396 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002397 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002398 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002399 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002400 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002401 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002402 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002403 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002404 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002405
Rafael Espindola692410e2014-01-21 23:06:54 +00002406 if (EC)
2407 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002408 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002409}
2410