blob: cb98f05bfccf1e4893bc7db10b9c7cd44efbc089 [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
Rafael Espindola6e040c02013-04-26 20:07:33 +000068static const char *
69getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
70 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000071 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
72
73 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000074 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75 sizeof(MachO::segment_command);
76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000078
79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000080 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000081}
82
Rafael Espindola56f976f2013-04-18 18:08:55 +000083static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000085}
86
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000087static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000088getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000089 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000090 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000091}
92
Rafael Espindola56f976f2013-04-18 18:08:55 +000093static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000094 if (P[15] == 0)
95 // Null terminated.
96 return P;
97 // Not null terminated, so this is a 16 char string.
98 return StringRef(P, 16);
99}
100
Rafael Espindola56f976f2013-04-18 18:08:55 +0000101// Helper to advance a section or symbol iterator multiple increments at a time.
102template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000103static void advance(T &it, size_t Val) {
104 while (Val--)
105 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000106}
107
108static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000109 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000110}
111
Charles Davis8bdfafd2013-09-01 04:28:48 +0000112static uint32_t
113getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
114 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000115}
116
117static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000118getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000120}
121
122static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000123 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000124 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000125 return (RE.r_word1 >> 24) & 1;
126 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000127}
128
129static bool
130getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131 const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000133}
134
135static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000136 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000137 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140}
141
142static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000143getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000145}
146
147static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000148 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000149 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152}
153
Rafael Espindola56f976f2013-04-18 18:08:55 +0000154static uint32_t getSectionFlags(const MachOObjectFile *O,
155 DataRefImpl Sec) {
156 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000157 MachO::section_64 Sect = O->getSection64(Sec);
158 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000160 MachO::section Sect = O->getSection(Sec);
161 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000162}
163
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000164static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000165getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
167 if (!CmdOrErr)
168 return CmdOrErr.getError();
169 if (CmdOrErr->cmdsize < 8)
170 return object_error::macho_small_load_command;
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000171 MachOObjectFile::LoadCommandInfo Load;
172 Load.Ptr = Ptr;
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000173 Load.C = CmdOrErr.get();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000174 return Load;
175}
176
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000177static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000178getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180 : sizeof(MachO::mach_header);
181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
182}
183
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000184static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000185getNextLoadCommandInfo(const MachOObjectFile *Obj,
186 const MachOObjectFile::LoadCommandInfo &L) {
187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
188}
189
Alexey Samsonov9f336632015-06-04 19:45:22 +0000190template <typename T>
191static void parseHeader(const MachOObjectFile *Obj, T &Header,
192 std::error_code &EC) {
193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
194 if (HeaderOrErr)
195 Header = HeaderOrErr.get();
196 else
197 EC = HeaderOrErr.getError();
198}
199
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000200// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201// sections to \param Sections, and optionally sets
202// \param IsPageZeroSegment to true.
203template <typename SegmentCmd>
204static std::error_code parseSegmentLoadCommand(
205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208 if (Load.C.cmdsize < SegmentLoadSize)
209 return object_error::macho_load_segment_too_small;
Alexey Samsonovf8a7bf82015-06-04 22:26:44 +0000210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
211 if (!SegOrErr)
212 return SegOrErr.getError();
213 SegmentCmd S = SegOrErr.get();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000214 const unsigned SectionSize =
215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218 return object_error::macho_load_segment_too_many_sections;
219 for (unsigned J = 0; J < S.nsects; ++J) {
220 const char *Sec = getSectionPtr(Obj, Load, J);
221 Sections.push_back(Sec);
222 }
223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
Rui Ueyama7d099192015-06-09 15:20:42 +0000224 return std::error_code();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000225}
226
Rafael Espindola48af1c22014-08-19 18:44:46 +0000227MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000234 if (is64Bit())
Alexey Samsonov9f336632015-06-04 19:45:22 +0000235 parseHeader(this, Header64, EC);
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000236 else
Alexey Samsonovfa5edc52015-06-04 22:49:55 +0000237 parseHeader(this, Header, EC);
Alexey Samsonov9f336632015-06-04 19:45:22 +0000238 if (EC)
239 return;
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000240
241 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000242 if (LoadCommandCount == 0)
243 return;
244
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000245 auto LoadOrErr = getFirstLoadCommandInfo(this);
246 if (!LoadOrErr) {
247 EC = LoadOrErr.getError();
248 return;
249 }
250 LoadCommandInfo Load = LoadOrErr.get();
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000253 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000254 // Multiple symbol tables
255 if (SymtabLoadCmd) {
256 EC = object_error::parse_failed;
257 return;
258 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000259 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
264 return;
265 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000266 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
271 return;
272 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000273 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
278 return;
279 }
280 LinkOptHintsLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
286 return;
287 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000288 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000289 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000290 // Multiple UUID load commands
291 if (UuidLoadCmd) {
292 EC = object_error::parse_failed;
293 return;
294 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000295 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000299 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000303 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000310 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
313 if (!LoadOrErr) {
314 EC = LoadOrErr.getError();
315 return;
316 }
317 Load = LoadOrErr.get();
318 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000319 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000320 assert(LoadCommands.size() == LoadCommandCount);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000321}
322
Rafael Espindola5e812af2014-01-30 02:49:50 +0000323void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000324 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000325 sizeof(MachO::nlist_64) :
326 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000327 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000328}
329
Rafael Espindola3acea392014-06-12 21:46:39 +0000330std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
331 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000332 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000333 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000334 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000335 if (Start < getData().begin() || Start >= getData().end())
336 report_fatal_error(
337 "Symbol name entry points before beginning or past end of file.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000338 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000339 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000340}
341
Rafael Espindola0e77a942014-12-10 20:46:55 +0000342unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
343 DataRefImpl DRI = Sec.getRawDataRefImpl();
344 uint32_t Flags = getSectionFlags(this, DRI);
345 return Flags & MachO::SECTION_TYPE;
346}
347
Rafael Espindola59128922015-06-24 18:14:41 +0000348uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
349 if (is64Bit()) {
350 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
351 return Entry.n_value;
352 }
353 MachO::nlist Entry = getSymbolTableEntry(Sym);
354 return Entry.n_value;
355}
356
Kevin Enderby980b2582014-06-05 21:21:57 +0000357// getIndirectName() returns the name of the alias'ed symbol who's string table
358// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000359std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
360 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000361 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000362 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
363 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
364 return object_error::parse_failed;
365 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000366 if (NValue >= StringTable.size())
367 return object_error::parse_failed;
368 const char *Start = &StringTable.data()[NValue];
369 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000370 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000371}
372
Rafael Espindola991af662015-06-24 19:11:10 +0000373uint64_t MachOObjectFile::getSymbolValue(DataRefImpl Sym) const {
374 uint64_t NValue = getNValue(Sym);
375 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Sym);
Rafael Espindola59128922015-06-24 18:14:41 +0000376 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0)
Rafael Espindola991af662015-06-24 19:11:10 +0000377 return UnknownAddress;
378 return NValue;
379}
380
381std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Sym,
382 uint64_t &Res) const {
383 Res = getSymbolValue(Sym);
Rui Ueyama7d099192015-06-09 15:20:42 +0000384 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000385}
386
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000387uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000388 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000389 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000391 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000392 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000393 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000394}
395
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000396uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000397 uint64_t Value;
398 getSymbolAddress(DRI, Value);
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000399 return Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000400}
401
Rafael Espindola3acea392014-06-12 21:46:39 +0000402std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
403 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000404 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000405 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000406
407 Res = SymbolRef::ST_Other;
408
409 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000410 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000411 Res = SymbolRef::ST_Debug;
Rui Ueyama7d099192015-06-09 15:20:42 +0000412 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000413 }
414
Charles Davis74ec8b02013-08-27 05:00:13 +0000415 switch (n_type & MachO::N_TYPE) {
416 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000417 Res = SymbolRef::ST_Unknown;
418 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000419 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000420 Res = SymbolRef::ST_Function;
421 break;
422 }
Rui Ueyama7d099192015-06-09 15:20:42 +0000423 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000424}
425
Rafael Espindola20122a42014-01-31 20:57:12 +0000426uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000427 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000428
Charles Davis8bdfafd2013-09-01 04:28:48 +0000429 uint8_t MachOType = Entry.n_type;
430 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000431
Rafael Espindola20122a42014-01-31 20:57:12 +0000432 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000433
Charles Davis74ec8b02013-08-27 05:00:13 +0000434 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000435 Result |= SymbolRef::SF_Undefined;
436
Tim Northovereaef0742014-05-30 13:22:59 +0000437 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
438 Result |= SymbolRef::SF_Indirect;
439
Rafael Espindolaa1356322013-11-02 05:03:24 +0000440 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000441 Result |= SymbolRef::SF_FormatSpecific;
442
Charles Davis74ec8b02013-08-27 05:00:13 +0000443 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000444 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000445 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000446 uint64_t Value;
447 getSymbolAddress(DRI, Value);
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000448 if (Value && Value != UnknownAddress)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000449 Result |= SymbolRef::SF_Common;
450 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000451
452 if (!(MachOType & MachO::N_PEXT))
453 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000454 }
455
Charles Davis74ec8b02013-08-27 05:00:13 +0000456 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000457 Result |= SymbolRef::SF_Weak;
458
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000459 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
460 Result |= SymbolRef::SF_Thumb;
461
Charles Davis74ec8b02013-08-27 05:00:13 +0000462 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000463 Result |= SymbolRef::SF_Absolute;
464
Rafael Espindola20122a42014-01-31 20:57:12 +0000465 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000466}
467
Rafael Espindola3acea392014-06-12 21:46:39 +0000468std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
469 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000470 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000471 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000472
473 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000474 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000475 } else {
476 DataRefImpl DRI;
477 DRI.d.a = index - 1;
Rafael Espindola0d85d102015-05-22 14:59:27 +0000478 if (DRI.d.a >= Sections.size())
479 report_fatal_error("getSymbolSection: Invalid section index.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000480 Res = section_iterator(SectionRef(DRI, this));
481 }
482
Rui Ueyama7d099192015-06-09 15:20:42 +0000483 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000484}
485
Rafael Espindola5e812af2014-01-30 02:49:50 +0000486void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000487 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000488}
489
Rafael Espindola3acea392014-06-12 21:46:39 +0000490std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
491 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000492 ArrayRef<char> Raw = getSectionRawName(Sec);
493 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000494 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000495}
496
Rafael Espindola80291272014-10-08 15:28:58 +0000497uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
498 if (is64Bit())
499 return getSection64(Sec).addr;
500 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000501}
502
Rafael Espindola80291272014-10-08 15:28:58 +0000503uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
504 if (is64Bit())
505 return getSection64(Sec).size;
506 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000507}
508
Rafael Espindola3acea392014-06-12 21:46:39 +0000509std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
510 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000511 uint32_t Offset;
512 uint64_t Size;
513
514 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000515 MachO::section_64 Sect = getSection64(Sec);
516 Offset = Sect.offset;
517 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000518 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000519 MachO::section Sect = getSection(Sec);
520 Offset = Sect.offset;
521 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000522 }
523
524 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000525 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000526}
527
Rafael Espindola80291272014-10-08 15:28:58 +0000528uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000529 uint32_t Align;
530 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000531 MachO::section_64 Sect = getSection64(Sec);
532 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000533 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000534 MachO::section Sect = getSection(Sec);
535 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000536 }
537
Rafael Espindola80291272014-10-08 15:28:58 +0000538 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000539}
540
Rafael Espindola80291272014-10-08 15:28:58 +0000541bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000542 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000543 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000544}
545
Rafael Espindola80291272014-10-08 15:28:58 +0000546bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000547 uint32_t Flags = getSectionFlags(this, Sec);
548 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000549 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
550 !(SectionType == MachO::S_ZEROFILL ||
551 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000552}
553
Rafael Espindola80291272014-10-08 15:28:58 +0000554bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000555 uint32_t Flags = getSectionFlags(this, Sec);
556 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000557 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
558 (SectionType == MachO::S_ZEROFILL ||
559 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000560}
561
Rafael Espindola80291272014-10-08 15:28:58 +0000562bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000563 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000564 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000565}
566
Rafael Espindola80291272014-10-08 15:28:58 +0000567bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
568 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000569 SymbolRef::Type ST;
570 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000571 if (ST == SymbolRef::ST_Unknown)
572 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000573
Rafael Espindola80291272014-10-08 15:28:58 +0000574 uint64_t SectBegin = getSectionAddress(Sec);
575 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000576 SectEnd += SectBegin;
577
578 uint64_t SymAddr;
579 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000580 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000581}
582
Rui Ueyamabc654b12013-09-27 21:47:05 +0000583relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000584 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000585 Ret.d.a = Sec.d.a;
586 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000587 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000588}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000589
Rafael Espindola56f976f2013-04-18 18:08:55 +0000590relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000591MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000592 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000593 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000594 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000595 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000596 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000597 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000598 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000599 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000600
Rafael Espindola56f976f2013-04-18 18:08:55 +0000601 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000602 Ret.d.a = Sec.d.a;
603 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000604 return relocation_iterator(RelocationRef(Ret, this));
605}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000606
Rafael Espindola5e812af2014-01-30 02:49:50 +0000607void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000608 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000609}
Owen Anderson171f4852011-10-24 23:20:07 +0000610
Rafael Espindola3acea392014-06-12 21:46:39 +0000611std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
612 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000613 uint64_t Offset;
614 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000615
616 DataRefImpl Sec;
617 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000618 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000619 Res = SecAddress + Offset;
Rui Ueyama7d099192015-06-09 15:20:42 +0000620 return std::error_code();
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000621}
622
Rafael Espindola3acea392014-06-12 21:46:39 +0000623std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
624 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000625 assert(getHeader().filetype == MachO::MH_OBJECT &&
626 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000627 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000628 Res = getAnyRelocationAddress(RE);
Rui Ueyama7d099192015-06-09 15:20:42 +0000629 return std::error_code();
David Meyer2fc34c52012-03-01 01:36:50 +0000630}
631
Rafael Espindola806f0062013-06-05 01:33:53 +0000632symbol_iterator
633MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000634 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000635 if (isRelocationScattered(RE))
636 return symbol_end();
637
Rafael Espindola56f976f2013-04-18 18:08:55 +0000638 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
639 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000640 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000641 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000642
Charles Davis8bdfafd2013-09-01 04:28:48 +0000643 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000644 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000645 sizeof(MachO::nlist_64) :
646 sizeof(MachO::nlist);
647 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000648 DataRefImpl Sym;
649 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000650 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000651}
652
Keno Fischerc780e8e2015-05-21 21:24:32 +0000653section_iterator
654MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
655 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
656}
657
Rafael Espindola3acea392014-06-12 21:46:39 +0000658std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
659 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000660 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000661 Res = getAnyRelocationType(RE);
Rui Ueyama7d099192015-06-09 15:20:42 +0000662 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000663}
664
Rafael Espindola3acea392014-06-12 21:46:39 +0000665std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000666MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
667 SmallVectorImpl<char> &Result) const {
668 StringRef res;
669 uint64_t RType;
670 getRelocationType(Rel, RType);
671
672 unsigned Arch = this->getArch();
673
674 switch (Arch) {
675 case Triple::x86: {
676 static const char *const Table[] = {
677 "GENERIC_RELOC_VANILLA",
678 "GENERIC_RELOC_PAIR",
679 "GENERIC_RELOC_SECTDIFF",
680 "GENERIC_RELOC_PB_LA_PTR",
681 "GENERIC_RELOC_LOCAL_SECTDIFF",
682 "GENERIC_RELOC_TLV" };
683
Eric Christopher13250cb2013-12-06 02:33:38 +0000684 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000685 res = "Unknown";
686 else
687 res = Table[RType];
688 break;
689 }
690 case Triple::x86_64: {
691 static const char *const Table[] = {
692 "X86_64_RELOC_UNSIGNED",
693 "X86_64_RELOC_SIGNED",
694 "X86_64_RELOC_BRANCH",
695 "X86_64_RELOC_GOT_LOAD",
696 "X86_64_RELOC_GOT",
697 "X86_64_RELOC_SUBTRACTOR",
698 "X86_64_RELOC_SIGNED_1",
699 "X86_64_RELOC_SIGNED_2",
700 "X86_64_RELOC_SIGNED_4",
701 "X86_64_RELOC_TLV" };
702
703 if (RType > 9)
704 res = "Unknown";
705 else
706 res = Table[RType];
707 break;
708 }
709 case Triple::arm: {
710 static const char *const Table[] = {
711 "ARM_RELOC_VANILLA",
712 "ARM_RELOC_PAIR",
713 "ARM_RELOC_SECTDIFF",
714 "ARM_RELOC_LOCAL_SECTDIFF",
715 "ARM_RELOC_PB_LA_PTR",
716 "ARM_RELOC_BR24",
717 "ARM_THUMB_RELOC_BR22",
718 "ARM_THUMB_32BIT_BRANCH",
719 "ARM_RELOC_HALF",
720 "ARM_RELOC_HALF_SECTDIFF" };
721
722 if (RType > 9)
723 res = "Unknown";
724 else
725 res = Table[RType];
726 break;
727 }
Tim Northover00ed9962014-03-29 10:18:08 +0000728 case Triple::aarch64: {
729 static const char *const Table[] = {
730 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
731 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
732 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
733 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
734 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
735 "ARM64_RELOC_ADDEND"
736 };
737
738 if (RType >= array_lengthof(Table))
739 res = "Unknown";
740 else
741 res = Table[RType];
742 break;
743 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000744 case Triple::ppc: {
745 static const char *const Table[] = {
746 "PPC_RELOC_VANILLA",
747 "PPC_RELOC_PAIR",
748 "PPC_RELOC_BR14",
749 "PPC_RELOC_BR24",
750 "PPC_RELOC_HI16",
751 "PPC_RELOC_LO16",
752 "PPC_RELOC_HA16",
753 "PPC_RELOC_LO14",
754 "PPC_RELOC_SECTDIFF",
755 "PPC_RELOC_PB_LA_PTR",
756 "PPC_RELOC_HI16_SECTDIFF",
757 "PPC_RELOC_LO16_SECTDIFF",
758 "PPC_RELOC_HA16_SECTDIFF",
759 "PPC_RELOC_JBSR",
760 "PPC_RELOC_LO14_SECTDIFF",
761 "PPC_RELOC_LOCAL_SECTDIFF" };
762
Eric Christopher13250cb2013-12-06 02:33:38 +0000763 if (RType > 15)
764 res = "Unknown";
765 else
766 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000767 break;
768 }
769 case Triple::UnknownArch:
770 res = "Unknown";
771 break;
772 }
773 Result.append(res.begin(), res.end());
Rui Ueyama7d099192015-06-09 15:20:42 +0000774 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000775}
776
Rafael Espindola3acea392014-06-12 21:46:39 +0000777std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
778 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000779 unsigned Arch = getArch();
780 uint64_t Type;
781 getRelocationType(Rel, Type);
782
783 Result = false;
784
785 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
786 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000787 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000788 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000789 } else if (Arch == Triple::x86_64) {
790 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000791 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000792 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000793 DataRefImpl RelPrev = Rel;
794 RelPrev.d.a--;
795 uint64_t PrevType;
796 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000797 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000798 Result = true;
799 }
800 }
801
Rui Ueyama7d099192015-06-09 15:20:42 +0000802 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000803}
804
Keno Fischer281b6942015-05-30 19:44:53 +0000805uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
806 MachO::any_relocation_info RE = getRelocation(Rel);
807 return getAnyRelocationLength(RE);
808}
809
Kevin Enderby980b2582014-06-05 21:21:57 +0000810//
811// guessLibraryShortName() is passed a name of a dynamic library and returns a
812// guess on what the short name is. Then name is returned as a substring of the
813// StringRef Name passed in. The name of the dynamic library is recognized as
814// a framework if it has one of the two following forms:
815// Foo.framework/Versions/A/Foo
816// Foo.framework/Foo
817// Where A and Foo can be any string. And may contain a trailing suffix
818// starting with an underbar. If the Name is recognized as a framework then
819// isFramework is set to true else it is set to false. If the Name has a
820// suffix then Suffix is set to the substring in Name that contains the suffix
821// else it is set to a NULL StringRef.
822//
823// The Name of the dynamic library is recognized as a library name if it has
824// one of the two following forms:
825// libFoo.A.dylib
826// libFoo.dylib
827// The library may have a suffix trailing the name Foo of the form:
828// libFoo_profile.A.dylib
829// libFoo_profile.dylib
830//
831// The Name of the dynamic library is also recognized as a library name if it
832// has the following form:
833// Foo.qtx
834//
835// If the Name of the dynamic library is none of the forms above then a NULL
836// StringRef is returned.
837//
838StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
839 bool &isFramework,
840 StringRef &Suffix) {
841 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
842 size_t a, b, c, d, Idx;
843
844 isFramework = false;
845 Suffix = StringRef();
846
847 // Pull off the last component and make Foo point to it
848 a = Name.rfind('/');
849 if (a == Name.npos || a == 0)
850 goto guess_library;
851 Foo = Name.slice(a+1, Name.npos);
852
853 // Look for a suffix starting with a '_'
854 Idx = Foo.rfind('_');
855 if (Idx != Foo.npos && Foo.size() >= 2) {
856 Suffix = Foo.slice(Idx, Foo.npos);
857 Foo = Foo.slice(0, Idx);
858 }
859
860 // First look for the form Foo.framework/Foo
861 b = Name.rfind('/', a);
862 if (b == Name.npos)
863 Idx = 0;
864 else
865 Idx = b+1;
866 F = Name.slice(Idx, Idx + Foo.size());
867 DotFramework = Name.slice(Idx + Foo.size(),
868 Idx + Foo.size() + sizeof(".framework/")-1);
869 if (F == Foo && DotFramework == ".framework/") {
870 isFramework = true;
871 return Foo;
872 }
873
874 // Next look for the form Foo.framework/Versions/A/Foo
875 if (b == Name.npos)
876 goto guess_library;
877 c = Name.rfind('/', b);
878 if (c == Name.npos || c == 0)
879 goto guess_library;
880 V = Name.slice(c+1, Name.npos);
881 if (!V.startswith("Versions/"))
882 goto guess_library;
883 d = Name.rfind('/', c);
884 if (d == Name.npos)
885 Idx = 0;
886 else
887 Idx = d+1;
888 F = Name.slice(Idx, Idx + Foo.size());
889 DotFramework = Name.slice(Idx + Foo.size(),
890 Idx + Foo.size() + sizeof(".framework/")-1);
891 if (F == Foo && DotFramework == ".framework/") {
892 isFramework = true;
893 return Foo;
894 }
895
896guess_library:
897 // pull off the suffix after the "." and make a point to it
898 a = Name.rfind('.');
899 if (a == Name.npos || a == 0)
900 return StringRef();
901 Dylib = Name.slice(a, Name.npos);
902 if (Dylib != ".dylib")
903 goto guess_qtx;
904
905 // First pull off the version letter for the form Foo.A.dylib if any.
906 if (a >= 3) {
907 Dot = Name.slice(a-2, a-1);
908 if (Dot == ".")
909 a = a - 2;
910 }
911
912 b = Name.rfind('/', a);
913 if (b == Name.npos)
914 b = 0;
915 else
916 b = b+1;
917 // ignore any suffix after an underbar like Foo_profile.A.dylib
918 Idx = Name.find('_', b);
919 if (Idx != Name.npos && Idx != b) {
920 Lib = Name.slice(b, Idx);
921 Suffix = Name.slice(Idx, a);
922 }
923 else
924 Lib = Name.slice(b, a);
925 // There are incorrect library names of the form:
926 // libATS.A_profile.dylib so check for these.
927 if (Lib.size() >= 3) {
928 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
929 if (Dot == ".")
930 Lib = Lib.slice(0, Lib.size()-2);
931 }
932 return Lib;
933
934guess_qtx:
935 Qtx = Name.slice(a, Name.npos);
936 if (Qtx != ".qtx")
937 return StringRef();
938 b = Name.rfind('/', a);
939 if (b == Name.npos)
940 Lib = Name.slice(0, a);
941 else
942 Lib = Name.slice(b+1, a);
943 // There are library names of the form: QT.A.qtx so check for these.
944 if (Lib.size() >= 3) {
945 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
946 if (Dot == ".")
947 Lib = Lib.slice(0, Lib.size()-2);
948 }
949 return Lib;
950}
951
952// getLibraryShortNameByIndex() is used to get the short name of the library
953// for an undefined symbol in a linked Mach-O binary that was linked with the
954// normal two-level namespace default (that is MH_TWOLEVEL in the header).
955// It is passed the index (0 - based) of the library as translated from
956// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +0000957std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +0000958 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000959 if (Index >= Libraries.size())
960 return object_error::parse_failed;
961
Kevin Enderby980b2582014-06-05 21:21:57 +0000962 // If the cache of LibrariesShortNames is not built up do that first for
963 // all the Libraries.
964 if (LibrariesShortNames.size() == 0) {
965 for (unsigned i = 0; i < Libraries.size(); i++) {
966 MachO::dylib_command D =
967 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +0000968 if (D.dylib.name >= D.cmdsize)
969 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +0000970 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +0000971 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +0000972 if (D.dylib.name+Name.size() >= D.cmdsize)
973 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +0000974 StringRef Suffix;
975 bool isFramework;
976 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +0000977 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +0000978 LibrariesShortNames.push_back(Name);
979 else
980 LibrariesShortNames.push_back(shortName);
981 }
982 }
983
984 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +0000985 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000986}
987
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000988basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +0000989 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000990}
991
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000992basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000993 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +0000994 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000995 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +0000996
Charles Davis8bdfafd2013-09-01 04:28:48 +0000997 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000998 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000999 sizeof(MachO::nlist_64) :
1000 sizeof(MachO::nlist);
1001 unsigned Offset = Symtab.symoff +
1002 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001003 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001004 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001005}
1006
Lang Hames36072da2014-05-12 21:39:59 +00001007basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1008 DataRefImpl DRI;
1009 if (!SymtabLoadCmd)
1010 return basic_symbol_iterator(SymbolRef(DRI, this));
1011
1012 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001013 if (Index >= Symtab.nsyms)
1014 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001015 unsigned SymbolTableEntrySize =
1016 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1017 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1018 DRI.p += Index * SymbolTableEntrySize;
1019 return basic_symbol_iterator(SymbolRef(DRI, this));
1020}
1021
Rafael Espindolab5155a52014-02-10 20:24:04 +00001022section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001023 DataRefImpl DRI;
1024 return section_iterator(SectionRef(DRI, this));
1025}
1026
Rafael Espindolab5155a52014-02-10 20:24:04 +00001027section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001028 DataRefImpl DRI;
1029 DRI.d.a = Sections.size();
1030 return section_iterator(SectionRef(DRI, this));
1031}
1032
Rafael Espindola56f976f2013-04-18 18:08:55 +00001033uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001034 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001035}
1036
Rafael Espindola56f976f2013-04-18 18:08:55 +00001037StringRef MachOObjectFile::getFileFormatName() const {
1038 unsigned CPUType = getCPUType(this);
1039 if (!is64Bit()) {
1040 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001041 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001042 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001043 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001044 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001045 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001046 return "Mach-O 32-bit ppc";
1047 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001048 return "Mach-O 32-bit unknown";
1049 }
1050 }
1051
Rafael Espindola56f976f2013-04-18 18:08:55 +00001052 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001053 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001054 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001055 case llvm::MachO::CPU_TYPE_ARM64:
1056 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001057 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001058 return "Mach-O 64-bit ppc64";
1059 default:
1060 return "Mach-O 64-bit unknown";
1061 }
1062}
1063
Alexey Samsonove6388e62013-06-18 15:03:28 +00001064Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1065 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001066 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001067 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001068 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001069 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001070 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001071 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001072 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001073 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001074 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001075 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001076 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001077 return Triple::ppc64;
1078 default:
1079 return Triple::UnknownArch;
1080 }
1081}
1082
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001083Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1084 const char **McpuDefault) {
1085 if (McpuDefault)
1086 *McpuDefault = nullptr;
1087
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001088 switch (CPUType) {
1089 case MachO::CPU_TYPE_I386:
1090 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1091 case MachO::CPU_SUBTYPE_I386_ALL:
1092 return Triple("i386-apple-darwin");
1093 default:
1094 return Triple();
1095 }
1096 case MachO::CPU_TYPE_X86_64:
1097 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1098 case MachO::CPU_SUBTYPE_X86_64_ALL:
1099 return Triple("x86_64-apple-darwin");
1100 case MachO::CPU_SUBTYPE_X86_64_H:
1101 return Triple("x86_64h-apple-darwin");
1102 default:
1103 return Triple();
1104 }
1105 case MachO::CPU_TYPE_ARM:
1106 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1107 case MachO::CPU_SUBTYPE_ARM_V4T:
1108 return Triple("armv4t-apple-darwin");
1109 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1110 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001111 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1112 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001113 case MachO::CPU_SUBTYPE_ARM_V6:
1114 return Triple("armv6-apple-darwin");
1115 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001116 if (McpuDefault)
1117 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001118 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001119 case MachO::CPU_SUBTYPE_ARM_V7:
1120 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001121 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001122 if (McpuDefault)
1123 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001124 return Triple("armv7em-apple-darwin");
1125 case MachO::CPU_SUBTYPE_ARM_V7K:
1126 return Triple("armv7k-apple-darwin");
1127 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001128 if (McpuDefault)
1129 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001130 return Triple("armv7m-apple-darwin");
1131 case MachO::CPU_SUBTYPE_ARM_V7S:
1132 return Triple("armv7s-apple-darwin");
1133 default:
1134 return Triple();
1135 }
1136 case MachO::CPU_TYPE_ARM64:
1137 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1138 case MachO::CPU_SUBTYPE_ARM64_ALL:
1139 return Triple("arm64-apple-darwin");
1140 default:
1141 return Triple();
1142 }
1143 case MachO::CPU_TYPE_POWERPC:
1144 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1145 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1146 return Triple("ppc-apple-darwin");
1147 default:
1148 return Triple();
1149 }
1150 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001151 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001152 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1153 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001154 default:
1155 return Triple();
1156 }
1157 default:
1158 return Triple();
1159 }
1160}
1161
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001162Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1163 const char **McpuDefault) {
1164 if (McpuDefault)
1165 *McpuDefault = nullptr;
1166
1167 switch (CPUType) {
1168 case MachO::CPU_TYPE_ARM:
1169 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1170 case MachO::CPU_SUBTYPE_ARM_V4T:
1171 return Triple("thumbv4t-apple-darwin");
1172 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1173 return Triple("thumbv5e-apple-darwin");
1174 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1175 return Triple("xscale-apple-darwin");
1176 case MachO::CPU_SUBTYPE_ARM_V6:
1177 return Triple("thumbv6-apple-darwin");
1178 case MachO::CPU_SUBTYPE_ARM_V6M:
1179 if (McpuDefault)
1180 *McpuDefault = "cortex-m0";
1181 return Triple("thumbv6m-apple-darwin");
1182 case MachO::CPU_SUBTYPE_ARM_V7:
1183 return Triple("thumbv7-apple-darwin");
1184 case MachO::CPU_SUBTYPE_ARM_V7EM:
1185 if (McpuDefault)
1186 *McpuDefault = "cortex-m4";
1187 return Triple("thumbv7em-apple-darwin");
1188 case MachO::CPU_SUBTYPE_ARM_V7K:
1189 return Triple("thumbv7k-apple-darwin");
1190 case MachO::CPU_SUBTYPE_ARM_V7M:
1191 if (McpuDefault)
1192 *McpuDefault = "cortex-m3";
1193 return Triple("thumbv7m-apple-darwin");
1194 case MachO::CPU_SUBTYPE_ARM_V7S:
1195 return Triple("thumbv7s-apple-darwin");
1196 default:
1197 return Triple();
1198 }
1199 default:
1200 return Triple();
1201 }
1202}
1203
1204Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1205 const char **McpuDefault,
1206 Triple *ThumbTriple) {
1207 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1208 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1209 McpuDefault);
1210 return T;
1211}
1212
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001213Triple MachOObjectFile::getHostArch() {
1214 return Triple(sys::getDefaultTargetTriple());
1215}
1216
Rafael Espindola72318b42014-08-08 16:30:17 +00001217bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1218 return StringSwitch<bool>(ArchFlag)
1219 .Case("i386", true)
1220 .Case("x86_64", true)
1221 .Case("x86_64h", true)
1222 .Case("armv4t", true)
1223 .Case("arm", true)
1224 .Case("armv5e", true)
1225 .Case("armv6", true)
1226 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001227 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001228 .Case("armv7em", true)
1229 .Case("armv7k", true)
1230 .Case("armv7m", true)
1231 .Case("armv7s", true)
1232 .Case("arm64", true)
1233 .Case("ppc", true)
1234 .Case("ppc64", true)
1235 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001236}
1237
Alexey Samsonove6388e62013-06-18 15:03:28 +00001238unsigned MachOObjectFile::getArch() const {
1239 return getArch(getCPUType(this));
1240}
1241
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001242Triple MachOObjectFile::getArch(const char **McpuDefault,
1243 Triple *ThumbTriple) const {
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001244 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1245 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001246}
1247
Rui Ueyamabc654b12013-09-27 21:47:05 +00001248relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001249 DataRefImpl DRI;
1250 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001251 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001252}
1253
Rui Ueyamabc654b12013-09-27 21:47:05 +00001254relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001255 DataRefImpl DRI;
1256 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001257 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001258}
1259
Kevin Enderby273ae012013-06-06 17:20:50 +00001260dice_iterator MachOObjectFile::begin_dices() const {
1261 DataRefImpl DRI;
1262 if (!DataInCodeLoadCmd)
1263 return dice_iterator(DiceRef(DRI, this));
1264
Charles Davis8bdfafd2013-09-01 04:28:48 +00001265 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1266 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001267 return dice_iterator(DiceRef(DRI, this));
1268}
1269
1270dice_iterator MachOObjectFile::end_dices() const {
1271 DataRefImpl DRI;
1272 if (!DataInCodeLoadCmd)
1273 return dice_iterator(DiceRef(DRI, this));
1274
Charles Davis8bdfafd2013-09-01 04:28:48 +00001275 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1276 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001277 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1278 return dice_iterator(DiceRef(DRI, this));
1279}
1280
Nick Kledzikd04bc352014-08-30 00:20:14 +00001281ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1282 : Trie(T), Malformed(false), Done(false) { }
1283
1284void ExportEntry::moveToFirst() {
1285 pushNode(0);
1286 pushDownUntilBottom();
1287}
1288
1289void ExportEntry::moveToEnd() {
1290 Stack.clear();
1291 Done = true;
1292}
1293
1294bool ExportEntry::operator==(const ExportEntry &Other) const {
1295 // Common case, one at end, other iterating from begin.
1296 if (Done || Other.Done)
1297 return (Done == Other.Done);
1298 // Not equal if different stack sizes.
1299 if (Stack.size() != Other.Stack.size())
1300 return false;
1301 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001302 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001303 return false;
1304 // Equal if all nodes in both stacks match.
1305 for (unsigned i=0; i < Stack.size(); ++i) {
1306 if (Stack[i].Start != Other.Stack[i].Start)
1307 return false;
1308 }
1309 return true;
1310}
1311
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001312uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1313 unsigned Count;
1314 uint64_t Result = decodeULEB128(Ptr, &Count);
1315 Ptr += Count;
1316 if (Ptr > Trie.end()) {
1317 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001318 Malformed = true;
1319 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001320 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001321}
1322
1323StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001324 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001325}
1326
1327uint64_t ExportEntry::flags() const {
1328 return Stack.back().Flags;
1329}
1330
1331uint64_t ExportEntry::address() const {
1332 return Stack.back().Address;
1333}
1334
1335uint64_t ExportEntry::other() const {
1336 return Stack.back().Other;
1337}
1338
1339StringRef ExportEntry::otherName() const {
1340 const char* ImportName = Stack.back().ImportName;
1341 if (ImportName)
1342 return StringRef(ImportName);
1343 return StringRef();
1344}
1345
1346uint32_t ExportEntry::nodeOffset() const {
1347 return Stack.back().Start - Trie.begin();
1348}
1349
1350ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1351 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1352 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1353 ParentStringLength(0), IsExportNode(false) {
1354}
1355
1356void ExportEntry::pushNode(uint64_t offset) {
1357 const uint8_t *Ptr = Trie.begin() + offset;
1358 NodeState State(Ptr);
1359 uint64_t ExportInfoSize = readULEB128(State.Current);
1360 State.IsExportNode = (ExportInfoSize != 0);
1361 const uint8_t* Children = State.Current + ExportInfoSize;
1362 if (State.IsExportNode) {
1363 State.Flags = readULEB128(State.Current);
1364 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1365 State.Address = 0;
1366 State.Other = readULEB128(State.Current); // dylib ordinal
1367 State.ImportName = reinterpret_cast<const char*>(State.Current);
1368 } else {
1369 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001370 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1371 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001372 }
1373 }
1374 State.ChildCount = *Children;
1375 State.Current = Children + 1;
1376 State.NextChildIndex = 0;
1377 State.ParentStringLength = CumulativeString.size();
1378 Stack.push_back(State);
1379}
1380
1381void ExportEntry::pushDownUntilBottom() {
1382 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1383 NodeState &Top = Stack.back();
1384 CumulativeString.resize(Top.ParentStringLength);
1385 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001386 char C = *Top.Current;
1387 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001388 }
1389 Top.Current += 1;
1390 uint64_t childNodeIndex = readULEB128(Top.Current);
1391 Top.NextChildIndex += 1;
1392 pushNode(childNodeIndex);
1393 }
1394 if (!Stack.back().IsExportNode) {
1395 Malformed = true;
1396 moveToEnd();
1397 }
1398}
1399
1400// We have a trie data structure and need a way to walk it that is compatible
1401// with the C++ iterator model. The solution is a non-recursive depth first
1402// traversal where the iterator contains a stack of parent nodes along with a
1403// string that is the accumulation of all edge strings along the parent chain
1404// to this point.
1405//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001406// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001407// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1408// node may have child nodes too.
1409//
1410// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1411// child until hitting a node with no children (which is an export node or
1412// else the trie is malformed). On the way down, each node is pushed on the
1413// stack ivar. If there is no more ways down, it pops up one and tries to go
1414// down a sibling path until a childless node is reached.
1415void ExportEntry::moveNext() {
1416 if (Stack.empty() || !Stack.back().IsExportNode) {
1417 Malformed = true;
1418 moveToEnd();
1419 return;
1420 }
1421
1422 Stack.pop_back();
1423 while (!Stack.empty()) {
1424 NodeState &Top = Stack.back();
1425 if (Top.NextChildIndex < Top.ChildCount) {
1426 pushDownUntilBottom();
1427 // Now at the next export node.
1428 return;
1429 } else {
1430 if (Top.IsExportNode) {
1431 // This node has no children but is itself an export node.
1432 CumulativeString.resize(Top.ParentStringLength);
1433 return;
1434 }
1435 Stack.pop_back();
1436 }
1437 }
1438 Done = true;
1439}
1440
1441iterator_range<export_iterator>
1442MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1443 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001444 if (Trie.size() == 0)
1445 Start.moveToEnd();
1446 else
1447 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001448
1449 ExportEntry Finish(Trie);
1450 Finish.moveToEnd();
1451
1452 return iterator_range<export_iterator>(export_iterator(Start),
1453 export_iterator(Finish));
1454}
1455
1456iterator_range<export_iterator> MachOObjectFile::exports() const {
1457 return exports(getDyldInfoExportsTrie());
1458}
1459
1460
Nick Kledzikac431442014-09-12 21:34:15 +00001461MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1462 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1463 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1464 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1465
1466void MachORebaseEntry::moveToFirst() {
1467 Ptr = Opcodes.begin();
1468 moveNext();
1469}
1470
1471void MachORebaseEntry::moveToEnd() {
1472 Ptr = Opcodes.end();
1473 RemainingLoopCount = 0;
1474 Done = true;
1475}
1476
1477void MachORebaseEntry::moveNext() {
1478 // If in the middle of some loop, move to next rebasing in loop.
1479 SegmentOffset += AdvanceAmount;
1480 if (RemainingLoopCount) {
1481 --RemainingLoopCount;
1482 return;
1483 }
1484 if (Ptr == Opcodes.end()) {
1485 Done = true;
1486 return;
1487 }
1488 bool More = true;
1489 while (More && !Malformed) {
1490 // Parse next opcode and set up next loop.
1491 uint8_t Byte = *Ptr++;
1492 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1493 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1494 switch (Opcode) {
1495 case MachO::REBASE_OPCODE_DONE:
1496 More = false;
1497 Done = true;
1498 moveToEnd();
1499 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1500 break;
1501 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1502 RebaseType = ImmValue;
1503 DEBUG_WITH_TYPE(
1504 "mach-o-rebase",
1505 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1506 << "RebaseType=" << (int) RebaseType << "\n");
1507 break;
1508 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1509 SegmentIndex = ImmValue;
1510 SegmentOffset = readULEB128();
1511 DEBUG_WITH_TYPE(
1512 "mach-o-rebase",
1513 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1514 << "SegmentIndex=" << SegmentIndex << ", "
1515 << format("SegmentOffset=0x%06X", SegmentOffset)
1516 << "\n");
1517 break;
1518 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1519 SegmentOffset += readULEB128();
1520 DEBUG_WITH_TYPE("mach-o-rebase",
1521 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1522 << format("SegmentOffset=0x%06X",
1523 SegmentOffset) << "\n");
1524 break;
1525 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1526 SegmentOffset += ImmValue * PointerSize;
1527 DEBUG_WITH_TYPE("mach-o-rebase",
1528 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1529 << format("SegmentOffset=0x%06X",
1530 SegmentOffset) << "\n");
1531 break;
1532 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1533 AdvanceAmount = PointerSize;
1534 RemainingLoopCount = ImmValue - 1;
1535 DEBUG_WITH_TYPE(
1536 "mach-o-rebase",
1537 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1538 << format("SegmentOffset=0x%06X", SegmentOffset)
1539 << ", AdvanceAmount=" << AdvanceAmount
1540 << ", RemainingLoopCount=" << RemainingLoopCount
1541 << "\n");
1542 return;
1543 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1544 AdvanceAmount = PointerSize;
1545 RemainingLoopCount = readULEB128() - 1;
1546 DEBUG_WITH_TYPE(
1547 "mach-o-rebase",
1548 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1549 << format("SegmentOffset=0x%06X", SegmentOffset)
1550 << ", AdvanceAmount=" << AdvanceAmount
1551 << ", RemainingLoopCount=" << RemainingLoopCount
1552 << "\n");
1553 return;
1554 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1555 AdvanceAmount = readULEB128() + PointerSize;
1556 RemainingLoopCount = 0;
1557 DEBUG_WITH_TYPE(
1558 "mach-o-rebase",
1559 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1560 << format("SegmentOffset=0x%06X", SegmentOffset)
1561 << ", AdvanceAmount=" << AdvanceAmount
1562 << ", RemainingLoopCount=" << RemainingLoopCount
1563 << "\n");
1564 return;
1565 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1566 RemainingLoopCount = readULEB128() - 1;
1567 AdvanceAmount = readULEB128() + PointerSize;
1568 DEBUG_WITH_TYPE(
1569 "mach-o-rebase",
1570 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1571 << format("SegmentOffset=0x%06X", SegmentOffset)
1572 << ", AdvanceAmount=" << AdvanceAmount
1573 << ", RemainingLoopCount=" << RemainingLoopCount
1574 << "\n");
1575 return;
1576 default:
1577 Malformed = true;
1578 }
1579 }
1580}
1581
1582uint64_t MachORebaseEntry::readULEB128() {
1583 unsigned Count;
1584 uint64_t Result = decodeULEB128(Ptr, &Count);
1585 Ptr += Count;
1586 if (Ptr > Opcodes.end()) {
1587 Ptr = Opcodes.end();
1588 Malformed = true;
1589 }
1590 return Result;
1591}
1592
1593uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1594
1595uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1596
1597StringRef MachORebaseEntry::typeName() const {
1598 switch (RebaseType) {
1599 case MachO::REBASE_TYPE_POINTER:
1600 return "pointer";
1601 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1602 return "text abs32";
1603 case MachO::REBASE_TYPE_TEXT_PCREL32:
1604 return "text rel32";
1605 }
1606 return "unknown";
1607}
1608
1609bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1610 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1611 return (Ptr == Other.Ptr) &&
1612 (RemainingLoopCount == Other.RemainingLoopCount) &&
1613 (Done == Other.Done);
1614}
1615
1616iterator_range<rebase_iterator>
1617MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1618 MachORebaseEntry Start(Opcodes, is64);
1619 Start.moveToFirst();
1620
1621 MachORebaseEntry Finish(Opcodes, is64);
1622 Finish.moveToEnd();
1623
1624 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1625 rebase_iterator(Finish));
1626}
1627
1628iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1629 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1630}
1631
Nick Kledzik56ebef42014-09-16 01:41:51 +00001632
1633MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1634 Kind BK)
1635 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1636 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1637 BindType(0), PointerSize(is64Bit ? 8 : 4),
1638 TableKind(BK), Malformed(false), Done(false) {}
1639
1640void MachOBindEntry::moveToFirst() {
1641 Ptr = Opcodes.begin();
1642 moveNext();
1643}
1644
1645void MachOBindEntry::moveToEnd() {
1646 Ptr = Opcodes.end();
1647 RemainingLoopCount = 0;
1648 Done = true;
1649}
1650
1651void MachOBindEntry::moveNext() {
1652 // If in the middle of some loop, move to next binding in loop.
1653 SegmentOffset += AdvanceAmount;
1654 if (RemainingLoopCount) {
1655 --RemainingLoopCount;
1656 return;
1657 }
1658 if (Ptr == Opcodes.end()) {
1659 Done = true;
1660 return;
1661 }
1662 bool More = true;
1663 while (More && !Malformed) {
1664 // Parse next opcode and set up next loop.
1665 uint8_t Byte = *Ptr++;
1666 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1667 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1668 int8_t SignExtended;
1669 const uint8_t *SymStart;
1670 switch (Opcode) {
1671 case MachO::BIND_OPCODE_DONE:
1672 if (TableKind == Kind::Lazy) {
1673 // Lazying bindings have a DONE opcode between entries. Need to ignore
1674 // it to advance to next entry. But need not if this is last entry.
1675 bool NotLastEntry = false;
1676 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1677 if (*P) {
1678 NotLastEntry = true;
1679 }
1680 }
1681 if (NotLastEntry)
1682 break;
1683 }
1684 More = false;
1685 Done = true;
1686 moveToEnd();
1687 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1688 break;
1689 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1690 Ordinal = ImmValue;
1691 DEBUG_WITH_TYPE(
1692 "mach-o-bind",
1693 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1694 << "Ordinal=" << Ordinal << "\n");
1695 break;
1696 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1697 Ordinal = readULEB128();
1698 DEBUG_WITH_TYPE(
1699 "mach-o-bind",
1700 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1701 << "Ordinal=" << Ordinal << "\n");
1702 break;
1703 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1704 if (ImmValue) {
1705 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1706 Ordinal = SignExtended;
1707 } else
1708 Ordinal = 0;
1709 DEBUG_WITH_TYPE(
1710 "mach-o-bind",
1711 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1712 << "Ordinal=" << Ordinal << "\n");
1713 break;
1714 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1715 Flags = ImmValue;
1716 SymStart = Ptr;
1717 while (*Ptr) {
1718 ++Ptr;
1719 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001720 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1721 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001722 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001723 DEBUG_WITH_TYPE(
1724 "mach-o-bind",
1725 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1726 << "SymbolName=" << SymbolName << "\n");
1727 if (TableKind == Kind::Weak) {
1728 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1729 return;
1730 }
1731 break;
1732 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1733 BindType = ImmValue;
1734 DEBUG_WITH_TYPE(
1735 "mach-o-bind",
1736 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1737 << "BindType=" << (int)BindType << "\n");
1738 break;
1739 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1740 Addend = readSLEB128();
1741 if (TableKind == Kind::Lazy)
1742 Malformed = true;
1743 DEBUG_WITH_TYPE(
1744 "mach-o-bind",
1745 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1746 << "Addend=" << Addend << "\n");
1747 break;
1748 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1749 SegmentIndex = ImmValue;
1750 SegmentOffset = readULEB128();
1751 DEBUG_WITH_TYPE(
1752 "mach-o-bind",
1753 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1754 << "SegmentIndex=" << SegmentIndex << ", "
1755 << format("SegmentOffset=0x%06X", SegmentOffset)
1756 << "\n");
1757 break;
1758 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1759 SegmentOffset += readULEB128();
1760 DEBUG_WITH_TYPE("mach-o-bind",
1761 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1762 << format("SegmentOffset=0x%06X",
1763 SegmentOffset) << "\n");
1764 break;
1765 case MachO::BIND_OPCODE_DO_BIND:
1766 AdvanceAmount = PointerSize;
1767 RemainingLoopCount = 0;
1768 DEBUG_WITH_TYPE("mach-o-bind",
1769 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1770 << format("SegmentOffset=0x%06X",
1771 SegmentOffset) << "\n");
1772 return;
1773 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001774 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001775 RemainingLoopCount = 0;
1776 if (TableKind == Kind::Lazy)
1777 Malformed = true;
1778 DEBUG_WITH_TYPE(
1779 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001780 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001781 << format("SegmentOffset=0x%06X", SegmentOffset)
1782 << ", AdvanceAmount=" << AdvanceAmount
1783 << ", RemainingLoopCount=" << RemainingLoopCount
1784 << "\n");
1785 return;
1786 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001787 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001788 RemainingLoopCount = 0;
1789 if (TableKind == Kind::Lazy)
1790 Malformed = true;
1791 DEBUG_WITH_TYPE("mach-o-bind",
1792 llvm::dbgs()
1793 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1794 << format("SegmentOffset=0x%06X",
1795 SegmentOffset) << "\n");
1796 return;
1797 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1798 RemainingLoopCount = readULEB128() - 1;
1799 AdvanceAmount = readULEB128() + PointerSize;
1800 if (TableKind == Kind::Lazy)
1801 Malformed = true;
1802 DEBUG_WITH_TYPE(
1803 "mach-o-bind",
1804 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1805 << format("SegmentOffset=0x%06X", SegmentOffset)
1806 << ", AdvanceAmount=" << AdvanceAmount
1807 << ", RemainingLoopCount=" << RemainingLoopCount
1808 << "\n");
1809 return;
1810 default:
1811 Malformed = true;
1812 }
1813 }
1814}
1815
1816uint64_t MachOBindEntry::readULEB128() {
1817 unsigned Count;
1818 uint64_t Result = decodeULEB128(Ptr, &Count);
1819 Ptr += Count;
1820 if (Ptr > Opcodes.end()) {
1821 Ptr = Opcodes.end();
1822 Malformed = true;
1823 }
1824 return Result;
1825}
1826
1827int64_t MachOBindEntry::readSLEB128() {
1828 unsigned Count;
1829 int64_t Result = decodeSLEB128(Ptr, &Count);
1830 Ptr += Count;
1831 if (Ptr > Opcodes.end()) {
1832 Ptr = Opcodes.end();
1833 Malformed = true;
1834 }
1835 return Result;
1836}
1837
1838
1839uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1840
1841uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1842
1843StringRef MachOBindEntry::typeName() const {
1844 switch (BindType) {
1845 case MachO::BIND_TYPE_POINTER:
1846 return "pointer";
1847 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1848 return "text abs32";
1849 case MachO::BIND_TYPE_TEXT_PCREL32:
1850 return "text rel32";
1851 }
1852 return "unknown";
1853}
1854
1855StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1856
1857int64_t MachOBindEntry::addend() const { return Addend; }
1858
1859uint32_t MachOBindEntry::flags() const { return Flags; }
1860
1861int MachOBindEntry::ordinal() const { return Ordinal; }
1862
1863bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1864 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1865 return (Ptr == Other.Ptr) &&
1866 (RemainingLoopCount == Other.RemainingLoopCount) &&
1867 (Done == Other.Done);
1868}
1869
1870iterator_range<bind_iterator>
1871MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1872 MachOBindEntry::Kind BKind) {
1873 MachOBindEntry Start(Opcodes, is64, BKind);
1874 Start.moveToFirst();
1875
1876 MachOBindEntry Finish(Opcodes, is64, BKind);
1877 Finish.moveToEnd();
1878
1879 return iterator_range<bind_iterator>(bind_iterator(Start),
1880 bind_iterator(Finish));
1881}
1882
1883iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1884 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1885 MachOBindEntry::Kind::Regular);
1886}
1887
1888iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1889 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1890 MachOBindEntry::Kind::Lazy);
1891}
1892
1893iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1894 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1895 MachOBindEntry::Kind::Weak);
1896}
1897
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001898MachOObjectFile::load_command_iterator
1899MachOObjectFile::begin_load_commands() const {
1900 return LoadCommands.begin();
1901}
1902
1903MachOObjectFile::load_command_iterator
1904MachOObjectFile::end_load_commands() const {
1905 return LoadCommands.end();
1906}
1907
1908iterator_range<MachOObjectFile::load_command_iterator>
1909MachOObjectFile::load_commands() const {
1910 return iterator_range<load_command_iterator>(begin_load_commands(),
1911 end_load_commands());
1912}
1913
Rafael Espindola56f976f2013-04-18 18:08:55 +00001914StringRef
1915MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1916 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1917 return parseSegmentOrSectionName(Raw.data());
1918}
1919
1920ArrayRef<char>
1921MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001922 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001923 const section_base *Base =
1924 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001925 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001926}
1927
1928ArrayRef<char>
1929MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001930 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001931 const section_base *Base =
1932 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001933 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001934}
1935
1936bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001937MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001938 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001939 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001940 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001941 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001942}
1943
Eric Christopher1d62c252013-07-22 22:25:07 +00001944unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001945 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001946 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001947 return RE.r_word1 & 0xffffff;
1948 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001949}
1950
Eric Christopher1d62c252013-07-22 22:25:07 +00001951bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001952 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001953 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001954 return (RE.r_word1 >> 27) & 1;
1955 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001956}
1957
Eric Christopher1d62c252013-07-22 22:25:07 +00001958bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001959 const MachO::any_relocation_info &RE) const {
1960 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001961}
1962
Eric Christopher1d62c252013-07-22 22:25:07 +00001963uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001964 const MachO::any_relocation_info &RE) const {
1965 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001966}
1967
Kevin Enderby9907d0a2014-11-04 00:43:16 +00001968uint32_t MachOObjectFile::getScatteredRelocationType(
1969 const MachO::any_relocation_info &RE) const {
1970 return (RE.r_word0 >> 24) & 0xf;
1971}
1972
Eric Christopher1d62c252013-07-22 22:25:07 +00001973unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001974 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001975 if (isRelocationScattered(RE))
1976 return getScatteredRelocationAddress(RE);
1977 return getPlainRelocationAddress(RE);
1978}
1979
Charles Davis8bdfafd2013-09-01 04:28:48 +00001980unsigned MachOObjectFile::getAnyRelocationPCRel(
1981 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001982 if (isRelocationScattered(RE))
1983 return getScatteredRelocationPCRel(this, RE);
1984 return getPlainRelocationPCRel(this, RE);
1985}
1986
Eric Christopher1d62c252013-07-22 22:25:07 +00001987unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001988 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001989 if (isRelocationScattered(RE))
1990 return getScatteredRelocationLength(RE);
1991 return getPlainRelocationLength(this, RE);
1992}
1993
1994unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00001995MachOObjectFile::getAnyRelocationType(
1996 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001997 if (isRelocationScattered(RE))
1998 return getScatteredRelocationType(RE);
1999 return getPlainRelocationType(this, RE);
2000}
2001
Rafael Espindola52501032013-04-30 15:40:54 +00002002SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002003MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002004 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002005 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002006 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002007 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2008 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2009 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002010 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002011 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002012 return SectionRef(DRI, this);
2013}
2014
Charles Davis8bdfafd2013-09-01 04:28:48 +00002015MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002016 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002017 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002018}
2019
Charles Davis8bdfafd2013-09-01 04:28:48 +00002020MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002021 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002022 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002023}
2024
Charles Davis8bdfafd2013-09-01 04:28:48 +00002025MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002026 unsigned Index) const {
2027 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002028 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002029}
2030
Charles Davis8bdfafd2013-09-01 04:28:48 +00002031MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2032 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002033 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002034 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002035}
2036
Charles Davis8bdfafd2013-09-01 04:28:48 +00002037MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002038MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002039 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002040 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002041}
2042
Charles Davis8bdfafd2013-09-01 04:28:48 +00002043MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002044MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002045 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002046 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002047}
2048
Charles Davis8bdfafd2013-09-01 04:28:48 +00002049MachO::linkedit_data_command
2050MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2051 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002052}
2053
Charles Davis8bdfafd2013-09-01 04:28:48 +00002054MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002055MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002056 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002057}
2058
Charles Davis8bdfafd2013-09-01 04:28:48 +00002059MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002060MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002061 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002062}
2063
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002064MachO::linker_option_command
2065MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2066 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002067}
2068
Jim Grosbach448334a2014-03-18 22:09:05 +00002069MachO::version_min_command
2070MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2071 return getStruct<MachO::version_min_command>(this, L.Ptr);
2072}
2073
Tim Northover8f9590b2014-06-30 14:40:57 +00002074MachO::dylib_command
2075MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2076 return getStruct<MachO::dylib_command>(this, L.Ptr);
2077}
2078
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002079MachO::dyld_info_command
2080MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2081 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2082}
2083
2084MachO::dylinker_command
2085MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2086 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2087}
2088
2089MachO::uuid_command
2090MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2091 return getStruct<MachO::uuid_command>(this, L.Ptr);
2092}
2093
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002094MachO::rpath_command
2095MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2096 return getStruct<MachO::rpath_command>(this, L.Ptr);
2097}
2098
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002099MachO::source_version_command
2100MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2101 return getStruct<MachO::source_version_command>(this, L.Ptr);
2102}
2103
2104MachO::entry_point_command
2105MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2106 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2107}
2108
Kevin Enderby0804f4672014-12-16 23:25:52 +00002109MachO::encryption_info_command
2110MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2111 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2112}
2113
Kevin Enderby57538292014-12-17 01:01:30 +00002114MachO::encryption_info_command_64
2115MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2116 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2117}
2118
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002119MachO::sub_framework_command
2120MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2121 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2122}
Tim Northover8f9590b2014-06-30 14:40:57 +00002123
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002124MachO::sub_umbrella_command
2125MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2126 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2127}
2128
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002129MachO::sub_library_command
2130MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2131 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2132}
2133
Kevin Enderby186eac32014-12-19 21:06:24 +00002134MachO::sub_client_command
2135MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2136 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2137}
2138
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002139MachO::routines_command
2140MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2141 return getStruct<MachO::routines_command>(this, L.Ptr);
2142}
2143
2144MachO::routines_command_64
2145MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2146 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2147}
2148
Kevin Enderby48ef5342014-12-23 22:56:39 +00002149MachO::thread_command
2150MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2151 return getStruct<MachO::thread_command>(this, L.Ptr);
2152}
2153
Charles Davis8bdfafd2013-09-01 04:28:48 +00002154MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002155MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002156 DataRefImpl Sec;
2157 Sec.d.a = Rel.d.a;
2158 uint32_t Offset;
2159 if (is64Bit()) {
2160 MachO::section_64 Sect = getSection64(Sec);
2161 Offset = Sect.reloff;
2162 } else {
2163 MachO::section Sect = getSection(Sec);
2164 Offset = Sect.reloff;
2165 }
2166
2167 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2168 getPtr(this, Offset)) + Rel.d.b;
2169 return getStruct<MachO::any_relocation_info>(
2170 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002171}
2172
Charles Davis8bdfafd2013-09-01 04:28:48 +00002173MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002174MachOObjectFile::getDice(DataRefImpl Rel) const {
2175 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002176 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002177}
2178
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002179const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002180 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002181}
2182
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002183const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2184 assert(is64Bit());
2185 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002186}
2187
Charles Davis8bdfafd2013-09-01 04:28:48 +00002188uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2189 const MachO::dysymtab_command &DLC,
2190 unsigned Index) const {
2191 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2192 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002193}
2194
Charles Davis8bdfafd2013-09-01 04:28:48 +00002195MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002196MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2197 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002198 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2199 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002200}
2201
Charles Davis8bdfafd2013-09-01 04:28:48 +00002202MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002203 if (SymtabLoadCmd)
2204 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2205
2206 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2207 MachO::symtab_command Cmd;
2208 Cmd.cmd = MachO::LC_SYMTAB;
2209 Cmd.cmdsize = sizeof(MachO::symtab_command);
2210 Cmd.symoff = 0;
2211 Cmd.nsyms = 0;
2212 Cmd.stroff = 0;
2213 Cmd.strsize = 0;
2214 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002215}
2216
Charles Davis8bdfafd2013-09-01 04:28:48 +00002217MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002218 if (DysymtabLoadCmd)
2219 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2220
2221 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2222 MachO::dysymtab_command Cmd;
2223 Cmd.cmd = MachO::LC_DYSYMTAB;
2224 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2225 Cmd.ilocalsym = 0;
2226 Cmd.nlocalsym = 0;
2227 Cmd.iextdefsym = 0;
2228 Cmd.nextdefsym = 0;
2229 Cmd.iundefsym = 0;
2230 Cmd.nundefsym = 0;
2231 Cmd.tocoff = 0;
2232 Cmd.ntoc = 0;
2233 Cmd.modtaboff = 0;
2234 Cmd.nmodtab = 0;
2235 Cmd.extrefsymoff = 0;
2236 Cmd.nextrefsyms = 0;
2237 Cmd.indirectsymoff = 0;
2238 Cmd.nindirectsyms = 0;
2239 Cmd.extreloff = 0;
2240 Cmd.nextrel = 0;
2241 Cmd.locreloff = 0;
2242 Cmd.nlocrel = 0;
2243 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002244}
2245
Charles Davis8bdfafd2013-09-01 04:28:48 +00002246MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002247MachOObjectFile::getDataInCodeLoadCommand() const {
2248 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002249 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002250
2251 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002252 MachO::linkedit_data_command Cmd;
2253 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2254 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2255 Cmd.dataoff = 0;
2256 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002257 return Cmd;
2258}
2259
Kevin Enderby9a509442015-01-27 21:28:24 +00002260MachO::linkedit_data_command
2261MachOObjectFile::getLinkOptHintsLoadCommand() const {
2262 if (LinkOptHintsLoadCmd)
2263 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2264
2265 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2266 // fields.
2267 MachO::linkedit_data_command Cmd;
2268 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2269 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2270 Cmd.dataoff = 0;
2271 Cmd.datasize = 0;
2272 return Cmd;
2273}
2274
Nick Kledzikd04bc352014-08-30 00:20:14 +00002275ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2276 if (!DyldInfoLoadCmd)
2277 return ArrayRef<uint8_t>();
2278
2279 MachO::dyld_info_command DyldInfo
2280 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2281 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2282 getPtr(this, DyldInfo.rebase_off));
2283 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2284}
2285
2286ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2287 if (!DyldInfoLoadCmd)
2288 return ArrayRef<uint8_t>();
2289
2290 MachO::dyld_info_command DyldInfo
2291 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2292 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2293 getPtr(this, DyldInfo.bind_off));
2294 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2295}
2296
2297ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2298 if (!DyldInfoLoadCmd)
2299 return ArrayRef<uint8_t>();
2300
2301 MachO::dyld_info_command DyldInfo
2302 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2303 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2304 getPtr(this, DyldInfo.weak_bind_off));
2305 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2306}
2307
2308ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2309 if (!DyldInfoLoadCmd)
2310 return ArrayRef<uint8_t>();
2311
2312 MachO::dyld_info_command DyldInfo
2313 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2314 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2315 getPtr(this, DyldInfo.lazy_bind_off));
2316 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2317}
2318
2319ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2320 if (!DyldInfoLoadCmd)
2321 return ArrayRef<uint8_t>();
2322
2323 MachO::dyld_info_command DyldInfo
2324 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2325 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2326 getPtr(this, DyldInfo.export_off));
2327 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2328}
2329
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002330ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2331 if (!UuidLoadCmd)
2332 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002333 // Returning a pointer is fine as uuid doesn't need endian swapping.
2334 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2335 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002336}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002337
Rafael Espindola6e040c02013-04-26 20:07:33 +00002338StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002339 MachO::symtab_command S = getSymtabLoadCommand();
2340 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002341}
2342
Rafael Espindola56f976f2013-04-18 18:08:55 +00002343bool MachOObjectFile::is64Bit() const {
2344 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002345 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002346}
2347
2348void MachOObjectFile::ReadULEB128s(uint64_t Index,
2349 SmallVectorImpl<uint64_t> &Out) const {
2350 DataExtractor extractor(ObjectFile::getData(), true, 0);
2351
2352 uint32_t offset = Index;
2353 uint64_t data = 0;
2354 while (uint64_t delta = extractor.getULEB128(&offset)) {
2355 data += delta;
2356 Out.push_back(data);
2357 }
2358}
2359
Rafael Espindolac66d7612014-08-17 19:09:37 +00002360bool MachOObjectFile::isRelocatableObject() const {
2361 return getHeader().filetype == MachO::MH_OBJECT;
2362}
2363
Rafael Espindola437b0d52014-07-31 03:12:45 +00002364ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002365ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2366 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002367 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002368 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002369 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002370 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002371 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002372 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002373 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002374 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002375 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002376 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002377 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002378 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002379
Rafael Espindola692410e2014-01-21 23:06:54 +00002380 if (EC)
2381 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002382 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002383}
2384