blob: 340faa44a311665123e83b8ecf425d9a972c0453 [file] [log] [blame]
Eric Christopher7b015c72011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Anderson27c579d2011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Tim Northover00ed9962014-03-29 10:18:08 +000016#include "llvm/ADT/STLExtras.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000017#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "llvm/ADT/Triple.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000019#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000020#include "llvm/Support/Debug.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000021#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000022#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000023#include "llvm/Support/LEB128.h"
24#include "llvm/Support/MachO.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000025#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000026#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000027#include <cctype>
28#include <cstring>
29#include <limits>
30
31using namespace llvm;
32using namespace object;
33
Artyom Skrobov7d602f72014-07-20 12:08:28 +000034namespace {
35 struct section_base {
36 char sectname[16];
37 char segname[16];
38 };
39}
Rafael Espindola56f976f2013-04-18 18:08:55 +000040
Alexey Samsonov9f336632015-06-04 19:45:22 +000041// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000042template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000043static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000044 // Don't read before the beginning or past the end of the file
45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46 report_fatal_error("Malformed MachO file.");
47
Rafael Espindola3cdeb172013-04-19 13:45:05 +000048 T Cmd;
49 memcpy(&Cmd, P, sizeof(T));
50 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000051 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000052 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000053}
54
Alexey Samsonov9f336632015-06-04 19:45:22 +000055template <typename T>
56static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57 // Don't read before the beginning or past the end of the file
58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59 return object_error::parse_failed;
60
61 T Cmd;
62 memcpy(&Cmd, P, sizeof(T));
63 if (O->isLittleEndian() != sys::IsLittleEndianHost)
64 MachO::swapStruct(Cmd);
65 return Cmd;
66}
67
Rafael Espindola6e040c02013-04-26 20:07:33 +000068static const char *
69getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
70 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000071 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
72
73 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000074 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75 sizeof(MachO::segment_command);
76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000078
79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000080 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000081}
82
Rafael Espindola56f976f2013-04-18 18:08:55 +000083static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000085}
86
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000087static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000088getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000089 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000090 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000091}
92
Rafael Espindola56f976f2013-04-18 18:08:55 +000093static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000094 if (P[15] == 0)
95 // Null terminated.
96 return P;
97 // Not null terminated, so this is a 16 char string.
98 return StringRef(P, 16);
99}
100
Rafael Espindola56f976f2013-04-18 18:08:55 +0000101// Helper to advance a section or symbol iterator multiple increments at a time.
102template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000103static void advance(T &it, size_t Val) {
104 while (Val--)
105 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000106}
107
108static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000109 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000110}
111
Charles Davis8bdfafd2013-09-01 04:28:48 +0000112static uint32_t
113getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
114 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000115}
116
117static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000118getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000120}
121
122static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000123 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000124 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000125 return (RE.r_word1 >> 24) & 1;
126 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000127}
128
129static bool
130getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131 const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000133}
134
135static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000136 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000137 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140}
141
142static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000143getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000145}
146
147static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000148 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000149 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152}
153
Rafael Espindola56f976f2013-04-18 18:08:55 +0000154static uint32_t getSectionFlags(const MachOObjectFile *O,
155 DataRefImpl Sec) {
156 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000157 MachO::section_64 Sect = O->getSection64(Sec);
158 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000160 MachO::section Sect = O->getSection(Sec);
161 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000162}
163
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000164static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000165getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
167 if (!CmdOrErr)
168 return CmdOrErr.getError();
169 if (CmdOrErr->cmdsize < 8)
170 return object_error::macho_small_load_command;
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000171 MachOObjectFile::LoadCommandInfo Load;
172 Load.Ptr = Ptr;
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000173 Load.C = CmdOrErr.get();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000174 return Load;
175}
176
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000177static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000178getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180 : sizeof(MachO::mach_header);
181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
182}
183
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000184static ErrorOr<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000185getNextLoadCommandInfo(const MachOObjectFile *Obj,
186 const MachOObjectFile::LoadCommandInfo &L) {
187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
188}
189
Alexey Samsonov9f336632015-06-04 19:45:22 +0000190template <typename T>
191static void parseHeader(const MachOObjectFile *Obj, T &Header,
192 std::error_code &EC) {
193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
194 if (HeaderOrErr)
195 Header = HeaderOrErr.get();
196 else
197 EC = HeaderOrErr.getError();
198}
199
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000200// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201// sections to \param Sections, and optionally sets
202// \param IsPageZeroSegment to true.
203template <typename SegmentCmd>
204static std::error_code parseSegmentLoadCommand(
205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208 if (Load.C.cmdsize < SegmentLoadSize)
209 return object_error::macho_load_segment_too_small;
Alexey Samsonovf8a7bf82015-06-04 22:26:44 +0000210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
211 if (!SegOrErr)
212 return SegOrErr.getError();
213 SegmentCmd S = SegOrErr.get();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000214 const unsigned SectionSize =
215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218 return object_error::macho_load_segment_too_many_sections;
219 for (unsigned J = 0; J < S.nsects; ++J) {
220 const char *Sec = getSectionPtr(Obj, Load, J);
221 Sections.push_back(Sec);
222 }
223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
Rui Ueyama7d099192015-06-09 15:20:42 +0000224 return std::error_code();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000225}
226
Rafael Espindola48af1c22014-08-19 18:44:46 +0000227MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000234 if (is64Bit())
Alexey Samsonov9f336632015-06-04 19:45:22 +0000235 parseHeader(this, Header64, EC);
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000236 else
Alexey Samsonovfa5edc52015-06-04 22:49:55 +0000237 parseHeader(this, Header, EC);
Alexey Samsonov9f336632015-06-04 19:45:22 +0000238 if (EC)
239 return;
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000240
241 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000242 if (LoadCommandCount == 0)
243 return;
244
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000245 auto LoadOrErr = getFirstLoadCommandInfo(this);
246 if (!LoadOrErr) {
247 EC = LoadOrErr.getError();
248 return;
249 }
250 LoadCommandInfo Load = LoadOrErr.get();
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000253 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000254 // Multiple symbol tables
255 if (SymtabLoadCmd) {
256 EC = object_error::parse_failed;
257 return;
258 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000259 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
264 return;
265 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000266 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
271 return;
272 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000273 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
278 return;
279 }
280 LinkOptHintsLoadCmd = Load.Ptr;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
286 return;
287 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000288 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000289 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000290 // Multiple UUID load commands
291 if (UuidLoadCmd) {
292 EC = object_error::parse_failed;
293 return;
294 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000295 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000299 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000303 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000310 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
313 if (!LoadOrErr) {
314 EC = LoadOrErr.getError();
315 return;
316 }
317 Load = LoadOrErr.get();
318 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000319 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000320 if (!SymtabLoadCmd) {
321 if (DysymtabLoadCmd) {
322 // Diagnostic("truncated or malformed object (contains LC_DYSYMTAB load "
323 // "command without a LC_SYMTAB load command)");
324 EC = object_error::parse_failed;
325 return;
326 }
327 } else if (DysymtabLoadCmd) {
328 MachO::symtab_command Symtab =
329 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
330 MachO::dysymtab_command Dysymtab =
331 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
332 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
333 // Diagnostic("truncated or malformed object (ilocalsym in LC_DYSYMTAB "
334 // "load command extends past the end of the symbol table)"
335 EC = object_error::parse_failed;
336 return;
337 }
338 uint64_t big_size = Dysymtab.ilocalsym;
339 big_size += Dysymtab.nlocalsym;
340 if (Dysymtab.nlocalsym != 0 && big_size > Symtab.nsyms) {
341 // Diagnostic("truncated or malformed object (ilocalsym plus nlocalsym "
342 // "in LC_DYSYMTAB load command extends past the end of the symbol table)"
343 EC = object_error::parse_failed;
344 return;
345 }
346 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
347 // Diagnostic("truncated or malformed object (nextdefsym in LC_DYSYMTAB "
348 // "load command extends past the end of the symbol table)"
349 EC = object_error::parse_failed;
350 return;
351 }
352 big_size = Dysymtab.iextdefsym;
353 big_size += Dysymtab.nextdefsym;
354 if (Dysymtab.nextdefsym != 0 && big_size > Symtab.nsyms) {
355 // Diagnostic("truncated or malformed object (iextdefsym plus nextdefsym "
356 // "in LC_DYSYMTAB load command extends past the end of the symbol table)"
357 EC = object_error::parse_failed;
358 return;
359 }
360 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
361 // Diagnostic("truncated or malformed object (nundefsym in LC_DYSYMTAB "
362 // "load command extends past the end of the symbol table)"
363 EC = object_error::parse_failed;
364 return;
365 }
366 big_size = Dysymtab.iundefsym;
367 big_size += Dysymtab.nundefsym;
368 if (Dysymtab.nundefsym != 0 && big_size > Symtab.nsyms) {
369 // Diagnostic("truncated or malformed object (iundefsym plus nundefsym "
370 // "in LC_DYSYMTAB load command extends past the end of the symbol table)"
371 EC = object_error::parse_failed;
372 return;
373 }
374 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000375 assert(LoadCommands.size() == LoadCommandCount);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000376}
377
Rafael Espindola5e812af2014-01-30 02:49:50 +0000378void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000379 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000380 sizeof(MachO::nlist_64) :
381 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000382 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000383}
384
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000385ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000386 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000387 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000388 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000389 if (Start < getData().begin() || Start >= getData().end())
Kevin Enderbyf681ec52016-01-22 18:47:14 +0000390 return object_error::parse_failed;
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000391 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000392}
393
Rafael Espindola0e77a942014-12-10 20:46:55 +0000394unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
395 DataRefImpl DRI = Sec.getRawDataRefImpl();
396 uint32_t Flags = getSectionFlags(this, DRI);
397 return Flags & MachO::SECTION_TYPE;
398}
399
Rafael Espindola59128922015-06-24 18:14:41 +0000400uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
401 if (is64Bit()) {
402 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
403 return Entry.n_value;
404 }
405 MachO::nlist Entry = getSymbolTableEntry(Sym);
406 return Entry.n_value;
407}
408
Kevin Enderby980b2582014-06-05 21:21:57 +0000409// getIndirectName() returns the name of the alias'ed symbol who's string table
410// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000411std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
412 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000413 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000414 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
415 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
416 return object_error::parse_failed;
417 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000418 if (NValue >= StringTable.size())
419 return object_error::parse_failed;
420 const char *Start = &StringTable.data()[NValue];
421 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000422 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000423}
424
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000425uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000426 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000427}
428
Rafael Espindolaed067c42015-07-03 18:19:00 +0000429ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
430 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000431}
432
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000433uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000434 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000435 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000436 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000437 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000438 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000439 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000440}
441
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000442uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000443 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000444}
445
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000446ErrorOr<SymbolRef::Type>
447MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000448 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000449 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000450
Rafael Espindola56f976f2013-04-18 18:08:55 +0000451 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000452 if (n_type & MachO::N_STAB)
453 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000454
Charles Davis74ec8b02013-08-27 05:00:13 +0000455 switch (n_type & MachO::N_TYPE) {
456 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000457 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000458 case MachO::N_SECT :
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000459 ErrorOr<section_iterator> SecOrError = getSymbolSection(Symb);
460 if (!SecOrError)
461 return SecOrError.getError();
462 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000463 if (Sec->isData() || Sec->isBSS())
464 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000465 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000466 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000467 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000468}
469
Rafael Espindola20122a42014-01-31 20:57:12 +0000470uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000471 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000472
Charles Davis8bdfafd2013-09-01 04:28:48 +0000473 uint8_t MachOType = Entry.n_type;
474 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000475
Rafael Espindola20122a42014-01-31 20:57:12 +0000476 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000477
Tim Northovereaef0742014-05-30 13:22:59 +0000478 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
479 Result |= SymbolRef::SF_Indirect;
480
Rafael Espindolaa1356322013-11-02 05:03:24 +0000481 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000482 Result |= SymbolRef::SF_FormatSpecific;
483
Charles Davis74ec8b02013-08-27 05:00:13 +0000484 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000485 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000486 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000487 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000488 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000489 else
490 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000491 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000492
493 if (!(MachOType & MachO::N_PEXT))
494 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000495 }
496
Charles Davis74ec8b02013-08-27 05:00:13 +0000497 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000498 Result |= SymbolRef::SF_Weak;
499
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000500 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
501 Result |= SymbolRef::SF_Thumb;
502
Charles Davis74ec8b02013-08-27 05:00:13 +0000503 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000504 Result |= SymbolRef::SF_Absolute;
505
Rafael Espindola20122a42014-01-31 20:57:12 +0000506 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000507}
508
Rafael Espindola8bab8892015-08-07 23:27:14 +0000509ErrorOr<section_iterator>
510MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000511 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000512 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000513
Rafael Espindola8bab8892015-08-07 23:27:14 +0000514 if (index == 0)
515 return section_end();
516 DataRefImpl DRI;
517 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000518 if (DRI.d.a >= Sections.size()){
519 // Diagnostic("bad section index (" + index + ") for symbol at index " +
520 // SymbolIndex);
Kevin Enderby1f472ea2016-01-21 21:13:27 +0000521 return object_error::parse_failed;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000522 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000523 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000524}
525
Rafael Espindola6bf32212015-06-24 19:57:32 +0000526unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
527 MachO::nlist_base Entry =
528 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
529 return Entry.n_sect - 1;
530}
531
Rafael Espindola5e812af2014-01-30 02:49:50 +0000532void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000533 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000534}
535
Rafael Espindola3acea392014-06-12 21:46:39 +0000536std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
537 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000538 ArrayRef<char> Raw = getSectionRawName(Sec);
539 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000540 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000541}
542
Rafael Espindola80291272014-10-08 15:28:58 +0000543uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
544 if (is64Bit())
545 return getSection64(Sec).addr;
546 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000547}
548
Rafael Espindola80291272014-10-08 15:28:58 +0000549uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000550 // In the case if a malformed Mach-O file where the section offset is past
551 // the end of the file or some part of the section size is past the end of
552 // the file return a size of zero or a size that covers the rest of the file
553 // but does not extend past the end of the file.
554 uint32_t SectOffset, SectType;
555 uint64_t SectSize;
556
557 if (is64Bit()) {
558 MachO::section_64 Sect = getSection64(Sec);
559 SectOffset = Sect.offset;
560 SectSize = Sect.size;
561 SectType = Sect.flags & MachO::SECTION_TYPE;
562 } else {
563 MachO::section Sect = getSection(Sec);
564 SectOffset = Sect.offset;
565 SectSize = Sect.size;
566 SectType = Sect.flags & MachO::SECTION_TYPE;
567 }
568 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
569 return SectSize;
570 uint64_t FileSize = getData().size();
571 if (SectOffset > FileSize)
572 return 0;
573 if (FileSize - SectOffset < SectSize)
574 return FileSize - SectOffset;
575 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000576}
577
Rafael Espindola3acea392014-06-12 21:46:39 +0000578std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
579 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000580 uint32_t Offset;
581 uint64_t Size;
582
583 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000584 MachO::section_64 Sect = getSection64(Sec);
585 Offset = Sect.offset;
586 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000587 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000588 MachO::section Sect = getSection(Sec);
589 Offset = Sect.offset;
590 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000591 }
592
593 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000594 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000595}
596
Rafael Espindola80291272014-10-08 15:28:58 +0000597uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000598 uint32_t Align;
599 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000600 MachO::section_64 Sect = getSection64(Sec);
601 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000602 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000603 MachO::section Sect = getSection(Sec);
604 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000605 }
606
Rafael Espindola80291272014-10-08 15:28:58 +0000607 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000608}
609
Rafael Espindola80291272014-10-08 15:28:58 +0000610bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000611 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000612 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000613}
614
Rafael Espindola80291272014-10-08 15:28:58 +0000615bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000616 uint32_t Flags = getSectionFlags(this, Sec);
617 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000618 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
619 !(SectionType == MachO::S_ZEROFILL ||
620 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000621}
622
Rafael Espindola80291272014-10-08 15:28:58 +0000623bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000624 uint32_t Flags = getSectionFlags(this, Sec);
625 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000626 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
627 (SectionType == MachO::S_ZEROFILL ||
628 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000629}
630
Rafael Espindola6bf32212015-06-24 19:57:32 +0000631unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
632 return Sec.getRawDataRefImpl().d.a;
633}
634
Rafael Espindola80291272014-10-08 15:28:58 +0000635bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000636 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000637 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000638}
639
Steven Wuf2fe0142016-02-29 19:40:10 +0000640bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
641 StringRef SegmentName = getSectionFinalSegmentName(Sec);
642 StringRef SectName;
643 if (!getSectionName(Sec, SectName))
644 return (SegmentName == "__LLVM" && SectName == "__bitcode");
645 return false;
646}
647
Rui Ueyamabc654b12013-09-27 21:47:05 +0000648relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000649 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000650 Ret.d.a = Sec.d.a;
651 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000652 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000653}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000654
Rafael Espindola56f976f2013-04-18 18:08:55 +0000655relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000656MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000657 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000658 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000659 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000660 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000661 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000662 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000663 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000664 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000665
Rafael Espindola56f976f2013-04-18 18:08:55 +0000666 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000667 Ret.d.a = Sec.d.a;
668 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000669 return relocation_iterator(RelocationRef(Ret, this));
670}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000671
Rafael Espindola5e812af2014-01-30 02:49:50 +0000672void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000673 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000674}
Owen Anderson171f4852011-10-24 23:20:07 +0000675
Rafael Espindola96d071c2015-06-29 23:29:12 +0000676uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000677 assert(getHeader().filetype == MachO::MH_OBJECT &&
678 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000679 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000680 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000681}
682
Rafael Espindola806f0062013-06-05 01:33:53 +0000683symbol_iterator
684MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000685 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000686 if (isRelocationScattered(RE))
687 return symbol_end();
688
Rafael Espindola56f976f2013-04-18 18:08:55 +0000689 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
690 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000691 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000692 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000693
Charles Davis8bdfafd2013-09-01 04:28:48 +0000694 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000695 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000696 sizeof(MachO::nlist_64) :
697 sizeof(MachO::nlist);
698 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000699 DataRefImpl Sym;
700 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000701 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000702}
703
Keno Fischerc780e8e2015-05-21 21:24:32 +0000704section_iterator
705MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
706 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
707}
708
Rafael Espindola99c041b2015-06-30 01:53:01 +0000709uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000710 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000711 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000712}
713
Rafael Espindola41bb4322015-06-30 04:08:37 +0000714void MachOObjectFile::getRelocationTypeName(
715 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000716 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000717 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000718
719 unsigned Arch = this->getArch();
720
721 switch (Arch) {
722 case Triple::x86: {
723 static const char *const Table[] = {
724 "GENERIC_RELOC_VANILLA",
725 "GENERIC_RELOC_PAIR",
726 "GENERIC_RELOC_SECTDIFF",
727 "GENERIC_RELOC_PB_LA_PTR",
728 "GENERIC_RELOC_LOCAL_SECTDIFF",
729 "GENERIC_RELOC_TLV" };
730
Eric Christopher13250cb2013-12-06 02:33:38 +0000731 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000732 res = "Unknown";
733 else
734 res = Table[RType];
735 break;
736 }
737 case Triple::x86_64: {
738 static const char *const Table[] = {
739 "X86_64_RELOC_UNSIGNED",
740 "X86_64_RELOC_SIGNED",
741 "X86_64_RELOC_BRANCH",
742 "X86_64_RELOC_GOT_LOAD",
743 "X86_64_RELOC_GOT",
744 "X86_64_RELOC_SUBTRACTOR",
745 "X86_64_RELOC_SIGNED_1",
746 "X86_64_RELOC_SIGNED_2",
747 "X86_64_RELOC_SIGNED_4",
748 "X86_64_RELOC_TLV" };
749
750 if (RType > 9)
751 res = "Unknown";
752 else
753 res = Table[RType];
754 break;
755 }
756 case Triple::arm: {
757 static const char *const Table[] = {
758 "ARM_RELOC_VANILLA",
759 "ARM_RELOC_PAIR",
760 "ARM_RELOC_SECTDIFF",
761 "ARM_RELOC_LOCAL_SECTDIFF",
762 "ARM_RELOC_PB_LA_PTR",
763 "ARM_RELOC_BR24",
764 "ARM_THUMB_RELOC_BR22",
765 "ARM_THUMB_32BIT_BRANCH",
766 "ARM_RELOC_HALF",
767 "ARM_RELOC_HALF_SECTDIFF" };
768
769 if (RType > 9)
770 res = "Unknown";
771 else
772 res = Table[RType];
773 break;
774 }
Tim Northover00ed9962014-03-29 10:18:08 +0000775 case Triple::aarch64: {
776 static const char *const Table[] = {
777 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
778 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
779 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
780 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
781 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
782 "ARM64_RELOC_ADDEND"
783 };
784
785 if (RType >= array_lengthof(Table))
786 res = "Unknown";
787 else
788 res = Table[RType];
789 break;
790 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000791 case Triple::ppc: {
792 static const char *const Table[] = {
793 "PPC_RELOC_VANILLA",
794 "PPC_RELOC_PAIR",
795 "PPC_RELOC_BR14",
796 "PPC_RELOC_BR24",
797 "PPC_RELOC_HI16",
798 "PPC_RELOC_LO16",
799 "PPC_RELOC_HA16",
800 "PPC_RELOC_LO14",
801 "PPC_RELOC_SECTDIFF",
802 "PPC_RELOC_PB_LA_PTR",
803 "PPC_RELOC_HI16_SECTDIFF",
804 "PPC_RELOC_LO16_SECTDIFF",
805 "PPC_RELOC_HA16_SECTDIFF",
806 "PPC_RELOC_JBSR",
807 "PPC_RELOC_LO14_SECTDIFF",
808 "PPC_RELOC_LOCAL_SECTDIFF" };
809
Eric Christopher13250cb2013-12-06 02:33:38 +0000810 if (RType > 15)
811 res = "Unknown";
812 else
813 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000814 break;
815 }
816 case Triple::UnknownArch:
817 res = "Unknown";
818 break;
819 }
820 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000821}
822
Keno Fischer281b6942015-05-30 19:44:53 +0000823uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
824 MachO::any_relocation_info RE = getRelocation(Rel);
825 return getAnyRelocationLength(RE);
826}
827
Kevin Enderby980b2582014-06-05 21:21:57 +0000828//
829// guessLibraryShortName() is passed a name of a dynamic library and returns a
830// guess on what the short name is. Then name is returned as a substring of the
831// StringRef Name passed in. The name of the dynamic library is recognized as
832// a framework if it has one of the two following forms:
833// Foo.framework/Versions/A/Foo
834// Foo.framework/Foo
835// Where A and Foo can be any string. And may contain a trailing suffix
836// starting with an underbar. If the Name is recognized as a framework then
837// isFramework is set to true else it is set to false. If the Name has a
838// suffix then Suffix is set to the substring in Name that contains the suffix
839// else it is set to a NULL StringRef.
840//
841// The Name of the dynamic library is recognized as a library name if it has
842// one of the two following forms:
843// libFoo.A.dylib
844// libFoo.dylib
845// The library may have a suffix trailing the name Foo of the form:
846// libFoo_profile.A.dylib
847// libFoo_profile.dylib
848//
849// The Name of the dynamic library is also recognized as a library name if it
850// has the following form:
851// Foo.qtx
852//
853// If the Name of the dynamic library is none of the forms above then a NULL
854// StringRef is returned.
855//
856StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
857 bool &isFramework,
858 StringRef &Suffix) {
859 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
860 size_t a, b, c, d, Idx;
861
862 isFramework = false;
863 Suffix = StringRef();
864
865 // Pull off the last component and make Foo point to it
866 a = Name.rfind('/');
867 if (a == Name.npos || a == 0)
868 goto guess_library;
869 Foo = Name.slice(a+1, Name.npos);
870
871 // Look for a suffix starting with a '_'
872 Idx = Foo.rfind('_');
873 if (Idx != Foo.npos && Foo.size() >= 2) {
874 Suffix = Foo.slice(Idx, Foo.npos);
875 Foo = Foo.slice(0, Idx);
876 }
877
878 // First look for the form Foo.framework/Foo
879 b = Name.rfind('/', a);
880 if (b == Name.npos)
881 Idx = 0;
882 else
883 Idx = b+1;
884 F = Name.slice(Idx, Idx + Foo.size());
885 DotFramework = Name.slice(Idx + Foo.size(),
886 Idx + Foo.size() + sizeof(".framework/")-1);
887 if (F == Foo && DotFramework == ".framework/") {
888 isFramework = true;
889 return Foo;
890 }
891
892 // Next look for the form Foo.framework/Versions/A/Foo
893 if (b == Name.npos)
894 goto guess_library;
895 c = Name.rfind('/', b);
896 if (c == Name.npos || c == 0)
897 goto guess_library;
898 V = Name.slice(c+1, Name.npos);
899 if (!V.startswith("Versions/"))
900 goto guess_library;
901 d = Name.rfind('/', c);
902 if (d == Name.npos)
903 Idx = 0;
904 else
905 Idx = d+1;
906 F = Name.slice(Idx, Idx + Foo.size());
907 DotFramework = Name.slice(Idx + Foo.size(),
908 Idx + Foo.size() + sizeof(".framework/")-1);
909 if (F == Foo && DotFramework == ".framework/") {
910 isFramework = true;
911 return Foo;
912 }
913
914guess_library:
915 // pull off the suffix after the "." and make a point to it
916 a = Name.rfind('.');
917 if (a == Name.npos || a == 0)
918 return StringRef();
919 Dylib = Name.slice(a, Name.npos);
920 if (Dylib != ".dylib")
921 goto guess_qtx;
922
923 // First pull off the version letter for the form Foo.A.dylib if any.
924 if (a >= 3) {
925 Dot = Name.slice(a-2, a-1);
926 if (Dot == ".")
927 a = a - 2;
928 }
929
930 b = Name.rfind('/', a);
931 if (b == Name.npos)
932 b = 0;
933 else
934 b = b+1;
935 // ignore any suffix after an underbar like Foo_profile.A.dylib
936 Idx = Name.find('_', b);
937 if (Idx != Name.npos && Idx != b) {
938 Lib = Name.slice(b, Idx);
939 Suffix = Name.slice(Idx, a);
940 }
941 else
942 Lib = Name.slice(b, a);
943 // There are incorrect library names of the form:
944 // libATS.A_profile.dylib so check for these.
945 if (Lib.size() >= 3) {
946 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
947 if (Dot == ".")
948 Lib = Lib.slice(0, Lib.size()-2);
949 }
950 return Lib;
951
952guess_qtx:
953 Qtx = Name.slice(a, Name.npos);
954 if (Qtx != ".qtx")
955 return StringRef();
956 b = Name.rfind('/', a);
957 if (b == Name.npos)
958 Lib = Name.slice(0, a);
959 else
960 Lib = Name.slice(b+1, a);
961 // There are library names of the form: QT.A.qtx so check for these.
962 if (Lib.size() >= 3) {
963 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
964 if (Dot == ".")
965 Lib = Lib.slice(0, Lib.size()-2);
966 }
967 return Lib;
968}
969
970// getLibraryShortNameByIndex() is used to get the short name of the library
971// for an undefined symbol in a linked Mach-O binary that was linked with the
972// normal two-level namespace default (that is MH_TWOLEVEL in the header).
973// It is passed the index (0 - based) of the library as translated from
974// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +0000975std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +0000976 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000977 if (Index >= Libraries.size())
978 return object_error::parse_failed;
979
Kevin Enderby980b2582014-06-05 21:21:57 +0000980 // If the cache of LibrariesShortNames is not built up do that first for
981 // all the Libraries.
982 if (LibrariesShortNames.size() == 0) {
983 for (unsigned i = 0; i < Libraries.size(); i++) {
984 MachO::dylib_command D =
985 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +0000986 if (D.dylib.name >= D.cmdsize)
987 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +0000988 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +0000989 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +0000990 if (D.dylib.name+Name.size() >= D.cmdsize)
991 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +0000992 StringRef Suffix;
993 bool isFramework;
994 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +0000995 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +0000996 LibrariesShortNames.push_back(Name);
997 else
998 LibrariesShortNames.push_back(shortName);
999 }
1000 }
1001
1002 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001003 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001004}
1005
Rafael Espindola76ad2322015-07-06 14:55:37 +00001006section_iterator
1007MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1008 DataRefImpl Sec;
1009 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1010 return section_iterator(SectionRef(Sec, this));
1011}
1012
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001013basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001014 DataRefImpl DRI;
1015 MachO::symtab_command Symtab = getSymtabLoadCommand();
1016 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1017 return basic_symbol_iterator(SymbolRef(DRI, this));
1018
Lang Hames36072da2014-05-12 21:39:59 +00001019 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001020}
1021
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001022basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001023 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001024 MachO::symtab_command Symtab = getSymtabLoadCommand();
1025 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001026 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001027
Rafael Espindola75c30362013-04-24 19:47:55 +00001028 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001029 sizeof(MachO::nlist_64) :
1030 sizeof(MachO::nlist);
1031 unsigned Offset = Symtab.symoff +
1032 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001033 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001034 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001035}
1036
Lang Hames36072da2014-05-12 21:39:59 +00001037basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001038 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001039 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001040 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001041 unsigned SymbolTableEntrySize =
1042 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001043 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001044 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1045 DRI.p += Index * SymbolTableEntrySize;
1046 return basic_symbol_iterator(SymbolRef(DRI, this));
1047}
1048
Rafael Espindolab5155a52014-02-10 20:24:04 +00001049section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001050 DataRefImpl DRI;
1051 return section_iterator(SectionRef(DRI, this));
1052}
1053
Rafael Espindolab5155a52014-02-10 20:24:04 +00001054section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001055 DataRefImpl DRI;
1056 DRI.d.a = Sections.size();
1057 return section_iterator(SectionRef(DRI, this));
1058}
1059
Rafael Espindola56f976f2013-04-18 18:08:55 +00001060uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001061 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001062}
1063
Rafael Espindola56f976f2013-04-18 18:08:55 +00001064StringRef MachOObjectFile::getFileFormatName() const {
1065 unsigned CPUType = getCPUType(this);
1066 if (!is64Bit()) {
1067 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001068 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001069 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001070 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001071 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001072 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001073 return "Mach-O 32-bit ppc";
1074 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001075 return "Mach-O 32-bit unknown";
1076 }
1077 }
1078
Rafael Espindola56f976f2013-04-18 18:08:55 +00001079 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001080 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001081 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001082 case llvm::MachO::CPU_TYPE_ARM64:
1083 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001084 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001085 return "Mach-O 64-bit ppc64";
1086 default:
1087 return "Mach-O 64-bit unknown";
1088 }
1089}
1090
Alexey Samsonove6388e62013-06-18 15:03:28 +00001091Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1092 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001093 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001094 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001095 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001096 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001097 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001098 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001099 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001100 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001101 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001102 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001103 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001104 return Triple::ppc64;
1105 default:
1106 return Triple::UnknownArch;
1107 }
1108}
1109
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001110Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1111 const char **McpuDefault) {
1112 if (McpuDefault)
1113 *McpuDefault = nullptr;
1114
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001115 switch (CPUType) {
1116 case MachO::CPU_TYPE_I386:
1117 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1118 case MachO::CPU_SUBTYPE_I386_ALL:
1119 return Triple("i386-apple-darwin");
1120 default:
1121 return Triple();
1122 }
1123 case MachO::CPU_TYPE_X86_64:
1124 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1125 case MachO::CPU_SUBTYPE_X86_64_ALL:
1126 return Triple("x86_64-apple-darwin");
1127 case MachO::CPU_SUBTYPE_X86_64_H:
1128 return Triple("x86_64h-apple-darwin");
1129 default:
1130 return Triple();
1131 }
1132 case MachO::CPU_TYPE_ARM:
1133 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1134 case MachO::CPU_SUBTYPE_ARM_V4T:
1135 return Triple("armv4t-apple-darwin");
1136 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1137 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001138 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1139 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001140 case MachO::CPU_SUBTYPE_ARM_V6:
1141 return Triple("armv6-apple-darwin");
1142 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001143 if (McpuDefault)
1144 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001145 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001146 case MachO::CPU_SUBTYPE_ARM_V7:
1147 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001148 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001149 if (McpuDefault)
1150 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001151 return Triple("armv7em-apple-darwin");
1152 case MachO::CPU_SUBTYPE_ARM_V7K:
1153 return Triple("armv7k-apple-darwin");
1154 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001155 if (McpuDefault)
1156 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001157 return Triple("armv7m-apple-darwin");
1158 case MachO::CPU_SUBTYPE_ARM_V7S:
1159 return Triple("armv7s-apple-darwin");
1160 default:
1161 return Triple();
1162 }
1163 case MachO::CPU_TYPE_ARM64:
1164 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1165 case MachO::CPU_SUBTYPE_ARM64_ALL:
1166 return Triple("arm64-apple-darwin");
1167 default:
1168 return Triple();
1169 }
1170 case MachO::CPU_TYPE_POWERPC:
1171 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1172 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1173 return Triple("ppc-apple-darwin");
1174 default:
1175 return Triple();
1176 }
1177 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001178 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001179 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1180 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001181 default:
1182 return Triple();
1183 }
1184 default:
1185 return Triple();
1186 }
1187}
1188
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001189Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1190 const char **McpuDefault) {
1191 if (McpuDefault)
1192 *McpuDefault = nullptr;
1193
1194 switch (CPUType) {
1195 case MachO::CPU_TYPE_ARM:
1196 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1197 case MachO::CPU_SUBTYPE_ARM_V4T:
1198 return Triple("thumbv4t-apple-darwin");
1199 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1200 return Triple("thumbv5e-apple-darwin");
1201 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1202 return Triple("xscale-apple-darwin");
1203 case MachO::CPU_SUBTYPE_ARM_V6:
1204 return Triple("thumbv6-apple-darwin");
1205 case MachO::CPU_SUBTYPE_ARM_V6M:
1206 if (McpuDefault)
1207 *McpuDefault = "cortex-m0";
1208 return Triple("thumbv6m-apple-darwin");
1209 case MachO::CPU_SUBTYPE_ARM_V7:
1210 return Triple("thumbv7-apple-darwin");
1211 case MachO::CPU_SUBTYPE_ARM_V7EM:
1212 if (McpuDefault)
1213 *McpuDefault = "cortex-m4";
1214 return Triple("thumbv7em-apple-darwin");
1215 case MachO::CPU_SUBTYPE_ARM_V7K:
1216 return Triple("thumbv7k-apple-darwin");
1217 case MachO::CPU_SUBTYPE_ARM_V7M:
1218 if (McpuDefault)
1219 *McpuDefault = "cortex-m3";
1220 return Triple("thumbv7m-apple-darwin");
1221 case MachO::CPU_SUBTYPE_ARM_V7S:
1222 return Triple("thumbv7s-apple-darwin");
1223 default:
1224 return Triple();
1225 }
1226 default:
1227 return Triple();
1228 }
1229}
1230
1231Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
NAKAMURA Takumi0a7d0ad2015-09-22 11:15:07 +00001232 const char **McpuDefault, Triple *ThumbTriple) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001233 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1234 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1235 McpuDefault);
1236 return T;
1237}
1238
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001239Triple MachOObjectFile::getHostArch() {
1240 return Triple(sys::getDefaultTargetTriple());
1241}
1242
Rafael Espindola72318b42014-08-08 16:30:17 +00001243bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1244 return StringSwitch<bool>(ArchFlag)
1245 .Case("i386", true)
1246 .Case("x86_64", true)
1247 .Case("x86_64h", true)
1248 .Case("armv4t", true)
1249 .Case("arm", true)
1250 .Case("armv5e", true)
1251 .Case("armv6", true)
1252 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001253 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001254 .Case("armv7em", true)
1255 .Case("armv7k", true)
1256 .Case("armv7m", true)
1257 .Case("armv7s", true)
1258 .Case("arm64", true)
1259 .Case("ppc", true)
1260 .Case("ppc64", true)
1261 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001262}
1263
Alexey Samsonove6388e62013-06-18 15:03:28 +00001264unsigned MachOObjectFile::getArch() const {
1265 return getArch(getCPUType(this));
1266}
1267
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001268Triple MachOObjectFile::getArch(const char **McpuDefault,
1269 Triple *ThumbTriple) const {
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001270 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1271 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001272}
1273
Rui Ueyamabc654b12013-09-27 21:47:05 +00001274relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001275 DataRefImpl DRI;
1276 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001277 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001278}
1279
Rui Ueyamabc654b12013-09-27 21:47:05 +00001280relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001281 DataRefImpl DRI;
1282 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001283 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001284}
1285
Kevin Enderby273ae012013-06-06 17:20:50 +00001286dice_iterator MachOObjectFile::begin_dices() const {
1287 DataRefImpl DRI;
1288 if (!DataInCodeLoadCmd)
1289 return dice_iterator(DiceRef(DRI, this));
1290
Charles Davis8bdfafd2013-09-01 04:28:48 +00001291 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1292 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001293 return dice_iterator(DiceRef(DRI, this));
1294}
1295
1296dice_iterator MachOObjectFile::end_dices() const {
1297 DataRefImpl DRI;
1298 if (!DataInCodeLoadCmd)
1299 return dice_iterator(DiceRef(DRI, this));
1300
Charles Davis8bdfafd2013-09-01 04:28:48 +00001301 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1302 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001303 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1304 return dice_iterator(DiceRef(DRI, this));
1305}
1306
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001307ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1308 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001309
1310void ExportEntry::moveToFirst() {
1311 pushNode(0);
1312 pushDownUntilBottom();
1313}
1314
1315void ExportEntry::moveToEnd() {
1316 Stack.clear();
1317 Done = true;
1318}
1319
1320bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001321 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001322 if (Done || Other.Done)
1323 return (Done == Other.Done);
1324 // Not equal if different stack sizes.
1325 if (Stack.size() != Other.Stack.size())
1326 return false;
1327 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001328 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001329 return false;
1330 // Equal if all nodes in both stacks match.
1331 for (unsigned i=0; i < Stack.size(); ++i) {
1332 if (Stack[i].Start != Other.Stack[i].Start)
1333 return false;
1334 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001335 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001336}
1337
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001338uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1339 unsigned Count;
1340 uint64_t Result = decodeULEB128(Ptr, &Count);
1341 Ptr += Count;
1342 if (Ptr > Trie.end()) {
1343 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001344 Malformed = true;
1345 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001346 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001347}
1348
1349StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001350 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001351}
1352
1353uint64_t ExportEntry::flags() const {
1354 return Stack.back().Flags;
1355}
1356
1357uint64_t ExportEntry::address() const {
1358 return Stack.back().Address;
1359}
1360
1361uint64_t ExportEntry::other() const {
1362 return Stack.back().Other;
1363}
1364
1365StringRef ExportEntry::otherName() const {
1366 const char* ImportName = Stack.back().ImportName;
1367 if (ImportName)
1368 return StringRef(ImportName);
1369 return StringRef();
1370}
1371
1372uint32_t ExportEntry::nodeOffset() const {
1373 return Stack.back().Start - Trie.begin();
1374}
1375
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001376ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1377 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1378 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1379 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001380
1381void ExportEntry::pushNode(uint64_t offset) {
1382 const uint8_t *Ptr = Trie.begin() + offset;
1383 NodeState State(Ptr);
1384 uint64_t ExportInfoSize = readULEB128(State.Current);
1385 State.IsExportNode = (ExportInfoSize != 0);
1386 const uint8_t* Children = State.Current + ExportInfoSize;
1387 if (State.IsExportNode) {
1388 State.Flags = readULEB128(State.Current);
1389 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1390 State.Address = 0;
1391 State.Other = readULEB128(State.Current); // dylib ordinal
1392 State.ImportName = reinterpret_cast<const char*>(State.Current);
1393 } else {
1394 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001395 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001396 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001397 }
1398 }
1399 State.ChildCount = *Children;
1400 State.Current = Children + 1;
1401 State.NextChildIndex = 0;
1402 State.ParentStringLength = CumulativeString.size();
1403 Stack.push_back(State);
1404}
1405
1406void ExportEntry::pushDownUntilBottom() {
1407 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1408 NodeState &Top = Stack.back();
1409 CumulativeString.resize(Top.ParentStringLength);
1410 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001411 char C = *Top.Current;
1412 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001413 }
1414 Top.Current += 1;
1415 uint64_t childNodeIndex = readULEB128(Top.Current);
1416 Top.NextChildIndex += 1;
1417 pushNode(childNodeIndex);
1418 }
1419 if (!Stack.back().IsExportNode) {
1420 Malformed = true;
1421 moveToEnd();
1422 }
1423}
1424
1425// We have a trie data structure and need a way to walk it that is compatible
1426// with the C++ iterator model. The solution is a non-recursive depth first
1427// traversal where the iterator contains a stack of parent nodes along with a
1428// string that is the accumulation of all edge strings along the parent chain
1429// to this point.
1430//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001431// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001432// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001433// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001434//
1435// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1436// child until hitting a node with no children (which is an export node or
1437// else the trie is malformed). On the way down, each node is pushed on the
1438// stack ivar. If there is no more ways down, it pops up one and tries to go
1439// down a sibling path until a childless node is reached.
1440void ExportEntry::moveNext() {
1441 if (Stack.empty() || !Stack.back().IsExportNode) {
1442 Malformed = true;
1443 moveToEnd();
1444 return;
1445 }
1446
1447 Stack.pop_back();
1448 while (!Stack.empty()) {
1449 NodeState &Top = Stack.back();
1450 if (Top.NextChildIndex < Top.ChildCount) {
1451 pushDownUntilBottom();
1452 // Now at the next export node.
1453 return;
1454 } else {
1455 if (Top.IsExportNode) {
1456 // This node has no children but is itself an export node.
1457 CumulativeString.resize(Top.ParentStringLength);
1458 return;
1459 }
1460 Stack.pop_back();
1461 }
1462 }
1463 Done = true;
1464}
1465
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001466iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001467MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1468 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001469 if (Trie.size() == 0)
1470 Start.moveToEnd();
1471 else
1472 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001473
1474 ExportEntry Finish(Trie);
1475 Finish.moveToEnd();
1476
Craig Topper15576e12015-12-06 05:08:07 +00001477 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001478}
1479
1480iterator_range<export_iterator> MachOObjectFile::exports() const {
1481 return exports(getDyldInfoExportsTrie());
1482}
1483
Nick Kledzikac431442014-09-12 21:34:15 +00001484MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1485 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1486 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1487 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1488
1489void MachORebaseEntry::moveToFirst() {
1490 Ptr = Opcodes.begin();
1491 moveNext();
1492}
1493
1494void MachORebaseEntry::moveToEnd() {
1495 Ptr = Opcodes.end();
1496 RemainingLoopCount = 0;
1497 Done = true;
1498}
1499
1500void MachORebaseEntry::moveNext() {
1501 // If in the middle of some loop, move to next rebasing in loop.
1502 SegmentOffset += AdvanceAmount;
1503 if (RemainingLoopCount) {
1504 --RemainingLoopCount;
1505 return;
1506 }
1507 if (Ptr == Opcodes.end()) {
1508 Done = true;
1509 return;
1510 }
1511 bool More = true;
1512 while (More && !Malformed) {
1513 // Parse next opcode and set up next loop.
1514 uint8_t Byte = *Ptr++;
1515 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1516 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1517 switch (Opcode) {
1518 case MachO::REBASE_OPCODE_DONE:
1519 More = false;
1520 Done = true;
1521 moveToEnd();
1522 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1523 break;
1524 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1525 RebaseType = ImmValue;
1526 DEBUG_WITH_TYPE(
1527 "mach-o-rebase",
1528 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1529 << "RebaseType=" << (int) RebaseType << "\n");
1530 break;
1531 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1532 SegmentIndex = ImmValue;
1533 SegmentOffset = readULEB128();
1534 DEBUG_WITH_TYPE(
1535 "mach-o-rebase",
1536 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1537 << "SegmentIndex=" << SegmentIndex << ", "
1538 << format("SegmentOffset=0x%06X", SegmentOffset)
1539 << "\n");
1540 break;
1541 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1542 SegmentOffset += readULEB128();
1543 DEBUG_WITH_TYPE("mach-o-rebase",
1544 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1545 << format("SegmentOffset=0x%06X",
1546 SegmentOffset) << "\n");
1547 break;
1548 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1549 SegmentOffset += ImmValue * PointerSize;
1550 DEBUG_WITH_TYPE("mach-o-rebase",
1551 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1552 << format("SegmentOffset=0x%06X",
1553 SegmentOffset) << "\n");
1554 break;
1555 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1556 AdvanceAmount = PointerSize;
1557 RemainingLoopCount = ImmValue - 1;
1558 DEBUG_WITH_TYPE(
1559 "mach-o-rebase",
1560 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1561 << format("SegmentOffset=0x%06X", SegmentOffset)
1562 << ", AdvanceAmount=" << AdvanceAmount
1563 << ", RemainingLoopCount=" << RemainingLoopCount
1564 << "\n");
1565 return;
1566 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1567 AdvanceAmount = PointerSize;
1568 RemainingLoopCount = readULEB128() - 1;
1569 DEBUG_WITH_TYPE(
1570 "mach-o-rebase",
1571 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1572 << format("SegmentOffset=0x%06X", SegmentOffset)
1573 << ", AdvanceAmount=" << AdvanceAmount
1574 << ", RemainingLoopCount=" << RemainingLoopCount
1575 << "\n");
1576 return;
1577 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1578 AdvanceAmount = readULEB128() + PointerSize;
1579 RemainingLoopCount = 0;
1580 DEBUG_WITH_TYPE(
1581 "mach-o-rebase",
1582 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1583 << format("SegmentOffset=0x%06X", SegmentOffset)
1584 << ", AdvanceAmount=" << AdvanceAmount
1585 << ", RemainingLoopCount=" << RemainingLoopCount
1586 << "\n");
1587 return;
1588 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1589 RemainingLoopCount = readULEB128() - 1;
1590 AdvanceAmount = readULEB128() + PointerSize;
1591 DEBUG_WITH_TYPE(
1592 "mach-o-rebase",
1593 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1594 << format("SegmentOffset=0x%06X", SegmentOffset)
1595 << ", AdvanceAmount=" << AdvanceAmount
1596 << ", RemainingLoopCount=" << RemainingLoopCount
1597 << "\n");
1598 return;
1599 default:
1600 Malformed = true;
1601 }
1602 }
1603}
1604
1605uint64_t MachORebaseEntry::readULEB128() {
1606 unsigned Count;
1607 uint64_t Result = decodeULEB128(Ptr, &Count);
1608 Ptr += Count;
1609 if (Ptr > Opcodes.end()) {
1610 Ptr = Opcodes.end();
1611 Malformed = true;
1612 }
1613 return Result;
1614}
1615
1616uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1617
1618uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1619
1620StringRef MachORebaseEntry::typeName() const {
1621 switch (RebaseType) {
1622 case MachO::REBASE_TYPE_POINTER:
1623 return "pointer";
1624 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1625 return "text abs32";
1626 case MachO::REBASE_TYPE_TEXT_PCREL32:
1627 return "text rel32";
1628 }
1629 return "unknown";
1630}
1631
1632bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1633 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1634 return (Ptr == Other.Ptr) &&
1635 (RemainingLoopCount == Other.RemainingLoopCount) &&
1636 (Done == Other.Done);
1637}
1638
1639iterator_range<rebase_iterator>
1640MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1641 MachORebaseEntry Start(Opcodes, is64);
1642 Start.moveToFirst();
1643
1644 MachORebaseEntry Finish(Opcodes, is64);
1645 Finish.moveToEnd();
1646
Craig Topper15576e12015-12-06 05:08:07 +00001647 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001648}
1649
1650iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1651 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1652}
1653
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001654MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001655 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1656 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1657 BindType(0), PointerSize(is64Bit ? 8 : 4),
1658 TableKind(BK), Malformed(false), Done(false) {}
1659
1660void MachOBindEntry::moveToFirst() {
1661 Ptr = Opcodes.begin();
1662 moveNext();
1663}
1664
1665void MachOBindEntry::moveToEnd() {
1666 Ptr = Opcodes.end();
1667 RemainingLoopCount = 0;
1668 Done = true;
1669}
1670
1671void MachOBindEntry::moveNext() {
1672 // If in the middle of some loop, move to next binding in loop.
1673 SegmentOffset += AdvanceAmount;
1674 if (RemainingLoopCount) {
1675 --RemainingLoopCount;
1676 return;
1677 }
1678 if (Ptr == Opcodes.end()) {
1679 Done = true;
1680 return;
1681 }
1682 bool More = true;
1683 while (More && !Malformed) {
1684 // Parse next opcode and set up next loop.
1685 uint8_t Byte = *Ptr++;
1686 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1687 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1688 int8_t SignExtended;
1689 const uint8_t *SymStart;
1690 switch (Opcode) {
1691 case MachO::BIND_OPCODE_DONE:
1692 if (TableKind == Kind::Lazy) {
1693 // Lazying bindings have a DONE opcode between entries. Need to ignore
1694 // it to advance to next entry. But need not if this is last entry.
1695 bool NotLastEntry = false;
1696 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1697 if (*P) {
1698 NotLastEntry = true;
1699 }
1700 }
1701 if (NotLastEntry)
1702 break;
1703 }
1704 More = false;
1705 Done = true;
1706 moveToEnd();
1707 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1708 break;
1709 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1710 Ordinal = ImmValue;
1711 DEBUG_WITH_TYPE(
1712 "mach-o-bind",
1713 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1714 << "Ordinal=" << Ordinal << "\n");
1715 break;
1716 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1717 Ordinal = readULEB128();
1718 DEBUG_WITH_TYPE(
1719 "mach-o-bind",
1720 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1721 << "Ordinal=" << Ordinal << "\n");
1722 break;
1723 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1724 if (ImmValue) {
1725 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1726 Ordinal = SignExtended;
1727 } else
1728 Ordinal = 0;
1729 DEBUG_WITH_TYPE(
1730 "mach-o-bind",
1731 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1732 << "Ordinal=" << Ordinal << "\n");
1733 break;
1734 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1735 Flags = ImmValue;
1736 SymStart = Ptr;
1737 while (*Ptr) {
1738 ++Ptr;
1739 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001740 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1741 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001742 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001743 DEBUG_WITH_TYPE(
1744 "mach-o-bind",
1745 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1746 << "SymbolName=" << SymbolName << "\n");
1747 if (TableKind == Kind::Weak) {
1748 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1749 return;
1750 }
1751 break;
1752 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1753 BindType = ImmValue;
1754 DEBUG_WITH_TYPE(
1755 "mach-o-bind",
1756 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1757 << "BindType=" << (int)BindType << "\n");
1758 break;
1759 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1760 Addend = readSLEB128();
1761 if (TableKind == Kind::Lazy)
1762 Malformed = true;
1763 DEBUG_WITH_TYPE(
1764 "mach-o-bind",
1765 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1766 << "Addend=" << Addend << "\n");
1767 break;
1768 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1769 SegmentIndex = ImmValue;
1770 SegmentOffset = readULEB128();
1771 DEBUG_WITH_TYPE(
1772 "mach-o-bind",
1773 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1774 << "SegmentIndex=" << SegmentIndex << ", "
1775 << format("SegmentOffset=0x%06X", SegmentOffset)
1776 << "\n");
1777 break;
1778 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1779 SegmentOffset += readULEB128();
1780 DEBUG_WITH_TYPE("mach-o-bind",
1781 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1782 << format("SegmentOffset=0x%06X",
1783 SegmentOffset) << "\n");
1784 break;
1785 case MachO::BIND_OPCODE_DO_BIND:
1786 AdvanceAmount = PointerSize;
1787 RemainingLoopCount = 0;
1788 DEBUG_WITH_TYPE("mach-o-bind",
1789 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1790 << format("SegmentOffset=0x%06X",
1791 SegmentOffset) << "\n");
1792 return;
1793 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001794 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001795 RemainingLoopCount = 0;
1796 if (TableKind == Kind::Lazy)
1797 Malformed = true;
1798 DEBUG_WITH_TYPE(
1799 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001800 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001801 << format("SegmentOffset=0x%06X", SegmentOffset)
1802 << ", AdvanceAmount=" << AdvanceAmount
1803 << ", RemainingLoopCount=" << RemainingLoopCount
1804 << "\n");
1805 return;
1806 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001807 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001808 RemainingLoopCount = 0;
1809 if (TableKind == Kind::Lazy)
1810 Malformed = true;
1811 DEBUG_WITH_TYPE("mach-o-bind",
1812 llvm::dbgs()
1813 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1814 << format("SegmentOffset=0x%06X",
1815 SegmentOffset) << "\n");
1816 return;
1817 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1818 RemainingLoopCount = readULEB128() - 1;
1819 AdvanceAmount = readULEB128() + PointerSize;
1820 if (TableKind == Kind::Lazy)
1821 Malformed = true;
1822 DEBUG_WITH_TYPE(
1823 "mach-o-bind",
1824 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1825 << format("SegmentOffset=0x%06X", SegmentOffset)
1826 << ", AdvanceAmount=" << AdvanceAmount
1827 << ", RemainingLoopCount=" << RemainingLoopCount
1828 << "\n");
1829 return;
1830 default:
1831 Malformed = true;
1832 }
1833 }
1834}
1835
1836uint64_t MachOBindEntry::readULEB128() {
1837 unsigned Count;
1838 uint64_t Result = decodeULEB128(Ptr, &Count);
1839 Ptr += Count;
1840 if (Ptr > Opcodes.end()) {
1841 Ptr = Opcodes.end();
1842 Malformed = true;
1843 }
1844 return Result;
1845}
1846
1847int64_t MachOBindEntry::readSLEB128() {
1848 unsigned Count;
1849 int64_t Result = decodeSLEB128(Ptr, &Count);
1850 Ptr += Count;
1851 if (Ptr > Opcodes.end()) {
1852 Ptr = Opcodes.end();
1853 Malformed = true;
1854 }
1855 return Result;
1856}
1857
Nick Kledzik56ebef42014-09-16 01:41:51 +00001858uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1859
1860uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1861
1862StringRef MachOBindEntry::typeName() const {
1863 switch (BindType) {
1864 case MachO::BIND_TYPE_POINTER:
1865 return "pointer";
1866 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1867 return "text abs32";
1868 case MachO::BIND_TYPE_TEXT_PCREL32:
1869 return "text rel32";
1870 }
1871 return "unknown";
1872}
1873
1874StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1875
1876int64_t MachOBindEntry::addend() const { return Addend; }
1877
1878uint32_t MachOBindEntry::flags() const { return Flags; }
1879
1880int MachOBindEntry::ordinal() const { return Ordinal; }
1881
1882bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1883 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1884 return (Ptr == Other.Ptr) &&
1885 (RemainingLoopCount == Other.RemainingLoopCount) &&
1886 (Done == Other.Done);
1887}
1888
1889iterator_range<bind_iterator>
1890MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1891 MachOBindEntry::Kind BKind) {
1892 MachOBindEntry Start(Opcodes, is64, BKind);
1893 Start.moveToFirst();
1894
1895 MachOBindEntry Finish(Opcodes, is64, BKind);
1896 Finish.moveToEnd();
1897
Craig Topper15576e12015-12-06 05:08:07 +00001898 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00001899}
1900
1901iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1902 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1903 MachOBindEntry::Kind::Regular);
1904}
1905
1906iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1907 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1908 MachOBindEntry::Kind::Lazy);
1909}
1910
1911iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1912 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1913 MachOBindEntry::Kind::Weak);
1914}
1915
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001916MachOObjectFile::load_command_iterator
1917MachOObjectFile::begin_load_commands() const {
1918 return LoadCommands.begin();
1919}
1920
1921MachOObjectFile::load_command_iterator
1922MachOObjectFile::end_load_commands() const {
1923 return LoadCommands.end();
1924}
1925
1926iterator_range<MachOObjectFile::load_command_iterator>
1927MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00001928 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001929}
1930
Rafael Espindola56f976f2013-04-18 18:08:55 +00001931StringRef
1932MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1933 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1934 return parseSegmentOrSectionName(Raw.data());
1935}
1936
1937ArrayRef<char>
1938MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001939 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001940 const section_base *Base =
1941 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001942 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001943}
1944
1945ArrayRef<char>
1946MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001947 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001948 const section_base *Base =
1949 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001950 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001951}
1952
1953bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001954MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001955 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001956 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001957 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001958 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001959}
1960
Eric Christopher1d62c252013-07-22 22:25:07 +00001961unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001962 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001963 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001964 return RE.r_word1 & 0xffffff;
1965 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001966}
1967
Eric Christopher1d62c252013-07-22 22:25:07 +00001968bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001969 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001970 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001971 return (RE.r_word1 >> 27) & 1;
1972 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001973}
1974
Eric Christopher1d62c252013-07-22 22:25:07 +00001975bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001976 const MachO::any_relocation_info &RE) const {
1977 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001978}
1979
Eric Christopher1d62c252013-07-22 22:25:07 +00001980uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001981 const MachO::any_relocation_info &RE) const {
1982 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001983}
1984
Kevin Enderby9907d0a2014-11-04 00:43:16 +00001985uint32_t MachOObjectFile::getScatteredRelocationType(
1986 const MachO::any_relocation_info &RE) const {
1987 return (RE.r_word0 >> 24) & 0xf;
1988}
1989
Eric Christopher1d62c252013-07-22 22:25:07 +00001990unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001991 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001992 if (isRelocationScattered(RE))
1993 return getScatteredRelocationAddress(RE);
1994 return getPlainRelocationAddress(RE);
1995}
1996
Charles Davis8bdfafd2013-09-01 04:28:48 +00001997unsigned MachOObjectFile::getAnyRelocationPCRel(
1998 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001999 if (isRelocationScattered(RE))
2000 return getScatteredRelocationPCRel(this, RE);
2001 return getPlainRelocationPCRel(this, RE);
2002}
2003
Eric Christopher1d62c252013-07-22 22:25:07 +00002004unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002005 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002006 if (isRelocationScattered(RE))
2007 return getScatteredRelocationLength(RE);
2008 return getPlainRelocationLength(this, RE);
2009}
2010
2011unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002012MachOObjectFile::getAnyRelocationType(
2013 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002014 if (isRelocationScattered(RE))
2015 return getScatteredRelocationType(RE);
2016 return getPlainRelocationType(this, RE);
2017}
2018
Rafael Espindola52501032013-04-30 15:40:54 +00002019SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002020MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002021 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002022 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002023 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002024 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2025 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2026 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002027 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002028 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002029 return SectionRef(DRI, this);
2030}
2031
Charles Davis8bdfafd2013-09-01 04:28:48 +00002032MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002033 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002034 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002035}
2036
Charles Davis8bdfafd2013-09-01 04:28:48 +00002037MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002038 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002039 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002040}
2041
Charles Davis8bdfafd2013-09-01 04:28:48 +00002042MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002043 unsigned Index) const {
2044 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002045 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002046}
2047
Charles Davis8bdfafd2013-09-01 04:28:48 +00002048MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2049 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002050 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002051 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002052}
2053
Charles Davis8bdfafd2013-09-01 04:28:48 +00002054MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002055MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002056 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002057 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002058}
2059
Charles Davis8bdfafd2013-09-01 04:28:48 +00002060MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002061MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002062 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002063 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002064}
2065
Charles Davis8bdfafd2013-09-01 04:28:48 +00002066MachO::linkedit_data_command
2067MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2068 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002069}
2070
Charles Davis8bdfafd2013-09-01 04:28:48 +00002071MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002072MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002073 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002074}
2075
Charles Davis8bdfafd2013-09-01 04:28:48 +00002076MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002077MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002078 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002079}
2080
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002081MachO::linker_option_command
2082MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2083 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002084}
2085
Jim Grosbach448334a2014-03-18 22:09:05 +00002086MachO::version_min_command
2087MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2088 return getStruct<MachO::version_min_command>(this, L.Ptr);
2089}
2090
Tim Northover8f9590b2014-06-30 14:40:57 +00002091MachO::dylib_command
2092MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2093 return getStruct<MachO::dylib_command>(this, L.Ptr);
2094}
2095
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002096MachO::dyld_info_command
2097MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2098 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2099}
2100
2101MachO::dylinker_command
2102MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2103 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2104}
2105
2106MachO::uuid_command
2107MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2108 return getStruct<MachO::uuid_command>(this, L.Ptr);
2109}
2110
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002111MachO::rpath_command
2112MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2113 return getStruct<MachO::rpath_command>(this, L.Ptr);
2114}
2115
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002116MachO::source_version_command
2117MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2118 return getStruct<MachO::source_version_command>(this, L.Ptr);
2119}
2120
2121MachO::entry_point_command
2122MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2123 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2124}
2125
Kevin Enderby0804f4672014-12-16 23:25:52 +00002126MachO::encryption_info_command
2127MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2128 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2129}
2130
Kevin Enderby57538292014-12-17 01:01:30 +00002131MachO::encryption_info_command_64
2132MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2133 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2134}
2135
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002136MachO::sub_framework_command
2137MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2138 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2139}
Tim Northover8f9590b2014-06-30 14:40:57 +00002140
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002141MachO::sub_umbrella_command
2142MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2143 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2144}
2145
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002146MachO::sub_library_command
2147MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2148 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2149}
2150
Kevin Enderby186eac32014-12-19 21:06:24 +00002151MachO::sub_client_command
2152MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2153 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2154}
2155
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002156MachO::routines_command
2157MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2158 return getStruct<MachO::routines_command>(this, L.Ptr);
2159}
2160
2161MachO::routines_command_64
2162MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2163 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2164}
2165
Kevin Enderby48ef5342014-12-23 22:56:39 +00002166MachO::thread_command
2167MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2168 return getStruct<MachO::thread_command>(this, L.Ptr);
2169}
2170
Charles Davis8bdfafd2013-09-01 04:28:48 +00002171MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002172MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002173 DataRefImpl Sec;
2174 Sec.d.a = Rel.d.a;
2175 uint32_t Offset;
2176 if (is64Bit()) {
2177 MachO::section_64 Sect = getSection64(Sec);
2178 Offset = Sect.reloff;
2179 } else {
2180 MachO::section Sect = getSection(Sec);
2181 Offset = Sect.reloff;
2182 }
2183
2184 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2185 getPtr(this, Offset)) + Rel.d.b;
2186 return getStruct<MachO::any_relocation_info>(
2187 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002188}
2189
Charles Davis8bdfafd2013-09-01 04:28:48 +00002190MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002191MachOObjectFile::getDice(DataRefImpl Rel) const {
2192 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002193 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002194}
2195
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002196const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002197 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002198}
2199
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002200const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2201 assert(is64Bit());
2202 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002203}
2204
Charles Davis8bdfafd2013-09-01 04:28:48 +00002205uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2206 const MachO::dysymtab_command &DLC,
2207 unsigned Index) const {
2208 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2209 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002210}
2211
Charles Davis8bdfafd2013-09-01 04:28:48 +00002212MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002213MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2214 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002215 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2216 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002217}
2218
Charles Davis8bdfafd2013-09-01 04:28:48 +00002219MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002220 if (SymtabLoadCmd)
2221 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2222
2223 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2224 MachO::symtab_command Cmd;
2225 Cmd.cmd = MachO::LC_SYMTAB;
2226 Cmd.cmdsize = sizeof(MachO::symtab_command);
2227 Cmd.symoff = 0;
2228 Cmd.nsyms = 0;
2229 Cmd.stroff = 0;
2230 Cmd.strsize = 0;
2231 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002232}
2233
Charles Davis8bdfafd2013-09-01 04:28:48 +00002234MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002235 if (DysymtabLoadCmd)
2236 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2237
2238 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2239 MachO::dysymtab_command Cmd;
2240 Cmd.cmd = MachO::LC_DYSYMTAB;
2241 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2242 Cmd.ilocalsym = 0;
2243 Cmd.nlocalsym = 0;
2244 Cmd.iextdefsym = 0;
2245 Cmd.nextdefsym = 0;
2246 Cmd.iundefsym = 0;
2247 Cmd.nundefsym = 0;
2248 Cmd.tocoff = 0;
2249 Cmd.ntoc = 0;
2250 Cmd.modtaboff = 0;
2251 Cmd.nmodtab = 0;
2252 Cmd.extrefsymoff = 0;
2253 Cmd.nextrefsyms = 0;
2254 Cmd.indirectsymoff = 0;
2255 Cmd.nindirectsyms = 0;
2256 Cmd.extreloff = 0;
2257 Cmd.nextrel = 0;
2258 Cmd.locreloff = 0;
2259 Cmd.nlocrel = 0;
2260 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002261}
2262
Charles Davis8bdfafd2013-09-01 04:28:48 +00002263MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002264MachOObjectFile::getDataInCodeLoadCommand() const {
2265 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002266 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002267
2268 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002269 MachO::linkedit_data_command Cmd;
2270 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2271 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2272 Cmd.dataoff = 0;
2273 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002274 return Cmd;
2275}
2276
Kevin Enderby9a509442015-01-27 21:28:24 +00002277MachO::linkedit_data_command
2278MachOObjectFile::getLinkOptHintsLoadCommand() const {
2279 if (LinkOptHintsLoadCmd)
2280 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2281
2282 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2283 // fields.
2284 MachO::linkedit_data_command Cmd;
2285 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2286 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2287 Cmd.dataoff = 0;
2288 Cmd.datasize = 0;
2289 return Cmd;
2290}
2291
Nick Kledzikd04bc352014-08-30 00:20:14 +00002292ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002293 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002294 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002295
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002296 MachO::dyld_info_command DyldInfo =
2297 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2298 const uint8_t *Ptr =
2299 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002300 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002301}
2302
2303ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002304 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002305 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002306
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002307 MachO::dyld_info_command DyldInfo =
2308 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2309 const uint8_t *Ptr =
2310 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002311 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002312}
2313
2314ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002315 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002316 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002317
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002318 MachO::dyld_info_command DyldInfo =
2319 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2320 const uint8_t *Ptr =
2321 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002322 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002323}
2324
2325ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002326 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002327 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002328
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002329 MachO::dyld_info_command DyldInfo =
2330 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2331 const uint8_t *Ptr =
2332 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002333 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002334}
2335
2336ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002337 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002338 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002339
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002340 MachO::dyld_info_command DyldInfo =
2341 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2342 const uint8_t *Ptr =
2343 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002344 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002345}
2346
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002347ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2348 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002349 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002350 // Returning a pointer is fine as uuid doesn't need endian swapping.
2351 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002352 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002353}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002354
Rafael Espindola6e040c02013-04-26 20:07:33 +00002355StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002356 MachO::symtab_command S = getSymtabLoadCommand();
2357 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002358}
2359
Rafael Espindola56f976f2013-04-18 18:08:55 +00002360bool MachOObjectFile::is64Bit() const {
2361 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002362 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002363}
2364
2365void MachOObjectFile::ReadULEB128s(uint64_t Index,
2366 SmallVectorImpl<uint64_t> &Out) const {
2367 DataExtractor extractor(ObjectFile::getData(), true, 0);
2368
2369 uint32_t offset = Index;
2370 uint64_t data = 0;
2371 while (uint64_t delta = extractor.getULEB128(&offset)) {
2372 data += delta;
2373 Out.push_back(data);
2374 }
2375}
2376
Rafael Espindolac66d7612014-08-17 19:09:37 +00002377bool MachOObjectFile::isRelocatableObject() const {
2378 return getHeader().filetype == MachO::MH_OBJECT;
2379}
2380
Rafael Espindola437b0d52014-07-31 03:12:45 +00002381ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002382ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2383 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002384 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002385 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002386 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002387 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002388 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002389 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002390 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002391 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002392 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002393 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002394 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002395 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002396
Rafael Espindola692410e2014-01-21 23:06:54 +00002397 if (EC)
2398 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002399 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002400}