blob: 075d959be1d71a52752586eaff1d00eb206fbe87 [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);
224 return object_error::success;
225}
226
Rafael Espindola48af1c22014-08-19 18:44:46 +0000227MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000234 if (is64Bit())
Alexey Samsonov9f336632015-06-04 19:45:22 +0000235 parseHeader(this, Header64, EC);
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000236 else
Alexey Samsonovfa5edc52015-06-04 22:49:55 +0000237 parseHeader(this, Header, EC);
Alexey Samsonov9f336632015-06-04 19:45:22 +0000238 if (EC)
239 return;
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000240
241 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000242 if (LoadCommandCount == 0)
243 return;
244
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000245 auto LoadOrErr = getFirstLoadCommandInfo(this);
246 if (!LoadOrErr) {
247 EC = LoadOrErr.getError();
248 return;
249 }
250 LoadCommandInfo Load = LoadOrErr.get();
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000253 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000254 // Multiple symbol tables
255 if (SymtabLoadCmd) {
256 EC = object_error::parse_failed;
257 return;
258 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000259 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
264 return;
265 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000266 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
271 return;
272 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000273 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
278 return;
279 }
280 LinkOptHintsLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
286 return;
287 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000288 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000289 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000290 // Multiple UUID load commands
291 if (UuidLoadCmd) {
292 EC = object_error::parse_failed;
293 return;
294 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000295 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000299 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000303 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000310 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
313 if (!LoadOrErr) {
314 EC = LoadOrErr.getError();
315 return;
316 }
317 Load = LoadOrErr.get();
318 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000319 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000320 assert(LoadCommands.size() == LoadCommandCount);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000321}
322
Rafael Espindola5e812af2014-01-30 02:49:50 +0000323void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000324 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000325 sizeof(MachO::nlist_64) :
326 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000327 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000328}
329
Rafael Espindola3acea392014-06-12 21:46:39 +0000330std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
331 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000332 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000333 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000334 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000335 if (Start < getData().begin() || Start >= getData().end())
336 report_fatal_error(
337 "Symbol name entry points before beginning or past end of file.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000338 Res = StringRef(Start);
339 return object_error::success;
340}
341
Rafael Espindola0e77a942014-12-10 20:46:55 +0000342unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
343 DataRefImpl DRI = Sec.getRawDataRefImpl();
344 uint32_t Flags = getSectionFlags(this, DRI);
345 return Flags & MachO::SECTION_TYPE;
346}
347
Kevin Enderby980b2582014-06-05 21:21:57 +0000348// getIndirectName() returns the name of the alias'ed symbol who's string table
349// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000350std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
351 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000352 StringRef StringTable = getStringTableData();
353 uint64_t NValue;
354 if (is64Bit()) {
355 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
356 NValue = Entry.n_value;
357 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
358 return object_error::parse_failed;
359 } else {
360 MachO::nlist Entry = getSymbolTableEntry(Symb);
361 NValue = Entry.n_value;
362 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
363 return object_error::parse_failed;
364 }
365 if (NValue >= StringTable.size())
366 return object_error::parse_failed;
367 const char *Start = &StringTable.data()[NValue];
368 Res = StringRef(Start);
369 return object_error::success;
370}
371
Rafael Espindola3acea392014-06-12 21:46:39 +0000372std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
373 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000374 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000375 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000376 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
377 Entry.n_value == 0)
378 Res = UnknownAddressOrSize;
379 else
380 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000381 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000382 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000383 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
384 Entry.n_value == 0)
385 Res = UnknownAddressOrSize;
386 else
387 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000388 }
389 return object_error::success;
390}
391
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000392uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000393 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000394 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000395 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000396 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000397 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000398 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000399}
400
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000401uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000402 uint64_t Value;
403 getSymbolAddress(DRI, Value);
Rafael Espindola62a07cb2015-05-22 15:43:00 +0000404 uint32_t flags = getSymbolFlags(DRI);
405 if (flags & SymbolRef::SF_Common)
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000406 return Value;
407 return UnknownAddressOrSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000408}
409
Rafael Espindola3acea392014-06-12 21:46:39 +0000410std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
411 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000412 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000413 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000414
415 Res = SymbolRef::ST_Other;
416
417 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000418 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000419 Res = SymbolRef::ST_Debug;
420 return object_error::success;
421 }
422
Charles Davis74ec8b02013-08-27 05:00:13 +0000423 switch (n_type & MachO::N_TYPE) {
424 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000425 Res = SymbolRef::ST_Unknown;
426 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000427 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000428 Res = SymbolRef::ST_Function;
429 break;
430 }
431 return object_error::success;
432}
433
Rafael Espindola20122a42014-01-31 20:57:12 +0000434uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000435 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000436
Charles Davis8bdfafd2013-09-01 04:28:48 +0000437 uint8_t MachOType = Entry.n_type;
438 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000439
Rafael Espindola20122a42014-01-31 20:57:12 +0000440 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000441
Charles Davis74ec8b02013-08-27 05:00:13 +0000442 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000443 Result |= SymbolRef::SF_Undefined;
444
Tim Northovereaef0742014-05-30 13:22:59 +0000445 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
446 Result |= SymbolRef::SF_Indirect;
447
Rafael Espindolaa1356322013-11-02 05:03:24 +0000448 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000449 Result |= SymbolRef::SF_FormatSpecific;
450
Charles Davis74ec8b02013-08-27 05:00:13 +0000451 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000452 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000453 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000454 uint64_t Value;
455 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000456 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000457 Result |= SymbolRef::SF_Common;
458 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000459
460 if (!(MachOType & MachO::N_PEXT))
461 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000462 }
463
Charles Davis74ec8b02013-08-27 05:00:13 +0000464 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000465 Result |= SymbolRef::SF_Weak;
466
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000467 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
468 Result |= SymbolRef::SF_Thumb;
469
Charles Davis74ec8b02013-08-27 05:00:13 +0000470 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000471 Result |= SymbolRef::SF_Absolute;
472
Rafael Espindola20122a42014-01-31 20:57:12 +0000473 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000474}
475
Rafael Espindola3acea392014-06-12 21:46:39 +0000476std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
477 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000478 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000479 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000480
481 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000482 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000483 } else {
484 DataRefImpl DRI;
485 DRI.d.a = index - 1;
Rafael Espindola0d85d102015-05-22 14:59:27 +0000486 if (DRI.d.a >= Sections.size())
487 report_fatal_error("getSymbolSection: Invalid section index.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000488 Res = section_iterator(SectionRef(DRI, this));
489 }
490
491 return object_error::success;
492}
493
Rafael Espindola5e812af2014-01-30 02:49:50 +0000494void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000495 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000496}
497
Rafael Espindola3acea392014-06-12 21:46:39 +0000498std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
499 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000500 ArrayRef<char> Raw = getSectionRawName(Sec);
501 Result = parseSegmentOrSectionName(Raw.data());
502 return object_error::success;
503}
504
Rafael Espindola80291272014-10-08 15:28:58 +0000505uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
506 if (is64Bit())
507 return getSection64(Sec).addr;
508 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000509}
510
Rafael Espindola80291272014-10-08 15:28:58 +0000511uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
512 if (is64Bit())
513 return getSection64(Sec).size;
514 return getSection(Sec).size;
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);
533 return object_error::success;
534}
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 Espindola80291272014-10-08 15:28:58 +0000570bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000571 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000572 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000573}
574
Rafael Espindola80291272014-10-08 15:28:58 +0000575bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
576 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000577 SymbolRef::Type ST;
578 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000579 if (ST == SymbolRef::ST_Unknown)
580 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000581
Rafael Espindola80291272014-10-08 15:28:58 +0000582 uint64_t SectBegin = getSectionAddress(Sec);
583 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000584 SectEnd += SectBegin;
585
586 uint64_t SymAddr;
587 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000588 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000589}
590
Rui Ueyamabc654b12013-09-27 21:47:05 +0000591relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000592 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000593 Ret.d.a = Sec.d.a;
594 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000595 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000596}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000597
Rafael Espindola56f976f2013-04-18 18:08:55 +0000598relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000599MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000600 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000601 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000602 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000603 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000604 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000605 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000606 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000607 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000608
Rafael Espindola56f976f2013-04-18 18:08:55 +0000609 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000610 Ret.d.a = Sec.d.a;
611 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000612 return relocation_iterator(RelocationRef(Ret, this));
613}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000614
Rafael Espindola5e812af2014-01-30 02:49:50 +0000615void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000616 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000617}
Owen Anderson171f4852011-10-24 23:20:07 +0000618
Rafael Espindola3acea392014-06-12 21:46:39 +0000619std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
620 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000621 uint64_t Offset;
622 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000623
624 DataRefImpl Sec;
625 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000626 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000627 Res = SecAddress + Offset;
628 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000629}
630
Rafael Espindola3acea392014-06-12 21:46:39 +0000631std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
632 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000633 assert(getHeader().filetype == MachO::MH_OBJECT &&
634 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000635 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000636 Res = getAnyRelocationAddress(RE);
637 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000638}
639
Rafael Espindola806f0062013-06-05 01:33:53 +0000640symbol_iterator
641MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000642 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000643 if (isRelocationScattered(RE))
644 return symbol_end();
645
Rafael Espindola56f976f2013-04-18 18:08:55 +0000646 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
647 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000648 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000649 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000650
Charles Davis8bdfafd2013-09-01 04:28:48 +0000651 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000652 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000653 sizeof(MachO::nlist_64) :
654 sizeof(MachO::nlist);
655 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000656 DataRefImpl Sym;
657 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000658 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000659}
660
Keno Fischerc780e8e2015-05-21 21:24:32 +0000661section_iterator
662MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
663 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
664}
665
Rafael Espindola3acea392014-06-12 21:46:39 +0000666std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
667 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000668 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000669 Res = getAnyRelocationType(RE);
670 return object_error::success;
671}
672
Rafael Espindola3acea392014-06-12 21:46:39 +0000673std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000674MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
675 SmallVectorImpl<char> &Result) const {
676 StringRef res;
677 uint64_t RType;
678 getRelocationType(Rel, RType);
679
680 unsigned Arch = this->getArch();
681
682 switch (Arch) {
683 case Triple::x86: {
684 static const char *const Table[] = {
685 "GENERIC_RELOC_VANILLA",
686 "GENERIC_RELOC_PAIR",
687 "GENERIC_RELOC_SECTDIFF",
688 "GENERIC_RELOC_PB_LA_PTR",
689 "GENERIC_RELOC_LOCAL_SECTDIFF",
690 "GENERIC_RELOC_TLV" };
691
Eric Christopher13250cb2013-12-06 02:33:38 +0000692 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000693 res = "Unknown";
694 else
695 res = Table[RType];
696 break;
697 }
698 case Triple::x86_64: {
699 static const char *const Table[] = {
700 "X86_64_RELOC_UNSIGNED",
701 "X86_64_RELOC_SIGNED",
702 "X86_64_RELOC_BRANCH",
703 "X86_64_RELOC_GOT_LOAD",
704 "X86_64_RELOC_GOT",
705 "X86_64_RELOC_SUBTRACTOR",
706 "X86_64_RELOC_SIGNED_1",
707 "X86_64_RELOC_SIGNED_2",
708 "X86_64_RELOC_SIGNED_4",
709 "X86_64_RELOC_TLV" };
710
711 if (RType > 9)
712 res = "Unknown";
713 else
714 res = Table[RType];
715 break;
716 }
717 case Triple::arm: {
718 static const char *const Table[] = {
719 "ARM_RELOC_VANILLA",
720 "ARM_RELOC_PAIR",
721 "ARM_RELOC_SECTDIFF",
722 "ARM_RELOC_LOCAL_SECTDIFF",
723 "ARM_RELOC_PB_LA_PTR",
724 "ARM_RELOC_BR24",
725 "ARM_THUMB_RELOC_BR22",
726 "ARM_THUMB_32BIT_BRANCH",
727 "ARM_RELOC_HALF",
728 "ARM_RELOC_HALF_SECTDIFF" };
729
730 if (RType > 9)
731 res = "Unknown";
732 else
733 res = Table[RType];
734 break;
735 }
Tim Northover00ed9962014-03-29 10:18:08 +0000736 case Triple::aarch64: {
737 static const char *const Table[] = {
738 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
739 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
740 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
741 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
742 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
743 "ARM64_RELOC_ADDEND"
744 };
745
746 if (RType >= array_lengthof(Table))
747 res = "Unknown";
748 else
749 res = Table[RType];
750 break;
751 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000752 case Triple::ppc: {
753 static const char *const Table[] = {
754 "PPC_RELOC_VANILLA",
755 "PPC_RELOC_PAIR",
756 "PPC_RELOC_BR14",
757 "PPC_RELOC_BR24",
758 "PPC_RELOC_HI16",
759 "PPC_RELOC_LO16",
760 "PPC_RELOC_HA16",
761 "PPC_RELOC_LO14",
762 "PPC_RELOC_SECTDIFF",
763 "PPC_RELOC_PB_LA_PTR",
764 "PPC_RELOC_HI16_SECTDIFF",
765 "PPC_RELOC_LO16_SECTDIFF",
766 "PPC_RELOC_HA16_SECTDIFF",
767 "PPC_RELOC_JBSR",
768 "PPC_RELOC_LO14_SECTDIFF",
769 "PPC_RELOC_LOCAL_SECTDIFF" };
770
Eric Christopher13250cb2013-12-06 02:33:38 +0000771 if (RType > 15)
772 res = "Unknown";
773 else
774 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000775 break;
776 }
777 case Triple::UnknownArch:
778 res = "Unknown";
779 break;
780 }
781 Result.append(res.begin(), res.end());
782 return object_error::success;
783}
784
Rafael Espindola3acea392014-06-12 21:46:39 +0000785std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
786 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000787 unsigned Arch = getArch();
788 uint64_t Type;
789 getRelocationType(Rel, Type);
790
791 Result = false;
792
793 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
794 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000795 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000796 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000797 } else if (Arch == Triple::x86_64) {
798 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000799 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000800 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000801 DataRefImpl RelPrev = Rel;
802 RelPrev.d.a--;
803 uint64_t PrevType;
804 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000805 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000806 Result = true;
807 }
808 }
809
810 return object_error::success;
811}
812
Keno Fischer281b6942015-05-30 19:44:53 +0000813uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
814 MachO::any_relocation_info RE = getRelocation(Rel);
815 return getAnyRelocationLength(RE);
816}
817
Kevin Enderby980b2582014-06-05 21:21:57 +0000818//
819// guessLibraryShortName() is passed a name of a dynamic library and returns a
820// guess on what the short name is. Then name is returned as a substring of the
821// StringRef Name passed in. The name of the dynamic library is recognized as
822// a framework if it has one of the two following forms:
823// Foo.framework/Versions/A/Foo
824// Foo.framework/Foo
825// Where A and Foo can be any string. And may contain a trailing suffix
826// starting with an underbar. If the Name is recognized as a framework then
827// isFramework is set to true else it is set to false. If the Name has a
828// suffix then Suffix is set to the substring in Name that contains the suffix
829// else it is set to a NULL StringRef.
830//
831// The Name of the dynamic library is recognized as a library name if it has
832// one of the two following forms:
833// libFoo.A.dylib
834// libFoo.dylib
835// The library may have a suffix trailing the name Foo of the form:
836// libFoo_profile.A.dylib
837// libFoo_profile.dylib
838//
839// The Name of the dynamic library is also recognized as a library name if it
840// has the following form:
841// Foo.qtx
842//
843// If the Name of the dynamic library is none of the forms above then a NULL
844// StringRef is returned.
845//
846StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
847 bool &isFramework,
848 StringRef &Suffix) {
849 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
850 size_t a, b, c, d, Idx;
851
852 isFramework = false;
853 Suffix = StringRef();
854
855 // Pull off the last component and make Foo point to it
856 a = Name.rfind('/');
857 if (a == Name.npos || a == 0)
858 goto guess_library;
859 Foo = Name.slice(a+1, Name.npos);
860
861 // Look for a suffix starting with a '_'
862 Idx = Foo.rfind('_');
863 if (Idx != Foo.npos && Foo.size() >= 2) {
864 Suffix = Foo.slice(Idx, Foo.npos);
865 Foo = Foo.slice(0, Idx);
866 }
867
868 // First look for the form Foo.framework/Foo
869 b = Name.rfind('/', a);
870 if (b == Name.npos)
871 Idx = 0;
872 else
873 Idx = b+1;
874 F = Name.slice(Idx, Idx + Foo.size());
875 DotFramework = Name.slice(Idx + Foo.size(),
876 Idx + Foo.size() + sizeof(".framework/")-1);
877 if (F == Foo && DotFramework == ".framework/") {
878 isFramework = true;
879 return Foo;
880 }
881
882 // Next look for the form Foo.framework/Versions/A/Foo
883 if (b == Name.npos)
884 goto guess_library;
885 c = Name.rfind('/', b);
886 if (c == Name.npos || c == 0)
887 goto guess_library;
888 V = Name.slice(c+1, Name.npos);
889 if (!V.startswith("Versions/"))
890 goto guess_library;
891 d = Name.rfind('/', c);
892 if (d == Name.npos)
893 Idx = 0;
894 else
895 Idx = d+1;
896 F = Name.slice(Idx, Idx + Foo.size());
897 DotFramework = Name.slice(Idx + Foo.size(),
898 Idx + Foo.size() + sizeof(".framework/")-1);
899 if (F == Foo && DotFramework == ".framework/") {
900 isFramework = true;
901 return Foo;
902 }
903
904guess_library:
905 // pull off the suffix after the "." and make a point to it
906 a = Name.rfind('.');
907 if (a == Name.npos || a == 0)
908 return StringRef();
909 Dylib = Name.slice(a, Name.npos);
910 if (Dylib != ".dylib")
911 goto guess_qtx;
912
913 // First pull off the version letter for the form Foo.A.dylib if any.
914 if (a >= 3) {
915 Dot = Name.slice(a-2, a-1);
916 if (Dot == ".")
917 a = a - 2;
918 }
919
920 b = Name.rfind('/', a);
921 if (b == Name.npos)
922 b = 0;
923 else
924 b = b+1;
925 // ignore any suffix after an underbar like Foo_profile.A.dylib
926 Idx = Name.find('_', b);
927 if (Idx != Name.npos && Idx != b) {
928 Lib = Name.slice(b, Idx);
929 Suffix = Name.slice(Idx, a);
930 }
931 else
932 Lib = Name.slice(b, a);
933 // There are incorrect library names of the form:
934 // libATS.A_profile.dylib so check for these.
935 if (Lib.size() >= 3) {
936 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
937 if (Dot == ".")
938 Lib = Lib.slice(0, Lib.size()-2);
939 }
940 return Lib;
941
942guess_qtx:
943 Qtx = Name.slice(a, Name.npos);
944 if (Qtx != ".qtx")
945 return StringRef();
946 b = Name.rfind('/', a);
947 if (b == Name.npos)
948 Lib = Name.slice(0, a);
949 else
950 Lib = Name.slice(b+1, a);
951 // There are library names of the form: QT.A.qtx so check for these.
952 if (Lib.size() >= 3) {
953 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
954 if (Dot == ".")
955 Lib = Lib.slice(0, Lib.size()-2);
956 }
957 return Lib;
958}
959
960// getLibraryShortNameByIndex() is used to get the short name of the library
961// for an undefined symbol in a linked Mach-O binary that was linked with the
962// normal two-level namespace default (that is MH_TWOLEVEL in the header).
963// It is passed the index (0 - based) of the library as translated from
964// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +0000965std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +0000966 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000967 if (Index >= Libraries.size())
968 return object_error::parse_failed;
969
Kevin Enderby980b2582014-06-05 21:21:57 +0000970 // If the cache of LibrariesShortNames is not built up do that first for
971 // all the Libraries.
972 if (LibrariesShortNames.size() == 0) {
973 for (unsigned i = 0; i < Libraries.size(); i++) {
974 MachO::dylib_command D =
975 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +0000976 if (D.dylib.name >= D.cmdsize)
977 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +0000978 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +0000979 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +0000980 if (D.dylib.name+Name.size() >= D.cmdsize)
981 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +0000982 StringRef Suffix;
983 bool isFramework;
984 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +0000985 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +0000986 LibrariesShortNames.push_back(Name);
987 else
988 LibrariesShortNames.push_back(shortName);
989 }
990 }
991
992 Res = LibrariesShortNames[Index];
993 return object_error::success;
994}
995
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000996basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +0000997 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000998}
999
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001000basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001001 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001002 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001003 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001004
Charles Davis8bdfafd2013-09-01 04:28:48 +00001005 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001006 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001007 sizeof(MachO::nlist_64) :
1008 sizeof(MachO::nlist);
1009 unsigned Offset = Symtab.symoff +
1010 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001011 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001012 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001013}
1014
Lang Hames36072da2014-05-12 21:39:59 +00001015basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1016 DataRefImpl DRI;
1017 if (!SymtabLoadCmd)
1018 return basic_symbol_iterator(SymbolRef(DRI, this));
1019
1020 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001021 if (Index >= Symtab.nsyms)
1022 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001023 unsigned SymbolTableEntrySize =
1024 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1025 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1026 DRI.p += Index * SymbolTableEntrySize;
1027 return basic_symbol_iterator(SymbolRef(DRI, this));
1028}
1029
Rafael Espindolab5155a52014-02-10 20:24:04 +00001030section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001031 DataRefImpl DRI;
1032 return section_iterator(SectionRef(DRI, this));
1033}
1034
Rafael Espindolab5155a52014-02-10 20:24:04 +00001035section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001036 DataRefImpl DRI;
1037 DRI.d.a = Sections.size();
1038 return section_iterator(SectionRef(DRI, this));
1039}
1040
Rafael Espindola56f976f2013-04-18 18:08:55 +00001041uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001042 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001043}
1044
Rafael Espindola56f976f2013-04-18 18:08:55 +00001045StringRef MachOObjectFile::getFileFormatName() const {
1046 unsigned CPUType = getCPUType(this);
1047 if (!is64Bit()) {
1048 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001049 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001050 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001051 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001052 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001053 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001054 return "Mach-O 32-bit ppc";
1055 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001056 return "Mach-O 32-bit unknown";
1057 }
1058 }
1059
Rafael Espindola56f976f2013-04-18 18:08:55 +00001060 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001061 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001062 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001063 case llvm::MachO::CPU_TYPE_ARM64:
1064 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001065 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001066 return "Mach-O 64-bit ppc64";
1067 default:
1068 return "Mach-O 64-bit unknown";
1069 }
1070}
1071
Alexey Samsonove6388e62013-06-18 15:03:28 +00001072Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1073 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001074 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001075 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001076 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001077 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001078 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001079 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001080 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001081 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001082 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001083 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001084 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001085 return Triple::ppc64;
1086 default:
1087 return Triple::UnknownArch;
1088 }
1089}
1090
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001091Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1092 const char **McpuDefault) {
1093 if (McpuDefault)
1094 *McpuDefault = nullptr;
1095
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001096 switch (CPUType) {
1097 case MachO::CPU_TYPE_I386:
1098 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1099 case MachO::CPU_SUBTYPE_I386_ALL:
1100 return Triple("i386-apple-darwin");
1101 default:
1102 return Triple();
1103 }
1104 case MachO::CPU_TYPE_X86_64:
1105 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1106 case MachO::CPU_SUBTYPE_X86_64_ALL:
1107 return Triple("x86_64-apple-darwin");
1108 case MachO::CPU_SUBTYPE_X86_64_H:
1109 return Triple("x86_64h-apple-darwin");
1110 default:
1111 return Triple();
1112 }
1113 case MachO::CPU_TYPE_ARM:
1114 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1115 case MachO::CPU_SUBTYPE_ARM_V4T:
1116 return Triple("armv4t-apple-darwin");
1117 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1118 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001119 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1120 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001121 case MachO::CPU_SUBTYPE_ARM_V6:
1122 return Triple("armv6-apple-darwin");
1123 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001124 if (McpuDefault)
1125 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001126 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001127 case MachO::CPU_SUBTYPE_ARM_V7:
1128 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001129 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001130 if (McpuDefault)
1131 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001132 return Triple("armv7em-apple-darwin");
1133 case MachO::CPU_SUBTYPE_ARM_V7K:
1134 return Triple("armv7k-apple-darwin");
1135 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001136 if (McpuDefault)
1137 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001138 return Triple("armv7m-apple-darwin");
1139 case MachO::CPU_SUBTYPE_ARM_V7S:
1140 return Triple("armv7s-apple-darwin");
1141 default:
1142 return Triple();
1143 }
1144 case MachO::CPU_TYPE_ARM64:
1145 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1146 case MachO::CPU_SUBTYPE_ARM64_ALL:
1147 return Triple("arm64-apple-darwin");
1148 default:
1149 return Triple();
1150 }
1151 case MachO::CPU_TYPE_POWERPC:
1152 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1153 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1154 return Triple("ppc-apple-darwin");
1155 default:
1156 return Triple();
1157 }
1158 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001159 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001160 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1161 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001162 default:
1163 return Triple();
1164 }
1165 default:
1166 return Triple();
1167 }
1168}
1169
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001170Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1171 const char **McpuDefault) {
1172 if (McpuDefault)
1173 *McpuDefault = nullptr;
1174
1175 switch (CPUType) {
1176 case MachO::CPU_TYPE_ARM:
1177 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1178 case MachO::CPU_SUBTYPE_ARM_V4T:
1179 return Triple("thumbv4t-apple-darwin");
1180 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1181 return Triple("thumbv5e-apple-darwin");
1182 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1183 return Triple("xscale-apple-darwin");
1184 case MachO::CPU_SUBTYPE_ARM_V6:
1185 return Triple("thumbv6-apple-darwin");
1186 case MachO::CPU_SUBTYPE_ARM_V6M:
1187 if (McpuDefault)
1188 *McpuDefault = "cortex-m0";
1189 return Triple("thumbv6m-apple-darwin");
1190 case MachO::CPU_SUBTYPE_ARM_V7:
1191 return Triple("thumbv7-apple-darwin");
1192 case MachO::CPU_SUBTYPE_ARM_V7EM:
1193 if (McpuDefault)
1194 *McpuDefault = "cortex-m4";
1195 return Triple("thumbv7em-apple-darwin");
1196 case MachO::CPU_SUBTYPE_ARM_V7K:
1197 return Triple("thumbv7k-apple-darwin");
1198 case MachO::CPU_SUBTYPE_ARM_V7M:
1199 if (McpuDefault)
1200 *McpuDefault = "cortex-m3";
1201 return Triple("thumbv7m-apple-darwin");
1202 case MachO::CPU_SUBTYPE_ARM_V7S:
1203 return Triple("thumbv7s-apple-darwin");
1204 default:
1205 return Triple();
1206 }
1207 default:
1208 return Triple();
1209 }
1210}
1211
1212Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1213 const char **McpuDefault,
1214 Triple *ThumbTriple) {
1215 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1216 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1217 McpuDefault);
1218 return T;
1219}
1220
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001221Triple MachOObjectFile::getHostArch() {
1222 return Triple(sys::getDefaultTargetTriple());
1223}
1224
Rafael Espindola72318b42014-08-08 16:30:17 +00001225bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1226 return StringSwitch<bool>(ArchFlag)
1227 .Case("i386", true)
1228 .Case("x86_64", true)
1229 .Case("x86_64h", true)
1230 .Case("armv4t", true)
1231 .Case("arm", true)
1232 .Case("armv5e", true)
1233 .Case("armv6", true)
1234 .Case("armv6m", true)
1235 .Case("armv7em", true)
1236 .Case("armv7k", true)
1237 .Case("armv7m", true)
1238 .Case("armv7s", true)
1239 .Case("arm64", true)
1240 .Case("ppc", true)
1241 .Case("ppc64", true)
1242 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001243}
1244
Alexey Samsonove6388e62013-06-18 15:03:28 +00001245unsigned MachOObjectFile::getArch() const {
1246 return getArch(getCPUType(this));
1247}
1248
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001249Triple MachOObjectFile::getArch(const char **McpuDefault,
1250 Triple *ThumbTriple) const {
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001251 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1252 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001253}
1254
Rui Ueyamabc654b12013-09-27 21:47:05 +00001255relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001256 DataRefImpl DRI;
1257 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001258 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001259}
1260
Rui Ueyamabc654b12013-09-27 21:47:05 +00001261relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001262 DataRefImpl DRI;
1263 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001264 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001265}
1266
Kevin Enderby273ae012013-06-06 17:20:50 +00001267dice_iterator MachOObjectFile::begin_dices() const {
1268 DataRefImpl DRI;
1269 if (!DataInCodeLoadCmd)
1270 return dice_iterator(DiceRef(DRI, this));
1271
Charles Davis8bdfafd2013-09-01 04:28:48 +00001272 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1273 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001274 return dice_iterator(DiceRef(DRI, this));
1275}
1276
1277dice_iterator MachOObjectFile::end_dices() const {
1278 DataRefImpl DRI;
1279 if (!DataInCodeLoadCmd)
1280 return dice_iterator(DiceRef(DRI, this));
1281
Charles Davis8bdfafd2013-09-01 04:28:48 +00001282 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1283 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001284 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1285 return dice_iterator(DiceRef(DRI, this));
1286}
1287
Nick Kledzikd04bc352014-08-30 00:20:14 +00001288ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1289 : Trie(T), Malformed(false), Done(false) { }
1290
1291void ExportEntry::moveToFirst() {
1292 pushNode(0);
1293 pushDownUntilBottom();
1294}
1295
1296void ExportEntry::moveToEnd() {
1297 Stack.clear();
1298 Done = true;
1299}
1300
1301bool ExportEntry::operator==(const ExportEntry &Other) const {
1302 // Common case, one at end, other iterating from begin.
1303 if (Done || Other.Done)
1304 return (Done == Other.Done);
1305 // Not equal if different stack sizes.
1306 if (Stack.size() != Other.Stack.size())
1307 return false;
1308 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001309 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001310 return false;
1311 // Equal if all nodes in both stacks match.
1312 for (unsigned i=0; i < Stack.size(); ++i) {
1313 if (Stack[i].Start != Other.Stack[i].Start)
1314 return false;
1315 }
1316 return true;
1317}
1318
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001319uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1320 unsigned Count;
1321 uint64_t Result = decodeULEB128(Ptr, &Count);
1322 Ptr += Count;
1323 if (Ptr > Trie.end()) {
1324 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001325 Malformed = true;
1326 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001327 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001328}
1329
1330StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001331 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001332}
1333
1334uint64_t ExportEntry::flags() const {
1335 return Stack.back().Flags;
1336}
1337
1338uint64_t ExportEntry::address() const {
1339 return Stack.back().Address;
1340}
1341
1342uint64_t ExportEntry::other() const {
1343 return Stack.back().Other;
1344}
1345
1346StringRef ExportEntry::otherName() const {
1347 const char* ImportName = Stack.back().ImportName;
1348 if (ImportName)
1349 return StringRef(ImportName);
1350 return StringRef();
1351}
1352
1353uint32_t ExportEntry::nodeOffset() const {
1354 return Stack.back().Start - Trie.begin();
1355}
1356
1357ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1358 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1359 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1360 ParentStringLength(0), IsExportNode(false) {
1361}
1362
1363void ExportEntry::pushNode(uint64_t offset) {
1364 const uint8_t *Ptr = Trie.begin() + offset;
1365 NodeState State(Ptr);
1366 uint64_t ExportInfoSize = readULEB128(State.Current);
1367 State.IsExportNode = (ExportInfoSize != 0);
1368 const uint8_t* Children = State.Current + ExportInfoSize;
1369 if (State.IsExportNode) {
1370 State.Flags = readULEB128(State.Current);
1371 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1372 State.Address = 0;
1373 State.Other = readULEB128(State.Current); // dylib ordinal
1374 State.ImportName = reinterpret_cast<const char*>(State.Current);
1375 } else {
1376 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001377 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1378 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001379 }
1380 }
1381 State.ChildCount = *Children;
1382 State.Current = Children + 1;
1383 State.NextChildIndex = 0;
1384 State.ParentStringLength = CumulativeString.size();
1385 Stack.push_back(State);
1386}
1387
1388void ExportEntry::pushDownUntilBottom() {
1389 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1390 NodeState &Top = Stack.back();
1391 CumulativeString.resize(Top.ParentStringLength);
1392 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001393 char C = *Top.Current;
1394 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001395 }
1396 Top.Current += 1;
1397 uint64_t childNodeIndex = readULEB128(Top.Current);
1398 Top.NextChildIndex += 1;
1399 pushNode(childNodeIndex);
1400 }
1401 if (!Stack.back().IsExportNode) {
1402 Malformed = true;
1403 moveToEnd();
1404 }
1405}
1406
1407// We have a trie data structure and need a way to walk it that is compatible
1408// with the C++ iterator model. The solution is a non-recursive depth first
1409// traversal where the iterator contains a stack of parent nodes along with a
1410// string that is the accumulation of all edge strings along the parent chain
1411// to this point.
1412//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001413// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001414// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1415// node may have child nodes too.
1416//
1417// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1418// child until hitting a node with no children (which is an export node or
1419// else the trie is malformed). On the way down, each node is pushed on the
1420// stack ivar. If there is no more ways down, it pops up one and tries to go
1421// down a sibling path until a childless node is reached.
1422void ExportEntry::moveNext() {
1423 if (Stack.empty() || !Stack.back().IsExportNode) {
1424 Malformed = true;
1425 moveToEnd();
1426 return;
1427 }
1428
1429 Stack.pop_back();
1430 while (!Stack.empty()) {
1431 NodeState &Top = Stack.back();
1432 if (Top.NextChildIndex < Top.ChildCount) {
1433 pushDownUntilBottom();
1434 // Now at the next export node.
1435 return;
1436 } else {
1437 if (Top.IsExportNode) {
1438 // This node has no children but is itself an export node.
1439 CumulativeString.resize(Top.ParentStringLength);
1440 return;
1441 }
1442 Stack.pop_back();
1443 }
1444 }
1445 Done = true;
1446}
1447
1448iterator_range<export_iterator>
1449MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1450 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001451 if (Trie.size() == 0)
1452 Start.moveToEnd();
1453 else
1454 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001455
1456 ExportEntry Finish(Trie);
1457 Finish.moveToEnd();
1458
1459 return iterator_range<export_iterator>(export_iterator(Start),
1460 export_iterator(Finish));
1461}
1462
1463iterator_range<export_iterator> MachOObjectFile::exports() const {
1464 return exports(getDyldInfoExportsTrie());
1465}
1466
1467
Nick Kledzikac431442014-09-12 21:34:15 +00001468MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1469 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1470 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1471 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1472
1473void MachORebaseEntry::moveToFirst() {
1474 Ptr = Opcodes.begin();
1475 moveNext();
1476}
1477
1478void MachORebaseEntry::moveToEnd() {
1479 Ptr = Opcodes.end();
1480 RemainingLoopCount = 0;
1481 Done = true;
1482}
1483
1484void MachORebaseEntry::moveNext() {
1485 // If in the middle of some loop, move to next rebasing in loop.
1486 SegmentOffset += AdvanceAmount;
1487 if (RemainingLoopCount) {
1488 --RemainingLoopCount;
1489 return;
1490 }
1491 if (Ptr == Opcodes.end()) {
1492 Done = true;
1493 return;
1494 }
1495 bool More = true;
1496 while (More && !Malformed) {
1497 // Parse next opcode and set up next loop.
1498 uint8_t Byte = *Ptr++;
1499 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1500 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1501 switch (Opcode) {
1502 case MachO::REBASE_OPCODE_DONE:
1503 More = false;
1504 Done = true;
1505 moveToEnd();
1506 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1507 break;
1508 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1509 RebaseType = ImmValue;
1510 DEBUG_WITH_TYPE(
1511 "mach-o-rebase",
1512 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1513 << "RebaseType=" << (int) RebaseType << "\n");
1514 break;
1515 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1516 SegmentIndex = ImmValue;
1517 SegmentOffset = readULEB128();
1518 DEBUG_WITH_TYPE(
1519 "mach-o-rebase",
1520 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1521 << "SegmentIndex=" << SegmentIndex << ", "
1522 << format("SegmentOffset=0x%06X", SegmentOffset)
1523 << "\n");
1524 break;
1525 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1526 SegmentOffset += readULEB128();
1527 DEBUG_WITH_TYPE("mach-o-rebase",
1528 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1529 << format("SegmentOffset=0x%06X",
1530 SegmentOffset) << "\n");
1531 break;
1532 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1533 SegmentOffset += ImmValue * PointerSize;
1534 DEBUG_WITH_TYPE("mach-o-rebase",
1535 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1536 << format("SegmentOffset=0x%06X",
1537 SegmentOffset) << "\n");
1538 break;
1539 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1540 AdvanceAmount = PointerSize;
1541 RemainingLoopCount = ImmValue - 1;
1542 DEBUG_WITH_TYPE(
1543 "mach-o-rebase",
1544 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1545 << format("SegmentOffset=0x%06X", SegmentOffset)
1546 << ", AdvanceAmount=" << AdvanceAmount
1547 << ", RemainingLoopCount=" << RemainingLoopCount
1548 << "\n");
1549 return;
1550 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1551 AdvanceAmount = PointerSize;
1552 RemainingLoopCount = readULEB128() - 1;
1553 DEBUG_WITH_TYPE(
1554 "mach-o-rebase",
1555 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1556 << format("SegmentOffset=0x%06X", SegmentOffset)
1557 << ", AdvanceAmount=" << AdvanceAmount
1558 << ", RemainingLoopCount=" << RemainingLoopCount
1559 << "\n");
1560 return;
1561 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1562 AdvanceAmount = readULEB128() + PointerSize;
1563 RemainingLoopCount = 0;
1564 DEBUG_WITH_TYPE(
1565 "mach-o-rebase",
1566 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1567 << format("SegmentOffset=0x%06X", SegmentOffset)
1568 << ", AdvanceAmount=" << AdvanceAmount
1569 << ", RemainingLoopCount=" << RemainingLoopCount
1570 << "\n");
1571 return;
1572 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1573 RemainingLoopCount = readULEB128() - 1;
1574 AdvanceAmount = readULEB128() + PointerSize;
1575 DEBUG_WITH_TYPE(
1576 "mach-o-rebase",
1577 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1578 << format("SegmentOffset=0x%06X", SegmentOffset)
1579 << ", AdvanceAmount=" << AdvanceAmount
1580 << ", RemainingLoopCount=" << RemainingLoopCount
1581 << "\n");
1582 return;
1583 default:
1584 Malformed = true;
1585 }
1586 }
1587}
1588
1589uint64_t MachORebaseEntry::readULEB128() {
1590 unsigned Count;
1591 uint64_t Result = decodeULEB128(Ptr, &Count);
1592 Ptr += Count;
1593 if (Ptr > Opcodes.end()) {
1594 Ptr = Opcodes.end();
1595 Malformed = true;
1596 }
1597 return Result;
1598}
1599
1600uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1601
1602uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1603
1604StringRef MachORebaseEntry::typeName() const {
1605 switch (RebaseType) {
1606 case MachO::REBASE_TYPE_POINTER:
1607 return "pointer";
1608 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1609 return "text abs32";
1610 case MachO::REBASE_TYPE_TEXT_PCREL32:
1611 return "text rel32";
1612 }
1613 return "unknown";
1614}
1615
1616bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1617 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1618 return (Ptr == Other.Ptr) &&
1619 (RemainingLoopCount == Other.RemainingLoopCount) &&
1620 (Done == Other.Done);
1621}
1622
1623iterator_range<rebase_iterator>
1624MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1625 MachORebaseEntry Start(Opcodes, is64);
1626 Start.moveToFirst();
1627
1628 MachORebaseEntry Finish(Opcodes, is64);
1629 Finish.moveToEnd();
1630
1631 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1632 rebase_iterator(Finish));
1633}
1634
1635iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1636 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1637}
1638
Nick Kledzik56ebef42014-09-16 01:41:51 +00001639
1640MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1641 Kind BK)
1642 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1643 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1644 BindType(0), PointerSize(is64Bit ? 8 : 4),
1645 TableKind(BK), Malformed(false), Done(false) {}
1646
1647void MachOBindEntry::moveToFirst() {
1648 Ptr = Opcodes.begin();
1649 moveNext();
1650}
1651
1652void MachOBindEntry::moveToEnd() {
1653 Ptr = Opcodes.end();
1654 RemainingLoopCount = 0;
1655 Done = true;
1656}
1657
1658void MachOBindEntry::moveNext() {
1659 // If in the middle of some loop, move to next binding in loop.
1660 SegmentOffset += AdvanceAmount;
1661 if (RemainingLoopCount) {
1662 --RemainingLoopCount;
1663 return;
1664 }
1665 if (Ptr == Opcodes.end()) {
1666 Done = true;
1667 return;
1668 }
1669 bool More = true;
1670 while (More && !Malformed) {
1671 // Parse next opcode and set up next loop.
1672 uint8_t Byte = *Ptr++;
1673 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1674 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1675 int8_t SignExtended;
1676 const uint8_t *SymStart;
1677 switch (Opcode) {
1678 case MachO::BIND_OPCODE_DONE:
1679 if (TableKind == Kind::Lazy) {
1680 // Lazying bindings have a DONE opcode between entries. Need to ignore
1681 // it to advance to next entry. But need not if this is last entry.
1682 bool NotLastEntry = false;
1683 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1684 if (*P) {
1685 NotLastEntry = true;
1686 }
1687 }
1688 if (NotLastEntry)
1689 break;
1690 }
1691 More = false;
1692 Done = true;
1693 moveToEnd();
1694 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1695 break;
1696 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1697 Ordinal = ImmValue;
1698 DEBUG_WITH_TYPE(
1699 "mach-o-bind",
1700 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1701 << "Ordinal=" << Ordinal << "\n");
1702 break;
1703 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1704 Ordinal = readULEB128();
1705 DEBUG_WITH_TYPE(
1706 "mach-o-bind",
1707 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1708 << "Ordinal=" << Ordinal << "\n");
1709 break;
1710 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1711 if (ImmValue) {
1712 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1713 Ordinal = SignExtended;
1714 } else
1715 Ordinal = 0;
1716 DEBUG_WITH_TYPE(
1717 "mach-o-bind",
1718 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1719 << "Ordinal=" << Ordinal << "\n");
1720 break;
1721 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1722 Flags = ImmValue;
1723 SymStart = Ptr;
1724 while (*Ptr) {
1725 ++Ptr;
1726 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001727 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1728 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001729 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001730 DEBUG_WITH_TYPE(
1731 "mach-o-bind",
1732 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1733 << "SymbolName=" << SymbolName << "\n");
1734 if (TableKind == Kind::Weak) {
1735 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1736 return;
1737 }
1738 break;
1739 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1740 BindType = ImmValue;
1741 DEBUG_WITH_TYPE(
1742 "mach-o-bind",
1743 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1744 << "BindType=" << (int)BindType << "\n");
1745 break;
1746 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1747 Addend = readSLEB128();
1748 if (TableKind == Kind::Lazy)
1749 Malformed = true;
1750 DEBUG_WITH_TYPE(
1751 "mach-o-bind",
1752 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1753 << "Addend=" << Addend << "\n");
1754 break;
1755 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1756 SegmentIndex = ImmValue;
1757 SegmentOffset = readULEB128();
1758 DEBUG_WITH_TYPE(
1759 "mach-o-bind",
1760 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1761 << "SegmentIndex=" << SegmentIndex << ", "
1762 << format("SegmentOffset=0x%06X", SegmentOffset)
1763 << "\n");
1764 break;
1765 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1766 SegmentOffset += readULEB128();
1767 DEBUG_WITH_TYPE("mach-o-bind",
1768 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1769 << format("SegmentOffset=0x%06X",
1770 SegmentOffset) << "\n");
1771 break;
1772 case MachO::BIND_OPCODE_DO_BIND:
1773 AdvanceAmount = PointerSize;
1774 RemainingLoopCount = 0;
1775 DEBUG_WITH_TYPE("mach-o-bind",
1776 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1777 << format("SegmentOffset=0x%06X",
1778 SegmentOffset) << "\n");
1779 return;
1780 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001781 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001782 RemainingLoopCount = 0;
1783 if (TableKind == Kind::Lazy)
1784 Malformed = true;
1785 DEBUG_WITH_TYPE(
1786 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001787 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001788 << format("SegmentOffset=0x%06X", SegmentOffset)
1789 << ", AdvanceAmount=" << AdvanceAmount
1790 << ", RemainingLoopCount=" << RemainingLoopCount
1791 << "\n");
1792 return;
1793 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001794 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001795 RemainingLoopCount = 0;
1796 if (TableKind == Kind::Lazy)
1797 Malformed = true;
1798 DEBUG_WITH_TYPE("mach-o-bind",
1799 llvm::dbgs()
1800 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1801 << format("SegmentOffset=0x%06X",
1802 SegmentOffset) << "\n");
1803 return;
1804 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1805 RemainingLoopCount = readULEB128() - 1;
1806 AdvanceAmount = readULEB128() + PointerSize;
1807 if (TableKind == Kind::Lazy)
1808 Malformed = true;
1809 DEBUG_WITH_TYPE(
1810 "mach-o-bind",
1811 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1812 << format("SegmentOffset=0x%06X", SegmentOffset)
1813 << ", AdvanceAmount=" << AdvanceAmount
1814 << ", RemainingLoopCount=" << RemainingLoopCount
1815 << "\n");
1816 return;
1817 default:
1818 Malformed = true;
1819 }
1820 }
1821}
1822
1823uint64_t MachOBindEntry::readULEB128() {
1824 unsigned Count;
1825 uint64_t Result = decodeULEB128(Ptr, &Count);
1826 Ptr += Count;
1827 if (Ptr > Opcodes.end()) {
1828 Ptr = Opcodes.end();
1829 Malformed = true;
1830 }
1831 return Result;
1832}
1833
1834int64_t MachOBindEntry::readSLEB128() {
1835 unsigned Count;
1836 int64_t Result = decodeSLEB128(Ptr, &Count);
1837 Ptr += Count;
1838 if (Ptr > Opcodes.end()) {
1839 Ptr = Opcodes.end();
1840 Malformed = true;
1841 }
1842 return Result;
1843}
1844
1845
1846uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1847
1848uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1849
1850StringRef MachOBindEntry::typeName() const {
1851 switch (BindType) {
1852 case MachO::BIND_TYPE_POINTER:
1853 return "pointer";
1854 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1855 return "text abs32";
1856 case MachO::BIND_TYPE_TEXT_PCREL32:
1857 return "text rel32";
1858 }
1859 return "unknown";
1860}
1861
1862StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1863
1864int64_t MachOBindEntry::addend() const { return Addend; }
1865
1866uint32_t MachOBindEntry::flags() const { return Flags; }
1867
1868int MachOBindEntry::ordinal() const { return Ordinal; }
1869
1870bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1871 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1872 return (Ptr == Other.Ptr) &&
1873 (RemainingLoopCount == Other.RemainingLoopCount) &&
1874 (Done == Other.Done);
1875}
1876
1877iterator_range<bind_iterator>
1878MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1879 MachOBindEntry::Kind BKind) {
1880 MachOBindEntry Start(Opcodes, is64, BKind);
1881 Start.moveToFirst();
1882
1883 MachOBindEntry Finish(Opcodes, is64, BKind);
1884 Finish.moveToEnd();
1885
1886 return iterator_range<bind_iterator>(bind_iterator(Start),
1887 bind_iterator(Finish));
1888}
1889
1890iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1891 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1892 MachOBindEntry::Kind::Regular);
1893}
1894
1895iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1896 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1897 MachOBindEntry::Kind::Lazy);
1898}
1899
1900iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1901 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1902 MachOBindEntry::Kind::Weak);
1903}
1904
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001905MachOObjectFile::load_command_iterator
1906MachOObjectFile::begin_load_commands() const {
1907 return LoadCommands.begin();
1908}
1909
1910MachOObjectFile::load_command_iterator
1911MachOObjectFile::end_load_commands() const {
1912 return LoadCommands.end();
1913}
1914
1915iterator_range<MachOObjectFile::load_command_iterator>
1916MachOObjectFile::load_commands() const {
1917 return iterator_range<load_command_iterator>(begin_load_commands(),
1918 end_load_commands());
1919}
1920
Rafael Espindola56f976f2013-04-18 18:08:55 +00001921StringRef
1922MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1923 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1924 return parseSegmentOrSectionName(Raw.data());
1925}
1926
1927ArrayRef<char>
1928MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001929 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001930 const section_base *Base =
1931 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001932 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001933}
1934
1935ArrayRef<char>
1936MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001937 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001938 const section_base *Base =
1939 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001940 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001941}
1942
1943bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001944MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001945 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001946 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001947 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001948 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001949}
1950
Eric Christopher1d62c252013-07-22 22:25:07 +00001951unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001952 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001953 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001954 return RE.r_word1 & 0xffffff;
1955 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001956}
1957
Eric Christopher1d62c252013-07-22 22:25:07 +00001958bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001959 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001960 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001961 return (RE.r_word1 >> 27) & 1;
1962 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001963}
1964
Eric Christopher1d62c252013-07-22 22:25:07 +00001965bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001966 const MachO::any_relocation_info &RE) const {
1967 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001968}
1969
Eric Christopher1d62c252013-07-22 22:25:07 +00001970uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001971 const MachO::any_relocation_info &RE) const {
1972 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001973}
1974
Kevin Enderby9907d0a2014-11-04 00:43:16 +00001975uint32_t MachOObjectFile::getScatteredRelocationType(
1976 const MachO::any_relocation_info &RE) const {
1977 return (RE.r_word0 >> 24) & 0xf;
1978}
1979
Eric Christopher1d62c252013-07-22 22:25:07 +00001980unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001981 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001982 if (isRelocationScattered(RE))
1983 return getScatteredRelocationAddress(RE);
1984 return getPlainRelocationAddress(RE);
1985}
1986
Charles Davis8bdfafd2013-09-01 04:28:48 +00001987unsigned MachOObjectFile::getAnyRelocationPCRel(
1988 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001989 if (isRelocationScattered(RE))
1990 return getScatteredRelocationPCRel(this, RE);
1991 return getPlainRelocationPCRel(this, RE);
1992}
1993
Eric Christopher1d62c252013-07-22 22:25:07 +00001994unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001995 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001996 if (isRelocationScattered(RE))
1997 return getScatteredRelocationLength(RE);
1998 return getPlainRelocationLength(this, RE);
1999}
2000
2001unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002002MachOObjectFile::getAnyRelocationType(
2003 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002004 if (isRelocationScattered(RE))
2005 return getScatteredRelocationType(RE);
2006 return getPlainRelocationType(this, RE);
2007}
2008
Rafael Espindola52501032013-04-30 15:40:54 +00002009SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002010MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002011 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002012 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002013 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002014 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2015 DataRefImpl DRI;
2016 DRI.d.a = SecNum;
2017 return SectionRef(DRI, this);
2018}
2019
Charles Davis8bdfafd2013-09-01 04:28:48 +00002020MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002021 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002022 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002023}
2024
Charles Davis8bdfafd2013-09-01 04:28:48 +00002025MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002026 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002027 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002028}
2029
Charles Davis8bdfafd2013-09-01 04:28:48 +00002030MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002031 unsigned Index) const {
2032 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002033 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002034}
2035
Charles Davis8bdfafd2013-09-01 04:28:48 +00002036MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2037 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002038 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002039 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002040}
2041
Charles Davis8bdfafd2013-09-01 04:28:48 +00002042MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002043MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002044 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002045 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002046}
2047
Charles Davis8bdfafd2013-09-01 04:28:48 +00002048MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002049MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002050 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002051 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002052}
2053
Charles Davis8bdfafd2013-09-01 04:28:48 +00002054MachO::linkedit_data_command
2055MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2056 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002057}
2058
Charles Davis8bdfafd2013-09-01 04:28:48 +00002059MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002060MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002061 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002062}
2063
Charles Davis8bdfafd2013-09-01 04:28:48 +00002064MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002065MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002066 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002067}
2068
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002069MachO::linker_option_command
2070MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2071 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002072}
2073
Jim Grosbach448334a2014-03-18 22:09:05 +00002074MachO::version_min_command
2075MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2076 return getStruct<MachO::version_min_command>(this, L.Ptr);
2077}
2078
Tim Northover8f9590b2014-06-30 14:40:57 +00002079MachO::dylib_command
2080MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2081 return getStruct<MachO::dylib_command>(this, L.Ptr);
2082}
2083
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002084MachO::dyld_info_command
2085MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2086 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2087}
2088
2089MachO::dylinker_command
2090MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2091 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2092}
2093
2094MachO::uuid_command
2095MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2096 return getStruct<MachO::uuid_command>(this, L.Ptr);
2097}
2098
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002099MachO::rpath_command
2100MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2101 return getStruct<MachO::rpath_command>(this, L.Ptr);
2102}
2103
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002104MachO::source_version_command
2105MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2106 return getStruct<MachO::source_version_command>(this, L.Ptr);
2107}
2108
2109MachO::entry_point_command
2110MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2111 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2112}
2113
Kevin Enderby0804f4672014-12-16 23:25:52 +00002114MachO::encryption_info_command
2115MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2116 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2117}
2118
Kevin Enderby57538292014-12-17 01:01:30 +00002119MachO::encryption_info_command_64
2120MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2121 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2122}
2123
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002124MachO::sub_framework_command
2125MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2126 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2127}
Tim Northover8f9590b2014-06-30 14:40:57 +00002128
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002129MachO::sub_umbrella_command
2130MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2131 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2132}
2133
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002134MachO::sub_library_command
2135MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2136 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2137}
2138
Kevin Enderby186eac32014-12-19 21:06:24 +00002139MachO::sub_client_command
2140MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2141 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2142}
2143
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002144MachO::routines_command
2145MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2146 return getStruct<MachO::routines_command>(this, L.Ptr);
2147}
2148
2149MachO::routines_command_64
2150MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2151 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2152}
2153
Kevin Enderby48ef5342014-12-23 22:56:39 +00002154MachO::thread_command
2155MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2156 return getStruct<MachO::thread_command>(this, L.Ptr);
2157}
2158
Charles Davis8bdfafd2013-09-01 04:28:48 +00002159MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002160MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002161 DataRefImpl Sec;
2162 Sec.d.a = Rel.d.a;
2163 uint32_t Offset;
2164 if (is64Bit()) {
2165 MachO::section_64 Sect = getSection64(Sec);
2166 Offset = Sect.reloff;
2167 } else {
2168 MachO::section Sect = getSection(Sec);
2169 Offset = Sect.reloff;
2170 }
2171
2172 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2173 getPtr(this, Offset)) + Rel.d.b;
2174 return getStruct<MachO::any_relocation_info>(
2175 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002176}
2177
Charles Davis8bdfafd2013-09-01 04:28:48 +00002178MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002179MachOObjectFile::getDice(DataRefImpl Rel) const {
2180 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002181 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002182}
2183
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002184const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002185 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002186}
2187
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002188const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2189 assert(is64Bit());
2190 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002191}
2192
Charles Davis8bdfafd2013-09-01 04:28:48 +00002193uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2194 const MachO::dysymtab_command &DLC,
2195 unsigned Index) const {
2196 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2197 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002198}
2199
Charles Davis8bdfafd2013-09-01 04:28:48 +00002200MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002201MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2202 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002203 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2204 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002205}
2206
Charles Davis8bdfafd2013-09-01 04:28:48 +00002207MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002208 if (SymtabLoadCmd)
2209 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2210
2211 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2212 MachO::symtab_command Cmd;
2213 Cmd.cmd = MachO::LC_SYMTAB;
2214 Cmd.cmdsize = sizeof(MachO::symtab_command);
2215 Cmd.symoff = 0;
2216 Cmd.nsyms = 0;
2217 Cmd.stroff = 0;
2218 Cmd.strsize = 0;
2219 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002220}
2221
Charles Davis8bdfafd2013-09-01 04:28:48 +00002222MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002223 if (DysymtabLoadCmd)
2224 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2225
2226 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2227 MachO::dysymtab_command Cmd;
2228 Cmd.cmd = MachO::LC_DYSYMTAB;
2229 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2230 Cmd.ilocalsym = 0;
2231 Cmd.nlocalsym = 0;
2232 Cmd.iextdefsym = 0;
2233 Cmd.nextdefsym = 0;
2234 Cmd.iundefsym = 0;
2235 Cmd.nundefsym = 0;
2236 Cmd.tocoff = 0;
2237 Cmd.ntoc = 0;
2238 Cmd.modtaboff = 0;
2239 Cmd.nmodtab = 0;
2240 Cmd.extrefsymoff = 0;
2241 Cmd.nextrefsyms = 0;
2242 Cmd.indirectsymoff = 0;
2243 Cmd.nindirectsyms = 0;
2244 Cmd.extreloff = 0;
2245 Cmd.nextrel = 0;
2246 Cmd.locreloff = 0;
2247 Cmd.nlocrel = 0;
2248 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002249}
2250
Charles Davis8bdfafd2013-09-01 04:28:48 +00002251MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002252MachOObjectFile::getDataInCodeLoadCommand() const {
2253 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002254 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002255
2256 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002257 MachO::linkedit_data_command Cmd;
2258 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2259 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2260 Cmd.dataoff = 0;
2261 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002262 return Cmd;
2263}
2264
Kevin Enderby9a509442015-01-27 21:28:24 +00002265MachO::linkedit_data_command
2266MachOObjectFile::getLinkOptHintsLoadCommand() const {
2267 if (LinkOptHintsLoadCmd)
2268 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2269
2270 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2271 // fields.
2272 MachO::linkedit_data_command Cmd;
2273 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2274 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2275 Cmd.dataoff = 0;
2276 Cmd.datasize = 0;
2277 return Cmd;
2278}
2279
Nick Kledzikd04bc352014-08-30 00:20:14 +00002280ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2281 if (!DyldInfoLoadCmd)
2282 return ArrayRef<uint8_t>();
2283
2284 MachO::dyld_info_command DyldInfo
2285 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2286 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2287 getPtr(this, DyldInfo.rebase_off));
2288 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2289}
2290
2291ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2292 if (!DyldInfoLoadCmd)
2293 return ArrayRef<uint8_t>();
2294
2295 MachO::dyld_info_command DyldInfo
2296 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2297 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2298 getPtr(this, DyldInfo.bind_off));
2299 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2300}
2301
2302ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2303 if (!DyldInfoLoadCmd)
2304 return ArrayRef<uint8_t>();
2305
2306 MachO::dyld_info_command DyldInfo
2307 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2308 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2309 getPtr(this, DyldInfo.weak_bind_off));
2310 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2311}
2312
2313ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2314 if (!DyldInfoLoadCmd)
2315 return ArrayRef<uint8_t>();
2316
2317 MachO::dyld_info_command DyldInfo
2318 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2319 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2320 getPtr(this, DyldInfo.lazy_bind_off));
2321 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2322}
2323
2324ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2325 if (!DyldInfoLoadCmd)
2326 return ArrayRef<uint8_t>();
2327
2328 MachO::dyld_info_command DyldInfo
2329 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2330 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2331 getPtr(this, DyldInfo.export_off));
2332 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2333}
2334
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002335ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2336 if (!UuidLoadCmd)
2337 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002338 // Returning a pointer is fine as uuid doesn't need endian swapping.
2339 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2340 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002341}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002342
Rafael Espindola6e040c02013-04-26 20:07:33 +00002343StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002344 MachO::symtab_command S = getSymtabLoadCommand();
2345 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002346}
2347
Rafael Espindola56f976f2013-04-18 18:08:55 +00002348bool MachOObjectFile::is64Bit() const {
2349 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002350 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002351}
2352
2353void MachOObjectFile::ReadULEB128s(uint64_t Index,
2354 SmallVectorImpl<uint64_t> &Out) const {
2355 DataExtractor extractor(ObjectFile::getData(), true, 0);
2356
2357 uint32_t offset = Index;
2358 uint64_t data = 0;
2359 while (uint64_t delta = extractor.getULEB128(&offset)) {
2360 data += delta;
2361 Out.push_back(data);
2362 }
2363}
2364
Rafael Espindolac66d7612014-08-17 19:09:37 +00002365bool MachOObjectFile::isRelocatableObject() const {
2366 return getHeader().filetype == MachO::MH_OBJECT;
2367}
2368
Rafael Espindola437b0d52014-07-31 03:12:45 +00002369ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002370ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2371 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002372 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002373 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002374 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002375 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002376 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002377 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002378 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002379 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002380 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002381 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002382 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002383 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002384
Rafael Espindola692410e2014-01-21 23:06:54 +00002385 if (EC)
2386 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002387 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002388}
2389