blob: 01f2fc5d488819ced5bb471f5cbac11d349e7dfb [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
Filipe Cabecinhas40139502015-01-15 22:52:38 +000041template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000042static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000043 // Don't read before the beginning or past the end of the file
44 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
45 report_fatal_error("Malformed MachO file.");
46
Rafael Espindola3cdeb172013-04-19 13:45:05 +000047 T Cmd;
48 memcpy(&Cmd, P, sizeof(T));
49 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000050 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000051 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000052}
53
Filipe Cabecinhas40139502015-01-15 22:52:38 +000054template <typename SegmentCmd>
55static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
56 uint32_t Cmdsize) {
57 const unsigned SectionSize = sizeof(SegmentCmd);
58 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
59 S.nsects * SectionSize > Cmdsize - sizeof(S))
60 report_fatal_error(
61 "Number of sections too large for size of load command.");
62 return S.nsects;
63}
64
Rafael Espindola56f976f2013-04-18 18:08:55 +000065static uint32_t
66getSegmentLoadCommandNumSections(const MachOObjectFile *O,
67 const MachOObjectFile::LoadCommandInfo &L) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000068 if (O->is64Bit())
69 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
70 L.C.cmdsize);
71
72 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
73 L.C.cmdsize);
Rafael Espindola5ffc0792013-04-07 16:07:35 +000074}
75
Nick Kledzik56ebef42014-09-16 01:41:51 +000076static bool isPageZeroSegment(const MachOObjectFile *O,
77 const MachOObjectFile::LoadCommandInfo &L) {
78 if (O->is64Bit()) {
79 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
80 return StringRef("__PAGEZERO").equals(S.segname);
81 }
82 MachO::segment_command S = O->getSegmentLoadCommand(L);
83 return StringRef("__PAGEZERO").equals(S.segname);
84}
85
86
Rafael Espindola6e040c02013-04-26 20:07:33 +000087static const char *
88getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
89 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000090 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
91
92 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000093 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
94 sizeof(MachO::segment_command);
95 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
96 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000097
98 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000099 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +0000100}
101
Rafael Espindola56f976f2013-04-18 18:08:55 +0000102static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
103 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000104}
105
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000106static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +0000107getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000108 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000109 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000110}
111
Rafael Espindola56f976f2013-04-18 18:08:55 +0000112static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000113 if (P[15] == 0)
114 // Null terminated.
115 return P;
116 // Not null terminated, so this is a 16 char string.
117 return StringRef(P, 16);
118}
119
Rafael Espindola56f976f2013-04-18 18:08:55 +0000120// Helper to advance a section or symbol iterator multiple increments at a time.
121template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000122static void advance(T &it, size_t Val) {
123 while (Val--)
124 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000125}
126
127static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000128 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000129}
130
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131static uint32_t
132getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
133 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134}
135
136static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000137getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
138 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000139}
140
141static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000142 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000143 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000144 return (RE.r_word1 >> 24) & 1;
145 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000146}
147
148static bool
149getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150 const MachO::any_relocation_info &RE) {
151 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152}
153
154static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000155 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000156 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000157 return (RE.r_word1 >> 25) & 3;
158 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159}
160
161static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000162getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
163 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000164}
165
166static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000167 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000168 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000169 return RE.r_word1 >> 28;
170 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000171}
172
Rafael Espindola56f976f2013-04-18 18:08:55 +0000173static uint32_t getSectionFlags(const MachOObjectFile *O,
174 DataRefImpl Sec) {
175 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000176 MachO::section_64 Sect = O->getSection64(Sec);
177 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000178 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000179 MachO::section Sect = O->getSection(Sec);
180 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000181}
182
Rafael Espindola48af1c22014-08-19 18:44:46 +0000183MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
184 bool Is64bits, std::error_code &EC)
185 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000186 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000187 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
188 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
189 HasPageZeroSegment(false) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000190 uint32_t LoadCommandCount = this->getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000191 if (LoadCommandCount == 0)
192 return;
193
Charles Davis8bdfafd2013-09-01 04:28:48 +0000194 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
195 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000196
197 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000198 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000199 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000200 // Multiple symbol tables
201 if (SymtabLoadCmd) {
202 EC = object_error::parse_failed;
203 return;
204 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000205 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000206 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000207 // Multiple dynamic symbol tables
208 if (DysymtabLoadCmd) {
209 EC = object_error::parse_failed;
210 return;
211 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000212 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000213 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000214 // Multiple data in code tables
215 if (DataInCodeLoadCmd) {
216 EC = object_error::parse_failed;
217 return;
218 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000219 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000220 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
221 // Multiple linker optimization hint tables
222 if (LinkOptHintsLoadCmd) {
223 EC = object_error::parse_failed;
224 return;
225 }
226 LinkOptHintsLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000227 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
228 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000229 // Multiple dyldinfo load commands
230 if (DyldInfoLoadCmd) {
231 EC = object_error::parse_failed;
232 return;
233 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000234 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000235 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000236 // Multiple UUID load commands
237 if (UuidLoadCmd) {
238 EC = object_error::parse_failed;
239 return;
240 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000241 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000242 } else if (Load.C.cmd == SegmentLoadType) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +0000243 const unsigned SegmentLoadSize = this->is64Bit()
244 ? sizeof(MachO::segment_command_64)
245 : sizeof(MachO::segment_command);
246 if (Load.C.cmdsize < SegmentLoadSize)
247 report_fatal_error("Segment load command size is too small.");
248
Rafael Espindola56f976f2013-04-18 18:08:55 +0000249 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
250 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000251 const char *Sec = getSectionPtr(this, Load, J);
252 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000253 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000254 if (isPageZeroSegment(this, Load))
255 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000256 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
257 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
258 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
259 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
260 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
261 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000262 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000263
264 if (I == LoadCommandCount - 1)
265 break;
266 else
267 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000268 }
269}
270
Rafael Espindola5e812af2014-01-30 02:49:50 +0000271void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000272 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000273 sizeof(MachO::nlist_64) :
274 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000275 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000276}
277
Rafael Espindola3acea392014-06-12 21:46:39 +0000278std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
279 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000280 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000281 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000282 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000283 if (Start < getData().begin() || Start >= getData().end())
284 report_fatal_error(
285 "Symbol name entry points before beginning or past end of file.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000286 Res = StringRef(Start);
287 return object_error::success;
288}
289
Rafael Espindola0e77a942014-12-10 20:46:55 +0000290unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
291 DataRefImpl DRI = Sec.getRawDataRefImpl();
292 uint32_t Flags = getSectionFlags(this, DRI);
293 return Flags & MachO::SECTION_TYPE;
294}
295
Kevin Enderby980b2582014-06-05 21:21:57 +0000296// getIndirectName() returns the name of the alias'ed symbol who's string table
297// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000298std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
299 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000300 StringRef StringTable = getStringTableData();
301 uint64_t NValue;
302 if (is64Bit()) {
303 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
304 NValue = Entry.n_value;
305 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
306 return object_error::parse_failed;
307 } else {
308 MachO::nlist Entry = getSymbolTableEntry(Symb);
309 NValue = Entry.n_value;
310 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
311 return object_error::parse_failed;
312 }
313 if (NValue >= StringTable.size())
314 return object_error::parse_failed;
315 const char *Start = &StringTable.data()[NValue];
316 Res = StringRef(Start);
317 return object_error::success;
318}
319
Rafael Espindola3acea392014-06-12 21:46:39 +0000320std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
321 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000322 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000323 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000324 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
325 Entry.n_value == 0)
326 Res = UnknownAddressOrSize;
327 else
328 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000329 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000330 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000331 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
332 Entry.n_value == 0)
333 Res = UnknownAddressOrSize;
334 else
335 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000336 }
337 return object_error::success;
338}
339
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000340uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000341 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000342 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000343 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000344 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000345 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000346 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000347}
348
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000349uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000350 uint64_t Value;
351 getSymbolAddress(DRI, Value);
Rafael Espindola62a07cb2015-05-22 15:43:00 +0000352 uint32_t flags = getSymbolFlags(DRI);
353 if (flags & SymbolRef::SF_Common)
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000354 return Value;
355 return UnknownAddressOrSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000356}
357
Rafael Espindola3acea392014-06-12 21:46:39 +0000358std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
359 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000360 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000361 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000362
363 Res = SymbolRef::ST_Other;
364
365 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000366 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000367 Res = SymbolRef::ST_Debug;
368 return object_error::success;
369 }
370
Charles Davis74ec8b02013-08-27 05:00:13 +0000371 switch (n_type & MachO::N_TYPE) {
372 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000373 Res = SymbolRef::ST_Unknown;
374 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000375 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000376 Res = SymbolRef::ST_Function;
377 break;
378 }
379 return object_error::success;
380}
381
Rafael Espindola20122a42014-01-31 20:57:12 +0000382uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000383 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000384
Charles Davis8bdfafd2013-09-01 04:28:48 +0000385 uint8_t MachOType = Entry.n_type;
386 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000387
Rafael Espindola20122a42014-01-31 20:57:12 +0000388 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000389
Charles Davis74ec8b02013-08-27 05:00:13 +0000390 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000391 Result |= SymbolRef::SF_Undefined;
392
Tim Northovereaef0742014-05-30 13:22:59 +0000393 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
394 Result |= SymbolRef::SF_Indirect;
395
Rafael Espindolaa1356322013-11-02 05:03:24 +0000396 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000397 Result |= SymbolRef::SF_FormatSpecific;
398
Charles Davis74ec8b02013-08-27 05:00:13 +0000399 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000400 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000401 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000402 uint64_t Value;
403 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000404 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000405 Result |= SymbolRef::SF_Common;
406 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000407
408 if (!(MachOType & MachO::N_PEXT))
409 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000410 }
411
Charles Davis74ec8b02013-08-27 05:00:13 +0000412 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000413 Result |= SymbolRef::SF_Weak;
414
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000415 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
416 Result |= SymbolRef::SF_Thumb;
417
Charles Davis74ec8b02013-08-27 05:00:13 +0000418 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000419 Result |= SymbolRef::SF_Absolute;
420
Rafael Espindola20122a42014-01-31 20:57:12 +0000421 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000422}
423
Rafael Espindola3acea392014-06-12 21:46:39 +0000424std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
425 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000426 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000427 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000428
429 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000430 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000431 } else {
432 DataRefImpl DRI;
433 DRI.d.a = index - 1;
Rafael Espindola0d85d102015-05-22 14:59:27 +0000434 if (DRI.d.a >= Sections.size())
435 report_fatal_error("getSymbolSection: Invalid section index.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000436 Res = section_iterator(SectionRef(DRI, this));
437 }
438
439 return object_error::success;
440}
441
Rafael Espindola5e812af2014-01-30 02:49:50 +0000442void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000443 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000444}
445
Rafael Espindola3acea392014-06-12 21:46:39 +0000446std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
447 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000448 ArrayRef<char> Raw = getSectionRawName(Sec);
449 Result = parseSegmentOrSectionName(Raw.data());
450 return object_error::success;
451}
452
Rafael Espindola80291272014-10-08 15:28:58 +0000453uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
454 if (is64Bit())
455 return getSection64(Sec).addr;
456 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000457}
458
Rafael Espindola80291272014-10-08 15:28:58 +0000459uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
460 if (is64Bit())
461 return getSection64(Sec).size;
462 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000463}
464
Rafael Espindola3acea392014-06-12 21:46:39 +0000465std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
466 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000467 uint32_t Offset;
468 uint64_t Size;
469
470 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000471 MachO::section_64 Sect = getSection64(Sec);
472 Offset = Sect.offset;
473 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000474 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000475 MachO::section Sect = getSection(Sec);
476 Offset = Sect.offset;
477 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000478 }
479
480 Res = this->getData().substr(Offset, Size);
481 return object_error::success;
482}
483
Rafael Espindola80291272014-10-08 15:28:58 +0000484uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000485 uint32_t Align;
486 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000487 MachO::section_64 Sect = getSection64(Sec);
488 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000489 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000490 MachO::section Sect = getSection(Sec);
491 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000492 }
493
Rafael Espindola80291272014-10-08 15:28:58 +0000494 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000495}
496
Rafael Espindola80291272014-10-08 15:28:58 +0000497bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000498 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000499 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000500}
501
Rafael Espindola80291272014-10-08 15:28:58 +0000502bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000503 uint32_t Flags = getSectionFlags(this, Sec);
504 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000505 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
506 !(SectionType == MachO::S_ZEROFILL ||
507 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000508}
509
Rafael Espindola80291272014-10-08 15:28:58 +0000510bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000511 uint32_t Flags = getSectionFlags(this, Sec);
512 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000513 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
514 (SectionType == MachO::S_ZEROFILL ||
515 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000516}
517
Rafael Espindola80291272014-10-08 15:28:58 +0000518bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000519 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000520 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000521}
522
Rafael Espindola80291272014-10-08 15:28:58 +0000523bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
524 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000525 SymbolRef::Type ST;
526 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000527 if (ST == SymbolRef::ST_Unknown)
528 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000529
Rafael Espindola80291272014-10-08 15:28:58 +0000530 uint64_t SectBegin = getSectionAddress(Sec);
531 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000532 SectEnd += SectBegin;
533
534 uint64_t SymAddr;
535 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000536 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537}
538
Rui Ueyamabc654b12013-09-27 21:47:05 +0000539relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000540 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000541 Ret.d.a = Sec.d.a;
542 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000543 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000544}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000545
Rafael Espindola56f976f2013-04-18 18:08:55 +0000546relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000547MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000548 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000549 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000550 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000551 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000552 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000553 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000554 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000555 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000556
Rafael Espindola56f976f2013-04-18 18:08:55 +0000557 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000558 Ret.d.a = Sec.d.a;
559 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000560 return relocation_iterator(RelocationRef(Ret, this));
561}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000562
Rafael Espindola5e812af2014-01-30 02:49:50 +0000563void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000564 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000565}
Owen Anderson171f4852011-10-24 23:20:07 +0000566
Rafael Espindola3acea392014-06-12 21:46:39 +0000567std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
568 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000569 uint64_t Offset;
570 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000571
572 DataRefImpl Sec;
573 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000574 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000575 Res = SecAddress + Offset;
576 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000577}
578
Rafael Espindola3acea392014-06-12 21:46:39 +0000579std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
580 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000581 assert(getHeader().filetype == MachO::MH_OBJECT &&
582 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000583 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000584 Res = getAnyRelocationAddress(RE);
585 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000586}
587
Rafael Espindola806f0062013-06-05 01:33:53 +0000588symbol_iterator
589MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000590 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000591 if (isRelocationScattered(RE))
592 return symbol_end();
593
Rafael Espindola56f976f2013-04-18 18:08:55 +0000594 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
595 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000596 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000597 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000598
Charles Davis8bdfafd2013-09-01 04:28:48 +0000599 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000600 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000601 sizeof(MachO::nlist_64) :
602 sizeof(MachO::nlist);
603 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000604 DataRefImpl Sym;
605 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000606 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000607}
608
Keno Fischerc780e8e2015-05-21 21:24:32 +0000609section_iterator
610MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
611 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
612}
613
Rafael Espindola3acea392014-06-12 21:46:39 +0000614std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
615 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000616 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000617 Res = getAnyRelocationType(RE);
618 return object_error::success;
619}
620
Rafael Espindola3acea392014-06-12 21:46:39 +0000621std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000622MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
623 SmallVectorImpl<char> &Result) const {
624 StringRef res;
625 uint64_t RType;
626 getRelocationType(Rel, RType);
627
628 unsigned Arch = this->getArch();
629
630 switch (Arch) {
631 case Triple::x86: {
632 static const char *const Table[] = {
633 "GENERIC_RELOC_VANILLA",
634 "GENERIC_RELOC_PAIR",
635 "GENERIC_RELOC_SECTDIFF",
636 "GENERIC_RELOC_PB_LA_PTR",
637 "GENERIC_RELOC_LOCAL_SECTDIFF",
638 "GENERIC_RELOC_TLV" };
639
Eric Christopher13250cb2013-12-06 02:33:38 +0000640 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000641 res = "Unknown";
642 else
643 res = Table[RType];
644 break;
645 }
646 case Triple::x86_64: {
647 static const char *const Table[] = {
648 "X86_64_RELOC_UNSIGNED",
649 "X86_64_RELOC_SIGNED",
650 "X86_64_RELOC_BRANCH",
651 "X86_64_RELOC_GOT_LOAD",
652 "X86_64_RELOC_GOT",
653 "X86_64_RELOC_SUBTRACTOR",
654 "X86_64_RELOC_SIGNED_1",
655 "X86_64_RELOC_SIGNED_2",
656 "X86_64_RELOC_SIGNED_4",
657 "X86_64_RELOC_TLV" };
658
659 if (RType > 9)
660 res = "Unknown";
661 else
662 res = Table[RType];
663 break;
664 }
665 case Triple::arm: {
666 static const char *const Table[] = {
667 "ARM_RELOC_VANILLA",
668 "ARM_RELOC_PAIR",
669 "ARM_RELOC_SECTDIFF",
670 "ARM_RELOC_LOCAL_SECTDIFF",
671 "ARM_RELOC_PB_LA_PTR",
672 "ARM_RELOC_BR24",
673 "ARM_THUMB_RELOC_BR22",
674 "ARM_THUMB_32BIT_BRANCH",
675 "ARM_RELOC_HALF",
676 "ARM_RELOC_HALF_SECTDIFF" };
677
678 if (RType > 9)
679 res = "Unknown";
680 else
681 res = Table[RType];
682 break;
683 }
Tim Northover00ed9962014-03-29 10:18:08 +0000684 case Triple::aarch64: {
685 static const char *const Table[] = {
686 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
687 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
688 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
689 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
690 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
691 "ARM64_RELOC_ADDEND"
692 };
693
694 if (RType >= array_lengthof(Table))
695 res = "Unknown";
696 else
697 res = Table[RType];
698 break;
699 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000700 case Triple::ppc: {
701 static const char *const Table[] = {
702 "PPC_RELOC_VANILLA",
703 "PPC_RELOC_PAIR",
704 "PPC_RELOC_BR14",
705 "PPC_RELOC_BR24",
706 "PPC_RELOC_HI16",
707 "PPC_RELOC_LO16",
708 "PPC_RELOC_HA16",
709 "PPC_RELOC_LO14",
710 "PPC_RELOC_SECTDIFF",
711 "PPC_RELOC_PB_LA_PTR",
712 "PPC_RELOC_HI16_SECTDIFF",
713 "PPC_RELOC_LO16_SECTDIFF",
714 "PPC_RELOC_HA16_SECTDIFF",
715 "PPC_RELOC_JBSR",
716 "PPC_RELOC_LO14_SECTDIFF",
717 "PPC_RELOC_LOCAL_SECTDIFF" };
718
Eric Christopher13250cb2013-12-06 02:33:38 +0000719 if (RType > 15)
720 res = "Unknown";
721 else
722 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000723 break;
724 }
725 case Triple::UnknownArch:
726 res = "Unknown";
727 break;
728 }
729 Result.append(res.begin(), res.end());
730 return object_error::success;
731}
732
Rafael Espindola3acea392014-06-12 21:46:39 +0000733std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
734 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000735 unsigned Arch = getArch();
736 uint64_t Type;
737 getRelocationType(Rel, Type);
738
739 Result = false;
740
741 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
742 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000743 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000744 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000745 } else if (Arch == Triple::x86_64) {
746 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000747 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000748 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000749 DataRefImpl RelPrev = Rel;
750 RelPrev.d.a--;
751 uint64_t PrevType;
752 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000753 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000754 Result = true;
755 }
756 }
757
758 return object_error::success;
759}
760
Keno Fischer281b6942015-05-30 19:44:53 +0000761uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
762 MachO::any_relocation_info RE = getRelocation(Rel);
763 return getAnyRelocationLength(RE);
764}
765
Kevin Enderby980b2582014-06-05 21:21:57 +0000766//
767// guessLibraryShortName() is passed a name of a dynamic library and returns a
768// guess on what the short name is. Then name is returned as a substring of the
769// StringRef Name passed in. The name of the dynamic library is recognized as
770// a framework if it has one of the two following forms:
771// Foo.framework/Versions/A/Foo
772// Foo.framework/Foo
773// Where A and Foo can be any string. And may contain a trailing suffix
774// starting with an underbar. If the Name is recognized as a framework then
775// isFramework is set to true else it is set to false. If the Name has a
776// suffix then Suffix is set to the substring in Name that contains the suffix
777// else it is set to a NULL StringRef.
778//
779// The Name of the dynamic library is recognized as a library name if it has
780// one of the two following forms:
781// libFoo.A.dylib
782// libFoo.dylib
783// The library may have a suffix trailing the name Foo of the form:
784// libFoo_profile.A.dylib
785// libFoo_profile.dylib
786//
787// The Name of the dynamic library is also recognized as a library name if it
788// has the following form:
789// Foo.qtx
790//
791// If the Name of the dynamic library is none of the forms above then a NULL
792// StringRef is returned.
793//
794StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
795 bool &isFramework,
796 StringRef &Suffix) {
797 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
798 size_t a, b, c, d, Idx;
799
800 isFramework = false;
801 Suffix = StringRef();
802
803 // Pull off the last component and make Foo point to it
804 a = Name.rfind('/');
805 if (a == Name.npos || a == 0)
806 goto guess_library;
807 Foo = Name.slice(a+1, Name.npos);
808
809 // Look for a suffix starting with a '_'
810 Idx = Foo.rfind('_');
811 if (Idx != Foo.npos && Foo.size() >= 2) {
812 Suffix = Foo.slice(Idx, Foo.npos);
813 Foo = Foo.slice(0, Idx);
814 }
815
816 // First look for the form Foo.framework/Foo
817 b = Name.rfind('/', a);
818 if (b == Name.npos)
819 Idx = 0;
820 else
821 Idx = b+1;
822 F = Name.slice(Idx, Idx + Foo.size());
823 DotFramework = Name.slice(Idx + Foo.size(),
824 Idx + Foo.size() + sizeof(".framework/")-1);
825 if (F == Foo && DotFramework == ".framework/") {
826 isFramework = true;
827 return Foo;
828 }
829
830 // Next look for the form Foo.framework/Versions/A/Foo
831 if (b == Name.npos)
832 goto guess_library;
833 c = Name.rfind('/', b);
834 if (c == Name.npos || c == 0)
835 goto guess_library;
836 V = Name.slice(c+1, Name.npos);
837 if (!V.startswith("Versions/"))
838 goto guess_library;
839 d = Name.rfind('/', c);
840 if (d == Name.npos)
841 Idx = 0;
842 else
843 Idx = d+1;
844 F = Name.slice(Idx, Idx + Foo.size());
845 DotFramework = Name.slice(Idx + Foo.size(),
846 Idx + Foo.size() + sizeof(".framework/")-1);
847 if (F == Foo && DotFramework == ".framework/") {
848 isFramework = true;
849 return Foo;
850 }
851
852guess_library:
853 // pull off the suffix after the "." and make a point to it
854 a = Name.rfind('.');
855 if (a == Name.npos || a == 0)
856 return StringRef();
857 Dylib = Name.slice(a, Name.npos);
858 if (Dylib != ".dylib")
859 goto guess_qtx;
860
861 // First pull off the version letter for the form Foo.A.dylib if any.
862 if (a >= 3) {
863 Dot = Name.slice(a-2, a-1);
864 if (Dot == ".")
865 a = a - 2;
866 }
867
868 b = Name.rfind('/', a);
869 if (b == Name.npos)
870 b = 0;
871 else
872 b = b+1;
873 // ignore any suffix after an underbar like Foo_profile.A.dylib
874 Idx = Name.find('_', b);
875 if (Idx != Name.npos && Idx != b) {
876 Lib = Name.slice(b, Idx);
877 Suffix = Name.slice(Idx, a);
878 }
879 else
880 Lib = Name.slice(b, a);
881 // There are incorrect library names of the form:
882 // libATS.A_profile.dylib so check for these.
883 if (Lib.size() >= 3) {
884 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
885 if (Dot == ".")
886 Lib = Lib.slice(0, Lib.size()-2);
887 }
888 return Lib;
889
890guess_qtx:
891 Qtx = Name.slice(a, Name.npos);
892 if (Qtx != ".qtx")
893 return StringRef();
894 b = Name.rfind('/', a);
895 if (b == Name.npos)
896 Lib = Name.slice(0, a);
897 else
898 Lib = Name.slice(b+1, a);
899 // There are library names of the form: QT.A.qtx so check for these.
900 if (Lib.size() >= 3) {
901 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
902 if (Dot == ".")
903 Lib = Lib.slice(0, Lib.size()-2);
904 }
905 return Lib;
906}
907
908// getLibraryShortNameByIndex() is used to get the short name of the library
909// for an undefined symbol in a linked Mach-O binary that was linked with the
910// normal two-level namespace default (that is MH_TWOLEVEL in the header).
911// It is passed the index (0 - based) of the library as translated from
912// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +0000913std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +0000914 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000915 if (Index >= Libraries.size())
916 return object_error::parse_failed;
917
Kevin Enderby980b2582014-06-05 21:21:57 +0000918 // If the cache of LibrariesShortNames is not built up do that first for
919 // all the Libraries.
920 if (LibrariesShortNames.size() == 0) {
921 for (unsigned i = 0; i < Libraries.size(); i++) {
922 MachO::dylib_command D =
923 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +0000924 if (D.dylib.name >= D.cmdsize)
925 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +0000926 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +0000927 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +0000928 if (D.dylib.name+Name.size() >= D.cmdsize)
929 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +0000930 StringRef Suffix;
931 bool isFramework;
932 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +0000933 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +0000934 LibrariesShortNames.push_back(Name);
935 else
936 LibrariesShortNames.push_back(shortName);
937 }
938 }
939
940 Res = LibrariesShortNames[Index];
941 return object_error::success;
942}
943
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000944basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +0000945 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000946}
947
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000948basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000949 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +0000950 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000951 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +0000952
Charles Davis8bdfafd2013-09-01 04:28:48 +0000953 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000954 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000955 sizeof(MachO::nlist_64) :
956 sizeof(MachO::nlist);
957 unsigned Offset = Symtab.symoff +
958 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000959 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000960 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000961}
962
Lang Hames36072da2014-05-12 21:39:59 +0000963basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
964 DataRefImpl DRI;
965 if (!SymtabLoadCmd)
966 return basic_symbol_iterator(SymbolRef(DRI, this));
967
968 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +0000969 if (Index >= Symtab.nsyms)
970 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +0000971 unsigned SymbolTableEntrySize =
972 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
973 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
974 DRI.p += Index * SymbolTableEntrySize;
975 return basic_symbol_iterator(SymbolRef(DRI, this));
976}
977
Rafael Espindolab5155a52014-02-10 20:24:04 +0000978section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000979 DataRefImpl DRI;
980 return section_iterator(SectionRef(DRI, this));
981}
982
Rafael Espindolab5155a52014-02-10 20:24:04 +0000983section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000984 DataRefImpl DRI;
985 DRI.d.a = Sections.size();
986 return section_iterator(SectionRef(DRI, this));
987}
988
Rafael Espindola56f976f2013-04-18 18:08:55 +0000989uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +0000990 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +0000991}
992
Rafael Espindola56f976f2013-04-18 18:08:55 +0000993StringRef MachOObjectFile::getFileFormatName() const {
994 unsigned CPUType = getCPUType(this);
995 if (!is64Bit()) {
996 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +0000997 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000998 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +0000999 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001000 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001001 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001002 return "Mach-O 32-bit ppc";
1003 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001004 return "Mach-O 32-bit unknown";
1005 }
1006 }
1007
Rafael Espindola56f976f2013-04-18 18:08:55 +00001008 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001009 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001010 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001011 case llvm::MachO::CPU_TYPE_ARM64:
1012 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001013 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001014 return "Mach-O 64-bit ppc64";
1015 default:
1016 return "Mach-O 64-bit unknown";
1017 }
1018}
1019
Alexey Samsonove6388e62013-06-18 15:03:28 +00001020Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1021 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001022 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001023 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001024 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001025 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001026 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001027 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001028 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001029 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001030 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001031 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001032 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001033 return Triple::ppc64;
1034 default:
1035 return Triple::UnknownArch;
1036 }
1037}
1038
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001039Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1040 const char **McpuDefault) {
1041 if (McpuDefault)
1042 *McpuDefault = nullptr;
1043
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001044 switch (CPUType) {
1045 case MachO::CPU_TYPE_I386:
1046 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1047 case MachO::CPU_SUBTYPE_I386_ALL:
1048 return Triple("i386-apple-darwin");
1049 default:
1050 return Triple();
1051 }
1052 case MachO::CPU_TYPE_X86_64:
1053 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1054 case MachO::CPU_SUBTYPE_X86_64_ALL:
1055 return Triple("x86_64-apple-darwin");
1056 case MachO::CPU_SUBTYPE_X86_64_H:
1057 return Triple("x86_64h-apple-darwin");
1058 default:
1059 return Triple();
1060 }
1061 case MachO::CPU_TYPE_ARM:
1062 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1063 case MachO::CPU_SUBTYPE_ARM_V4T:
1064 return Triple("armv4t-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1066 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001067 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1068 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001069 case MachO::CPU_SUBTYPE_ARM_V6:
1070 return Triple("armv6-apple-darwin");
1071 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001072 if (McpuDefault)
1073 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001074 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001075 case MachO::CPU_SUBTYPE_ARM_V7:
1076 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001077 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001078 if (McpuDefault)
1079 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001080 return Triple("armv7em-apple-darwin");
1081 case MachO::CPU_SUBTYPE_ARM_V7K:
1082 return Triple("armv7k-apple-darwin");
1083 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001084 if (McpuDefault)
1085 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001086 return Triple("armv7m-apple-darwin");
1087 case MachO::CPU_SUBTYPE_ARM_V7S:
1088 return Triple("armv7s-apple-darwin");
1089 default:
1090 return Triple();
1091 }
1092 case MachO::CPU_TYPE_ARM64:
1093 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1094 case MachO::CPU_SUBTYPE_ARM64_ALL:
1095 return Triple("arm64-apple-darwin");
1096 default:
1097 return Triple();
1098 }
1099 case MachO::CPU_TYPE_POWERPC:
1100 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1101 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1102 return Triple("ppc-apple-darwin");
1103 default:
1104 return Triple();
1105 }
1106 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001107 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001108 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1109 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001110 default:
1111 return Triple();
1112 }
1113 default:
1114 return Triple();
1115 }
1116}
1117
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001118Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1119 const char **McpuDefault) {
1120 if (McpuDefault)
1121 *McpuDefault = nullptr;
1122
1123 switch (CPUType) {
1124 case MachO::CPU_TYPE_ARM:
1125 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1126 case MachO::CPU_SUBTYPE_ARM_V4T:
1127 return Triple("thumbv4t-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1129 return Triple("thumbv5e-apple-darwin");
1130 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1131 return Triple("xscale-apple-darwin");
1132 case MachO::CPU_SUBTYPE_ARM_V6:
1133 return Triple("thumbv6-apple-darwin");
1134 case MachO::CPU_SUBTYPE_ARM_V6M:
1135 if (McpuDefault)
1136 *McpuDefault = "cortex-m0";
1137 return Triple("thumbv6m-apple-darwin");
1138 case MachO::CPU_SUBTYPE_ARM_V7:
1139 return Triple("thumbv7-apple-darwin");
1140 case MachO::CPU_SUBTYPE_ARM_V7EM:
1141 if (McpuDefault)
1142 *McpuDefault = "cortex-m4";
1143 return Triple("thumbv7em-apple-darwin");
1144 case MachO::CPU_SUBTYPE_ARM_V7K:
1145 return Triple("thumbv7k-apple-darwin");
1146 case MachO::CPU_SUBTYPE_ARM_V7M:
1147 if (McpuDefault)
1148 *McpuDefault = "cortex-m3";
1149 return Triple("thumbv7m-apple-darwin");
1150 case MachO::CPU_SUBTYPE_ARM_V7S:
1151 return Triple("thumbv7s-apple-darwin");
1152 default:
1153 return Triple();
1154 }
1155 default:
1156 return Triple();
1157 }
1158}
1159
1160Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1161 const char **McpuDefault,
1162 Triple *ThumbTriple) {
1163 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1164 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1165 McpuDefault);
1166 return T;
1167}
1168
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001169Triple MachOObjectFile::getHostArch() {
1170 return Triple(sys::getDefaultTargetTriple());
1171}
1172
Rafael Espindola72318b42014-08-08 16:30:17 +00001173bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1174 return StringSwitch<bool>(ArchFlag)
1175 .Case("i386", true)
1176 .Case("x86_64", true)
1177 .Case("x86_64h", true)
1178 .Case("armv4t", true)
1179 .Case("arm", true)
1180 .Case("armv5e", true)
1181 .Case("armv6", true)
1182 .Case("armv6m", true)
1183 .Case("armv7em", true)
1184 .Case("armv7k", true)
1185 .Case("armv7m", true)
1186 .Case("armv7s", true)
1187 .Case("arm64", true)
1188 .Case("ppc", true)
1189 .Case("ppc64", true)
1190 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001191}
1192
Alexey Samsonove6388e62013-06-18 15:03:28 +00001193unsigned MachOObjectFile::getArch() const {
1194 return getArch(getCPUType(this));
1195}
1196
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001197Triple MachOObjectFile::getArch(const char **McpuDefault,
1198 Triple *ThumbTriple) const {
1199 Triple T;
1200 if (is64Bit()) {
1201 MachO::mach_header_64 H_64;
1202 H_64 = getHeader64();
1203 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1204 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1205 McpuDefault);
1206 } else {
1207 MachO::mach_header H;
1208 H = getHeader();
1209 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1210 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1211 McpuDefault);
1212 }
1213 return T;
1214}
1215
Rui Ueyamabc654b12013-09-27 21:47:05 +00001216relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001217 DataRefImpl DRI;
1218 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001219 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001220}
1221
Rui Ueyamabc654b12013-09-27 21:47:05 +00001222relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001223 DataRefImpl DRI;
1224 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001225 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001226}
1227
Kevin Enderby273ae012013-06-06 17:20:50 +00001228dice_iterator MachOObjectFile::begin_dices() const {
1229 DataRefImpl DRI;
1230 if (!DataInCodeLoadCmd)
1231 return dice_iterator(DiceRef(DRI, this));
1232
Charles Davis8bdfafd2013-09-01 04:28:48 +00001233 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1234 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001235 return dice_iterator(DiceRef(DRI, this));
1236}
1237
1238dice_iterator MachOObjectFile::end_dices() const {
1239 DataRefImpl DRI;
1240 if (!DataInCodeLoadCmd)
1241 return dice_iterator(DiceRef(DRI, this));
1242
Charles Davis8bdfafd2013-09-01 04:28:48 +00001243 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1244 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001245 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1246 return dice_iterator(DiceRef(DRI, this));
1247}
1248
Nick Kledzikd04bc352014-08-30 00:20:14 +00001249ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1250 : Trie(T), Malformed(false), Done(false) { }
1251
1252void ExportEntry::moveToFirst() {
1253 pushNode(0);
1254 pushDownUntilBottom();
1255}
1256
1257void ExportEntry::moveToEnd() {
1258 Stack.clear();
1259 Done = true;
1260}
1261
1262bool ExportEntry::operator==(const ExportEntry &Other) const {
1263 // Common case, one at end, other iterating from begin.
1264 if (Done || Other.Done)
1265 return (Done == Other.Done);
1266 // Not equal if different stack sizes.
1267 if (Stack.size() != Other.Stack.size())
1268 return false;
1269 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001270 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001271 return false;
1272 // Equal if all nodes in both stacks match.
1273 for (unsigned i=0; i < Stack.size(); ++i) {
1274 if (Stack[i].Start != Other.Stack[i].Start)
1275 return false;
1276 }
1277 return true;
1278}
1279
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001280uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1281 unsigned Count;
1282 uint64_t Result = decodeULEB128(Ptr, &Count);
1283 Ptr += Count;
1284 if (Ptr > Trie.end()) {
1285 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001286 Malformed = true;
1287 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001288 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001289}
1290
1291StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001292 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001293}
1294
1295uint64_t ExportEntry::flags() const {
1296 return Stack.back().Flags;
1297}
1298
1299uint64_t ExportEntry::address() const {
1300 return Stack.back().Address;
1301}
1302
1303uint64_t ExportEntry::other() const {
1304 return Stack.back().Other;
1305}
1306
1307StringRef ExportEntry::otherName() const {
1308 const char* ImportName = Stack.back().ImportName;
1309 if (ImportName)
1310 return StringRef(ImportName);
1311 return StringRef();
1312}
1313
1314uint32_t ExportEntry::nodeOffset() const {
1315 return Stack.back().Start - Trie.begin();
1316}
1317
1318ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1319 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1320 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1321 ParentStringLength(0), IsExportNode(false) {
1322}
1323
1324void ExportEntry::pushNode(uint64_t offset) {
1325 const uint8_t *Ptr = Trie.begin() + offset;
1326 NodeState State(Ptr);
1327 uint64_t ExportInfoSize = readULEB128(State.Current);
1328 State.IsExportNode = (ExportInfoSize != 0);
1329 const uint8_t* Children = State.Current + ExportInfoSize;
1330 if (State.IsExportNode) {
1331 State.Flags = readULEB128(State.Current);
1332 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1333 State.Address = 0;
1334 State.Other = readULEB128(State.Current); // dylib ordinal
1335 State.ImportName = reinterpret_cast<const char*>(State.Current);
1336 } else {
1337 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001338 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1339 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001340 }
1341 }
1342 State.ChildCount = *Children;
1343 State.Current = Children + 1;
1344 State.NextChildIndex = 0;
1345 State.ParentStringLength = CumulativeString.size();
1346 Stack.push_back(State);
1347}
1348
1349void ExportEntry::pushDownUntilBottom() {
1350 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1351 NodeState &Top = Stack.back();
1352 CumulativeString.resize(Top.ParentStringLength);
1353 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001354 char C = *Top.Current;
1355 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001356 }
1357 Top.Current += 1;
1358 uint64_t childNodeIndex = readULEB128(Top.Current);
1359 Top.NextChildIndex += 1;
1360 pushNode(childNodeIndex);
1361 }
1362 if (!Stack.back().IsExportNode) {
1363 Malformed = true;
1364 moveToEnd();
1365 }
1366}
1367
1368// We have a trie data structure and need a way to walk it that is compatible
1369// with the C++ iterator model. The solution is a non-recursive depth first
1370// traversal where the iterator contains a stack of parent nodes along with a
1371// string that is the accumulation of all edge strings along the parent chain
1372// to this point.
1373//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001374// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001375// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1376// node may have child nodes too.
1377//
1378// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1379// child until hitting a node with no children (which is an export node or
1380// else the trie is malformed). On the way down, each node is pushed on the
1381// stack ivar. If there is no more ways down, it pops up one and tries to go
1382// down a sibling path until a childless node is reached.
1383void ExportEntry::moveNext() {
1384 if (Stack.empty() || !Stack.back().IsExportNode) {
1385 Malformed = true;
1386 moveToEnd();
1387 return;
1388 }
1389
1390 Stack.pop_back();
1391 while (!Stack.empty()) {
1392 NodeState &Top = Stack.back();
1393 if (Top.NextChildIndex < Top.ChildCount) {
1394 pushDownUntilBottom();
1395 // Now at the next export node.
1396 return;
1397 } else {
1398 if (Top.IsExportNode) {
1399 // This node has no children but is itself an export node.
1400 CumulativeString.resize(Top.ParentStringLength);
1401 return;
1402 }
1403 Stack.pop_back();
1404 }
1405 }
1406 Done = true;
1407}
1408
1409iterator_range<export_iterator>
1410MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1411 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001412 if (Trie.size() == 0)
1413 Start.moveToEnd();
1414 else
1415 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001416
1417 ExportEntry Finish(Trie);
1418 Finish.moveToEnd();
1419
1420 return iterator_range<export_iterator>(export_iterator(Start),
1421 export_iterator(Finish));
1422}
1423
1424iterator_range<export_iterator> MachOObjectFile::exports() const {
1425 return exports(getDyldInfoExportsTrie());
1426}
1427
1428
Nick Kledzikac431442014-09-12 21:34:15 +00001429MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1430 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1431 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1432 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1433
1434void MachORebaseEntry::moveToFirst() {
1435 Ptr = Opcodes.begin();
1436 moveNext();
1437}
1438
1439void MachORebaseEntry::moveToEnd() {
1440 Ptr = Opcodes.end();
1441 RemainingLoopCount = 0;
1442 Done = true;
1443}
1444
1445void MachORebaseEntry::moveNext() {
1446 // If in the middle of some loop, move to next rebasing in loop.
1447 SegmentOffset += AdvanceAmount;
1448 if (RemainingLoopCount) {
1449 --RemainingLoopCount;
1450 return;
1451 }
1452 if (Ptr == Opcodes.end()) {
1453 Done = true;
1454 return;
1455 }
1456 bool More = true;
1457 while (More && !Malformed) {
1458 // Parse next opcode and set up next loop.
1459 uint8_t Byte = *Ptr++;
1460 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1461 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1462 switch (Opcode) {
1463 case MachO::REBASE_OPCODE_DONE:
1464 More = false;
1465 Done = true;
1466 moveToEnd();
1467 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1468 break;
1469 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1470 RebaseType = ImmValue;
1471 DEBUG_WITH_TYPE(
1472 "mach-o-rebase",
1473 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1474 << "RebaseType=" << (int) RebaseType << "\n");
1475 break;
1476 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1477 SegmentIndex = ImmValue;
1478 SegmentOffset = readULEB128();
1479 DEBUG_WITH_TYPE(
1480 "mach-o-rebase",
1481 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1482 << "SegmentIndex=" << SegmentIndex << ", "
1483 << format("SegmentOffset=0x%06X", SegmentOffset)
1484 << "\n");
1485 break;
1486 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1487 SegmentOffset += readULEB128();
1488 DEBUG_WITH_TYPE("mach-o-rebase",
1489 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1490 << format("SegmentOffset=0x%06X",
1491 SegmentOffset) << "\n");
1492 break;
1493 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1494 SegmentOffset += ImmValue * PointerSize;
1495 DEBUG_WITH_TYPE("mach-o-rebase",
1496 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1497 << format("SegmentOffset=0x%06X",
1498 SegmentOffset) << "\n");
1499 break;
1500 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1501 AdvanceAmount = PointerSize;
1502 RemainingLoopCount = ImmValue - 1;
1503 DEBUG_WITH_TYPE(
1504 "mach-o-rebase",
1505 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1506 << format("SegmentOffset=0x%06X", SegmentOffset)
1507 << ", AdvanceAmount=" << AdvanceAmount
1508 << ", RemainingLoopCount=" << RemainingLoopCount
1509 << "\n");
1510 return;
1511 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1512 AdvanceAmount = PointerSize;
1513 RemainingLoopCount = readULEB128() - 1;
1514 DEBUG_WITH_TYPE(
1515 "mach-o-rebase",
1516 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1517 << format("SegmentOffset=0x%06X", SegmentOffset)
1518 << ", AdvanceAmount=" << AdvanceAmount
1519 << ", RemainingLoopCount=" << RemainingLoopCount
1520 << "\n");
1521 return;
1522 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1523 AdvanceAmount = readULEB128() + PointerSize;
1524 RemainingLoopCount = 0;
1525 DEBUG_WITH_TYPE(
1526 "mach-o-rebase",
1527 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1528 << format("SegmentOffset=0x%06X", SegmentOffset)
1529 << ", AdvanceAmount=" << AdvanceAmount
1530 << ", RemainingLoopCount=" << RemainingLoopCount
1531 << "\n");
1532 return;
1533 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1534 RemainingLoopCount = readULEB128() - 1;
1535 AdvanceAmount = readULEB128() + PointerSize;
1536 DEBUG_WITH_TYPE(
1537 "mach-o-rebase",
1538 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1539 << format("SegmentOffset=0x%06X", SegmentOffset)
1540 << ", AdvanceAmount=" << AdvanceAmount
1541 << ", RemainingLoopCount=" << RemainingLoopCount
1542 << "\n");
1543 return;
1544 default:
1545 Malformed = true;
1546 }
1547 }
1548}
1549
1550uint64_t MachORebaseEntry::readULEB128() {
1551 unsigned Count;
1552 uint64_t Result = decodeULEB128(Ptr, &Count);
1553 Ptr += Count;
1554 if (Ptr > Opcodes.end()) {
1555 Ptr = Opcodes.end();
1556 Malformed = true;
1557 }
1558 return Result;
1559}
1560
1561uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1562
1563uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1564
1565StringRef MachORebaseEntry::typeName() const {
1566 switch (RebaseType) {
1567 case MachO::REBASE_TYPE_POINTER:
1568 return "pointer";
1569 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1570 return "text abs32";
1571 case MachO::REBASE_TYPE_TEXT_PCREL32:
1572 return "text rel32";
1573 }
1574 return "unknown";
1575}
1576
1577bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1578 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1579 return (Ptr == Other.Ptr) &&
1580 (RemainingLoopCount == Other.RemainingLoopCount) &&
1581 (Done == Other.Done);
1582}
1583
1584iterator_range<rebase_iterator>
1585MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1586 MachORebaseEntry Start(Opcodes, is64);
1587 Start.moveToFirst();
1588
1589 MachORebaseEntry Finish(Opcodes, is64);
1590 Finish.moveToEnd();
1591
1592 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1593 rebase_iterator(Finish));
1594}
1595
1596iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1597 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1598}
1599
Nick Kledzik56ebef42014-09-16 01:41:51 +00001600
1601MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1602 Kind BK)
1603 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1604 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1605 BindType(0), PointerSize(is64Bit ? 8 : 4),
1606 TableKind(BK), Malformed(false), Done(false) {}
1607
1608void MachOBindEntry::moveToFirst() {
1609 Ptr = Opcodes.begin();
1610 moveNext();
1611}
1612
1613void MachOBindEntry::moveToEnd() {
1614 Ptr = Opcodes.end();
1615 RemainingLoopCount = 0;
1616 Done = true;
1617}
1618
1619void MachOBindEntry::moveNext() {
1620 // If in the middle of some loop, move to next binding in loop.
1621 SegmentOffset += AdvanceAmount;
1622 if (RemainingLoopCount) {
1623 --RemainingLoopCount;
1624 return;
1625 }
1626 if (Ptr == Opcodes.end()) {
1627 Done = true;
1628 return;
1629 }
1630 bool More = true;
1631 while (More && !Malformed) {
1632 // Parse next opcode and set up next loop.
1633 uint8_t Byte = *Ptr++;
1634 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1635 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1636 int8_t SignExtended;
1637 const uint8_t *SymStart;
1638 switch (Opcode) {
1639 case MachO::BIND_OPCODE_DONE:
1640 if (TableKind == Kind::Lazy) {
1641 // Lazying bindings have a DONE opcode between entries. Need to ignore
1642 // it to advance to next entry. But need not if this is last entry.
1643 bool NotLastEntry = false;
1644 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1645 if (*P) {
1646 NotLastEntry = true;
1647 }
1648 }
1649 if (NotLastEntry)
1650 break;
1651 }
1652 More = false;
1653 Done = true;
1654 moveToEnd();
1655 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1656 break;
1657 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1658 Ordinal = ImmValue;
1659 DEBUG_WITH_TYPE(
1660 "mach-o-bind",
1661 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1662 << "Ordinal=" << Ordinal << "\n");
1663 break;
1664 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1665 Ordinal = readULEB128();
1666 DEBUG_WITH_TYPE(
1667 "mach-o-bind",
1668 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1669 << "Ordinal=" << Ordinal << "\n");
1670 break;
1671 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1672 if (ImmValue) {
1673 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1674 Ordinal = SignExtended;
1675 } else
1676 Ordinal = 0;
1677 DEBUG_WITH_TYPE(
1678 "mach-o-bind",
1679 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1680 << "Ordinal=" << Ordinal << "\n");
1681 break;
1682 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1683 Flags = ImmValue;
1684 SymStart = Ptr;
1685 while (*Ptr) {
1686 ++Ptr;
1687 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001688 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1689 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001690 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001691 DEBUG_WITH_TYPE(
1692 "mach-o-bind",
1693 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1694 << "SymbolName=" << SymbolName << "\n");
1695 if (TableKind == Kind::Weak) {
1696 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1697 return;
1698 }
1699 break;
1700 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1701 BindType = ImmValue;
1702 DEBUG_WITH_TYPE(
1703 "mach-o-bind",
1704 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1705 << "BindType=" << (int)BindType << "\n");
1706 break;
1707 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1708 Addend = readSLEB128();
1709 if (TableKind == Kind::Lazy)
1710 Malformed = true;
1711 DEBUG_WITH_TYPE(
1712 "mach-o-bind",
1713 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1714 << "Addend=" << Addend << "\n");
1715 break;
1716 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1717 SegmentIndex = ImmValue;
1718 SegmentOffset = readULEB128();
1719 DEBUG_WITH_TYPE(
1720 "mach-o-bind",
1721 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1722 << "SegmentIndex=" << SegmentIndex << ", "
1723 << format("SegmentOffset=0x%06X", SegmentOffset)
1724 << "\n");
1725 break;
1726 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1727 SegmentOffset += readULEB128();
1728 DEBUG_WITH_TYPE("mach-o-bind",
1729 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1730 << format("SegmentOffset=0x%06X",
1731 SegmentOffset) << "\n");
1732 break;
1733 case MachO::BIND_OPCODE_DO_BIND:
1734 AdvanceAmount = PointerSize;
1735 RemainingLoopCount = 0;
1736 DEBUG_WITH_TYPE("mach-o-bind",
1737 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1738 << format("SegmentOffset=0x%06X",
1739 SegmentOffset) << "\n");
1740 return;
1741 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001742 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001743 RemainingLoopCount = 0;
1744 if (TableKind == Kind::Lazy)
1745 Malformed = true;
1746 DEBUG_WITH_TYPE(
1747 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001748 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001749 << format("SegmentOffset=0x%06X", SegmentOffset)
1750 << ", AdvanceAmount=" << AdvanceAmount
1751 << ", RemainingLoopCount=" << RemainingLoopCount
1752 << "\n");
1753 return;
1754 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001755 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001756 RemainingLoopCount = 0;
1757 if (TableKind == Kind::Lazy)
1758 Malformed = true;
1759 DEBUG_WITH_TYPE("mach-o-bind",
1760 llvm::dbgs()
1761 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1762 << format("SegmentOffset=0x%06X",
1763 SegmentOffset) << "\n");
1764 return;
1765 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1766 RemainingLoopCount = readULEB128() - 1;
1767 AdvanceAmount = readULEB128() + PointerSize;
1768 if (TableKind == Kind::Lazy)
1769 Malformed = true;
1770 DEBUG_WITH_TYPE(
1771 "mach-o-bind",
1772 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1773 << format("SegmentOffset=0x%06X", SegmentOffset)
1774 << ", AdvanceAmount=" << AdvanceAmount
1775 << ", RemainingLoopCount=" << RemainingLoopCount
1776 << "\n");
1777 return;
1778 default:
1779 Malformed = true;
1780 }
1781 }
1782}
1783
1784uint64_t MachOBindEntry::readULEB128() {
1785 unsigned Count;
1786 uint64_t Result = decodeULEB128(Ptr, &Count);
1787 Ptr += Count;
1788 if (Ptr > Opcodes.end()) {
1789 Ptr = Opcodes.end();
1790 Malformed = true;
1791 }
1792 return Result;
1793}
1794
1795int64_t MachOBindEntry::readSLEB128() {
1796 unsigned Count;
1797 int64_t Result = decodeSLEB128(Ptr, &Count);
1798 Ptr += Count;
1799 if (Ptr > Opcodes.end()) {
1800 Ptr = Opcodes.end();
1801 Malformed = true;
1802 }
1803 return Result;
1804}
1805
1806
1807uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1808
1809uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1810
1811StringRef MachOBindEntry::typeName() const {
1812 switch (BindType) {
1813 case MachO::BIND_TYPE_POINTER:
1814 return "pointer";
1815 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1816 return "text abs32";
1817 case MachO::BIND_TYPE_TEXT_PCREL32:
1818 return "text rel32";
1819 }
1820 return "unknown";
1821}
1822
1823StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1824
1825int64_t MachOBindEntry::addend() const { return Addend; }
1826
1827uint32_t MachOBindEntry::flags() const { return Flags; }
1828
1829int MachOBindEntry::ordinal() const { return Ordinal; }
1830
1831bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1832 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1833 return (Ptr == Other.Ptr) &&
1834 (RemainingLoopCount == Other.RemainingLoopCount) &&
1835 (Done == Other.Done);
1836}
1837
1838iterator_range<bind_iterator>
1839MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1840 MachOBindEntry::Kind BKind) {
1841 MachOBindEntry Start(Opcodes, is64, BKind);
1842 Start.moveToFirst();
1843
1844 MachOBindEntry Finish(Opcodes, is64, BKind);
1845 Finish.moveToEnd();
1846
1847 return iterator_range<bind_iterator>(bind_iterator(Start),
1848 bind_iterator(Finish));
1849}
1850
1851iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1852 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1853 MachOBindEntry::Kind::Regular);
1854}
1855
1856iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1857 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1858 MachOBindEntry::Kind::Lazy);
1859}
1860
1861iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1862 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1863 MachOBindEntry::Kind::Weak);
1864}
1865
Rafael Espindola56f976f2013-04-18 18:08:55 +00001866StringRef
1867MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1868 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1869 return parseSegmentOrSectionName(Raw.data());
1870}
1871
1872ArrayRef<char>
1873MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001874 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001875 const section_base *Base =
1876 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001877 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001878}
1879
1880ArrayRef<char>
1881MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001882 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001883 const section_base *Base =
1884 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001885 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001886}
1887
1888bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001889MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001890 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001891 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001892 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001893 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001894}
1895
Eric Christopher1d62c252013-07-22 22:25:07 +00001896unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001897 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001898 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001899 return RE.r_word1 & 0xffffff;
1900 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001901}
1902
Eric Christopher1d62c252013-07-22 22:25:07 +00001903bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001904 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001905 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001906 return (RE.r_word1 >> 27) & 1;
1907 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001908}
1909
Eric Christopher1d62c252013-07-22 22:25:07 +00001910bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001911 const MachO::any_relocation_info &RE) const {
1912 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001913}
1914
Eric Christopher1d62c252013-07-22 22:25:07 +00001915uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001916 const MachO::any_relocation_info &RE) const {
1917 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001918}
1919
Kevin Enderby9907d0a2014-11-04 00:43:16 +00001920uint32_t MachOObjectFile::getScatteredRelocationType(
1921 const MachO::any_relocation_info &RE) const {
1922 return (RE.r_word0 >> 24) & 0xf;
1923}
1924
Eric Christopher1d62c252013-07-22 22:25:07 +00001925unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001926 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001927 if (isRelocationScattered(RE))
1928 return getScatteredRelocationAddress(RE);
1929 return getPlainRelocationAddress(RE);
1930}
1931
Charles Davis8bdfafd2013-09-01 04:28:48 +00001932unsigned MachOObjectFile::getAnyRelocationPCRel(
1933 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001934 if (isRelocationScattered(RE))
1935 return getScatteredRelocationPCRel(this, RE);
1936 return getPlainRelocationPCRel(this, RE);
1937}
1938
Eric Christopher1d62c252013-07-22 22:25:07 +00001939unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001940 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001941 if (isRelocationScattered(RE))
1942 return getScatteredRelocationLength(RE);
1943 return getPlainRelocationLength(this, RE);
1944}
1945
1946unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00001947MachOObjectFile::getAnyRelocationType(
1948 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001949 if (isRelocationScattered(RE))
1950 return getScatteredRelocationType(RE);
1951 return getPlainRelocationType(this, RE);
1952}
1953
Rafael Espindola52501032013-04-30 15:40:54 +00001954SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00001955MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001956 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00001957 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00001958 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00001959 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1960 DataRefImpl DRI;
1961 DRI.d.a = SecNum;
1962 return SectionRef(DRI, this);
1963}
1964
Rafael Espindola56f976f2013-04-18 18:08:55 +00001965MachOObjectFile::LoadCommandInfo
1966MachOObjectFile::getFirstLoadCommandInfo() const {
1967 MachOObjectFile::LoadCommandInfo Load;
1968
Charles Davis8bdfafd2013-09-01 04:28:48 +00001969 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1970 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001971 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001972 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001973 if (Load.C.cmdsize < 8)
1974 report_fatal_error("Load command with size < 8 bytes.");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001975 return Load;
1976}
1977
1978MachOObjectFile::LoadCommandInfo
1979MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1980 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001981 Next.Ptr = L.Ptr + L.C.cmdsize;
1982 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001983 if (Next.C.cmdsize < 8)
1984 report_fatal_error("Load command with size < 8 bytes.");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001985 return Next;
1986}
1987
Charles Davis8bdfafd2013-09-01 04:28:48 +00001988MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00001989 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001990 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001991}
1992
Charles Davis8bdfafd2013-09-01 04:28:48 +00001993MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00001994 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001995 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001996}
1997
Charles Davis8bdfafd2013-09-01 04:28:48 +00001998MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00001999 unsigned Index) const {
2000 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002001 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002002}
2003
Charles Davis8bdfafd2013-09-01 04:28:48 +00002004MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2005 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002006 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002007 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002008}
2009
Charles Davis8bdfafd2013-09-01 04:28:48 +00002010MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002011MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002012 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002013 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002014}
2015
Charles Davis8bdfafd2013-09-01 04:28:48 +00002016MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002017MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002018 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002019 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002020}
2021
Charles Davis8bdfafd2013-09-01 04:28:48 +00002022MachO::linkedit_data_command
2023MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2024 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002025}
2026
Charles Davis8bdfafd2013-09-01 04:28:48 +00002027MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002028MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002029 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002030}
2031
Charles Davis8bdfafd2013-09-01 04:28:48 +00002032MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002033MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002034 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002035}
2036
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002037MachO::linker_option_command
2038MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2039 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002040}
2041
Jim Grosbach448334a2014-03-18 22:09:05 +00002042MachO::version_min_command
2043MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2044 return getStruct<MachO::version_min_command>(this, L.Ptr);
2045}
2046
Tim Northover8f9590b2014-06-30 14:40:57 +00002047MachO::dylib_command
2048MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2049 return getStruct<MachO::dylib_command>(this, L.Ptr);
2050}
2051
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002052MachO::dyld_info_command
2053MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2054 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2055}
2056
2057MachO::dylinker_command
2058MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2059 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2060}
2061
2062MachO::uuid_command
2063MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2064 return getStruct<MachO::uuid_command>(this, L.Ptr);
2065}
2066
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002067MachO::rpath_command
2068MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2069 return getStruct<MachO::rpath_command>(this, L.Ptr);
2070}
2071
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002072MachO::source_version_command
2073MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2074 return getStruct<MachO::source_version_command>(this, L.Ptr);
2075}
2076
2077MachO::entry_point_command
2078MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2079 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2080}
2081
Kevin Enderby0804f4672014-12-16 23:25:52 +00002082MachO::encryption_info_command
2083MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2084 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2085}
2086
Kevin Enderby57538292014-12-17 01:01:30 +00002087MachO::encryption_info_command_64
2088MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2089 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2090}
2091
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002092MachO::sub_framework_command
2093MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2094 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2095}
Tim Northover8f9590b2014-06-30 14:40:57 +00002096
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002097MachO::sub_umbrella_command
2098MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2099 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2100}
2101
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002102MachO::sub_library_command
2103MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2104 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2105}
2106
Kevin Enderby186eac32014-12-19 21:06:24 +00002107MachO::sub_client_command
2108MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2109 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2110}
2111
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002112MachO::routines_command
2113MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2114 return getStruct<MachO::routines_command>(this, L.Ptr);
2115}
2116
2117MachO::routines_command_64
2118MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2119 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2120}
2121
Kevin Enderby48ef5342014-12-23 22:56:39 +00002122MachO::thread_command
2123MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2124 return getStruct<MachO::thread_command>(this, L.Ptr);
2125}
2126
Charles Davis8bdfafd2013-09-01 04:28:48 +00002127MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002128MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002129 DataRefImpl Sec;
2130 Sec.d.a = Rel.d.a;
2131 uint32_t Offset;
2132 if (is64Bit()) {
2133 MachO::section_64 Sect = getSection64(Sec);
2134 Offset = Sect.reloff;
2135 } else {
2136 MachO::section Sect = getSection(Sec);
2137 Offset = Sect.reloff;
2138 }
2139
2140 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2141 getPtr(this, Offset)) + Rel.d.b;
2142 return getStruct<MachO::any_relocation_info>(
2143 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002144}
2145
Charles Davis8bdfafd2013-09-01 04:28:48 +00002146MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002147MachOObjectFile::getDice(DataRefImpl Rel) const {
2148 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002149 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002150}
2151
Charles Davis8bdfafd2013-09-01 04:28:48 +00002152MachO::mach_header MachOObjectFile::getHeader() const {
2153 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002154}
2155
Charles Davis8bdfafd2013-09-01 04:28:48 +00002156MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2157 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002158}
2159
Charles Davis8bdfafd2013-09-01 04:28:48 +00002160uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2161 const MachO::dysymtab_command &DLC,
2162 unsigned Index) const {
2163 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2164 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002165}
2166
Charles Davis8bdfafd2013-09-01 04:28:48 +00002167MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002168MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2169 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002170 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2171 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002172}
2173
Charles Davis8bdfafd2013-09-01 04:28:48 +00002174MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002175 if (SymtabLoadCmd)
2176 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2177
2178 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2179 MachO::symtab_command Cmd;
2180 Cmd.cmd = MachO::LC_SYMTAB;
2181 Cmd.cmdsize = sizeof(MachO::symtab_command);
2182 Cmd.symoff = 0;
2183 Cmd.nsyms = 0;
2184 Cmd.stroff = 0;
2185 Cmd.strsize = 0;
2186 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002187}
2188
Charles Davis8bdfafd2013-09-01 04:28:48 +00002189MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002190 if (DysymtabLoadCmd)
2191 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2192
2193 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2194 MachO::dysymtab_command Cmd;
2195 Cmd.cmd = MachO::LC_DYSYMTAB;
2196 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2197 Cmd.ilocalsym = 0;
2198 Cmd.nlocalsym = 0;
2199 Cmd.iextdefsym = 0;
2200 Cmd.nextdefsym = 0;
2201 Cmd.iundefsym = 0;
2202 Cmd.nundefsym = 0;
2203 Cmd.tocoff = 0;
2204 Cmd.ntoc = 0;
2205 Cmd.modtaboff = 0;
2206 Cmd.nmodtab = 0;
2207 Cmd.extrefsymoff = 0;
2208 Cmd.nextrefsyms = 0;
2209 Cmd.indirectsymoff = 0;
2210 Cmd.nindirectsyms = 0;
2211 Cmd.extreloff = 0;
2212 Cmd.nextrel = 0;
2213 Cmd.locreloff = 0;
2214 Cmd.nlocrel = 0;
2215 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002216}
2217
Charles Davis8bdfafd2013-09-01 04:28:48 +00002218MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002219MachOObjectFile::getDataInCodeLoadCommand() const {
2220 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002221 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002222
2223 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002224 MachO::linkedit_data_command Cmd;
2225 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2226 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2227 Cmd.dataoff = 0;
2228 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002229 return Cmd;
2230}
2231
Kevin Enderby9a509442015-01-27 21:28:24 +00002232MachO::linkedit_data_command
2233MachOObjectFile::getLinkOptHintsLoadCommand() const {
2234 if (LinkOptHintsLoadCmd)
2235 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2236
2237 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2238 // fields.
2239 MachO::linkedit_data_command Cmd;
2240 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2241 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2242 Cmd.dataoff = 0;
2243 Cmd.datasize = 0;
2244 return Cmd;
2245}
2246
Nick Kledzikd04bc352014-08-30 00:20:14 +00002247ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2248 if (!DyldInfoLoadCmd)
2249 return ArrayRef<uint8_t>();
2250
2251 MachO::dyld_info_command DyldInfo
2252 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2253 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2254 getPtr(this, DyldInfo.rebase_off));
2255 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2256}
2257
2258ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2259 if (!DyldInfoLoadCmd)
2260 return ArrayRef<uint8_t>();
2261
2262 MachO::dyld_info_command DyldInfo
2263 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2264 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2265 getPtr(this, DyldInfo.bind_off));
2266 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2267}
2268
2269ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2270 if (!DyldInfoLoadCmd)
2271 return ArrayRef<uint8_t>();
2272
2273 MachO::dyld_info_command DyldInfo
2274 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2275 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2276 getPtr(this, DyldInfo.weak_bind_off));
2277 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2278}
2279
2280ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2281 if (!DyldInfoLoadCmd)
2282 return ArrayRef<uint8_t>();
2283
2284 MachO::dyld_info_command DyldInfo
2285 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2286 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2287 getPtr(this, DyldInfo.lazy_bind_off));
2288 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2289}
2290
2291ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2292 if (!DyldInfoLoadCmd)
2293 return ArrayRef<uint8_t>();
2294
2295 MachO::dyld_info_command DyldInfo
2296 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2297 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2298 getPtr(this, DyldInfo.export_off));
2299 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2300}
2301
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002302ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2303 if (!UuidLoadCmd)
2304 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002305 // Returning a pointer is fine as uuid doesn't need endian swapping.
2306 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2307 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002308}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002309
Rafael Espindola6e040c02013-04-26 20:07:33 +00002310StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002311 MachO::symtab_command S = getSymtabLoadCommand();
2312 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002313}
2314
Rafael Espindola56f976f2013-04-18 18:08:55 +00002315bool MachOObjectFile::is64Bit() const {
2316 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002317 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002318}
2319
2320void MachOObjectFile::ReadULEB128s(uint64_t Index,
2321 SmallVectorImpl<uint64_t> &Out) const {
2322 DataExtractor extractor(ObjectFile::getData(), true, 0);
2323
2324 uint32_t offset = Index;
2325 uint64_t data = 0;
2326 while (uint64_t delta = extractor.getULEB128(&offset)) {
2327 data += delta;
2328 Out.push_back(data);
2329 }
2330}
2331
Rafael Espindolac66d7612014-08-17 19:09:37 +00002332bool MachOObjectFile::isRelocatableObject() const {
2333 return getHeader().filetype == MachO::MH_OBJECT;
2334}
2335
Rafael Espindola437b0d52014-07-31 03:12:45 +00002336ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002337ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2338 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002339 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002340 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002341 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002342 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002343 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002344 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002345 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002346 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002347 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002348 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002349 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002350 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002351
Rafael Espindola692410e2014-01-21 23:06:54 +00002352 if (EC)
2353 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002354 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002355}
2356