blob: d1f79b225ee42d155e87c3922255f9b6bdf52277 [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;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000282 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 Espindola5d0c2ff2015-07-02 20:55:21 +0000330ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000331 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000332 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000333 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000334 if (Start < getData().begin() || Start >= getData().end())
335 report_fatal_error(
336 "Symbol name entry points before beginning or past end of file.");
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000337 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000338}
339
Rafael Espindola0e77a942014-12-10 20:46:55 +0000340unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
341 DataRefImpl DRI = Sec.getRawDataRefImpl();
342 uint32_t Flags = getSectionFlags(this, DRI);
343 return Flags & MachO::SECTION_TYPE;
344}
345
Rafael Espindola59128922015-06-24 18:14:41 +0000346uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
347 if (is64Bit()) {
348 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
349 return Entry.n_value;
350 }
351 MachO::nlist Entry = getSymbolTableEntry(Sym);
352 return Entry.n_value;
353}
354
Kevin Enderby980b2582014-06-05 21:21:57 +0000355// getIndirectName() returns the name of the alias'ed symbol who's string table
356// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000357std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
358 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000359 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000360 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
361 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362 return object_error::parse_failed;
363 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000364 if (NValue >= StringTable.size())
365 return object_error::parse_failed;
366 const char *Start = &StringTable.data()[NValue];
367 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000368 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000369}
370
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000371uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000372 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000373}
374
Rafael Espindolaed067c42015-07-03 18:19:00 +0000375ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
376 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000377}
378
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000379uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000380 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000381 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000382 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000383 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000384 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000385 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000386}
387
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000388uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000389 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000390}
391
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000392SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000393 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000394 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000395
Rafael Espindola56f976f2013-04-18 18:08:55 +0000396 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000397 if (n_type & MachO::N_STAB)
398 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000399
Charles Davis74ec8b02013-08-27 05:00:13 +0000400 switch (n_type & MachO::N_TYPE) {
401 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000402 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000403 case MachO::N_SECT :
Kuba Breckade833222015-11-12 09:40:29 +0000404 section_iterator Sec = *getSymbolSection(Symb);
405 if (Sec->isData() || Sec->isBSS())
406 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000407 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000408 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000409 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000410}
411
Rafael Espindola20122a42014-01-31 20:57:12 +0000412uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000414
Charles Davis8bdfafd2013-09-01 04:28:48 +0000415 uint8_t MachOType = Entry.n_type;
416 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000417
Rafael Espindola20122a42014-01-31 20:57:12 +0000418 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000419
Tim Northovereaef0742014-05-30 13:22:59 +0000420 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
421 Result |= SymbolRef::SF_Indirect;
422
Rafael Espindolaa1356322013-11-02 05:03:24 +0000423 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000424 Result |= SymbolRef::SF_FormatSpecific;
425
Charles Davis74ec8b02013-08-27 05:00:13 +0000426 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000427 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000428 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000429 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000430 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000431 else
432 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000433 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000434
435 if (!(MachOType & MachO::N_PEXT))
436 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437 }
438
Charles Davis74ec8b02013-08-27 05:00:13 +0000439 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000440 Result |= SymbolRef::SF_Weak;
441
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000442 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
443 Result |= SymbolRef::SF_Thumb;
444
Charles Davis74ec8b02013-08-27 05:00:13 +0000445 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000446 Result |= SymbolRef::SF_Absolute;
447
Rafael Espindola20122a42014-01-31 20:57:12 +0000448 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000449}
450
Rafael Espindola8bab8892015-08-07 23:27:14 +0000451ErrorOr<section_iterator>
452MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000453 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000454 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000455
Rafael Espindola8bab8892015-08-07 23:27:14 +0000456 if (index == 0)
457 return section_end();
458 DataRefImpl DRI;
459 DRI.d.a = index - 1;
460 if (DRI.d.a >= Sections.size())
461 report_fatal_error("getSymbolSection: Invalid section index.");
462 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000463}
464
Rafael Espindola6bf32212015-06-24 19:57:32 +0000465unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
466 MachO::nlist_base Entry =
467 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
468 return Entry.n_sect - 1;
469}
470
Rafael Espindola5e812af2014-01-30 02:49:50 +0000471void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000472 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000473}
474
Rafael Espindola3acea392014-06-12 21:46:39 +0000475std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
476 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000477 ArrayRef<char> Raw = getSectionRawName(Sec);
478 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000479 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000480}
481
Rafael Espindola80291272014-10-08 15:28:58 +0000482uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
483 if (is64Bit())
484 return getSection64(Sec).addr;
485 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000486}
487
Rafael Espindola80291272014-10-08 15:28:58 +0000488uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000489 // In the case if a malformed Mach-O file where the section offset is past
490 // the end of the file or some part of the section size is past the end of
491 // the file return a size of zero or a size that covers the rest of the file
492 // but does not extend past the end of the file.
493 uint32_t SectOffset, SectType;
494 uint64_t SectSize;
495
496 if (is64Bit()) {
497 MachO::section_64 Sect = getSection64(Sec);
498 SectOffset = Sect.offset;
499 SectSize = Sect.size;
500 SectType = Sect.flags & MachO::SECTION_TYPE;
501 } else {
502 MachO::section Sect = getSection(Sec);
503 SectOffset = Sect.offset;
504 SectSize = Sect.size;
505 SectType = Sect.flags & MachO::SECTION_TYPE;
506 }
507 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
508 return SectSize;
509 uint64_t FileSize = getData().size();
510 if (SectOffset > FileSize)
511 return 0;
512 if (FileSize - SectOffset < SectSize)
513 return FileSize - SectOffset;
514 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000515}
516
Rafael Espindola3acea392014-06-12 21:46:39 +0000517std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
518 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000519 uint32_t Offset;
520 uint64_t Size;
521
522 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000523 MachO::section_64 Sect = getSection64(Sec);
524 Offset = Sect.offset;
525 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000526 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000527 MachO::section Sect = getSection(Sec);
528 Offset = Sect.offset;
529 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000530 }
531
532 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000533 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000534}
535
Rafael Espindola80291272014-10-08 15:28:58 +0000536uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537 uint32_t Align;
538 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000539 MachO::section_64 Sect = getSection64(Sec);
540 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000541 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000542 MachO::section Sect = getSection(Sec);
543 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000544 }
545
Rafael Espindola80291272014-10-08 15:28:58 +0000546 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000547}
548
Rafael Espindola80291272014-10-08 15:28:58 +0000549bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000550 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000551 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000552}
553
Rafael Espindola80291272014-10-08 15:28:58 +0000554bool MachOObjectFile::isSectionData(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);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000560}
561
Rafael Espindola80291272014-10-08 15:28:58 +0000562bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000563 uint32_t Flags = getSectionFlags(this, Sec);
564 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000565 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
566 (SectionType == MachO::S_ZEROFILL ||
567 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000568}
569
Rafael Espindola6bf32212015-06-24 19:57:32 +0000570unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
571 return Sec.getRawDataRefImpl().d.a;
572}
573
Rafael Espindola80291272014-10-08 15:28:58 +0000574bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000575 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000576 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000577}
578
Rui Ueyamabc654b12013-09-27 21:47:05 +0000579relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000580 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000581 Ret.d.a = Sec.d.a;
582 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000583 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000584}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000585
Rafael Espindola56f976f2013-04-18 18:08:55 +0000586relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000587MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000588 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000589 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000590 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000591 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000592 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000593 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000594 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000595 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000596
Rafael Espindola56f976f2013-04-18 18:08:55 +0000597 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000598 Ret.d.a = Sec.d.a;
599 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000600 return relocation_iterator(RelocationRef(Ret, this));
601}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000602
Rafael Espindola5e812af2014-01-30 02:49:50 +0000603void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000604 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000605}
Owen Anderson171f4852011-10-24 23:20:07 +0000606
Rafael Espindola96d071c2015-06-29 23:29:12 +0000607uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000608 assert(getHeader().filetype == MachO::MH_OBJECT &&
609 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000610 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000611 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000612}
613
Rafael Espindola806f0062013-06-05 01:33:53 +0000614symbol_iterator
615MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000616 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000617 if (isRelocationScattered(RE))
618 return symbol_end();
619
Rafael Espindola56f976f2013-04-18 18:08:55 +0000620 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
621 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000622 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000623 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000624
Charles Davis8bdfafd2013-09-01 04:28:48 +0000625 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000626 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000627 sizeof(MachO::nlist_64) :
628 sizeof(MachO::nlist);
629 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000630 DataRefImpl Sym;
631 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000632 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000633}
634
Keno Fischerc780e8e2015-05-21 21:24:32 +0000635section_iterator
636MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
637 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
638}
639
Rafael Espindola99c041b2015-06-30 01:53:01 +0000640uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000641 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000642 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000643}
644
Rafael Espindola41bb4322015-06-30 04:08:37 +0000645void MachOObjectFile::getRelocationTypeName(
646 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000647 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000648 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000649
650 unsigned Arch = this->getArch();
651
652 switch (Arch) {
653 case Triple::x86: {
654 static const char *const Table[] = {
655 "GENERIC_RELOC_VANILLA",
656 "GENERIC_RELOC_PAIR",
657 "GENERIC_RELOC_SECTDIFF",
658 "GENERIC_RELOC_PB_LA_PTR",
659 "GENERIC_RELOC_LOCAL_SECTDIFF",
660 "GENERIC_RELOC_TLV" };
661
Eric Christopher13250cb2013-12-06 02:33:38 +0000662 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000663 res = "Unknown";
664 else
665 res = Table[RType];
666 break;
667 }
668 case Triple::x86_64: {
669 static const char *const Table[] = {
670 "X86_64_RELOC_UNSIGNED",
671 "X86_64_RELOC_SIGNED",
672 "X86_64_RELOC_BRANCH",
673 "X86_64_RELOC_GOT_LOAD",
674 "X86_64_RELOC_GOT",
675 "X86_64_RELOC_SUBTRACTOR",
676 "X86_64_RELOC_SIGNED_1",
677 "X86_64_RELOC_SIGNED_2",
678 "X86_64_RELOC_SIGNED_4",
679 "X86_64_RELOC_TLV" };
680
681 if (RType > 9)
682 res = "Unknown";
683 else
684 res = Table[RType];
685 break;
686 }
687 case Triple::arm: {
688 static const char *const Table[] = {
689 "ARM_RELOC_VANILLA",
690 "ARM_RELOC_PAIR",
691 "ARM_RELOC_SECTDIFF",
692 "ARM_RELOC_LOCAL_SECTDIFF",
693 "ARM_RELOC_PB_LA_PTR",
694 "ARM_RELOC_BR24",
695 "ARM_THUMB_RELOC_BR22",
696 "ARM_THUMB_32BIT_BRANCH",
697 "ARM_RELOC_HALF",
698 "ARM_RELOC_HALF_SECTDIFF" };
699
700 if (RType > 9)
701 res = "Unknown";
702 else
703 res = Table[RType];
704 break;
705 }
Tim Northover00ed9962014-03-29 10:18:08 +0000706 case Triple::aarch64: {
707 static const char *const Table[] = {
708 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
709 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
710 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
711 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
712 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
713 "ARM64_RELOC_ADDEND"
714 };
715
716 if (RType >= array_lengthof(Table))
717 res = "Unknown";
718 else
719 res = Table[RType];
720 break;
721 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000722 case Triple::ppc: {
723 static const char *const Table[] = {
724 "PPC_RELOC_VANILLA",
725 "PPC_RELOC_PAIR",
726 "PPC_RELOC_BR14",
727 "PPC_RELOC_BR24",
728 "PPC_RELOC_HI16",
729 "PPC_RELOC_LO16",
730 "PPC_RELOC_HA16",
731 "PPC_RELOC_LO14",
732 "PPC_RELOC_SECTDIFF",
733 "PPC_RELOC_PB_LA_PTR",
734 "PPC_RELOC_HI16_SECTDIFF",
735 "PPC_RELOC_LO16_SECTDIFF",
736 "PPC_RELOC_HA16_SECTDIFF",
737 "PPC_RELOC_JBSR",
738 "PPC_RELOC_LO14_SECTDIFF",
739 "PPC_RELOC_LOCAL_SECTDIFF" };
740
Eric Christopher13250cb2013-12-06 02:33:38 +0000741 if (RType > 15)
742 res = "Unknown";
743 else
744 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000745 break;
746 }
747 case Triple::UnknownArch:
748 res = "Unknown";
749 break;
750 }
751 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000752}
753
Keno Fischer281b6942015-05-30 19:44:53 +0000754uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
755 MachO::any_relocation_info RE = getRelocation(Rel);
756 return getAnyRelocationLength(RE);
757}
758
Kevin Enderby980b2582014-06-05 21:21:57 +0000759//
760// guessLibraryShortName() is passed a name of a dynamic library and returns a
761// guess on what the short name is. Then name is returned as a substring of the
762// StringRef Name passed in. The name of the dynamic library is recognized as
763// a framework if it has one of the two following forms:
764// Foo.framework/Versions/A/Foo
765// Foo.framework/Foo
766// Where A and Foo can be any string. And may contain a trailing suffix
767// starting with an underbar. If the Name is recognized as a framework then
768// isFramework is set to true else it is set to false. If the Name has a
769// suffix then Suffix is set to the substring in Name that contains the suffix
770// else it is set to a NULL StringRef.
771//
772// The Name of the dynamic library is recognized as a library name if it has
773// one of the two following forms:
774// libFoo.A.dylib
775// libFoo.dylib
776// The library may have a suffix trailing the name Foo of the form:
777// libFoo_profile.A.dylib
778// libFoo_profile.dylib
779//
780// The Name of the dynamic library is also recognized as a library name if it
781// has the following form:
782// Foo.qtx
783//
784// If the Name of the dynamic library is none of the forms above then a NULL
785// StringRef is returned.
786//
787StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
788 bool &isFramework,
789 StringRef &Suffix) {
790 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
791 size_t a, b, c, d, Idx;
792
793 isFramework = false;
794 Suffix = StringRef();
795
796 // Pull off the last component and make Foo point to it
797 a = Name.rfind('/');
798 if (a == Name.npos || a == 0)
799 goto guess_library;
800 Foo = Name.slice(a+1, Name.npos);
801
802 // Look for a suffix starting with a '_'
803 Idx = Foo.rfind('_');
804 if (Idx != Foo.npos && Foo.size() >= 2) {
805 Suffix = Foo.slice(Idx, Foo.npos);
806 Foo = Foo.slice(0, Idx);
807 }
808
809 // First look for the form Foo.framework/Foo
810 b = Name.rfind('/', a);
811 if (b == Name.npos)
812 Idx = 0;
813 else
814 Idx = b+1;
815 F = Name.slice(Idx, Idx + Foo.size());
816 DotFramework = Name.slice(Idx + Foo.size(),
817 Idx + Foo.size() + sizeof(".framework/")-1);
818 if (F == Foo && DotFramework == ".framework/") {
819 isFramework = true;
820 return Foo;
821 }
822
823 // Next look for the form Foo.framework/Versions/A/Foo
824 if (b == Name.npos)
825 goto guess_library;
826 c = Name.rfind('/', b);
827 if (c == Name.npos || c == 0)
828 goto guess_library;
829 V = Name.slice(c+1, Name.npos);
830 if (!V.startswith("Versions/"))
831 goto guess_library;
832 d = Name.rfind('/', c);
833 if (d == Name.npos)
834 Idx = 0;
835 else
836 Idx = d+1;
837 F = Name.slice(Idx, Idx + Foo.size());
838 DotFramework = Name.slice(Idx + Foo.size(),
839 Idx + Foo.size() + sizeof(".framework/")-1);
840 if (F == Foo && DotFramework == ".framework/") {
841 isFramework = true;
842 return Foo;
843 }
844
845guess_library:
846 // pull off the suffix after the "." and make a point to it
847 a = Name.rfind('.');
848 if (a == Name.npos || a == 0)
849 return StringRef();
850 Dylib = Name.slice(a, Name.npos);
851 if (Dylib != ".dylib")
852 goto guess_qtx;
853
854 // First pull off the version letter for the form Foo.A.dylib if any.
855 if (a >= 3) {
856 Dot = Name.slice(a-2, a-1);
857 if (Dot == ".")
858 a = a - 2;
859 }
860
861 b = Name.rfind('/', a);
862 if (b == Name.npos)
863 b = 0;
864 else
865 b = b+1;
866 // ignore any suffix after an underbar like Foo_profile.A.dylib
867 Idx = Name.find('_', b);
868 if (Idx != Name.npos && Idx != b) {
869 Lib = Name.slice(b, Idx);
870 Suffix = Name.slice(Idx, a);
871 }
872 else
873 Lib = Name.slice(b, a);
874 // There are incorrect library names of the form:
875 // libATS.A_profile.dylib so check for these.
876 if (Lib.size() >= 3) {
877 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
878 if (Dot == ".")
879 Lib = Lib.slice(0, Lib.size()-2);
880 }
881 return Lib;
882
883guess_qtx:
884 Qtx = Name.slice(a, Name.npos);
885 if (Qtx != ".qtx")
886 return StringRef();
887 b = Name.rfind('/', a);
888 if (b == Name.npos)
889 Lib = Name.slice(0, a);
890 else
891 Lib = Name.slice(b+1, a);
892 // There are library names of the form: QT.A.qtx so check for these.
893 if (Lib.size() >= 3) {
894 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
895 if (Dot == ".")
896 Lib = Lib.slice(0, Lib.size()-2);
897 }
898 return Lib;
899}
900
901// getLibraryShortNameByIndex() is used to get the short name of the library
902// for an undefined symbol in a linked Mach-O binary that was linked with the
903// normal two-level namespace default (that is MH_TWOLEVEL in the header).
904// It is passed the index (0 - based) of the library as translated from
905// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +0000906std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +0000907 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000908 if (Index >= Libraries.size())
909 return object_error::parse_failed;
910
Kevin Enderby980b2582014-06-05 21:21:57 +0000911 // If the cache of LibrariesShortNames is not built up do that first for
912 // all the Libraries.
913 if (LibrariesShortNames.size() == 0) {
914 for (unsigned i = 0; i < Libraries.size(); i++) {
915 MachO::dylib_command D =
916 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +0000917 if (D.dylib.name >= D.cmdsize)
918 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +0000919 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +0000920 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +0000921 if (D.dylib.name+Name.size() >= D.cmdsize)
922 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +0000923 StringRef Suffix;
924 bool isFramework;
925 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +0000926 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +0000927 LibrariesShortNames.push_back(Name);
928 else
929 LibrariesShortNames.push_back(shortName);
930 }
931 }
932
933 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +0000934 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000935}
936
Rafael Espindola76ad2322015-07-06 14:55:37 +0000937section_iterator
938MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
939 DataRefImpl Sec;
940 Sec.d.a = Rel->getRawDataRefImpl().d.a;
941 return section_iterator(SectionRef(Sec, this));
942}
943
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000944basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +0000945 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000946}
947
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000948basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000949 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +0000950 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000951 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +0000952
Charles Davis8bdfafd2013-09-01 04:28:48 +0000953 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000954 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000955 sizeof(MachO::nlist_64) :
956 sizeof(MachO::nlist);
957 unsigned Offset = Symtab.symoff +
958 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000959 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000960 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000961}
962
Lang Hames36072da2014-05-12 21:39:59 +0000963basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
964 DataRefImpl DRI;
965 if (!SymtabLoadCmd)
966 return basic_symbol_iterator(SymbolRef(DRI, this));
967
968 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +0000969 if (Index >= Symtab.nsyms)
970 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +0000971 unsigned SymbolTableEntrySize =
972 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
973 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
974 DRI.p += Index * SymbolTableEntrySize;
975 return basic_symbol_iterator(SymbolRef(DRI, this));
976}
977
Rafael Espindolab5155a52014-02-10 20:24:04 +0000978section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000979 DataRefImpl DRI;
980 return section_iterator(SectionRef(DRI, this));
981}
982
Rafael Espindolab5155a52014-02-10 20:24:04 +0000983section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000984 DataRefImpl DRI;
985 DRI.d.a = Sections.size();
986 return section_iterator(SectionRef(DRI, this));
987}
988
Rafael Espindola56f976f2013-04-18 18:08:55 +0000989uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +0000990 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +0000991}
992
Rafael Espindola56f976f2013-04-18 18:08:55 +0000993StringRef MachOObjectFile::getFileFormatName() const {
994 unsigned CPUType = getCPUType(this);
995 if (!is64Bit()) {
996 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +0000997 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000998 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +0000999 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001000 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001001 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001002 return "Mach-O 32-bit ppc";
1003 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001004 return "Mach-O 32-bit unknown";
1005 }
1006 }
1007
Rafael Espindola56f976f2013-04-18 18:08:55 +00001008 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001009 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001010 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001011 case llvm::MachO::CPU_TYPE_ARM64:
1012 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001013 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001014 return "Mach-O 64-bit ppc64";
1015 default:
1016 return "Mach-O 64-bit unknown";
1017 }
1018}
1019
Alexey Samsonove6388e62013-06-18 15:03:28 +00001020Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1021 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001022 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001023 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001024 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001025 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001026 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001027 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001028 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001029 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001030 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001031 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001032 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001033 return Triple::ppc64;
1034 default:
1035 return Triple::UnknownArch;
1036 }
1037}
1038
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001039Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1040 const char **McpuDefault) {
1041 if (McpuDefault)
1042 *McpuDefault = nullptr;
1043
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001044 switch (CPUType) {
1045 case MachO::CPU_TYPE_I386:
1046 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1047 case MachO::CPU_SUBTYPE_I386_ALL:
1048 return Triple("i386-apple-darwin");
1049 default:
1050 return Triple();
1051 }
1052 case MachO::CPU_TYPE_X86_64:
1053 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1054 case MachO::CPU_SUBTYPE_X86_64_ALL:
1055 return Triple("x86_64-apple-darwin");
1056 case MachO::CPU_SUBTYPE_X86_64_H:
1057 return Triple("x86_64h-apple-darwin");
1058 default:
1059 return Triple();
1060 }
1061 case MachO::CPU_TYPE_ARM:
1062 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1063 case MachO::CPU_SUBTYPE_ARM_V4T:
1064 return Triple("armv4t-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1066 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001067 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1068 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001069 case MachO::CPU_SUBTYPE_ARM_V6:
1070 return Triple("armv6-apple-darwin");
1071 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001072 if (McpuDefault)
1073 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001074 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001075 case MachO::CPU_SUBTYPE_ARM_V7:
1076 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001077 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001078 if (McpuDefault)
1079 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001080 return Triple("armv7em-apple-darwin");
1081 case MachO::CPU_SUBTYPE_ARM_V7K:
1082 return Triple("armv7k-apple-darwin");
1083 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001084 if (McpuDefault)
1085 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001086 return Triple("armv7m-apple-darwin");
1087 case MachO::CPU_SUBTYPE_ARM_V7S:
1088 return Triple("armv7s-apple-darwin");
1089 default:
1090 return Triple();
1091 }
1092 case MachO::CPU_TYPE_ARM64:
1093 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1094 case MachO::CPU_SUBTYPE_ARM64_ALL:
1095 return Triple("arm64-apple-darwin");
1096 default:
1097 return Triple();
1098 }
1099 case MachO::CPU_TYPE_POWERPC:
1100 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1101 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1102 return Triple("ppc-apple-darwin");
1103 default:
1104 return Triple();
1105 }
1106 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001107 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001108 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1109 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001110 default:
1111 return Triple();
1112 }
1113 default:
1114 return Triple();
1115 }
1116}
1117
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001118Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1119 const char **McpuDefault) {
1120 if (McpuDefault)
1121 *McpuDefault = nullptr;
1122
1123 switch (CPUType) {
1124 case MachO::CPU_TYPE_ARM:
1125 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1126 case MachO::CPU_SUBTYPE_ARM_V4T:
1127 return Triple("thumbv4t-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1129 return Triple("thumbv5e-apple-darwin");
1130 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1131 return Triple("xscale-apple-darwin");
1132 case MachO::CPU_SUBTYPE_ARM_V6:
1133 return Triple("thumbv6-apple-darwin");
1134 case MachO::CPU_SUBTYPE_ARM_V6M:
1135 if (McpuDefault)
1136 *McpuDefault = "cortex-m0";
1137 return Triple("thumbv6m-apple-darwin");
1138 case MachO::CPU_SUBTYPE_ARM_V7:
1139 return Triple("thumbv7-apple-darwin");
1140 case MachO::CPU_SUBTYPE_ARM_V7EM:
1141 if (McpuDefault)
1142 *McpuDefault = "cortex-m4";
1143 return Triple("thumbv7em-apple-darwin");
1144 case MachO::CPU_SUBTYPE_ARM_V7K:
1145 return Triple("thumbv7k-apple-darwin");
1146 case MachO::CPU_SUBTYPE_ARM_V7M:
1147 if (McpuDefault)
1148 *McpuDefault = "cortex-m3";
1149 return Triple("thumbv7m-apple-darwin");
1150 case MachO::CPU_SUBTYPE_ARM_V7S:
1151 return Triple("thumbv7s-apple-darwin");
1152 default:
1153 return Triple();
1154 }
1155 default:
1156 return Triple();
1157 }
1158}
1159
1160Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
NAKAMURA Takumi0a7d0ad2015-09-22 11:15:07 +00001161 const char **McpuDefault, Triple *ThumbTriple) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001162 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1163 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1164 McpuDefault);
1165 return T;
1166}
1167
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001168Triple MachOObjectFile::getHostArch() {
1169 return Triple(sys::getDefaultTargetTriple());
1170}
1171
Rafael Espindola72318b42014-08-08 16:30:17 +00001172bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1173 return StringSwitch<bool>(ArchFlag)
1174 .Case("i386", true)
1175 .Case("x86_64", true)
1176 .Case("x86_64h", true)
1177 .Case("armv4t", true)
1178 .Case("arm", true)
1179 .Case("armv5e", true)
1180 .Case("armv6", true)
1181 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001182 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001183 .Case("armv7em", true)
1184 .Case("armv7k", true)
1185 .Case("armv7m", true)
1186 .Case("armv7s", true)
1187 .Case("arm64", true)
1188 .Case("ppc", true)
1189 .Case("ppc64", true)
1190 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001191}
1192
Alexey Samsonove6388e62013-06-18 15:03:28 +00001193unsigned MachOObjectFile::getArch() const {
1194 return getArch(getCPUType(this));
1195}
1196
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001197Triple MachOObjectFile::getArch(const char **McpuDefault,
1198 Triple *ThumbTriple) const {
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001199 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1200 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001201}
1202
Rui Ueyamabc654b12013-09-27 21:47:05 +00001203relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001204 DataRefImpl DRI;
1205 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001206 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001207}
1208
Rui Ueyamabc654b12013-09-27 21:47:05 +00001209relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001210 DataRefImpl DRI;
1211 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001212 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001213}
1214
Kevin Enderby273ae012013-06-06 17:20:50 +00001215dice_iterator MachOObjectFile::begin_dices() const {
1216 DataRefImpl DRI;
1217 if (!DataInCodeLoadCmd)
1218 return dice_iterator(DiceRef(DRI, this));
1219
Charles Davis8bdfafd2013-09-01 04:28:48 +00001220 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1221 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001222 return dice_iterator(DiceRef(DRI, this));
1223}
1224
1225dice_iterator MachOObjectFile::end_dices() const {
1226 DataRefImpl DRI;
1227 if (!DataInCodeLoadCmd)
1228 return dice_iterator(DiceRef(DRI, this));
1229
Charles Davis8bdfafd2013-09-01 04:28:48 +00001230 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1231 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001232 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1233 return dice_iterator(DiceRef(DRI, this));
1234}
1235
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001236ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1237 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001238
1239void ExportEntry::moveToFirst() {
1240 pushNode(0);
1241 pushDownUntilBottom();
1242}
1243
1244void ExportEntry::moveToEnd() {
1245 Stack.clear();
1246 Done = true;
1247}
1248
1249bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001250 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001251 if (Done || Other.Done)
1252 return (Done == Other.Done);
1253 // Not equal if different stack sizes.
1254 if (Stack.size() != Other.Stack.size())
1255 return false;
1256 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001257 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001258 return false;
1259 // Equal if all nodes in both stacks match.
1260 for (unsigned i=0; i < Stack.size(); ++i) {
1261 if (Stack[i].Start != Other.Stack[i].Start)
1262 return false;
1263 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001264 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001265}
1266
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001267uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1268 unsigned Count;
1269 uint64_t Result = decodeULEB128(Ptr, &Count);
1270 Ptr += Count;
1271 if (Ptr > Trie.end()) {
1272 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001273 Malformed = true;
1274 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001275 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001276}
1277
1278StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001279 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001280}
1281
1282uint64_t ExportEntry::flags() const {
1283 return Stack.back().Flags;
1284}
1285
1286uint64_t ExportEntry::address() const {
1287 return Stack.back().Address;
1288}
1289
1290uint64_t ExportEntry::other() const {
1291 return Stack.back().Other;
1292}
1293
1294StringRef ExportEntry::otherName() const {
1295 const char* ImportName = Stack.back().ImportName;
1296 if (ImportName)
1297 return StringRef(ImportName);
1298 return StringRef();
1299}
1300
1301uint32_t ExportEntry::nodeOffset() const {
1302 return Stack.back().Start - Trie.begin();
1303}
1304
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001305ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1306 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1307 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1308 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001309
1310void ExportEntry::pushNode(uint64_t offset) {
1311 const uint8_t *Ptr = Trie.begin() + offset;
1312 NodeState State(Ptr);
1313 uint64_t ExportInfoSize = readULEB128(State.Current);
1314 State.IsExportNode = (ExportInfoSize != 0);
1315 const uint8_t* Children = State.Current + ExportInfoSize;
1316 if (State.IsExportNode) {
1317 State.Flags = readULEB128(State.Current);
1318 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1319 State.Address = 0;
1320 State.Other = readULEB128(State.Current); // dylib ordinal
1321 State.ImportName = reinterpret_cast<const char*>(State.Current);
1322 } else {
1323 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001324 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001325 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001326 }
1327 }
1328 State.ChildCount = *Children;
1329 State.Current = Children + 1;
1330 State.NextChildIndex = 0;
1331 State.ParentStringLength = CumulativeString.size();
1332 Stack.push_back(State);
1333}
1334
1335void ExportEntry::pushDownUntilBottom() {
1336 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1337 NodeState &Top = Stack.back();
1338 CumulativeString.resize(Top.ParentStringLength);
1339 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001340 char C = *Top.Current;
1341 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001342 }
1343 Top.Current += 1;
1344 uint64_t childNodeIndex = readULEB128(Top.Current);
1345 Top.NextChildIndex += 1;
1346 pushNode(childNodeIndex);
1347 }
1348 if (!Stack.back().IsExportNode) {
1349 Malformed = true;
1350 moveToEnd();
1351 }
1352}
1353
1354// We have a trie data structure and need a way to walk it that is compatible
1355// with the C++ iterator model. The solution is a non-recursive depth first
1356// traversal where the iterator contains a stack of parent nodes along with a
1357// string that is the accumulation of all edge strings along the parent chain
1358// to this point.
1359//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001360// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001361// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001362// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001363//
1364// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1365// child until hitting a node with no children (which is an export node or
1366// else the trie is malformed). On the way down, each node is pushed on the
1367// stack ivar. If there is no more ways down, it pops up one and tries to go
1368// down a sibling path until a childless node is reached.
1369void ExportEntry::moveNext() {
1370 if (Stack.empty() || !Stack.back().IsExportNode) {
1371 Malformed = true;
1372 moveToEnd();
1373 return;
1374 }
1375
1376 Stack.pop_back();
1377 while (!Stack.empty()) {
1378 NodeState &Top = Stack.back();
1379 if (Top.NextChildIndex < Top.ChildCount) {
1380 pushDownUntilBottom();
1381 // Now at the next export node.
1382 return;
1383 } else {
1384 if (Top.IsExportNode) {
1385 // This node has no children but is itself an export node.
1386 CumulativeString.resize(Top.ParentStringLength);
1387 return;
1388 }
1389 Stack.pop_back();
1390 }
1391 }
1392 Done = true;
1393}
1394
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001395iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001396MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1397 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001398 if (Trie.size() == 0)
1399 Start.moveToEnd();
1400 else
1401 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001402
1403 ExportEntry Finish(Trie);
1404 Finish.moveToEnd();
1405
Craig Topper15576e12015-12-06 05:08:07 +00001406 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001407}
1408
1409iterator_range<export_iterator> MachOObjectFile::exports() const {
1410 return exports(getDyldInfoExportsTrie());
1411}
1412
Nick Kledzikac431442014-09-12 21:34:15 +00001413MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1414 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1415 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1416 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1417
1418void MachORebaseEntry::moveToFirst() {
1419 Ptr = Opcodes.begin();
1420 moveNext();
1421}
1422
1423void MachORebaseEntry::moveToEnd() {
1424 Ptr = Opcodes.end();
1425 RemainingLoopCount = 0;
1426 Done = true;
1427}
1428
1429void MachORebaseEntry::moveNext() {
1430 // If in the middle of some loop, move to next rebasing in loop.
1431 SegmentOffset += AdvanceAmount;
1432 if (RemainingLoopCount) {
1433 --RemainingLoopCount;
1434 return;
1435 }
1436 if (Ptr == Opcodes.end()) {
1437 Done = true;
1438 return;
1439 }
1440 bool More = true;
1441 while (More && !Malformed) {
1442 // Parse next opcode and set up next loop.
1443 uint8_t Byte = *Ptr++;
1444 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1445 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1446 switch (Opcode) {
1447 case MachO::REBASE_OPCODE_DONE:
1448 More = false;
1449 Done = true;
1450 moveToEnd();
1451 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1452 break;
1453 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1454 RebaseType = ImmValue;
1455 DEBUG_WITH_TYPE(
1456 "mach-o-rebase",
1457 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1458 << "RebaseType=" << (int) RebaseType << "\n");
1459 break;
1460 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1461 SegmentIndex = ImmValue;
1462 SegmentOffset = readULEB128();
1463 DEBUG_WITH_TYPE(
1464 "mach-o-rebase",
1465 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1466 << "SegmentIndex=" << SegmentIndex << ", "
1467 << format("SegmentOffset=0x%06X", SegmentOffset)
1468 << "\n");
1469 break;
1470 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1471 SegmentOffset += readULEB128();
1472 DEBUG_WITH_TYPE("mach-o-rebase",
1473 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1474 << format("SegmentOffset=0x%06X",
1475 SegmentOffset) << "\n");
1476 break;
1477 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1478 SegmentOffset += ImmValue * PointerSize;
1479 DEBUG_WITH_TYPE("mach-o-rebase",
1480 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1481 << format("SegmentOffset=0x%06X",
1482 SegmentOffset) << "\n");
1483 break;
1484 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1485 AdvanceAmount = PointerSize;
1486 RemainingLoopCount = ImmValue - 1;
1487 DEBUG_WITH_TYPE(
1488 "mach-o-rebase",
1489 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1490 << format("SegmentOffset=0x%06X", SegmentOffset)
1491 << ", AdvanceAmount=" << AdvanceAmount
1492 << ", RemainingLoopCount=" << RemainingLoopCount
1493 << "\n");
1494 return;
1495 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1496 AdvanceAmount = PointerSize;
1497 RemainingLoopCount = readULEB128() - 1;
1498 DEBUG_WITH_TYPE(
1499 "mach-o-rebase",
1500 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1501 << format("SegmentOffset=0x%06X", SegmentOffset)
1502 << ", AdvanceAmount=" << AdvanceAmount
1503 << ", RemainingLoopCount=" << RemainingLoopCount
1504 << "\n");
1505 return;
1506 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1507 AdvanceAmount = readULEB128() + PointerSize;
1508 RemainingLoopCount = 0;
1509 DEBUG_WITH_TYPE(
1510 "mach-o-rebase",
1511 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1512 << format("SegmentOffset=0x%06X", SegmentOffset)
1513 << ", AdvanceAmount=" << AdvanceAmount
1514 << ", RemainingLoopCount=" << RemainingLoopCount
1515 << "\n");
1516 return;
1517 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1518 RemainingLoopCount = readULEB128() - 1;
1519 AdvanceAmount = readULEB128() + PointerSize;
1520 DEBUG_WITH_TYPE(
1521 "mach-o-rebase",
1522 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1523 << format("SegmentOffset=0x%06X", SegmentOffset)
1524 << ", AdvanceAmount=" << AdvanceAmount
1525 << ", RemainingLoopCount=" << RemainingLoopCount
1526 << "\n");
1527 return;
1528 default:
1529 Malformed = true;
1530 }
1531 }
1532}
1533
1534uint64_t MachORebaseEntry::readULEB128() {
1535 unsigned Count;
1536 uint64_t Result = decodeULEB128(Ptr, &Count);
1537 Ptr += Count;
1538 if (Ptr > Opcodes.end()) {
1539 Ptr = Opcodes.end();
1540 Malformed = true;
1541 }
1542 return Result;
1543}
1544
1545uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1546
1547uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1548
1549StringRef MachORebaseEntry::typeName() const {
1550 switch (RebaseType) {
1551 case MachO::REBASE_TYPE_POINTER:
1552 return "pointer";
1553 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1554 return "text abs32";
1555 case MachO::REBASE_TYPE_TEXT_PCREL32:
1556 return "text rel32";
1557 }
1558 return "unknown";
1559}
1560
1561bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1562 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1563 return (Ptr == Other.Ptr) &&
1564 (RemainingLoopCount == Other.RemainingLoopCount) &&
1565 (Done == Other.Done);
1566}
1567
1568iterator_range<rebase_iterator>
1569MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1570 MachORebaseEntry Start(Opcodes, is64);
1571 Start.moveToFirst();
1572
1573 MachORebaseEntry Finish(Opcodes, is64);
1574 Finish.moveToEnd();
1575
Craig Topper15576e12015-12-06 05:08:07 +00001576 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001577}
1578
1579iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1580 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1581}
1582
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001583MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001584 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1585 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1586 BindType(0), PointerSize(is64Bit ? 8 : 4),
1587 TableKind(BK), Malformed(false), Done(false) {}
1588
1589void MachOBindEntry::moveToFirst() {
1590 Ptr = Opcodes.begin();
1591 moveNext();
1592}
1593
1594void MachOBindEntry::moveToEnd() {
1595 Ptr = Opcodes.end();
1596 RemainingLoopCount = 0;
1597 Done = true;
1598}
1599
1600void MachOBindEntry::moveNext() {
1601 // If in the middle of some loop, move to next binding in loop.
1602 SegmentOffset += AdvanceAmount;
1603 if (RemainingLoopCount) {
1604 --RemainingLoopCount;
1605 return;
1606 }
1607 if (Ptr == Opcodes.end()) {
1608 Done = true;
1609 return;
1610 }
1611 bool More = true;
1612 while (More && !Malformed) {
1613 // Parse next opcode and set up next loop.
1614 uint8_t Byte = *Ptr++;
1615 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1616 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1617 int8_t SignExtended;
1618 const uint8_t *SymStart;
1619 switch (Opcode) {
1620 case MachO::BIND_OPCODE_DONE:
1621 if (TableKind == Kind::Lazy) {
1622 // Lazying bindings have a DONE opcode between entries. Need to ignore
1623 // it to advance to next entry. But need not if this is last entry.
1624 bool NotLastEntry = false;
1625 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1626 if (*P) {
1627 NotLastEntry = true;
1628 }
1629 }
1630 if (NotLastEntry)
1631 break;
1632 }
1633 More = false;
1634 Done = true;
1635 moveToEnd();
1636 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1637 break;
1638 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1639 Ordinal = ImmValue;
1640 DEBUG_WITH_TYPE(
1641 "mach-o-bind",
1642 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1643 << "Ordinal=" << Ordinal << "\n");
1644 break;
1645 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1646 Ordinal = readULEB128();
1647 DEBUG_WITH_TYPE(
1648 "mach-o-bind",
1649 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1650 << "Ordinal=" << Ordinal << "\n");
1651 break;
1652 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1653 if (ImmValue) {
1654 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1655 Ordinal = SignExtended;
1656 } else
1657 Ordinal = 0;
1658 DEBUG_WITH_TYPE(
1659 "mach-o-bind",
1660 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1661 << "Ordinal=" << Ordinal << "\n");
1662 break;
1663 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1664 Flags = ImmValue;
1665 SymStart = Ptr;
1666 while (*Ptr) {
1667 ++Ptr;
1668 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001669 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1670 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001671 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001672 DEBUG_WITH_TYPE(
1673 "mach-o-bind",
1674 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1675 << "SymbolName=" << SymbolName << "\n");
1676 if (TableKind == Kind::Weak) {
1677 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1678 return;
1679 }
1680 break;
1681 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1682 BindType = ImmValue;
1683 DEBUG_WITH_TYPE(
1684 "mach-o-bind",
1685 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1686 << "BindType=" << (int)BindType << "\n");
1687 break;
1688 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1689 Addend = readSLEB128();
1690 if (TableKind == Kind::Lazy)
1691 Malformed = true;
1692 DEBUG_WITH_TYPE(
1693 "mach-o-bind",
1694 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1695 << "Addend=" << Addend << "\n");
1696 break;
1697 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1698 SegmentIndex = ImmValue;
1699 SegmentOffset = readULEB128();
1700 DEBUG_WITH_TYPE(
1701 "mach-o-bind",
1702 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1703 << "SegmentIndex=" << SegmentIndex << ", "
1704 << format("SegmentOffset=0x%06X", SegmentOffset)
1705 << "\n");
1706 break;
1707 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1708 SegmentOffset += readULEB128();
1709 DEBUG_WITH_TYPE("mach-o-bind",
1710 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1711 << format("SegmentOffset=0x%06X",
1712 SegmentOffset) << "\n");
1713 break;
1714 case MachO::BIND_OPCODE_DO_BIND:
1715 AdvanceAmount = PointerSize;
1716 RemainingLoopCount = 0;
1717 DEBUG_WITH_TYPE("mach-o-bind",
1718 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1719 << format("SegmentOffset=0x%06X",
1720 SegmentOffset) << "\n");
1721 return;
1722 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001723 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001724 RemainingLoopCount = 0;
1725 if (TableKind == Kind::Lazy)
1726 Malformed = true;
1727 DEBUG_WITH_TYPE(
1728 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001729 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001730 << format("SegmentOffset=0x%06X", SegmentOffset)
1731 << ", AdvanceAmount=" << AdvanceAmount
1732 << ", RemainingLoopCount=" << RemainingLoopCount
1733 << "\n");
1734 return;
1735 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001736 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001737 RemainingLoopCount = 0;
1738 if (TableKind == Kind::Lazy)
1739 Malformed = true;
1740 DEBUG_WITH_TYPE("mach-o-bind",
1741 llvm::dbgs()
1742 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1743 << format("SegmentOffset=0x%06X",
1744 SegmentOffset) << "\n");
1745 return;
1746 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1747 RemainingLoopCount = readULEB128() - 1;
1748 AdvanceAmount = readULEB128() + PointerSize;
1749 if (TableKind == Kind::Lazy)
1750 Malformed = true;
1751 DEBUG_WITH_TYPE(
1752 "mach-o-bind",
1753 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1754 << format("SegmentOffset=0x%06X", SegmentOffset)
1755 << ", AdvanceAmount=" << AdvanceAmount
1756 << ", RemainingLoopCount=" << RemainingLoopCount
1757 << "\n");
1758 return;
1759 default:
1760 Malformed = true;
1761 }
1762 }
1763}
1764
1765uint64_t MachOBindEntry::readULEB128() {
1766 unsigned Count;
1767 uint64_t Result = decodeULEB128(Ptr, &Count);
1768 Ptr += Count;
1769 if (Ptr > Opcodes.end()) {
1770 Ptr = Opcodes.end();
1771 Malformed = true;
1772 }
1773 return Result;
1774}
1775
1776int64_t MachOBindEntry::readSLEB128() {
1777 unsigned Count;
1778 int64_t Result = decodeSLEB128(Ptr, &Count);
1779 Ptr += Count;
1780 if (Ptr > Opcodes.end()) {
1781 Ptr = Opcodes.end();
1782 Malformed = true;
1783 }
1784 return Result;
1785}
1786
Nick Kledzik56ebef42014-09-16 01:41:51 +00001787uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1788
1789uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1790
1791StringRef MachOBindEntry::typeName() const {
1792 switch (BindType) {
1793 case MachO::BIND_TYPE_POINTER:
1794 return "pointer";
1795 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1796 return "text abs32";
1797 case MachO::BIND_TYPE_TEXT_PCREL32:
1798 return "text rel32";
1799 }
1800 return "unknown";
1801}
1802
1803StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1804
1805int64_t MachOBindEntry::addend() const { return Addend; }
1806
1807uint32_t MachOBindEntry::flags() const { return Flags; }
1808
1809int MachOBindEntry::ordinal() const { return Ordinal; }
1810
1811bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1812 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1813 return (Ptr == Other.Ptr) &&
1814 (RemainingLoopCount == Other.RemainingLoopCount) &&
1815 (Done == Other.Done);
1816}
1817
1818iterator_range<bind_iterator>
1819MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1820 MachOBindEntry::Kind BKind) {
1821 MachOBindEntry Start(Opcodes, is64, BKind);
1822 Start.moveToFirst();
1823
1824 MachOBindEntry Finish(Opcodes, is64, BKind);
1825 Finish.moveToEnd();
1826
Craig Topper15576e12015-12-06 05:08:07 +00001827 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00001828}
1829
1830iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1831 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1832 MachOBindEntry::Kind::Regular);
1833}
1834
1835iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1836 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1837 MachOBindEntry::Kind::Lazy);
1838}
1839
1840iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1841 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1842 MachOBindEntry::Kind::Weak);
1843}
1844
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001845MachOObjectFile::load_command_iterator
1846MachOObjectFile::begin_load_commands() const {
1847 return LoadCommands.begin();
1848}
1849
1850MachOObjectFile::load_command_iterator
1851MachOObjectFile::end_load_commands() const {
1852 return LoadCommands.end();
1853}
1854
1855iterator_range<MachOObjectFile::load_command_iterator>
1856MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00001857 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001858}
1859
Rafael Espindola56f976f2013-04-18 18:08:55 +00001860StringRef
1861MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1862 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1863 return parseSegmentOrSectionName(Raw.data());
1864}
1865
1866ArrayRef<char>
1867MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001868 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001869 const section_base *Base =
1870 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001871 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001872}
1873
1874ArrayRef<char>
1875MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001876 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001877 const section_base *Base =
1878 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001879 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001880}
1881
1882bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001883MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001884 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001885 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001886 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001887 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001888}
1889
Eric Christopher1d62c252013-07-22 22:25:07 +00001890unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001891 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001892 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001893 return RE.r_word1 & 0xffffff;
1894 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001895}
1896
Eric Christopher1d62c252013-07-22 22:25:07 +00001897bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001898 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001899 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001900 return (RE.r_word1 >> 27) & 1;
1901 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001902}
1903
Eric Christopher1d62c252013-07-22 22:25:07 +00001904bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001905 const MachO::any_relocation_info &RE) const {
1906 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001907}
1908
Eric Christopher1d62c252013-07-22 22:25:07 +00001909uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001910 const MachO::any_relocation_info &RE) const {
1911 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001912}
1913
Kevin Enderby9907d0a2014-11-04 00:43:16 +00001914uint32_t MachOObjectFile::getScatteredRelocationType(
1915 const MachO::any_relocation_info &RE) const {
1916 return (RE.r_word0 >> 24) & 0xf;
1917}
1918
Eric Christopher1d62c252013-07-22 22:25:07 +00001919unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001920 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001921 if (isRelocationScattered(RE))
1922 return getScatteredRelocationAddress(RE);
1923 return getPlainRelocationAddress(RE);
1924}
1925
Charles Davis8bdfafd2013-09-01 04:28:48 +00001926unsigned MachOObjectFile::getAnyRelocationPCRel(
1927 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001928 if (isRelocationScattered(RE))
1929 return getScatteredRelocationPCRel(this, RE);
1930 return getPlainRelocationPCRel(this, RE);
1931}
1932
Eric Christopher1d62c252013-07-22 22:25:07 +00001933unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001934 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001935 if (isRelocationScattered(RE))
1936 return getScatteredRelocationLength(RE);
1937 return getPlainRelocationLength(this, RE);
1938}
1939
1940unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00001941MachOObjectFile::getAnyRelocationType(
1942 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001943 if (isRelocationScattered(RE))
1944 return getScatteredRelocationType(RE);
1945 return getPlainRelocationType(this, RE);
1946}
1947
Rafael Espindola52501032013-04-30 15:40:54 +00001948SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00001949MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001950 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00001951 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00001952 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00001953 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1954 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1955 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00001956 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00001957 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00001958 return SectionRef(DRI, this);
1959}
1960
Charles Davis8bdfafd2013-09-01 04:28:48 +00001961MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00001962 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001963 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001964}
1965
Charles Davis8bdfafd2013-09-01 04:28:48 +00001966MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00001967 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001968 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001969}
1970
Charles Davis8bdfafd2013-09-01 04:28:48 +00001971MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00001972 unsigned Index) const {
1973 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001974 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001975}
1976
Charles Davis8bdfafd2013-09-01 04:28:48 +00001977MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1978 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001979 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001980 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001981}
1982
Charles Davis8bdfafd2013-09-01 04:28:48 +00001983MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00001984MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001985 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001986 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001987}
1988
Charles Davis8bdfafd2013-09-01 04:28:48 +00001989MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00001990MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001991 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001992 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001993}
1994
Charles Davis8bdfafd2013-09-01 04:28:48 +00001995MachO::linkedit_data_command
1996MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1997 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001998}
1999
Charles Davis8bdfafd2013-09-01 04:28:48 +00002000MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002001MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002002 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002003}
2004
Charles Davis8bdfafd2013-09-01 04:28:48 +00002005MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002006MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002007 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002008}
2009
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002010MachO::linker_option_command
2011MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2012 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002013}
2014
Jim Grosbach448334a2014-03-18 22:09:05 +00002015MachO::version_min_command
2016MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2017 return getStruct<MachO::version_min_command>(this, L.Ptr);
2018}
2019
Tim Northover8f9590b2014-06-30 14:40:57 +00002020MachO::dylib_command
2021MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2022 return getStruct<MachO::dylib_command>(this, L.Ptr);
2023}
2024
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002025MachO::dyld_info_command
2026MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2027 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2028}
2029
2030MachO::dylinker_command
2031MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2032 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2033}
2034
2035MachO::uuid_command
2036MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2037 return getStruct<MachO::uuid_command>(this, L.Ptr);
2038}
2039
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002040MachO::rpath_command
2041MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2042 return getStruct<MachO::rpath_command>(this, L.Ptr);
2043}
2044
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002045MachO::source_version_command
2046MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2047 return getStruct<MachO::source_version_command>(this, L.Ptr);
2048}
2049
2050MachO::entry_point_command
2051MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2052 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2053}
2054
Kevin Enderby0804f4672014-12-16 23:25:52 +00002055MachO::encryption_info_command
2056MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2057 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2058}
2059
Kevin Enderby57538292014-12-17 01:01:30 +00002060MachO::encryption_info_command_64
2061MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2062 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2063}
2064
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002065MachO::sub_framework_command
2066MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2067 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2068}
Tim Northover8f9590b2014-06-30 14:40:57 +00002069
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002070MachO::sub_umbrella_command
2071MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2072 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2073}
2074
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002075MachO::sub_library_command
2076MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2077 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2078}
2079
Kevin Enderby186eac32014-12-19 21:06:24 +00002080MachO::sub_client_command
2081MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2082 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2083}
2084
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002085MachO::routines_command
2086MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2087 return getStruct<MachO::routines_command>(this, L.Ptr);
2088}
2089
2090MachO::routines_command_64
2091MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2092 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2093}
2094
Kevin Enderby48ef5342014-12-23 22:56:39 +00002095MachO::thread_command
2096MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2097 return getStruct<MachO::thread_command>(this, L.Ptr);
2098}
2099
Charles Davis8bdfafd2013-09-01 04:28:48 +00002100MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002101MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002102 DataRefImpl Sec;
2103 Sec.d.a = Rel.d.a;
2104 uint32_t Offset;
2105 if (is64Bit()) {
2106 MachO::section_64 Sect = getSection64(Sec);
2107 Offset = Sect.reloff;
2108 } else {
2109 MachO::section Sect = getSection(Sec);
2110 Offset = Sect.reloff;
2111 }
2112
2113 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2114 getPtr(this, Offset)) + Rel.d.b;
2115 return getStruct<MachO::any_relocation_info>(
2116 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002117}
2118
Charles Davis8bdfafd2013-09-01 04:28:48 +00002119MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002120MachOObjectFile::getDice(DataRefImpl Rel) const {
2121 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002122 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002123}
2124
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002125const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002126 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002127}
2128
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002129const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2130 assert(is64Bit());
2131 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002132}
2133
Charles Davis8bdfafd2013-09-01 04:28:48 +00002134uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2135 const MachO::dysymtab_command &DLC,
2136 unsigned Index) const {
2137 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2138 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002139}
2140
Charles Davis8bdfafd2013-09-01 04:28:48 +00002141MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002142MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2143 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002144 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2145 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002146}
2147
Charles Davis8bdfafd2013-09-01 04:28:48 +00002148MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002149 if (SymtabLoadCmd)
2150 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2151
2152 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2153 MachO::symtab_command Cmd;
2154 Cmd.cmd = MachO::LC_SYMTAB;
2155 Cmd.cmdsize = sizeof(MachO::symtab_command);
2156 Cmd.symoff = 0;
2157 Cmd.nsyms = 0;
2158 Cmd.stroff = 0;
2159 Cmd.strsize = 0;
2160 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002161}
2162
Charles Davis8bdfafd2013-09-01 04:28:48 +00002163MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002164 if (DysymtabLoadCmd)
2165 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2166
2167 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2168 MachO::dysymtab_command Cmd;
2169 Cmd.cmd = MachO::LC_DYSYMTAB;
2170 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2171 Cmd.ilocalsym = 0;
2172 Cmd.nlocalsym = 0;
2173 Cmd.iextdefsym = 0;
2174 Cmd.nextdefsym = 0;
2175 Cmd.iundefsym = 0;
2176 Cmd.nundefsym = 0;
2177 Cmd.tocoff = 0;
2178 Cmd.ntoc = 0;
2179 Cmd.modtaboff = 0;
2180 Cmd.nmodtab = 0;
2181 Cmd.extrefsymoff = 0;
2182 Cmd.nextrefsyms = 0;
2183 Cmd.indirectsymoff = 0;
2184 Cmd.nindirectsyms = 0;
2185 Cmd.extreloff = 0;
2186 Cmd.nextrel = 0;
2187 Cmd.locreloff = 0;
2188 Cmd.nlocrel = 0;
2189 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002190}
2191
Charles Davis8bdfafd2013-09-01 04:28:48 +00002192MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002193MachOObjectFile::getDataInCodeLoadCommand() const {
2194 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002195 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002196
2197 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002198 MachO::linkedit_data_command Cmd;
2199 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2200 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2201 Cmd.dataoff = 0;
2202 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002203 return Cmd;
2204}
2205
Kevin Enderby9a509442015-01-27 21:28:24 +00002206MachO::linkedit_data_command
2207MachOObjectFile::getLinkOptHintsLoadCommand() const {
2208 if (LinkOptHintsLoadCmd)
2209 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2210
2211 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2212 // fields.
2213 MachO::linkedit_data_command Cmd;
2214 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2215 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2216 Cmd.dataoff = 0;
2217 Cmd.datasize = 0;
2218 return Cmd;
2219}
2220
Nick Kledzikd04bc352014-08-30 00:20:14 +00002221ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002222 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002223 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002224
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002225 MachO::dyld_info_command DyldInfo =
2226 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2227 const uint8_t *Ptr =
2228 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002229 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002230}
2231
2232ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002233 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002234 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002235
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002236 MachO::dyld_info_command DyldInfo =
2237 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2238 const uint8_t *Ptr =
2239 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002240 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002241}
2242
2243ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002244 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002245 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002246
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002247 MachO::dyld_info_command DyldInfo =
2248 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2249 const uint8_t *Ptr =
2250 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002251 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002252}
2253
2254ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002255 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002256 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002257
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002258 MachO::dyld_info_command DyldInfo =
2259 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2260 const uint8_t *Ptr =
2261 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002262 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002263}
2264
2265ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002266 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002267 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002268
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002269 MachO::dyld_info_command DyldInfo =
2270 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2271 const uint8_t *Ptr =
2272 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002273 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002274}
2275
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002276ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2277 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002278 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002279 // Returning a pointer is fine as uuid doesn't need endian swapping.
2280 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002281 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002282}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002283
Rafael Espindola6e040c02013-04-26 20:07:33 +00002284StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002285 MachO::symtab_command S = getSymtabLoadCommand();
2286 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002287}
2288
Rafael Espindola56f976f2013-04-18 18:08:55 +00002289bool MachOObjectFile::is64Bit() const {
2290 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002291 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002292}
2293
2294void MachOObjectFile::ReadULEB128s(uint64_t Index,
2295 SmallVectorImpl<uint64_t> &Out) const {
2296 DataExtractor extractor(ObjectFile::getData(), true, 0);
2297
2298 uint32_t offset = Index;
2299 uint64_t data = 0;
2300 while (uint64_t delta = extractor.getULEB128(&offset)) {
2301 data += delta;
2302 Out.push_back(data);
2303 }
2304}
2305
Rafael Espindolac66d7612014-08-17 19:09:37 +00002306bool MachOObjectFile::isRelocatableObject() const {
2307 return getHeader().filetype == MachO::MH_OBJECT;
2308}
2309
Rafael Espindola437b0d52014-07-31 03:12:45 +00002310ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002311ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2312 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002313 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002314 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002315 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002316 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002317 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002318 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002319 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002320 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002321 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002322 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002323 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002324 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002325
Rafael Espindola692410e2014-01-21 23:06:54 +00002326 if (EC)
2327 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002328 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002329}