blob: c1d138384441ffd3341ef716c95d6698f46ae25c [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 Samsonov4fdbed32015-06-04 19:34:14 +0000197static MachOObjectFile::LoadCommandInfo
198getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
199 MachOObjectFile::LoadCommandInfo Load;
200 Load.Ptr = Ptr;
201 Load.C = getStruct<MachO::load_command>(Obj, Load.Ptr);
202 if (Load.C.cmdsize < 8)
203 report_fatal_error("Load command with size < 8 bytes.");
204 return Load;
205}
206
207static MachOObjectFile::LoadCommandInfo
208getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
209 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
210 : sizeof(MachO::mach_header);
211 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
212}
213
214static MachOObjectFile::LoadCommandInfo
215getNextLoadCommandInfo(const MachOObjectFile *Obj,
216 const MachOObjectFile::LoadCommandInfo &L) {
217 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
218}
219
Alexey Samsonov9f336632015-06-04 19:45:22 +0000220template <typename T>
221static void parseHeader(const MachOObjectFile *Obj, T &Header,
222 std::error_code &EC) {
223 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
224 if (HeaderOrErr)
225 Header = HeaderOrErr.get();
226 else
227 EC = HeaderOrErr.getError();
228}
229
Rafael Espindola48af1c22014-08-19 18:44:46 +0000230MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
231 bool Is64bits, std::error_code &EC)
232 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000233 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000234 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
235 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
236 HasPageZeroSegment(false) {
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000237 if (is64Bit())
Alexey Samsonov9f336632015-06-04 19:45:22 +0000238 parseHeader(this, Header64, EC);
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000239 else
240 // First fields of MachO::mach_header_64 are the same as
241 // in MachO::mach_header.
Alexey Samsonov9f336632015-06-04 19:45:22 +0000242 parseHeader(this, *reinterpret_cast<MachO::mach_header *>(&this->Header64),
243 EC);
244 if (EC)
245 return;
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000246
247 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000248 if (LoadCommandCount == 0)
249 return;
250
Charles Davis8bdfafd2013-09-01 04:28:48 +0000251 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
252 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000253
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000254 LoadCommandInfo Load = getFirstLoadCommandInfo(this);
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000255 for (unsigned I = 0; I < LoadCommandCount; ++I) {
256 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000257 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000258 // Multiple symbol tables
259 if (SymtabLoadCmd) {
260 EC = object_error::parse_failed;
261 return;
262 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000263 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000264 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000265 // Multiple dynamic symbol tables
266 if (DysymtabLoadCmd) {
267 EC = object_error::parse_failed;
268 return;
269 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000270 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000271 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000272 // Multiple data in code tables
273 if (DataInCodeLoadCmd) {
274 EC = object_error::parse_failed;
275 return;
276 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000277 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000278 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
279 // Multiple linker optimization hint tables
280 if (LinkOptHintsLoadCmd) {
281 EC = object_error::parse_failed;
282 return;
283 }
284 LinkOptHintsLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000285 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
286 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000287 // Multiple dyldinfo load commands
288 if (DyldInfoLoadCmd) {
289 EC = object_error::parse_failed;
290 return;
291 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000292 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000293 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000294 // Multiple UUID load commands
295 if (UuidLoadCmd) {
296 EC = object_error::parse_failed;
297 return;
298 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000299 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000300 } else if (Load.C.cmd == SegmentLoadType) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +0000301 const unsigned SegmentLoadSize = this->is64Bit()
302 ? sizeof(MachO::segment_command_64)
303 : sizeof(MachO::segment_command);
304 if (Load.C.cmdsize < SegmentLoadSize)
305 report_fatal_error("Segment load command size is too small.");
306
Rafael Espindola56f976f2013-04-18 18:08:55 +0000307 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
308 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000309 const char *Sec = getSectionPtr(this, Load, J);
310 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000311 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000312 if (isPageZeroSegment(this, Load))
313 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000314 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
315 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
316 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
317 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
318 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
319 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000320 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000321 if (I < LoadCommandCount - 1)
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000322 Load = getNextLoadCommandInfo(this, Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000323 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000324 assert(LoadCommands.size() == LoadCommandCount);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000325}
326
Rafael Espindola5e812af2014-01-30 02:49:50 +0000327void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000328 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000329 sizeof(MachO::nlist_64) :
330 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000331 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000332}
333
Rafael Espindola3acea392014-06-12 21:46:39 +0000334std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
335 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000336 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000337 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000338 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000339 if (Start < getData().begin() || Start >= getData().end())
340 report_fatal_error(
341 "Symbol name entry points before beginning or past end of file.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000342 Res = StringRef(Start);
343 return object_error::success;
344}
345
Rafael Espindola0e77a942014-12-10 20:46:55 +0000346unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
347 DataRefImpl DRI = Sec.getRawDataRefImpl();
348 uint32_t Flags = getSectionFlags(this, DRI);
349 return Flags & MachO::SECTION_TYPE;
350}
351
Kevin Enderby980b2582014-06-05 21:21:57 +0000352// getIndirectName() returns the name of the alias'ed symbol who's string table
353// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000354std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
355 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000356 StringRef StringTable = getStringTableData();
357 uint64_t NValue;
358 if (is64Bit()) {
359 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
360 NValue = Entry.n_value;
361 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362 return object_error::parse_failed;
363 } else {
364 MachO::nlist Entry = getSymbolTableEntry(Symb);
365 NValue = Entry.n_value;
366 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
367 return object_error::parse_failed;
368 }
369 if (NValue >= StringTable.size())
370 return object_error::parse_failed;
371 const char *Start = &StringTable.data()[NValue];
372 Res = StringRef(Start);
373 return object_error::success;
374}
375
Rafael Espindola3acea392014-06-12 21:46:39 +0000376std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
377 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000378 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000379 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000380 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
381 Entry.n_value == 0)
382 Res = UnknownAddressOrSize;
383 else
384 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000385 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000386 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000387 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
388 Entry.n_value == 0)
389 Res = UnknownAddressOrSize;
390 else
391 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000392 }
393 return object_error::success;
394}
395
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000396uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000397 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000398 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000399 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000400 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000401 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000402 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000403}
404
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000405uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000406 uint64_t Value;
407 getSymbolAddress(DRI, Value);
Rafael Espindola62a07cb2015-05-22 15:43:00 +0000408 uint32_t flags = getSymbolFlags(DRI);
409 if (flags & SymbolRef::SF_Common)
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000410 return Value;
411 return UnknownAddressOrSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000412}
413
Rafael Espindola3acea392014-06-12 21:46:39 +0000414std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
415 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000416 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000417 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000418
419 Res = SymbolRef::ST_Other;
420
421 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000422 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000423 Res = SymbolRef::ST_Debug;
424 return object_error::success;
425 }
426
Charles Davis74ec8b02013-08-27 05:00:13 +0000427 switch (n_type & MachO::N_TYPE) {
428 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000429 Res = SymbolRef::ST_Unknown;
430 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000431 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000432 Res = SymbolRef::ST_Function;
433 break;
434 }
435 return object_error::success;
436}
437
Rafael Espindola20122a42014-01-31 20:57:12 +0000438uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000439 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000440
Charles Davis8bdfafd2013-09-01 04:28:48 +0000441 uint8_t MachOType = Entry.n_type;
442 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000443
Rafael Espindola20122a42014-01-31 20:57:12 +0000444 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000445
Charles Davis74ec8b02013-08-27 05:00:13 +0000446 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000447 Result |= SymbolRef::SF_Undefined;
448
Tim Northovereaef0742014-05-30 13:22:59 +0000449 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
450 Result |= SymbolRef::SF_Indirect;
451
Rafael Espindolaa1356322013-11-02 05:03:24 +0000452 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000453 Result |= SymbolRef::SF_FormatSpecific;
454
Charles Davis74ec8b02013-08-27 05:00:13 +0000455 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000456 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000457 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000458 uint64_t Value;
459 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000460 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000461 Result |= SymbolRef::SF_Common;
462 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000463
464 if (!(MachOType & MachO::N_PEXT))
465 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000466 }
467
Charles Davis74ec8b02013-08-27 05:00:13 +0000468 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000469 Result |= SymbolRef::SF_Weak;
470
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000471 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
472 Result |= SymbolRef::SF_Thumb;
473
Charles Davis74ec8b02013-08-27 05:00:13 +0000474 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000475 Result |= SymbolRef::SF_Absolute;
476
Rafael Espindola20122a42014-01-31 20:57:12 +0000477 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000478}
479
Rafael Espindola3acea392014-06-12 21:46:39 +0000480std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
481 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000482 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000483 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000484
485 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000486 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000487 } else {
488 DataRefImpl DRI;
489 DRI.d.a = index - 1;
Rafael Espindola0d85d102015-05-22 14:59:27 +0000490 if (DRI.d.a >= Sections.size())
491 report_fatal_error("getSymbolSection: Invalid section index.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000492 Res = section_iterator(SectionRef(DRI, this));
493 }
494
495 return object_error::success;
496}
497
Rafael Espindola5e812af2014-01-30 02:49:50 +0000498void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000499 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000500}
501
Rafael Espindola3acea392014-06-12 21:46:39 +0000502std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
503 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000504 ArrayRef<char> Raw = getSectionRawName(Sec);
505 Result = parseSegmentOrSectionName(Raw.data());
506 return object_error::success;
507}
508
Rafael Espindola80291272014-10-08 15:28:58 +0000509uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
510 if (is64Bit())
511 return getSection64(Sec).addr;
512 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000513}
514
Rafael Espindola80291272014-10-08 15:28:58 +0000515uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
516 if (is64Bit())
517 return getSection64(Sec).size;
518 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000519}
520
Rafael Espindola3acea392014-06-12 21:46:39 +0000521std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
522 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000523 uint32_t Offset;
524 uint64_t Size;
525
526 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000527 MachO::section_64 Sect = getSection64(Sec);
528 Offset = Sect.offset;
529 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000530 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000531 MachO::section Sect = getSection(Sec);
532 Offset = Sect.offset;
533 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000534 }
535
536 Res = this->getData().substr(Offset, Size);
537 return object_error::success;
538}
539
Rafael Espindola80291272014-10-08 15:28:58 +0000540uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000541 uint32_t Align;
542 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000543 MachO::section_64 Sect = getSection64(Sec);
544 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000545 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000546 MachO::section Sect = getSection(Sec);
547 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000548 }
549
Rafael Espindola80291272014-10-08 15:28:58 +0000550 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000551}
552
Rafael Espindola80291272014-10-08 15:28:58 +0000553bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000554 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000555 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000556}
557
Rafael Espindola80291272014-10-08 15:28:58 +0000558bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000559 uint32_t Flags = getSectionFlags(this, Sec);
560 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000561 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
562 !(SectionType == MachO::S_ZEROFILL ||
563 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000564}
565
Rafael Espindola80291272014-10-08 15:28:58 +0000566bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000567 uint32_t Flags = getSectionFlags(this, Sec);
568 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000569 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
570 (SectionType == MachO::S_ZEROFILL ||
571 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000572}
573
Rafael Espindola80291272014-10-08 15:28:58 +0000574bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000575 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000576 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000577}
578
Rafael Espindola80291272014-10-08 15:28:58 +0000579bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
580 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000581 SymbolRef::Type ST;
582 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000583 if (ST == SymbolRef::ST_Unknown)
584 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000585
Rafael Espindola80291272014-10-08 15:28:58 +0000586 uint64_t SectBegin = getSectionAddress(Sec);
587 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000588 SectEnd += SectBegin;
589
590 uint64_t SymAddr;
591 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000592 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000593}
594
Rui Ueyamabc654b12013-09-27 21:47:05 +0000595relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000596 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000597 Ret.d.a = Sec.d.a;
598 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000599 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000600}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000601
Rafael Espindola56f976f2013-04-18 18:08:55 +0000602relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000603MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000604 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000605 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000606 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000607 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000608 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000609 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000610 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000611 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000612
Rafael Espindola56f976f2013-04-18 18:08:55 +0000613 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000614 Ret.d.a = Sec.d.a;
615 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000616 return relocation_iterator(RelocationRef(Ret, this));
617}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000618
Rafael Espindola5e812af2014-01-30 02:49:50 +0000619void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000620 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000621}
Owen Anderson171f4852011-10-24 23:20:07 +0000622
Rafael Espindola3acea392014-06-12 21:46:39 +0000623std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
624 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000625 uint64_t Offset;
626 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000627
628 DataRefImpl Sec;
629 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000630 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000631 Res = SecAddress + Offset;
632 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000633}
634
Rafael Espindola3acea392014-06-12 21:46:39 +0000635std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
636 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000637 assert(getHeader().filetype == MachO::MH_OBJECT &&
638 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000639 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000640 Res = getAnyRelocationAddress(RE);
641 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000642}
643
Rafael Espindola806f0062013-06-05 01:33:53 +0000644symbol_iterator
645MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000646 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000647 if (isRelocationScattered(RE))
648 return symbol_end();
649
Rafael Espindola56f976f2013-04-18 18:08:55 +0000650 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
651 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000652 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000653 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000654
Charles Davis8bdfafd2013-09-01 04:28:48 +0000655 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000656 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000657 sizeof(MachO::nlist_64) :
658 sizeof(MachO::nlist);
659 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000660 DataRefImpl Sym;
661 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000662 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000663}
664
Keno Fischerc780e8e2015-05-21 21:24:32 +0000665section_iterator
666MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
667 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
668}
669
Rafael Espindola3acea392014-06-12 21:46:39 +0000670std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
671 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000672 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000673 Res = getAnyRelocationType(RE);
674 return object_error::success;
675}
676
Rafael Espindola3acea392014-06-12 21:46:39 +0000677std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000678MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
679 SmallVectorImpl<char> &Result) const {
680 StringRef res;
681 uint64_t RType;
682 getRelocationType(Rel, RType);
683
684 unsigned Arch = this->getArch();
685
686 switch (Arch) {
687 case Triple::x86: {
688 static const char *const Table[] = {
689 "GENERIC_RELOC_VANILLA",
690 "GENERIC_RELOC_PAIR",
691 "GENERIC_RELOC_SECTDIFF",
692 "GENERIC_RELOC_PB_LA_PTR",
693 "GENERIC_RELOC_LOCAL_SECTDIFF",
694 "GENERIC_RELOC_TLV" };
695
Eric Christopher13250cb2013-12-06 02:33:38 +0000696 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000697 res = "Unknown";
698 else
699 res = Table[RType];
700 break;
701 }
702 case Triple::x86_64: {
703 static const char *const Table[] = {
704 "X86_64_RELOC_UNSIGNED",
705 "X86_64_RELOC_SIGNED",
706 "X86_64_RELOC_BRANCH",
707 "X86_64_RELOC_GOT_LOAD",
708 "X86_64_RELOC_GOT",
709 "X86_64_RELOC_SUBTRACTOR",
710 "X86_64_RELOC_SIGNED_1",
711 "X86_64_RELOC_SIGNED_2",
712 "X86_64_RELOC_SIGNED_4",
713 "X86_64_RELOC_TLV" };
714
715 if (RType > 9)
716 res = "Unknown";
717 else
718 res = Table[RType];
719 break;
720 }
721 case Triple::arm: {
722 static const char *const Table[] = {
723 "ARM_RELOC_VANILLA",
724 "ARM_RELOC_PAIR",
725 "ARM_RELOC_SECTDIFF",
726 "ARM_RELOC_LOCAL_SECTDIFF",
727 "ARM_RELOC_PB_LA_PTR",
728 "ARM_RELOC_BR24",
729 "ARM_THUMB_RELOC_BR22",
730 "ARM_THUMB_32BIT_BRANCH",
731 "ARM_RELOC_HALF",
732 "ARM_RELOC_HALF_SECTDIFF" };
733
734 if (RType > 9)
735 res = "Unknown";
736 else
737 res = Table[RType];
738 break;
739 }
Tim Northover00ed9962014-03-29 10:18:08 +0000740 case Triple::aarch64: {
741 static const char *const Table[] = {
742 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
743 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
744 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
745 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
746 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
747 "ARM64_RELOC_ADDEND"
748 };
749
750 if (RType >= array_lengthof(Table))
751 res = "Unknown";
752 else
753 res = Table[RType];
754 break;
755 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000756 case Triple::ppc: {
757 static const char *const Table[] = {
758 "PPC_RELOC_VANILLA",
759 "PPC_RELOC_PAIR",
760 "PPC_RELOC_BR14",
761 "PPC_RELOC_BR24",
762 "PPC_RELOC_HI16",
763 "PPC_RELOC_LO16",
764 "PPC_RELOC_HA16",
765 "PPC_RELOC_LO14",
766 "PPC_RELOC_SECTDIFF",
767 "PPC_RELOC_PB_LA_PTR",
768 "PPC_RELOC_HI16_SECTDIFF",
769 "PPC_RELOC_LO16_SECTDIFF",
770 "PPC_RELOC_HA16_SECTDIFF",
771 "PPC_RELOC_JBSR",
772 "PPC_RELOC_LO14_SECTDIFF",
773 "PPC_RELOC_LOCAL_SECTDIFF" };
774
Eric Christopher13250cb2013-12-06 02:33:38 +0000775 if (RType > 15)
776 res = "Unknown";
777 else
778 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000779 break;
780 }
781 case Triple::UnknownArch:
782 res = "Unknown";
783 break;
784 }
785 Result.append(res.begin(), res.end());
786 return object_error::success;
787}
788
Rafael Espindola3acea392014-06-12 21:46:39 +0000789std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
790 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000791 unsigned Arch = getArch();
792 uint64_t Type;
793 getRelocationType(Rel, Type);
794
795 Result = false;
796
797 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
798 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000799 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000800 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000801 } else if (Arch == Triple::x86_64) {
802 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000803 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000804 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000805 DataRefImpl RelPrev = Rel;
806 RelPrev.d.a--;
807 uint64_t PrevType;
808 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000809 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000810 Result = true;
811 }
812 }
813
814 return object_error::success;
815}
816
Keno Fischer281b6942015-05-30 19:44:53 +0000817uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
818 MachO::any_relocation_info RE = getRelocation(Rel);
819 return getAnyRelocationLength(RE);
820}
821
Kevin Enderby980b2582014-06-05 21:21:57 +0000822//
823// guessLibraryShortName() is passed a name of a dynamic library and returns a
824// guess on what the short name is. Then name is returned as a substring of the
825// StringRef Name passed in. The name of the dynamic library is recognized as
826// a framework if it has one of the two following forms:
827// Foo.framework/Versions/A/Foo
828// Foo.framework/Foo
829// Where A and Foo can be any string. And may contain a trailing suffix
830// starting with an underbar. If the Name is recognized as a framework then
831// isFramework is set to true else it is set to false. If the Name has a
832// suffix then Suffix is set to the substring in Name that contains the suffix
833// else it is set to a NULL StringRef.
834//
835// The Name of the dynamic library is recognized as a library name if it has
836// one of the two following forms:
837// libFoo.A.dylib
838// libFoo.dylib
839// The library may have a suffix trailing the name Foo of the form:
840// libFoo_profile.A.dylib
841// libFoo_profile.dylib
842//
843// The Name of the dynamic library is also recognized as a library name if it
844// has the following form:
845// Foo.qtx
846//
847// If the Name of the dynamic library is none of the forms above then a NULL
848// StringRef is returned.
849//
850StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
851 bool &isFramework,
852 StringRef &Suffix) {
853 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
854 size_t a, b, c, d, Idx;
855
856 isFramework = false;
857 Suffix = StringRef();
858
859 // Pull off the last component and make Foo point to it
860 a = Name.rfind('/');
861 if (a == Name.npos || a == 0)
862 goto guess_library;
863 Foo = Name.slice(a+1, Name.npos);
864
865 // Look for a suffix starting with a '_'
866 Idx = Foo.rfind('_');
867 if (Idx != Foo.npos && Foo.size() >= 2) {
868 Suffix = Foo.slice(Idx, Foo.npos);
869 Foo = Foo.slice(0, Idx);
870 }
871
872 // First look for the form Foo.framework/Foo
873 b = Name.rfind('/', a);
874 if (b == Name.npos)
875 Idx = 0;
876 else
877 Idx = b+1;
878 F = Name.slice(Idx, Idx + Foo.size());
879 DotFramework = Name.slice(Idx + Foo.size(),
880 Idx + Foo.size() + sizeof(".framework/")-1);
881 if (F == Foo && DotFramework == ".framework/") {
882 isFramework = true;
883 return Foo;
884 }
885
886 // Next look for the form Foo.framework/Versions/A/Foo
887 if (b == Name.npos)
888 goto guess_library;
889 c = Name.rfind('/', b);
890 if (c == Name.npos || c == 0)
891 goto guess_library;
892 V = Name.slice(c+1, Name.npos);
893 if (!V.startswith("Versions/"))
894 goto guess_library;
895 d = Name.rfind('/', c);
896 if (d == Name.npos)
897 Idx = 0;
898 else
899 Idx = d+1;
900 F = Name.slice(Idx, Idx + Foo.size());
901 DotFramework = Name.slice(Idx + Foo.size(),
902 Idx + Foo.size() + sizeof(".framework/")-1);
903 if (F == Foo && DotFramework == ".framework/") {
904 isFramework = true;
905 return Foo;
906 }
907
908guess_library:
909 // pull off the suffix after the "." and make a point to it
910 a = Name.rfind('.');
911 if (a == Name.npos || a == 0)
912 return StringRef();
913 Dylib = Name.slice(a, Name.npos);
914 if (Dylib != ".dylib")
915 goto guess_qtx;
916
917 // First pull off the version letter for the form Foo.A.dylib if any.
918 if (a >= 3) {
919 Dot = Name.slice(a-2, a-1);
920 if (Dot == ".")
921 a = a - 2;
922 }
923
924 b = Name.rfind('/', a);
925 if (b == Name.npos)
926 b = 0;
927 else
928 b = b+1;
929 // ignore any suffix after an underbar like Foo_profile.A.dylib
930 Idx = Name.find('_', b);
931 if (Idx != Name.npos && Idx != b) {
932 Lib = Name.slice(b, Idx);
933 Suffix = Name.slice(Idx, a);
934 }
935 else
936 Lib = Name.slice(b, a);
937 // There are incorrect library names of the form:
938 // libATS.A_profile.dylib so check for these.
939 if (Lib.size() >= 3) {
940 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
941 if (Dot == ".")
942 Lib = Lib.slice(0, Lib.size()-2);
943 }
944 return Lib;
945
946guess_qtx:
947 Qtx = Name.slice(a, Name.npos);
948 if (Qtx != ".qtx")
949 return StringRef();
950 b = Name.rfind('/', a);
951 if (b == Name.npos)
952 Lib = Name.slice(0, a);
953 else
954 Lib = Name.slice(b+1, a);
955 // There are library names of the form: QT.A.qtx so check for these.
956 if (Lib.size() >= 3) {
957 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
958 if (Dot == ".")
959 Lib = Lib.slice(0, Lib.size()-2);
960 }
961 return Lib;
962}
963
964// getLibraryShortNameByIndex() is used to get the short name of the library
965// for an undefined symbol in a linked Mach-O binary that was linked with the
966// normal two-level namespace default (that is MH_TWOLEVEL in the header).
967// It is passed the index (0 - based) of the library as translated from
968// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +0000969std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +0000970 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000971 if (Index >= Libraries.size())
972 return object_error::parse_failed;
973
Kevin Enderby980b2582014-06-05 21:21:57 +0000974 // If the cache of LibrariesShortNames is not built up do that first for
975 // all the Libraries.
976 if (LibrariesShortNames.size() == 0) {
977 for (unsigned i = 0; i < Libraries.size(); i++) {
978 MachO::dylib_command D =
979 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +0000980 if (D.dylib.name >= D.cmdsize)
981 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +0000982 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +0000983 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +0000984 if (D.dylib.name+Name.size() >= D.cmdsize)
985 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +0000986 StringRef Suffix;
987 bool isFramework;
988 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +0000989 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +0000990 LibrariesShortNames.push_back(Name);
991 else
992 LibrariesShortNames.push_back(shortName);
993 }
994 }
995
996 Res = LibrariesShortNames[Index];
997 return object_error::success;
998}
999
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001000basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001001 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001002}
1003
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001004basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001005 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001006 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001007 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001008
Charles Davis8bdfafd2013-09-01 04:28:48 +00001009 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001010 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001011 sizeof(MachO::nlist_64) :
1012 sizeof(MachO::nlist);
1013 unsigned Offset = Symtab.symoff +
1014 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001015 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001016 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001017}
1018
Lang Hames36072da2014-05-12 21:39:59 +00001019basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1020 DataRefImpl DRI;
1021 if (!SymtabLoadCmd)
1022 return basic_symbol_iterator(SymbolRef(DRI, this));
1023
1024 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001025 if (Index >= Symtab.nsyms)
1026 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001027 unsigned SymbolTableEntrySize =
1028 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1029 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1030 DRI.p += Index * SymbolTableEntrySize;
1031 return basic_symbol_iterator(SymbolRef(DRI, this));
1032}
1033
Rafael Espindolab5155a52014-02-10 20:24:04 +00001034section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001035 DataRefImpl DRI;
1036 return section_iterator(SectionRef(DRI, this));
1037}
1038
Rafael Espindolab5155a52014-02-10 20:24:04 +00001039section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001040 DataRefImpl DRI;
1041 DRI.d.a = Sections.size();
1042 return section_iterator(SectionRef(DRI, this));
1043}
1044
Rafael Espindola56f976f2013-04-18 18:08:55 +00001045uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001046 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001047}
1048
Rafael Espindola56f976f2013-04-18 18:08:55 +00001049StringRef MachOObjectFile::getFileFormatName() const {
1050 unsigned CPUType = getCPUType(this);
1051 if (!is64Bit()) {
1052 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001053 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001054 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001055 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001056 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001057 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001058 return "Mach-O 32-bit ppc";
1059 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001060 return "Mach-O 32-bit unknown";
1061 }
1062 }
1063
Rafael Espindola56f976f2013-04-18 18:08:55 +00001064 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001065 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001066 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001067 case llvm::MachO::CPU_TYPE_ARM64:
1068 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001069 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001070 return "Mach-O 64-bit ppc64";
1071 default:
1072 return "Mach-O 64-bit unknown";
1073 }
1074}
1075
Alexey Samsonove6388e62013-06-18 15:03:28 +00001076Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1077 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001078 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001079 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001080 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001081 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001082 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001083 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001084 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001085 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001086 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001087 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001088 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001089 return Triple::ppc64;
1090 default:
1091 return Triple::UnknownArch;
1092 }
1093}
1094
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001095Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1096 const char **McpuDefault) {
1097 if (McpuDefault)
1098 *McpuDefault = nullptr;
1099
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001100 switch (CPUType) {
1101 case MachO::CPU_TYPE_I386:
1102 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1103 case MachO::CPU_SUBTYPE_I386_ALL:
1104 return Triple("i386-apple-darwin");
1105 default:
1106 return Triple();
1107 }
1108 case MachO::CPU_TYPE_X86_64:
1109 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1110 case MachO::CPU_SUBTYPE_X86_64_ALL:
1111 return Triple("x86_64-apple-darwin");
1112 case MachO::CPU_SUBTYPE_X86_64_H:
1113 return Triple("x86_64h-apple-darwin");
1114 default:
1115 return Triple();
1116 }
1117 case MachO::CPU_TYPE_ARM:
1118 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1119 case MachO::CPU_SUBTYPE_ARM_V4T:
1120 return Triple("armv4t-apple-darwin");
1121 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1122 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001123 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1124 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001125 case MachO::CPU_SUBTYPE_ARM_V6:
1126 return Triple("armv6-apple-darwin");
1127 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001128 if (McpuDefault)
1129 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001130 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001131 case MachO::CPU_SUBTYPE_ARM_V7:
1132 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001133 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001134 if (McpuDefault)
1135 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001136 return Triple("armv7em-apple-darwin");
1137 case MachO::CPU_SUBTYPE_ARM_V7K:
1138 return Triple("armv7k-apple-darwin");
1139 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001140 if (McpuDefault)
1141 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001142 return Triple("armv7m-apple-darwin");
1143 case MachO::CPU_SUBTYPE_ARM_V7S:
1144 return Triple("armv7s-apple-darwin");
1145 default:
1146 return Triple();
1147 }
1148 case MachO::CPU_TYPE_ARM64:
1149 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1150 case MachO::CPU_SUBTYPE_ARM64_ALL:
1151 return Triple("arm64-apple-darwin");
1152 default:
1153 return Triple();
1154 }
1155 case MachO::CPU_TYPE_POWERPC:
1156 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1157 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1158 return Triple("ppc-apple-darwin");
1159 default:
1160 return Triple();
1161 }
1162 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001163 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001164 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1165 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001166 default:
1167 return Triple();
1168 }
1169 default:
1170 return Triple();
1171 }
1172}
1173
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001174Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1175 const char **McpuDefault) {
1176 if (McpuDefault)
1177 *McpuDefault = nullptr;
1178
1179 switch (CPUType) {
1180 case MachO::CPU_TYPE_ARM:
1181 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1182 case MachO::CPU_SUBTYPE_ARM_V4T:
1183 return Triple("thumbv4t-apple-darwin");
1184 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1185 return Triple("thumbv5e-apple-darwin");
1186 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1187 return Triple("xscale-apple-darwin");
1188 case MachO::CPU_SUBTYPE_ARM_V6:
1189 return Triple("thumbv6-apple-darwin");
1190 case MachO::CPU_SUBTYPE_ARM_V6M:
1191 if (McpuDefault)
1192 *McpuDefault = "cortex-m0";
1193 return Triple("thumbv6m-apple-darwin");
1194 case MachO::CPU_SUBTYPE_ARM_V7:
1195 return Triple("thumbv7-apple-darwin");
1196 case MachO::CPU_SUBTYPE_ARM_V7EM:
1197 if (McpuDefault)
1198 *McpuDefault = "cortex-m4";
1199 return Triple("thumbv7em-apple-darwin");
1200 case MachO::CPU_SUBTYPE_ARM_V7K:
1201 return Triple("thumbv7k-apple-darwin");
1202 case MachO::CPU_SUBTYPE_ARM_V7M:
1203 if (McpuDefault)
1204 *McpuDefault = "cortex-m3";
1205 return Triple("thumbv7m-apple-darwin");
1206 case MachO::CPU_SUBTYPE_ARM_V7S:
1207 return Triple("thumbv7s-apple-darwin");
1208 default:
1209 return Triple();
1210 }
1211 default:
1212 return Triple();
1213 }
1214}
1215
1216Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1217 const char **McpuDefault,
1218 Triple *ThumbTriple) {
1219 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1220 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1221 McpuDefault);
1222 return T;
1223}
1224
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001225Triple MachOObjectFile::getHostArch() {
1226 return Triple(sys::getDefaultTargetTriple());
1227}
1228
Rafael Espindola72318b42014-08-08 16:30:17 +00001229bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1230 return StringSwitch<bool>(ArchFlag)
1231 .Case("i386", true)
1232 .Case("x86_64", true)
1233 .Case("x86_64h", true)
1234 .Case("armv4t", true)
1235 .Case("arm", true)
1236 .Case("armv5e", true)
1237 .Case("armv6", true)
1238 .Case("armv6m", true)
1239 .Case("armv7em", true)
1240 .Case("armv7k", true)
1241 .Case("armv7m", true)
1242 .Case("armv7s", true)
1243 .Case("arm64", true)
1244 .Case("ppc", true)
1245 .Case("ppc64", true)
1246 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001247}
1248
Alexey Samsonove6388e62013-06-18 15:03:28 +00001249unsigned MachOObjectFile::getArch() const {
1250 return getArch(getCPUType(this));
1251}
1252
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001253Triple MachOObjectFile::getArch(const char **McpuDefault,
1254 Triple *ThumbTriple) const {
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001255 const auto &Header = getHeader();
1256 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1257 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001258}
1259
Rui Ueyamabc654b12013-09-27 21:47:05 +00001260relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001261 DataRefImpl DRI;
1262 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001263 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001264}
1265
Rui Ueyamabc654b12013-09-27 21:47:05 +00001266relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001267 DataRefImpl DRI;
1268 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001269 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001270}
1271
Kevin Enderby273ae012013-06-06 17:20:50 +00001272dice_iterator MachOObjectFile::begin_dices() const {
1273 DataRefImpl DRI;
1274 if (!DataInCodeLoadCmd)
1275 return dice_iterator(DiceRef(DRI, this));
1276
Charles Davis8bdfafd2013-09-01 04:28:48 +00001277 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1278 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001279 return dice_iterator(DiceRef(DRI, this));
1280}
1281
1282dice_iterator MachOObjectFile::end_dices() const {
1283 DataRefImpl DRI;
1284 if (!DataInCodeLoadCmd)
1285 return dice_iterator(DiceRef(DRI, this));
1286
Charles Davis8bdfafd2013-09-01 04:28:48 +00001287 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1288 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001289 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1290 return dice_iterator(DiceRef(DRI, this));
1291}
1292
Nick Kledzikd04bc352014-08-30 00:20:14 +00001293ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1294 : Trie(T), Malformed(false), Done(false) { }
1295
1296void ExportEntry::moveToFirst() {
1297 pushNode(0);
1298 pushDownUntilBottom();
1299}
1300
1301void ExportEntry::moveToEnd() {
1302 Stack.clear();
1303 Done = true;
1304}
1305
1306bool ExportEntry::operator==(const ExportEntry &Other) const {
1307 // Common case, one at end, other iterating from begin.
1308 if (Done || Other.Done)
1309 return (Done == Other.Done);
1310 // Not equal if different stack sizes.
1311 if (Stack.size() != Other.Stack.size())
1312 return false;
1313 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001314 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001315 return false;
1316 // Equal if all nodes in both stacks match.
1317 for (unsigned i=0; i < Stack.size(); ++i) {
1318 if (Stack[i].Start != Other.Stack[i].Start)
1319 return false;
1320 }
1321 return true;
1322}
1323
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001324uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1325 unsigned Count;
1326 uint64_t Result = decodeULEB128(Ptr, &Count);
1327 Ptr += Count;
1328 if (Ptr > Trie.end()) {
1329 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001330 Malformed = true;
1331 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001332 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001333}
1334
1335StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001336 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001337}
1338
1339uint64_t ExportEntry::flags() const {
1340 return Stack.back().Flags;
1341}
1342
1343uint64_t ExportEntry::address() const {
1344 return Stack.back().Address;
1345}
1346
1347uint64_t ExportEntry::other() const {
1348 return Stack.back().Other;
1349}
1350
1351StringRef ExportEntry::otherName() const {
1352 const char* ImportName = Stack.back().ImportName;
1353 if (ImportName)
1354 return StringRef(ImportName);
1355 return StringRef();
1356}
1357
1358uint32_t ExportEntry::nodeOffset() const {
1359 return Stack.back().Start - Trie.begin();
1360}
1361
1362ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1363 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1364 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1365 ParentStringLength(0), IsExportNode(false) {
1366}
1367
1368void ExportEntry::pushNode(uint64_t offset) {
1369 const uint8_t *Ptr = Trie.begin() + offset;
1370 NodeState State(Ptr);
1371 uint64_t ExportInfoSize = readULEB128(State.Current);
1372 State.IsExportNode = (ExportInfoSize != 0);
1373 const uint8_t* Children = State.Current + ExportInfoSize;
1374 if (State.IsExportNode) {
1375 State.Flags = readULEB128(State.Current);
1376 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1377 State.Address = 0;
1378 State.Other = readULEB128(State.Current); // dylib ordinal
1379 State.ImportName = reinterpret_cast<const char*>(State.Current);
1380 } else {
1381 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001382 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1383 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001384 }
1385 }
1386 State.ChildCount = *Children;
1387 State.Current = Children + 1;
1388 State.NextChildIndex = 0;
1389 State.ParentStringLength = CumulativeString.size();
1390 Stack.push_back(State);
1391}
1392
1393void ExportEntry::pushDownUntilBottom() {
1394 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1395 NodeState &Top = Stack.back();
1396 CumulativeString.resize(Top.ParentStringLength);
1397 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001398 char C = *Top.Current;
1399 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001400 }
1401 Top.Current += 1;
1402 uint64_t childNodeIndex = readULEB128(Top.Current);
1403 Top.NextChildIndex += 1;
1404 pushNode(childNodeIndex);
1405 }
1406 if (!Stack.back().IsExportNode) {
1407 Malformed = true;
1408 moveToEnd();
1409 }
1410}
1411
1412// We have a trie data structure and need a way to walk it that is compatible
1413// with the C++ iterator model. The solution is a non-recursive depth first
1414// traversal where the iterator contains a stack of parent nodes along with a
1415// string that is the accumulation of all edge strings along the parent chain
1416// to this point.
1417//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001418// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001419// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1420// node may have child nodes too.
1421//
1422// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1423// child until hitting a node with no children (which is an export node or
1424// else the trie is malformed). On the way down, each node is pushed on the
1425// stack ivar. If there is no more ways down, it pops up one and tries to go
1426// down a sibling path until a childless node is reached.
1427void ExportEntry::moveNext() {
1428 if (Stack.empty() || !Stack.back().IsExportNode) {
1429 Malformed = true;
1430 moveToEnd();
1431 return;
1432 }
1433
1434 Stack.pop_back();
1435 while (!Stack.empty()) {
1436 NodeState &Top = Stack.back();
1437 if (Top.NextChildIndex < Top.ChildCount) {
1438 pushDownUntilBottom();
1439 // Now at the next export node.
1440 return;
1441 } else {
1442 if (Top.IsExportNode) {
1443 // This node has no children but is itself an export node.
1444 CumulativeString.resize(Top.ParentStringLength);
1445 return;
1446 }
1447 Stack.pop_back();
1448 }
1449 }
1450 Done = true;
1451}
1452
1453iterator_range<export_iterator>
1454MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1455 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001456 if (Trie.size() == 0)
1457 Start.moveToEnd();
1458 else
1459 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001460
1461 ExportEntry Finish(Trie);
1462 Finish.moveToEnd();
1463
1464 return iterator_range<export_iterator>(export_iterator(Start),
1465 export_iterator(Finish));
1466}
1467
1468iterator_range<export_iterator> MachOObjectFile::exports() const {
1469 return exports(getDyldInfoExportsTrie());
1470}
1471
1472
Nick Kledzikac431442014-09-12 21:34:15 +00001473MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1474 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1475 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1476 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1477
1478void MachORebaseEntry::moveToFirst() {
1479 Ptr = Opcodes.begin();
1480 moveNext();
1481}
1482
1483void MachORebaseEntry::moveToEnd() {
1484 Ptr = Opcodes.end();
1485 RemainingLoopCount = 0;
1486 Done = true;
1487}
1488
1489void MachORebaseEntry::moveNext() {
1490 // If in the middle of some loop, move to next rebasing in loop.
1491 SegmentOffset += AdvanceAmount;
1492 if (RemainingLoopCount) {
1493 --RemainingLoopCount;
1494 return;
1495 }
1496 if (Ptr == Opcodes.end()) {
1497 Done = true;
1498 return;
1499 }
1500 bool More = true;
1501 while (More && !Malformed) {
1502 // Parse next opcode and set up next loop.
1503 uint8_t Byte = *Ptr++;
1504 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1505 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1506 switch (Opcode) {
1507 case MachO::REBASE_OPCODE_DONE:
1508 More = false;
1509 Done = true;
1510 moveToEnd();
1511 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1512 break;
1513 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1514 RebaseType = ImmValue;
1515 DEBUG_WITH_TYPE(
1516 "mach-o-rebase",
1517 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1518 << "RebaseType=" << (int) RebaseType << "\n");
1519 break;
1520 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1521 SegmentIndex = ImmValue;
1522 SegmentOffset = readULEB128();
1523 DEBUG_WITH_TYPE(
1524 "mach-o-rebase",
1525 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1526 << "SegmentIndex=" << SegmentIndex << ", "
1527 << format("SegmentOffset=0x%06X", SegmentOffset)
1528 << "\n");
1529 break;
1530 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1531 SegmentOffset += readULEB128();
1532 DEBUG_WITH_TYPE("mach-o-rebase",
1533 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1534 << format("SegmentOffset=0x%06X",
1535 SegmentOffset) << "\n");
1536 break;
1537 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1538 SegmentOffset += ImmValue * PointerSize;
1539 DEBUG_WITH_TYPE("mach-o-rebase",
1540 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1541 << format("SegmentOffset=0x%06X",
1542 SegmentOffset) << "\n");
1543 break;
1544 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1545 AdvanceAmount = PointerSize;
1546 RemainingLoopCount = ImmValue - 1;
1547 DEBUG_WITH_TYPE(
1548 "mach-o-rebase",
1549 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1550 << format("SegmentOffset=0x%06X", SegmentOffset)
1551 << ", AdvanceAmount=" << AdvanceAmount
1552 << ", RemainingLoopCount=" << RemainingLoopCount
1553 << "\n");
1554 return;
1555 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1556 AdvanceAmount = PointerSize;
1557 RemainingLoopCount = readULEB128() - 1;
1558 DEBUG_WITH_TYPE(
1559 "mach-o-rebase",
1560 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1561 << format("SegmentOffset=0x%06X", SegmentOffset)
1562 << ", AdvanceAmount=" << AdvanceAmount
1563 << ", RemainingLoopCount=" << RemainingLoopCount
1564 << "\n");
1565 return;
1566 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1567 AdvanceAmount = readULEB128() + PointerSize;
1568 RemainingLoopCount = 0;
1569 DEBUG_WITH_TYPE(
1570 "mach-o-rebase",
1571 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1572 << format("SegmentOffset=0x%06X", SegmentOffset)
1573 << ", AdvanceAmount=" << AdvanceAmount
1574 << ", RemainingLoopCount=" << RemainingLoopCount
1575 << "\n");
1576 return;
1577 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1578 RemainingLoopCount = readULEB128() - 1;
1579 AdvanceAmount = readULEB128() + PointerSize;
1580 DEBUG_WITH_TYPE(
1581 "mach-o-rebase",
1582 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1583 << format("SegmentOffset=0x%06X", SegmentOffset)
1584 << ", AdvanceAmount=" << AdvanceAmount
1585 << ", RemainingLoopCount=" << RemainingLoopCount
1586 << "\n");
1587 return;
1588 default:
1589 Malformed = true;
1590 }
1591 }
1592}
1593
1594uint64_t MachORebaseEntry::readULEB128() {
1595 unsigned Count;
1596 uint64_t Result = decodeULEB128(Ptr, &Count);
1597 Ptr += Count;
1598 if (Ptr > Opcodes.end()) {
1599 Ptr = Opcodes.end();
1600 Malformed = true;
1601 }
1602 return Result;
1603}
1604
1605uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1606
1607uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1608
1609StringRef MachORebaseEntry::typeName() const {
1610 switch (RebaseType) {
1611 case MachO::REBASE_TYPE_POINTER:
1612 return "pointer";
1613 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1614 return "text abs32";
1615 case MachO::REBASE_TYPE_TEXT_PCREL32:
1616 return "text rel32";
1617 }
1618 return "unknown";
1619}
1620
1621bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1622 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1623 return (Ptr == Other.Ptr) &&
1624 (RemainingLoopCount == Other.RemainingLoopCount) &&
1625 (Done == Other.Done);
1626}
1627
1628iterator_range<rebase_iterator>
1629MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1630 MachORebaseEntry Start(Opcodes, is64);
1631 Start.moveToFirst();
1632
1633 MachORebaseEntry Finish(Opcodes, is64);
1634 Finish.moveToEnd();
1635
1636 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1637 rebase_iterator(Finish));
1638}
1639
1640iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1641 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1642}
1643
Nick Kledzik56ebef42014-09-16 01:41:51 +00001644
1645MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1646 Kind BK)
1647 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1648 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1649 BindType(0), PointerSize(is64Bit ? 8 : 4),
1650 TableKind(BK), Malformed(false), Done(false) {}
1651
1652void MachOBindEntry::moveToFirst() {
1653 Ptr = Opcodes.begin();
1654 moveNext();
1655}
1656
1657void MachOBindEntry::moveToEnd() {
1658 Ptr = Opcodes.end();
1659 RemainingLoopCount = 0;
1660 Done = true;
1661}
1662
1663void MachOBindEntry::moveNext() {
1664 // If in the middle of some loop, move to next binding in loop.
1665 SegmentOffset += AdvanceAmount;
1666 if (RemainingLoopCount) {
1667 --RemainingLoopCount;
1668 return;
1669 }
1670 if (Ptr == Opcodes.end()) {
1671 Done = true;
1672 return;
1673 }
1674 bool More = true;
1675 while (More && !Malformed) {
1676 // Parse next opcode and set up next loop.
1677 uint8_t Byte = *Ptr++;
1678 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1679 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1680 int8_t SignExtended;
1681 const uint8_t *SymStart;
1682 switch (Opcode) {
1683 case MachO::BIND_OPCODE_DONE:
1684 if (TableKind == Kind::Lazy) {
1685 // Lazying bindings have a DONE opcode between entries. Need to ignore
1686 // it to advance to next entry. But need not if this is last entry.
1687 bool NotLastEntry = false;
1688 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1689 if (*P) {
1690 NotLastEntry = true;
1691 }
1692 }
1693 if (NotLastEntry)
1694 break;
1695 }
1696 More = false;
1697 Done = true;
1698 moveToEnd();
1699 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1700 break;
1701 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1702 Ordinal = ImmValue;
1703 DEBUG_WITH_TYPE(
1704 "mach-o-bind",
1705 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1706 << "Ordinal=" << Ordinal << "\n");
1707 break;
1708 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1709 Ordinal = readULEB128();
1710 DEBUG_WITH_TYPE(
1711 "mach-o-bind",
1712 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1713 << "Ordinal=" << Ordinal << "\n");
1714 break;
1715 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1716 if (ImmValue) {
1717 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1718 Ordinal = SignExtended;
1719 } else
1720 Ordinal = 0;
1721 DEBUG_WITH_TYPE(
1722 "mach-o-bind",
1723 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1724 << "Ordinal=" << Ordinal << "\n");
1725 break;
1726 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1727 Flags = ImmValue;
1728 SymStart = Ptr;
1729 while (*Ptr) {
1730 ++Ptr;
1731 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001732 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1733 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001734 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001735 DEBUG_WITH_TYPE(
1736 "mach-o-bind",
1737 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1738 << "SymbolName=" << SymbolName << "\n");
1739 if (TableKind == Kind::Weak) {
1740 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1741 return;
1742 }
1743 break;
1744 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1745 BindType = ImmValue;
1746 DEBUG_WITH_TYPE(
1747 "mach-o-bind",
1748 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1749 << "BindType=" << (int)BindType << "\n");
1750 break;
1751 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1752 Addend = readSLEB128();
1753 if (TableKind == Kind::Lazy)
1754 Malformed = true;
1755 DEBUG_WITH_TYPE(
1756 "mach-o-bind",
1757 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1758 << "Addend=" << Addend << "\n");
1759 break;
1760 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1761 SegmentIndex = ImmValue;
1762 SegmentOffset = readULEB128();
1763 DEBUG_WITH_TYPE(
1764 "mach-o-bind",
1765 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1766 << "SegmentIndex=" << SegmentIndex << ", "
1767 << format("SegmentOffset=0x%06X", SegmentOffset)
1768 << "\n");
1769 break;
1770 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1771 SegmentOffset += readULEB128();
1772 DEBUG_WITH_TYPE("mach-o-bind",
1773 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1774 << format("SegmentOffset=0x%06X",
1775 SegmentOffset) << "\n");
1776 break;
1777 case MachO::BIND_OPCODE_DO_BIND:
1778 AdvanceAmount = PointerSize;
1779 RemainingLoopCount = 0;
1780 DEBUG_WITH_TYPE("mach-o-bind",
1781 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1782 << format("SegmentOffset=0x%06X",
1783 SegmentOffset) << "\n");
1784 return;
1785 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001786 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001787 RemainingLoopCount = 0;
1788 if (TableKind == Kind::Lazy)
1789 Malformed = true;
1790 DEBUG_WITH_TYPE(
1791 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001792 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001793 << format("SegmentOffset=0x%06X", SegmentOffset)
1794 << ", AdvanceAmount=" << AdvanceAmount
1795 << ", RemainingLoopCount=" << RemainingLoopCount
1796 << "\n");
1797 return;
1798 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001799 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001800 RemainingLoopCount = 0;
1801 if (TableKind == Kind::Lazy)
1802 Malformed = true;
1803 DEBUG_WITH_TYPE("mach-o-bind",
1804 llvm::dbgs()
1805 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1806 << format("SegmentOffset=0x%06X",
1807 SegmentOffset) << "\n");
1808 return;
1809 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1810 RemainingLoopCount = readULEB128() - 1;
1811 AdvanceAmount = readULEB128() + PointerSize;
1812 if (TableKind == Kind::Lazy)
1813 Malformed = true;
1814 DEBUG_WITH_TYPE(
1815 "mach-o-bind",
1816 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1817 << format("SegmentOffset=0x%06X", SegmentOffset)
1818 << ", AdvanceAmount=" << AdvanceAmount
1819 << ", RemainingLoopCount=" << RemainingLoopCount
1820 << "\n");
1821 return;
1822 default:
1823 Malformed = true;
1824 }
1825 }
1826}
1827
1828uint64_t MachOBindEntry::readULEB128() {
1829 unsigned Count;
1830 uint64_t Result = decodeULEB128(Ptr, &Count);
1831 Ptr += Count;
1832 if (Ptr > Opcodes.end()) {
1833 Ptr = Opcodes.end();
1834 Malformed = true;
1835 }
1836 return Result;
1837}
1838
1839int64_t MachOBindEntry::readSLEB128() {
1840 unsigned Count;
1841 int64_t Result = decodeSLEB128(Ptr, &Count);
1842 Ptr += Count;
1843 if (Ptr > Opcodes.end()) {
1844 Ptr = Opcodes.end();
1845 Malformed = true;
1846 }
1847 return Result;
1848}
1849
1850
1851uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1852
1853uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1854
1855StringRef MachOBindEntry::typeName() const {
1856 switch (BindType) {
1857 case MachO::BIND_TYPE_POINTER:
1858 return "pointer";
1859 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1860 return "text abs32";
1861 case MachO::BIND_TYPE_TEXT_PCREL32:
1862 return "text rel32";
1863 }
1864 return "unknown";
1865}
1866
1867StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1868
1869int64_t MachOBindEntry::addend() const { return Addend; }
1870
1871uint32_t MachOBindEntry::flags() const { return Flags; }
1872
1873int MachOBindEntry::ordinal() const { return Ordinal; }
1874
1875bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1876 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1877 return (Ptr == Other.Ptr) &&
1878 (RemainingLoopCount == Other.RemainingLoopCount) &&
1879 (Done == Other.Done);
1880}
1881
1882iterator_range<bind_iterator>
1883MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1884 MachOBindEntry::Kind BKind) {
1885 MachOBindEntry Start(Opcodes, is64, BKind);
1886 Start.moveToFirst();
1887
1888 MachOBindEntry Finish(Opcodes, is64, BKind);
1889 Finish.moveToEnd();
1890
1891 return iterator_range<bind_iterator>(bind_iterator(Start),
1892 bind_iterator(Finish));
1893}
1894
1895iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1896 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1897 MachOBindEntry::Kind::Regular);
1898}
1899
1900iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1901 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1902 MachOBindEntry::Kind::Lazy);
1903}
1904
1905iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1906 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1907 MachOBindEntry::Kind::Weak);
1908}
1909
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001910MachOObjectFile::load_command_iterator
1911MachOObjectFile::begin_load_commands() const {
1912 return LoadCommands.begin();
1913}
1914
1915MachOObjectFile::load_command_iterator
1916MachOObjectFile::end_load_commands() const {
1917 return LoadCommands.end();
1918}
1919
1920iterator_range<MachOObjectFile::load_command_iterator>
1921MachOObjectFile::load_commands() const {
1922 return iterator_range<load_command_iterator>(begin_load_commands(),
1923 end_load_commands());
1924}
1925
Rafael Espindola56f976f2013-04-18 18:08:55 +00001926StringRef
1927MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1928 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1929 return parseSegmentOrSectionName(Raw.data());
1930}
1931
1932ArrayRef<char>
1933MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001934 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001935 const section_base *Base =
1936 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001937 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001938}
1939
1940ArrayRef<char>
1941MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001942 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001943 const section_base *Base =
1944 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001945 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001946}
1947
1948bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001949MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001950 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001951 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001952 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001953 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001954}
1955
Eric Christopher1d62c252013-07-22 22:25:07 +00001956unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001957 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001958 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001959 return RE.r_word1 & 0xffffff;
1960 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001961}
1962
Eric Christopher1d62c252013-07-22 22:25:07 +00001963bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001964 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001965 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001966 return (RE.r_word1 >> 27) & 1;
1967 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001968}
1969
Eric Christopher1d62c252013-07-22 22:25:07 +00001970bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001971 const MachO::any_relocation_info &RE) const {
1972 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001973}
1974
Eric Christopher1d62c252013-07-22 22:25:07 +00001975uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001976 const MachO::any_relocation_info &RE) const {
1977 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001978}
1979
Kevin Enderby9907d0a2014-11-04 00:43:16 +00001980uint32_t MachOObjectFile::getScatteredRelocationType(
1981 const MachO::any_relocation_info &RE) const {
1982 return (RE.r_word0 >> 24) & 0xf;
1983}
1984
Eric Christopher1d62c252013-07-22 22:25:07 +00001985unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001986 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001987 if (isRelocationScattered(RE))
1988 return getScatteredRelocationAddress(RE);
1989 return getPlainRelocationAddress(RE);
1990}
1991
Charles Davis8bdfafd2013-09-01 04:28:48 +00001992unsigned MachOObjectFile::getAnyRelocationPCRel(
1993 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001994 if (isRelocationScattered(RE))
1995 return getScatteredRelocationPCRel(this, RE);
1996 return getPlainRelocationPCRel(this, RE);
1997}
1998
Eric Christopher1d62c252013-07-22 22:25:07 +00001999unsigned MachOObjectFile::getAnyRelocationLength(
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 getScatteredRelocationLength(RE);
2003 return getPlainRelocationLength(this, RE);
2004}
2005
2006unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002007MachOObjectFile::getAnyRelocationType(
2008 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002009 if (isRelocationScattered(RE))
2010 return getScatteredRelocationType(RE);
2011 return getPlainRelocationType(this, RE);
2012}
2013
Rafael Espindola52501032013-04-30 15:40:54 +00002014SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002015MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002016 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002017 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002018 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002019 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2020 DataRefImpl DRI;
2021 DRI.d.a = SecNum;
2022 return SectionRef(DRI, this);
2023}
2024
Charles Davis8bdfafd2013-09-01 04:28:48 +00002025MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002026 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002027 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002028}
2029
Charles Davis8bdfafd2013-09-01 04:28:48 +00002030MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002031 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002032 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002033}
2034
Charles Davis8bdfafd2013-09-01 04:28:48 +00002035MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002036 unsigned Index) const {
2037 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002038 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002039}
2040
Charles Davis8bdfafd2013-09-01 04:28:48 +00002041MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2042 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002043 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002044 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002045}
2046
Charles Davis8bdfafd2013-09-01 04:28:48 +00002047MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002048MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002049 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002050 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002051}
2052
Charles Davis8bdfafd2013-09-01 04:28:48 +00002053MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002054MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002055 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002056 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002057}
2058
Charles Davis8bdfafd2013-09-01 04:28:48 +00002059MachO::linkedit_data_command
2060MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2061 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002062}
2063
Charles Davis8bdfafd2013-09-01 04:28:48 +00002064MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002065MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002066 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002067}
2068
Charles Davis8bdfafd2013-09-01 04:28:48 +00002069MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002070MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002071 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002072}
2073
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002074MachO::linker_option_command
2075MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2076 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002077}
2078
Jim Grosbach448334a2014-03-18 22:09:05 +00002079MachO::version_min_command
2080MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2081 return getStruct<MachO::version_min_command>(this, L.Ptr);
2082}
2083
Tim Northover8f9590b2014-06-30 14:40:57 +00002084MachO::dylib_command
2085MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2086 return getStruct<MachO::dylib_command>(this, L.Ptr);
2087}
2088
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002089MachO::dyld_info_command
2090MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2091 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2092}
2093
2094MachO::dylinker_command
2095MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2096 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2097}
2098
2099MachO::uuid_command
2100MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2101 return getStruct<MachO::uuid_command>(this, L.Ptr);
2102}
2103
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002104MachO::rpath_command
2105MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2106 return getStruct<MachO::rpath_command>(this, L.Ptr);
2107}
2108
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002109MachO::source_version_command
2110MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2111 return getStruct<MachO::source_version_command>(this, L.Ptr);
2112}
2113
2114MachO::entry_point_command
2115MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2116 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2117}
2118
Kevin Enderby0804f4672014-12-16 23:25:52 +00002119MachO::encryption_info_command
2120MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2121 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2122}
2123
Kevin Enderby57538292014-12-17 01:01:30 +00002124MachO::encryption_info_command_64
2125MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2126 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2127}
2128
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002129MachO::sub_framework_command
2130MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2131 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2132}
Tim Northover8f9590b2014-06-30 14:40:57 +00002133
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002134MachO::sub_umbrella_command
2135MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2136 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2137}
2138
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002139MachO::sub_library_command
2140MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2141 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2142}
2143
Kevin Enderby186eac32014-12-19 21:06:24 +00002144MachO::sub_client_command
2145MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2146 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2147}
2148
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002149MachO::routines_command
2150MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2151 return getStruct<MachO::routines_command>(this, L.Ptr);
2152}
2153
2154MachO::routines_command_64
2155MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2156 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2157}
2158
Kevin Enderby48ef5342014-12-23 22:56:39 +00002159MachO::thread_command
2160MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2161 return getStruct<MachO::thread_command>(this, L.Ptr);
2162}
2163
Charles Davis8bdfafd2013-09-01 04:28:48 +00002164MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002165MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002166 DataRefImpl Sec;
2167 Sec.d.a = Rel.d.a;
2168 uint32_t Offset;
2169 if (is64Bit()) {
2170 MachO::section_64 Sect = getSection64(Sec);
2171 Offset = Sect.reloff;
2172 } else {
2173 MachO::section Sect = getSection(Sec);
2174 Offset = Sect.reloff;
2175 }
2176
2177 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2178 getPtr(this, Offset)) + Rel.d.b;
2179 return getStruct<MachO::any_relocation_info>(
2180 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002181}
2182
Charles Davis8bdfafd2013-09-01 04:28:48 +00002183MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002184MachOObjectFile::getDice(DataRefImpl Rel) const {
2185 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002186 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002187}
2188
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002189const MachO::mach_header &MachOObjectFile::getHeader() const {
2190 // First fields of MachO::mach_header_64 are the same as
2191 // in MachO::mach_header.
2192 return *reinterpret_cast<const MachO::mach_header *>(&this->Header64);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002193}
2194
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002195const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2196 assert(is64Bit());
2197 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002198}
2199
Charles Davis8bdfafd2013-09-01 04:28:48 +00002200uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2201 const MachO::dysymtab_command &DLC,
2202 unsigned Index) const {
2203 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2204 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002205}
2206
Charles Davis8bdfafd2013-09-01 04:28:48 +00002207MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002208MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2209 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002210 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2211 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002212}
2213
Charles Davis8bdfafd2013-09-01 04:28:48 +00002214MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002215 if (SymtabLoadCmd)
2216 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2217
2218 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2219 MachO::symtab_command Cmd;
2220 Cmd.cmd = MachO::LC_SYMTAB;
2221 Cmd.cmdsize = sizeof(MachO::symtab_command);
2222 Cmd.symoff = 0;
2223 Cmd.nsyms = 0;
2224 Cmd.stroff = 0;
2225 Cmd.strsize = 0;
2226 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002227}
2228
Charles Davis8bdfafd2013-09-01 04:28:48 +00002229MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002230 if (DysymtabLoadCmd)
2231 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2232
2233 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2234 MachO::dysymtab_command Cmd;
2235 Cmd.cmd = MachO::LC_DYSYMTAB;
2236 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2237 Cmd.ilocalsym = 0;
2238 Cmd.nlocalsym = 0;
2239 Cmd.iextdefsym = 0;
2240 Cmd.nextdefsym = 0;
2241 Cmd.iundefsym = 0;
2242 Cmd.nundefsym = 0;
2243 Cmd.tocoff = 0;
2244 Cmd.ntoc = 0;
2245 Cmd.modtaboff = 0;
2246 Cmd.nmodtab = 0;
2247 Cmd.extrefsymoff = 0;
2248 Cmd.nextrefsyms = 0;
2249 Cmd.indirectsymoff = 0;
2250 Cmd.nindirectsyms = 0;
2251 Cmd.extreloff = 0;
2252 Cmd.nextrel = 0;
2253 Cmd.locreloff = 0;
2254 Cmd.nlocrel = 0;
2255 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002256}
2257
Charles Davis8bdfafd2013-09-01 04:28:48 +00002258MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002259MachOObjectFile::getDataInCodeLoadCommand() const {
2260 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002261 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002262
2263 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002264 MachO::linkedit_data_command Cmd;
2265 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2266 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2267 Cmd.dataoff = 0;
2268 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002269 return Cmd;
2270}
2271
Kevin Enderby9a509442015-01-27 21:28:24 +00002272MachO::linkedit_data_command
2273MachOObjectFile::getLinkOptHintsLoadCommand() const {
2274 if (LinkOptHintsLoadCmd)
2275 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2276
2277 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2278 // fields.
2279 MachO::linkedit_data_command Cmd;
2280 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2281 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2282 Cmd.dataoff = 0;
2283 Cmd.datasize = 0;
2284 return Cmd;
2285}
2286
Nick Kledzikd04bc352014-08-30 00:20:14 +00002287ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2288 if (!DyldInfoLoadCmd)
2289 return ArrayRef<uint8_t>();
2290
2291 MachO::dyld_info_command DyldInfo
2292 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2293 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2294 getPtr(this, DyldInfo.rebase_off));
2295 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2296}
2297
2298ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2299 if (!DyldInfoLoadCmd)
2300 return ArrayRef<uint8_t>();
2301
2302 MachO::dyld_info_command DyldInfo
2303 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2304 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2305 getPtr(this, DyldInfo.bind_off));
2306 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2307}
2308
2309ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2310 if (!DyldInfoLoadCmd)
2311 return ArrayRef<uint8_t>();
2312
2313 MachO::dyld_info_command DyldInfo
2314 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2315 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2316 getPtr(this, DyldInfo.weak_bind_off));
2317 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2318}
2319
2320ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2321 if (!DyldInfoLoadCmd)
2322 return ArrayRef<uint8_t>();
2323
2324 MachO::dyld_info_command DyldInfo
2325 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2326 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2327 getPtr(this, DyldInfo.lazy_bind_off));
2328 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2329}
2330
2331ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2332 if (!DyldInfoLoadCmd)
2333 return ArrayRef<uint8_t>();
2334
2335 MachO::dyld_info_command DyldInfo
2336 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2337 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2338 getPtr(this, DyldInfo.export_off));
2339 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2340}
2341
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002342ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2343 if (!UuidLoadCmd)
2344 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002345 // Returning a pointer is fine as uuid doesn't need endian swapping.
2346 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2347 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002348}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002349
Rafael Espindola6e040c02013-04-26 20:07:33 +00002350StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002351 MachO::symtab_command S = getSymtabLoadCommand();
2352 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002353}
2354
Rafael Espindola56f976f2013-04-18 18:08:55 +00002355bool MachOObjectFile::is64Bit() const {
2356 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002357 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002358}
2359
2360void MachOObjectFile::ReadULEB128s(uint64_t Index,
2361 SmallVectorImpl<uint64_t> &Out) const {
2362 DataExtractor extractor(ObjectFile::getData(), true, 0);
2363
2364 uint32_t offset = Index;
2365 uint64_t data = 0;
2366 while (uint64_t delta = extractor.getULEB128(&offset)) {
2367 data += delta;
2368 Out.push_back(data);
2369 }
2370}
2371
Rafael Espindolac66d7612014-08-17 19:09:37 +00002372bool MachOObjectFile::isRelocatableObject() const {
2373 return getHeader().filetype == MachO::MH_OBJECT;
2374}
2375
Rafael Espindola437b0d52014-07-31 03:12:45 +00002376ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002377ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2378 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002379 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002380 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002381 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002382 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002383 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002384 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002385 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002386 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002387 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002388 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002389 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002390 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002391
Rafael Espindola692410e2014-01-21 23:06:54 +00002392 if (EC)
2393 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002394 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002395}
2396