blob: bbef6390dde52cc890ff18f40f959556a0ac99e5 [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
41template<typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000042static T getStruct(const MachOObjectFile *O, const char *P) {
Rafael Espindola3cdeb172013-04-19 13:45:05 +000043 T Cmd;
44 memcpy(&Cmd, P, sizeof(T));
45 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000046 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000047 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000048}
49
Rafael Espindola56f976f2013-04-18 18:08:55 +000050static uint32_t
51getSegmentLoadCommandNumSections(const MachOObjectFile *O,
52 const MachOObjectFile::LoadCommandInfo &L) {
53 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000054 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
55 return S.nsects;
Rafael Espindola421305a2013-04-07 20:01:29 +000056 }
Charles Davis8bdfafd2013-09-01 04:28:48 +000057 MachO::segment_command S = O->getSegmentLoadCommand(L);
58 return S.nsects;
Rafael Espindola5ffc0792013-04-07 16:07:35 +000059}
60
Nick Kledzik56ebef42014-09-16 01:41:51 +000061static bool isPageZeroSegment(const MachOObjectFile *O,
62 const MachOObjectFile::LoadCommandInfo &L) {
63 if (O->is64Bit()) {
64 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
65 return StringRef("__PAGEZERO").equals(S.segname);
66 }
67 MachO::segment_command S = O->getSegmentLoadCommand(L);
68 return StringRef("__PAGEZERO").equals(S.segname);
69}
70
71
Rafael Espindola6e040c02013-04-26 20:07:33 +000072static const char *
73getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
74 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000075 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
76
77 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000078 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
79 sizeof(MachO::segment_command);
80 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
81 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000082
83 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000084 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000085}
86
Rafael Espindola56f976f2013-04-18 18:08:55 +000087static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
88 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000089}
90
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000091static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000092getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000093 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000094 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000095}
96
Rafael Espindola56f976f2013-04-18 18:08:55 +000097static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000098 if (P[15] == 0)
99 // Null terminated.
100 return P;
101 // Not null terminated, so this is a 16 char string.
102 return StringRef(P, 16);
103}
104
Rafael Espindola56f976f2013-04-18 18:08:55 +0000105// Helper to advance a section or symbol iterator multiple increments at a time.
106template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000107static void advance(T &it, size_t Val) {
108 while (Val--)
109 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000110}
111
112static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000113 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000114}
115
116static void printRelocationTargetName(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000117 const MachO::any_relocation_info &RE,
Alp Tokere69170a2014-06-26 22:52:05 +0000118 raw_string_ostream &fmt) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000119 bool IsScattered = O->isRelocationScattered(RE);
120
121 // Target of a scattered relocation is an address. In the interest of
122 // generating pretty output, scan through the symbol table looking for a
123 // symbol that aligns with that address. If we find one, print it.
124 // Otherwise, we just print the hex address of the target.
125 if (IsScattered) {
126 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
127
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000128 for (const SymbolRef &Symbol : O->symbols()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000129 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000130 uint64_t Addr;
131 StringRef Name;
132
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000133 if ((ec = Symbol.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134 report_fatal_error(ec.message());
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000135 if (Addr != Val)
136 continue;
137 if ((ec = Symbol.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000138 report_fatal_error(ec.message());
139 fmt << Name;
140 return;
141 }
142
143 // If we couldn't find a symbol that this relocation refers to, try
144 // to find a section beginning instead.
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000145 for (const SectionRef &Section : O->sections()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000146 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000147
Rafael Espindola80291272014-10-08 15:28:58 +0000148 StringRef Name;
149 uint64_t Addr = Section.getAddress();
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000150 if (Addr != Val)
151 continue;
152 if ((ec = Section.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000153 report_fatal_error(ec.message());
154 fmt << Name;
155 return;
156 }
157
158 fmt << format("0x%x", Val);
159 return;
160 }
161
162 StringRef S;
163 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000164 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000165
166 if (isExtern) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000167 symbol_iterator SI = O->symbol_begin();
Rafael Espindola5e812af2014-01-30 02:49:50 +0000168 advance(SI, Val);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000169 SI->getName(S);
170 } else {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000171 section_iterator SI = O->section_begin();
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000172 // Adjust for the fact that sections are 1-indexed.
Rafael Espindola5e812af2014-01-30 02:49:50 +0000173 advance(SI, Val - 1);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000174 SI->getName(S);
175 }
176
177 fmt << S;
178}
179
Charles Davis8bdfafd2013-09-01 04:28:48 +0000180static uint32_t
181getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
182 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000183}
184
185static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000186getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
187 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000188}
189
190static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000191 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000192 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000193 return (RE.r_word1 >> 24) & 1;
194 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000195}
196
197static bool
198getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000199 const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000201}
202
203static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000204 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000205 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000206 return (RE.r_word1 >> 25) & 3;
207 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000208}
209
210static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000211getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000213}
214
215static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000216 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000217 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000218 return RE.r_word1 >> 28;
219 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000220}
221
Rafael Espindola56f976f2013-04-18 18:08:55 +0000222static uint32_t getSectionFlags(const MachOObjectFile *O,
223 DataRefImpl Sec) {
224 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000225 MachO::section_64 Sect = O->getSection64(Sec);
226 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000227 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000228 MachO::section Sect = O->getSection(Sec);
229 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000230}
231
Rafael Espindola48af1c22014-08-19 18:44:46 +0000232MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
233 bool Is64bits, std::error_code &EC)
234 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000235 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Nick Kledzik56ebef42014-09-16 01:41:51 +0000236 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000237 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000238 uint32_t LoadCommandCount = this->getHeader().ncmds;
239 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
240 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000241
242 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000243 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000244 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000245 // Multiple symbol tables
246 if (SymtabLoadCmd) {
247 EC = object_error::parse_failed;
248 return;
249 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000250 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000251 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000252 // Multiple dynamic symbol tables
253 if (DysymtabLoadCmd) {
254 EC = object_error::parse_failed;
255 return;
256 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000257 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000258 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000259 // Multiple data in code tables
260 if (DataInCodeLoadCmd) {
261 EC = object_error::parse_failed;
262 return;
263 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000264 DataInCodeLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000265 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
266 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000267 // Multiple dyldinfo load commands
268 if (DyldInfoLoadCmd) {
269 EC = object_error::parse_failed;
270 return;
271 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000272 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000273 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000274 // Multiple UUID load commands
275 if (UuidLoadCmd) {
276 EC = object_error::parse_failed;
277 return;
278 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000279 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000280 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000281 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
282 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000283 const char *Sec = getSectionPtr(this, Load, J);
284 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000285 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000286 if (isPageZeroSegment(this, Load))
287 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000288 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
289 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
290 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
291 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
292 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
293 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000294 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000295
296 if (I == LoadCommandCount - 1)
297 break;
298 else
299 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000300 }
301}
302
Rafael Espindola5e812af2014-01-30 02:49:50 +0000303void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000304 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000305 sizeof(MachO::nlist_64) :
306 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000307 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000308}
309
Rafael Espindola3acea392014-06-12 21:46:39 +0000310std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
311 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000312 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000313 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000314 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000315 Res = StringRef(Start);
316 return object_error::success;
317}
318
Kevin Enderby980b2582014-06-05 21:21:57 +0000319// getIndirectName() returns the name of the alias'ed symbol who's string table
320// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000321std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
322 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000323 StringRef StringTable = getStringTableData();
324 uint64_t NValue;
325 if (is64Bit()) {
326 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
327 NValue = Entry.n_value;
328 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
329 return object_error::parse_failed;
330 } else {
331 MachO::nlist Entry = getSymbolTableEntry(Symb);
332 NValue = Entry.n_value;
333 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
334 return object_error::parse_failed;
335 }
336 if (NValue >= StringTable.size())
337 return object_error::parse_failed;
338 const char *Start = &StringTable.data()[NValue];
339 Res = StringRef(Start);
340 return object_error::success;
341}
342
Rafael Espindola3acea392014-06-12 21:46:39 +0000343std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
344 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000345 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000346 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000347 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
348 Entry.n_value == 0)
349 Res = UnknownAddressOrSize;
350 else
351 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000352 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000353 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000354 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
355 Entry.n_value == 0)
356 Res = UnknownAddressOrSize;
357 else
358 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000359 }
360 return object_error::success;
361}
362
Rafael Espindola3acea392014-06-12 21:46:39 +0000363std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
364 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000365 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000366 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000367 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000368 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000369 } else {
370 Result = 0;
371 }
372 return object_error::success;
373}
374
Rafael Espindola3acea392014-06-12 21:46:39 +0000375std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
376 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000377 uint64_t BeginOffset;
378 uint64_t EndOffset = 0;
379 uint8_t SectionIndex;
380
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000381 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000382 uint64_t Value;
383 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000384 if (Value == UnknownAddressOrSize) {
385 Result = UnknownAddressOrSize;
386 return object_error::success;
387 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000388
389 BeginOffset = Value;
390
Charles Davis8bdfafd2013-09-01 04:28:48 +0000391 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000392 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000393 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000394 if (flags & SymbolRef::SF_Common)
395 Result = Value;
396 else
397 Result = UnknownAddressOrSize;
398 return object_error::success;
399 }
400 // Unfortunately symbols are unsorted so we need to touch all
401 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000402 for (const SymbolRef &Symbol : symbols()) {
403 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000404 Entry = getSymbolTableEntryBase(this, DRI);
405 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000406 if (Value == UnknownAddressOrSize)
407 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000408 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000409 if (!EndOffset || Value < EndOffset)
410 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000411 }
412 if (!EndOffset) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000413 DataRefImpl Sec;
414 Sec.d.a = SectionIndex-1;
Rafael Espindola80291272014-10-08 15:28:58 +0000415 uint64_t Size = getSectionSize(Sec);
416 EndOffset = getSectionAddress(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000417 EndOffset += Size;
418 }
419 Result = EndOffset - BeginOffset;
420 return object_error::success;
421}
422
Rafael Espindola3acea392014-06-12 21:46:39 +0000423std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
424 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000425 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000426 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000427
428 Res = SymbolRef::ST_Other;
429
430 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000431 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000432 Res = SymbolRef::ST_Debug;
433 return object_error::success;
434 }
435
Charles Davis74ec8b02013-08-27 05:00:13 +0000436 switch (n_type & MachO::N_TYPE) {
437 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000438 Res = SymbolRef::ST_Unknown;
439 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000440 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000441 Res = SymbolRef::ST_Function;
442 break;
443 }
444 return object_error::success;
445}
446
Rafael Espindola20122a42014-01-31 20:57:12 +0000447uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000448 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000449
Charles Davis8bdfafd2013-09-01 04:28:48 +0000450 uint8_t MachOType = Entry.n_type;
451 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000452
Rafael Espindola20122a42014-01-31 20:57:12 +0000453 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000454
Charles Davis74ec8b02013-08-27 05:00:13 +0000455 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000456 Result |= SymbolRef::SF_Undefined;
457
Tim Northovereaef0742014-05-30 13:22:59 +0000458 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
459 Result |= SymbolRef::SF_Indirect;
460
Rafael Espindolaa1356322013-11-02 05:03:24 +0000461 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000462 Result |= SymbolRef::SF_FormatSpecific;
463
Charles Davis74ec8b02013-08-27 05:00:13 +0000464 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000465 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000466 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000467 uint64_t Value;
468 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000469 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000470 Result |= SymbolRef::SF_Common;
471 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000472 }
473
Charles Davis74ec8b02013-08-27 05:00:13 +0000474 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000475 Result |= SymbolRef::SF_Weak;
476
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000477 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
478 Result |= SymbolRef::SF_Thumb;
479
Charles Davis74ec8b02013-08-27 05:00:13 +0000480 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000481 Result |= SymbolRef::SF_Absolute;
482
Rafael Espindola20122a42014-01-31 20:57:12 +0000483 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000484}
485
Rafael Espindola3acea392014-06-12 21:46:39 +0000486std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
487 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000488 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000489 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000490
491 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000492 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000493 } else {
494 DataRefImpl DRI;
495 DRI.d.a = index - 1;
496 Res = section_iterator(SectionRef(DRI, this));
497 }
498
499 return object_error::success;
500}
501
Rafael Espindola5e812af2014-01-30 02:49:50 +0000502void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000503 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000504}
505
Rafael Espindola3acea392014-06-12 21:46:39 +0000506std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
507 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000508 ArrayRef<char> Raw = getSectionRawName(Sec);
509 Result = parseSegmentOrSectionName(Raw.data());
510 return object_error::success;
511}
512
Rafael Espindola80291272014-10-08 15:28:58 +0000513uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
514 if (is64Bit())
515 return getSection64(Sec).addr;
516 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000517}
518
Rafael Espindola80291272014-10-08 15:28:58 +0000519uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
520 if (is64Bit())
521 return getSection64(Sec).size;
522 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000523}
524
Rafael Espindola3acea392014-06-12 21:46:39 +0000525std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
526 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000527 uint32_t Offset;
528 uint64_t Size;
529
530 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000531 MachO::section_64 Sect = getSection64(Sec);
532 Offset = Sect.offset;
533 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000534 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000535 MachO::section Sect = getSection(Sec);
536 Offset = Sect.offset;
537 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000538 }
539
540 Res = this->getData().substr(Offset, Size);
541 return object_error::success;
542}
543
Rafael Espindola80291272014-10-08 15:28:58 +0000544uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000545 uint32_t Align;
546 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000547 MachO::section_64 Sect = getSection64(Sec);
548 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000549 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000550 MachO::section Sect = getSection(Sec);
551 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000552 }
553
Rafael Espindola80291272014-10-08 15:28:58 +0000554 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000555}
556
Rafael Espindola80291272014-10-08 15:28:58 +0000557bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000558 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000559 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000560}
561
Rafael Espindola80291272014-10-08 15:28:58 +0000562bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000563 uint32_t Flags = getSectionFlags(this, Sec);
564 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000565 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
566 !(SectionType == MachO::S_ZEROFILL ||
567 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000568}
569
Rafael Espindola80291272014-10-08 15:28:58 +0000570bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000571 uint32_t Flags = getSectionFlags(this, Sec);
572 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000573 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
574 (SectionType == MachO::S_ZEROFILL ||
575 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000576}
577
Rafael Espindola80291272014-10-08 15:28:58 +0000578bool MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sect) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000579 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000580 return true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000581}
582
Rafael Espindola80291272014-10-08 15:28:58 +0000583bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000584 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000585 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000586}
587
Rafael Espindola80291272014-10-08 15:28:58 +0000588bool MachOObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000589 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis74ec8b02013-08-27 05:00:13 +0000590 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000591 return SectionType == MachO::S_ZEROFILL ||
592 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000593}
594
Rafael Espindola80291272014-10-08 15:28:58 +0000595bool MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000596 // Consider using the code from isSectionText to look for __const sections.
597 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
598 // to use section attributes to distinguish code from data.
599
600 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000601 return false;
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000602}
603
Rafael Espindola80291272014-10-08 15:28:58 +0000604bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
605 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000606 SymbolRef::Type ST;
607 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000608 if (ST == SymbolRef::ST_Unknown)
609 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000610
Rafael Espindola80291272014-10-08 15:28:58 +0000611 uint64_t SectBegin = getSectionAddress(Sec);
612 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000613 SectEnd += SectBegin;
614
615 uint64_t SymAddr;
616 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000617 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000618}
619
Rui Ueyamabc654b12013-09-27 21:47:05 +0000620relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000621 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000622 Ret.d.a = Sec.d.a;
623 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000624 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000625}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000626
Rafael Espindola56f976f2013-04-18 18:08:55 +0000627relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000628MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000629 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000630 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000631 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000632 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000633 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000634 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000635 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000636 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000637
Rafael Espindola56f976f2013-04-18 18:08:55 +0000638 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000639 Ret.d.a = Sec.d.a;
640 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000641 return relocation_iterator(RelocationRef(Ret, this));
642}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000643
Rafael Espindola5e812af2014-01-30 02:49:50 +0000644void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000645 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000646}
Owen Anderson171f4852011-10-24 23:20:07 +0000647
Rafael Espindola3acea392014-06-12 21:46:39 +0000648std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
649 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000650 uint64_t Offset;
651 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000652
653 DataRefImpl Sec;
654 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000655 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000656 Res = SecAddress + Offset;
657 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000658}
659
Rafael Espindola3acea392014-06-12 21:46:39 +0000660std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
661 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000662 assert(getHeader().filetype == MachO::MH_OBJECT &&
663 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000664 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000665 Res = getAnyRelocationAddress(RE);
666 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000667}
668
Rafael Espindola806f0062013-06-05 01:33:53 +0000669symbol_iterator
670MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000671 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000672 if (isRelocationScattered(RE))
673 return symbol_end();
674
Rafael Espindola56f976f2013-04-18 18:08:55 +0000675 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
676 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000677 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000678 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000679
Charles Davis8bdfafd2013-09-01 04:28:48 +0000680 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000681 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000682 sizeof(MachO::nlist_64) :
683 sizeof(MachO::nlist);
684 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000685 DataRefImpl Sym;
686 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000687 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000688}
689
Rafael Espindola3acea392014-06-12 21:46:39 +0000690std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
691 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000692 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000693 Res = getAnyRelocationType(RE);
694 return object_error::success;
695}
696
Rafael Espindola3acea392014-06-12 21:46:39 +0000697std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000698MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
699 SmallVectorImpl<char> &Result) const {
700 StringRef res;
701 uint64_t RType;
702 getRelocationType(Rel, RType);
703
704 unsigned Arch = this->getArch();
705
706 switch (Arch) {
707 case Triple::x86: {
708 static const char *const Table[] = {
709 "GENERIC_RELOC_VANILLA",
710 "GENERIC_RELOC_PAIR",
711 "GENERIC_RELOC_SECTDIFF",
712 "GENERIC_RELOC_PB_LA_PTR",
713 "GENERIC_RELOC_LOCAL_SECTDIFF",
714 "GENERIC_RELOC_TLV" };
715
Eric Christopher13250cb2013-12-06 02:33:38 +0000716 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000717 res = "Unknown";
718 else
719 res = Table[RType];
720 break;
721 }
722 case Triple::x86_64: {
723 static const char *const Table[] = {
724 "X86_64_RELOC_UNSIGNED",
725 "X86_64_RELOC_SIGNED",
726 "X86_64_RELOC_BRANCH",
727 "X86_64_RELOC_GOT_LOAD",
728 "X86_64_RELOC_GOT",
729 "X86_64_RELOC_SUBTRACTOR",
730 "X86_64_RELOC_SIGNED_1",
731 "X86_64_RELOC_SIGNED_2",
732 "X86_64_RELOC_SIGNED_4",
733 "X86_64_RELOC_TLV" };
734
735 if (RType > 9)
736 res = "Unknown";
737 else
738 res = Table[RType];
739 break;
740 }
741 case Triple::arm: {
742 static const char *const Table[] = {
743 "ARM_RELOC_VANILLA",
744 "ARM_RELOC_PAIR",
745 "ARM_RELOC_SECTDIFF",
746 "ARM_RELOC_LOCAL_SECTDIFF",
747 "ARM_RELOC_PB_LA_PTR",
748 "ARM_RELOC_BR24",
749 "ARM_THUMB_RELOC_BR22",
750 "ARM_THUMB_32BIT_BRANCH",
751 "ARM_RELOC_HALF",
752 "ARM_RELOC_HALF_SECTDIFF" };
753
754 if (RType > 9)
755 res = "Unknown";
756 else
757 res = Table[RType];
758 break;
759 }
Tim Northover00ed9962014-03-29 10:18:08 +0000760 case Triple::aarch64: {
761 static const char *const Table[] = {
762 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
763 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
764 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
765 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
766 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
767 "ARM64_RELOC_ADDEND"
768 };
769
770 if (RType >= array_lengthof(Table))
771 res = "Unknown";
772 else
773 res = Table[RType];
774 break;
775 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000776 case Triple::ppc: {
777 static const char *const Table[] = {
778 "PPC_RELOC_VANILLA",
779 "PPC_RELOC_PAIR",
780 "PPC_RELOC_BR14",
781 "PPC_RELOC_BR24",
782 "PPC_RELOC_HI16",
783 "PPC_RELOC_LO16",
784 "PPC_RELOC_HA16",
785 "PPC_RELOC_LO14",
786 "PPC_RELOC_SECTDIFF",
787 "PPC_RELOC_PB_LA_PTR",
788 "PPC_RELOC_HI16_SECTDIFF",
789 "PPC_RELOC_LO16_SECTDIFF",
790 "PPC_RELOC_HA16_SECTDIFF",
791 "PPC_RELOC_JBSR",
792 "PPC_RELOC_LO14_SECTDIFF",
793 "PPC_RELOC_LOCAL_SECTDIFF" };
794
Eric Christopher13250cb2013-12-06 02:33:38 +0000795 if (RType > 15)
796 res = "Unknown";
797 else
798 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000799 break;
800 }
801 case Triple::UnknownArch:
802 res = "Unknown";
803 break;
804 }
805 Result.append(res.begin(), res.end());
806 return object_error::success;
807}
808
Rafael Espindola3acea392014-06-12 21:46:39 +0000809std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000810MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000811 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000812 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000813
Rafael Espindola56f976f2013-04-18 18:08:55 +0000814 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000815
Alp Tokere69170a2014-06-26 22:52:05 +0000816 std::string fmtbuf;
817 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000818 unsigned Type = this->getAnyRelocationType(RE);
819 bool IsPCRel = this->getAnyRelocationPCRel(RE);
820
821 // Determine any addends that should be displayed with the relocation.
822 // These require decoding the relocation type, which is triple-specific.
823
824 // X86_64 has entirely custom relocation types.
825 if (Arch == Triple::x86_64) {
826 bool isPCRel = getAnyRelocationPCRel(RE);
827
828 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000829 case MachO::X86_64_RELOC_GOT_LOAD:
830 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000831 printRelocationTargetName(this, RE, fmt);
832 fmt << "@GOT";
833 if (isPCRel) fmt << "PCREL";
834 break;
835 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000836 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000837 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000838 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000839 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000840
Charles Davis8bdfafd2013-09-01 04:28:48 +0000841 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000842 // X86_64_RELOC_UNSIGNED.
843 // NOTE: Scattered relocations don't exist on x86_64.
844 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000845 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000846 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
847 "X86_64_RELOC_SUBTRACTOR.");
848
Charles Davis8bdfafd2013-09-01 04:28:48 +0000849 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
850 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000851 printRelocationTargetName(this, RENext, fmt);
852 fmt << "-";
853 printRelocationTargetName(this, RE, fmt);
854 break;
855 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000856 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000857 printRelocationTargetName(this, RE, fmt);
858 fmt << "@TLV";
859 if (isPCRel) fmt << "P";
860 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000861 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000862 printRelocationTargetName(this, RE, fmt);
863 fmt << "-1";
864 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000865 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000866 printRelocationTargetName(this, RE, fmt);
867 fmt << "-2";
868 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000869 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000870 printRelocationTargetName(this, RE, fmt);
871 fmt << "-4";
872 break;
873 default:
874 printRelocationTargetName(this, RE, fmt);
875 break;
876 }
877 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000878 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
879 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000880 // Generic relocation types...
881 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000882 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000883 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000884 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000885 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000886 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000887 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000888
889 // X86 sect diff's must be followed by a relocation of type
890 // GENERIC_RELOC_PAIR.
891 unsigned RType = getAnyRelocationType(RENext);
892
Charles Davis8bdfafd2013-09-01 04:28:48 +0000893 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000894 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
895 "GENERIC_RELOC_SECTDIFF.");
896
897 printRelocationTargetName(this, RE, fmt);
898 fmt << "-";
899 printRelocationTargetName(this, RENext, fmt);
900 break;
901 }
902 }
903
David Fangb88cdf62013-08-08 20:14:40 +0000904 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000905 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000906 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000907 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000908 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000909 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000910
911 // X86 sect diff's must be followed by a relocation of type
912 // GENERIC_RELOC_PAIR.
913 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000914 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000915 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
916 "GENERIC_RELOC_LOCAL_SECTDIFF.");
917
918 printRelocationTargetName(this, RE, fmt);
919 fmt << "-";
920 printRelocationTargetName(this, RENext, fmt);
921 break;
922 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000923 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000924 printRelocationTargetName(this, RE, fmt);
925 fmt << "@TLV";
926 if (IsPCRel) fmt << "P";
927 break;
928 }
929 default:
930 printRelocationTargetName(this, RE, fmt);
931 }
932 } else { // ARM-specific relocations
933 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000934 case MachO::ARM_RELOC_HALF:
935 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000936 // Half relocations steal a bit from the length field to encode
937 // whether this is an upper16 or a lower16 relocation.
938 bool isUpper = getAnyRelocationLength(RE) >> 1;
939
940 if (isUpper)
941 fmt << ":upper16:(";
942 else
943 fmt << ":lower16:(";
944 printRelocationTargetName(this, RE, fmt);
945
946 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000947 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000948 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000949
950 // ARM half relocs must be followed by a relocation of type
951 // ARM_RELOC_PAIR.
952 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000953 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000954 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000955 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000956
957 // NOTE: The half of the target virtual address is stashed in the
958 // address field of the secondary relocation, but we can't reverse
959 // engineer the constant offset from it without decoding the movw/movt
960 // instruction to find the other half in its immediate field.
961
962 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
963 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000964 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000965 fmt << "-";
966 printRelocationTargetName(this, RENext, fmt);
967 }
968
969 fmt << ")";
970 break;
971 }
972 default: {
973 printRelocationTargetName(this, RE, fmt);
974 }
975 }
976 }
977 } else
978 printRelocationTargetName(this, RE, fmt);
979
Alp Tokere69170a2014-06-26 22:52:05 +0000980 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000981 Result.append(fmtbuf.begin(), fmtbuf.end());
982 return object_error::success;
983}
984
Rafael Espindola3acea392014-06-12 21:46:39 +0000985std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
986 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000987 unsigned Arch = getArch();
988 uint64_t Type;
989 getRelocationType(Rel, Type);
990
991 Result = false;
992
993 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
994 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000995 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000996 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000997 } else if (Arch == Triple::x86_64) {
998 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000999 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001000 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001001 DataRefImpl RelPrev = Rel;
1002 RelPrev.d.a--;
1003 uint64_t PrevType;
1004 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001005 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001006 Result = true;
1007 }
1008 }
1009
1010 return object_error::success;
1011}
1012
Kevin Enderby980b2582014-06-05 21:21:57 +00001013//
1014// guessLibraryShortName() is passed a name of a dynamic library and returns a
1015// guess on what the short name is. Then name is returned as a substring of the
1016// StringRef Name passed in. The name of the dynamic library is recognized as
1017// a framework if it has one of the two following forms:
1018// Foo.framework/Versions/A/Foo
1019// Foo.framework/Foo
1020// Where A and Foo can be any string. And may contain a trailing suffix
1021// starting with an underbar. If the Name is recognized as a framework then
1022// isFramework is set to true else it is set to false. If the Name has a
1023// suffix then Suffix is set to the substring in Name that contains the suffix
1024// else it is set to a NULL StringRef.
1025//
1026// The Name of the dynamic library is recognized as a library name if it has
1027// one of the two following forms:
1028// libFoo.A.dylib
1029// libFoo.dylib
1030// The library may have a suffix trailing the name Foo of the form:
1031// libFoo_profile.A.dylib
1032// libFoo_profile.dylib
1033//
1034// The Name of the dynamic library is also recognized as a library name if it
1035// has the following form:
1036// Foo.qtx
1037//
1038// If the Name of the dynamic library is none of the forms above then a NULL
1039// StringRef is returned.
1040//
1041StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1042 bool &isFramework,
1043 StringRef &Suffix) {
1044 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1045 size_t a, b, c, d, Idx;
1046
1047 isFramework = false;
1048 Suffix = StringRef();
1049
1050 // Pull off the last component and make Foo point to it
1051 a = Name.rfind('/');
1052 if (a == Name.npos || a == 0)
1053 goto guess_library;
1054 Foo = Name.slice(a+1, Name.npos);
1055
1056 // Look for a suffix starting with a '_'
1057 Idx = Foo.rfind('_');
1058 if (Idx != Foo.npos && Foo.size() >= 2) {
1059 Suffix = Foo.slice(Idx, Foo.npos);
1060 Foo = Foo.slice(0, Idx);
1061 }
1062
1063 // First look for the form Foo.framework/Foo
1064 b = Name.rfind('/', a);
1065 if (b == Name.npos)
1066 Idx = 0;
1067 else
1068 Idx = b+1;
1069 F = Name.slice(Idx, Idx + Foo.size());
1070 DotFramework = Name.slice(Idx + Foo.size(),
1071 Idx + Foo.size() + sizeof(".framework/")-1);
1072 if (F == Foo && DotFramework == ".framework/") {
1073 isFramework = true;
1074 return Foo;
1075 }
1076
1077 // Next look for the form Foo.framework/Versions/A/Foo
1078 if (b == Name.npos)
1079 goto guess_library;
1080 c = Name.rfind('/', b);
1081 if (c == Name.npos || c == 0)
1082 goto guess_library;
1083 V = Name.slice(c+1, Name.npos);
1084 if (!V.startswith("Versions/"))
1085 goto guess_library;
1086 d = Name.rfind('/', c);
1087 if (d == Name.npos)
1088 Idx = 0;
1089 else
1090 Idx = d+1;
1091 F = Name.slice(Idx, Idx + Foo.size());
1092 DotFramework = Name.slice(Idx + Foo.size(),
1093 Idx + Foo.size() + sizeof(".framework/")-1);
1094 if (F == Foo && DotFramework == ".framework/") {
1095 isFramework = true;
1096 return Foo;
1097 }
1098
1099guess_library:
1100 // pull off the suffix after the "." and make a point to it
1101 a = Name.rfind('.');
1102 if (a == Name.npos || a == 0)
1103 return StringRef();
1104 Dylib = Name.slice(a, Name.npos);
1105 if (Dylib != ".dylib")
1106 goto guess_qtx;
1107
1108 // First pull off the version letter for the form Foo.A.dylib if any.
1109 if (a >= 3) {
1110 Dot = Name.slice(a-2, a-1);
1111 if (Dot == ".")
1112 a = a - 2;
1113 }
1114
1115 b = Name.rfind('/', a);
1116 if (b == Name.npos)
1117 b = 0;
1118 else
1119 b = b+1;
1120 // ignore any suffix after an underbar like Foo_profile.A.dylib
1121 Idx = Name.find('_', b);
1122 if (Idx != Name.npos && Idx != b) {
1123 Lib = Name.slice(b, Idx);
1124 Suffix = Name.slice(Idx, a);
1125 }
1126 else
1127 Lib = Name.slice(b, a);
1128 // There are incorrect library names of the form:
1129 // libATS.A_profile.dylib so check for these.
1130 if (Lib.size() >= 3) {
1131 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1132 if (Dot == ".")
1133 Lib = Lib.slice(0, Lib.size()-2);
1134 }
1135 return Lib;
1136
1137guess_qtx:
1138 Qtx = Name.slice(a, Name.npos);
1139 if (Qtx != ".qtx")
1140 return StringRef();
1141 b = Name.rfind('/', a);
1142 if (b == Name.npos)
1143 Lib = Name.slice(0, a);
1144 else
1145 Lib = Name.slice(b+1, a);
1146 // There are library names of the form: QT.A.qtx so check for these.
1147 if (Lib.size() >= 3) {
1148 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1149 if (Dot == ".")
1150 Lib = Lib.slice(0, Lib.size()-2);
1151 }
1152 return Lib;
1153}
1154
1155// getLibraryShortNameByIndex() is used to get the short name of the library
1156// for an undefined symbol in a linked Mach-O binary that was linked with the
1157// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1158// It is passed the index (0 - based) of the library as translated from
1159// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001160std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001161 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001162 if (Index >= Libraries.size())
1163 return object_error::parse_failed;
1164
Kevin Enderby980b2582014-06-05 21:21:57 +00001165 // If the cache of LibrariesShortNames is not built up do that first for
1166 // all the Libraries.
1167 if (LibrariesShortNames.size() == 0) {
1168 for (unsigned i = 0; i < Libraries.size(); i++) {
1169 MachO::dylib_command D =
1170 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001171 if (D.dylib.name >= D.cmdsize)
1172 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001173 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001174 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001175 if (D.dylib.name+Name.size() >= D.cmdsize)
1176 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001177 StringRef Suffix;
1178 bool isFramework;
1179 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001180 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001181 LibrariesShortNames.push_back(Name);
1182 else
1183 LibrariesShortNames.push_back(shortName);
1184 }
1185 }
1186
1187 Res = LibrariesShortNames[Index];
1188 return object_error::success;
1189}
1190
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001191basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001192 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001193}
1194
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001195basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001196 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001197 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001198 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001199
Charles Davis8bdfafd2013-09-01 04:28:48 +00001200 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001201 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001202 sizeof(MachO::nlist_64) :
1203 sizeof(MachO::nlist);
1204 unsigned Offset = Symtab.symoff +
1205 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001206 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001207 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001208}
1209
Lang Hames36072da2014-05-12 21:39:59 +00001210basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1211 DataRefImpl DRI;
1212 if (!SymtabLoadCmd)
1213 return basic_symbol_iterator(SymbolRef(DRI, this));
1214
1215 MachO::symtab_command Symtab = getSymtabLoadCommand();
1216 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1217 unsigned SymbolTableEntrySize =
1218 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1219 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1220 DRI.p += Index * SymbolTableEntrySize;
1221 return basic_symbol_iterator(SymbolRef(DRI, this));
1222}
1223
Rafael Espindolab5155a52014-02-10 20:24:04 +00001224section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001225 DataRefImpl DRI;
1226 return section_iterator(SectionRef(DRI, this));
1227}
1228
Rafael Espindolab5155a52014-02-10 20:24:04 +00001229section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001230 DataRefImpl DRI;
1231 DRI.d.a = Sections.size();
1232 return section_iterator(SectionRef(DRI, this));
1233}
1234
Rafael Espindola56f976f2013-04-18 18:08:55 +00001235uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001236 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001237}
1238
Rafael Espindola56f976f2013-04-18 18:08:55 +00001239StringRef MachOObjectFile::getFileFormatName() const {
1240 unsigned CPUType = getCPUType(this);
1241 if (!is64Bit()) {
1242 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001243 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001244 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001245 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001246 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001247 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001248 return "Mach-O 32-bit ppc";
1249 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001250 return "Mach-O 32-bit unknown";
1251 }
1252 }
1253
Rafael Espindola56f976f2013-04-18 18:08:55 +00001254 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001255 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001256 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001257 case llvm::MachO::CPU_TYPE_ARM64:
1258 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001259 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001260 return "Mach-O 64-bit ppc64";
1261 default:
1262 return "Mach-O 64-bit unknown";
1263 }
1264}
1265
Alexey Samsonove6388e62013-06-18 15:03:28 +00001266Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1267 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001268 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001269 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001270 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001271 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001272 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001273 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001274 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001275 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001276 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001277 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001278 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001279 return Triple::ppc64;
1280 default:
1281 return Triple::UnknownArch;
1282 }
1283}
1284
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001285Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1286 const char **McpuDefault) {
1287 if (McpuDefault)
1288 *McpuDefault = nullptr;
1289
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001290 switch (CPUType) {
1291 case MachO::CPU_TYPE_I386:
1292 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1293 case MachO::CPU_SUBTYPE_I386_ALL:
1294 return Triple("i386-apple-darwin");
1295 default:
1296 return Triple();
1297 }
1298 case MachO::CPU_TYPE_X86_64:
1299 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1300 case MachO::CPU_SUBTYPE_X86_64_ALL:
1301 return Triple("x86_64-apple-darwin");
1302 case MachO::CPU_SUBTYPE_X86_64_H:
1303 return Triple("x86_64h-apple-darwin");
1304 default:
1305 return Triple();
1306 }
1307 case MachO::CPU_TYPE_ARM:
1308 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1309 case MachO::CPU_SUBTYPE_ARM_V4T:
1310 return Triple("armv4t-apple-darwin");
1311 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1312 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001313 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1314 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001315 case MachO::CPU_SUBTYPE_ARM_V6:
1316 return Triple("armv6-apple-darwin");
1317 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001318 if (McpuDefault)
1319 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001320 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001321 case MachO::CPU_SUBTYPE_ARM_V7:
1322 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001323 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001324 if (McpuDefault)
1325 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001326 return Triple("armv7em-apple-darwin");
1327 case MachO::CPU_SUBTYPE_ARM_V7K:
1328 return Triple("armv7k-apple-darwin");
1329 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001330 if (McpuDefault)
1331 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001332 return Triple("armv7m-apple-darwin");
1333 case MachO::CPU_SUBTYPE_ARM_V7S:
1334 return Triple("armv7s-apple-darwin");
1335 default:
1336 return Triple();
1337 }
1338 case MachO::CPU_TYPE_ARM64:
1339 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1340 case MachO::CPU_SUBTYPE_ARM64_ALL:
1341 return Triple("arm64-apple-darwin");
1342 default:
1343 return Triple();
1344 }
1345 case MachO::CPU_TYPE_POWERPC:
1346 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1347 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1348 return Triple("ppc-apple-darwin");
1349 default:
1350 return Triple();
1351 }
1352 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001353 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001354 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1355 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001356 default:
1357 return Triple();
1358 }
1359 default:
1360 return Triple();
1361 }
1362}
1363
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001364Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1365 const char **McpuDefault) {
1366 if (McpuDefault)
1367 *McpuDefault = nullptr;
1368
1369 switch (CPUType) {
1370 case MachO::CPU_TYPE_ARM:
1371 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1372 case MachO::CPU_SUBTYPE_ARM_V4T:
1373 return Triple("thumbv4t-apple-darwin");
1374 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1375 return Triple("thumbv5e-apple-darwin");
1376 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1377 return Triple("xscale-apple-darwin");
1378 case MachO::CPU_SUBTYPE_ARM_V6:
1379 return Triple("thumbv6-apple-darwin");
1380 case MachO::CPU_SUBTYPE_ARM_V6M:
1381 if (McpuDefault)
1382 *McpuDefault = "cortex-m0";
1383 return Triple("thumbv6m-apple-darwin");
1384 case MachO::CPU_SUBTYPE_ARM_V7:
1385 return Triple("thumbv7-apple-darwin");
1386 case MachO::CPU_SUBTYPE_ARM_V7EM:
1387 if (McpuDefault)
1388 *McpuDefault = "cortex-m4";
1389 return Triple("thumbv7em-apple-darwin");
1390 case MachO::CPU_SUBTYPE_ARM_V7K:
1391 return Triple("thumbv7k-apple-darwin");
1392 case MachO::CPU_SUBTYPE_ARM_V7M:
1393 if (McpuDefault)
1394 *McpuDefault = "cortex-m3";
1395 return Triple("thumbv7m-apple-darwin");
1396 case MachO::CPU_SUBTYPE_ARM_V7S:
1397 return Triple("thumbv7s-apple-darwin");
1398 default:
1399 return Triple();
1400 }
1401 default:
1402 return Triple();
1403 }
1404}
1405
1406Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1407 const char **McpuDefault,
1408 Triple *ThumbTriple) {
1409 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1410 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1411 McpuDefault);
1412 return T;
1413}
1414
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001415Triple MachOObjectFile::getHostArch() {
1416 return Triple(sys::getDefaultTargetTriple());
1417}
1418
Rafael Espindola72318b42014-08-08 16:30:17 +00001419bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1420 return StringSwitch<bool>(ArchFlag)
1421 .Case("i386", true)
1422 .Case("x86_64", true)
1423 .Case("x86_64h", true)
1424 .Case("armv4t", true)
1425 .Case("arm", true)
1426 .Case("armv5e", true)
1427 .Case("armv6", true)
1428 .Case("armv6m", true)
1429 .Case("armv7em", true)
1430 .Case("armv7k", true)
1431 .Case("armv7m", true)
1432 .Case("armv7s", true)
1433 .Case("arm64", true)
1434 .Case("ppc", true)
1435 .Case("ppc64", true)
1436 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001437}
1438
Alexey Samsonove6388e62013-06-18 15:03:28 +00001439unsigned MachOObjectFile::getArch() const {
1440 return getArch(getCPUType(this));
1441}
1442
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001443Triple MachOObjectFile::getArch(const char **McpuDefault,
1444 Triple *ThumbTriple) const {
1445 Triple T;
1446 if (is64Bit()) {
1447 MachO::mach_header_64 H_64;
1448 H_64 = getHeader64();
1449 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1450 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1451 McpuDefault);
1452 } else {
1453 MachO::mach_header H;
1454 H = getHeader();
1455 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1456 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1457 McpuDefault);
1458 }
1459 return T;
1460}
1461
Rui Ueyamabc654b12013-09-27 21:47:05 +00001462relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001463 DataRefImpl DRI;
1464 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001465 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001466}
1467
Rui Ueyamabc654b12013-09-27 21:47:05 +00001468relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001469 DataRefImpl DRI;
1470 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001471 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001472}
1473
Kevin Enderby273ae012013-06-06 17:20:50 +00001474dice_iterator MachOObjectFile::begin_dices() const {
1475 DataRefImpl DRI;
1476 if (!DataInCodeLoadCmd)
1477 return dice_iterator(DiceRef(DRI, this));
1478
Charles Davis8bdfafd2013-09-01 04:28:48 +00001479 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1480 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001481 return dice_iterator(DiceRef(DRI, this));
1482}
1483
1484dice_iterator MachOObjectFile::end_dices() const {
1485 DataRefImpl DRI;
1486 if (!DataInCodeLoadCmd)
1487 return dice_iterator(DiceRef(DRI, this));
1488
Charles Davis8bdfafd2013-09-01 04:28:48 +00001489 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1490 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001491 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1492 return dice_iterator(DiceRef(DRI, this));
1493}
1494
Nick Kledzikd04bc352014-08-30 00:20:14 +00001495ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1496 : Trie(T), Malformed(false), Done(false) { }
1497
1498void ExportEntry::moveToFirst() {
1499 pushNode(0);
1500 pushDownUntilBottom();
1501}
1502
1503void ExportEntry::moveToEnd() {
1504 Stack.clear();
1505 Done = true;
1506}
1507
1508bool ExportEntry::operator==(const ExportEntry &Other) const {
1509 // Common case, one at end, other iterating from begin.
1510 if (Done || Other.Done)
1511 return (Done == Other.Done);
1512 // Not equal if different stack sizes.
1513 if (Stack.size() != Other.Stack.size())
1514 return false;
1515 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001516 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001517 return false;
1518 // Equal if all nodes in both stacks match.
1519 for (unsigned i=0; i < Stack.size(); ++i) {
1520 if (Stack[i].Start != Other.Stack[i].Start)
1521 return false;
1522 }
1523 return true;
1524}
1525
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001526uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1527 unsigned Count;
1528 uint64_t Result = decodeULEB128(Ptr, &Count);
1529 Ptr += Count;
1530 if (Ptr > Trie.end()) {
1531 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001532 Malformed = true;
1533 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001534 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001535}
1536
1537StringRef ExportEntry::name() const {
1538 return CumulativeString.str();
1539}
1540
1541uint64_t ExportEntry::flags() const {
1542 return Stack.back().Flags;
1543}
1544
1545uint64_t ExportEntry::address() const {
1546 return Stack.back().Address;
1547}
1548
1549uint64_t ExportEntry::other() const {
1550 return Stack.back().Other;
1551}
1552
1553StringRef ExportEntry::otherName() const {
1554 const char* ImportName = Stack.back().ImportName;
1555 if (ImportName)
1556 return StringRef(ImportName);
1557 return StringRef();
1558}
1559
1560uint32_t ExportEntry::nodeOffset() const {
1561 return Stack.back().Start - Trie.begin();
1562}
1563
1564ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1565 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1566 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1567 ParentStringLength(0), IsExportNode(false) {
1568}
1569
1570void ExportEntry::pushNode(uint64_t offset) {
1571 const uint8_t *Ptr = Trie.begin() + offset;
1572 NodeState State(Ptr);
1573 uint64_t ExportInfoSize = readULEB128(State.Current);
1574 State.IsExportNode = (ExportInfoSize != 0);
1575 const uint8_t* Children = State.Current + ExportInfoSize;
1576 if (State.IsExportNode) {
1577 State.Flags = readULEB128(State.Current);
1578 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1579 State.Address = 0;
1580 State.Other = readULEB128(State.Current); // dylib ordinal
1581 State.ImportName = reinterpret_cast<const char*>(State.Current);
1582 } else {
1583 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001584 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1585 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001586 }
1587 }
1588 State.ChildCount = *Children;
1589 State.Current = Children + 1;
1590 State.NextChildIndex = 0;
1591 State.ParentStringLength = CumulativeString.size();
1592 Stack.push_back(State);
1593}
1594
1595void ExportEntry::pushDownUntilBottom() {
1596 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1597 NodeState &Top = Stack.back();
1598 CumulativeString.resize(Top.ParentStringLength);
1599 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001600 char C = *Top.Current;
1601 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001602 }
1603 Top.Current += 1;
1604 uint64_t childNodeIndex = readULEB128(Top.Current);
1605 Top.NextChildIndex += 1;
1606 pushNode(childNodeIndex);
1607 }
1608 if (!Stack.back().IsExportNode) {
1609 Malformed = true;
1610 moveToEnd();
1611 }
1612}
1613
1614// We have a trie data structure and need a way to walk it that is compatible
1615// with the C++ iterator model. The solution is a non-recursive depth first
1616// traversal where the iterator contains a stack of parent nodes along with a
1617// string that is the accumulation of all edge strings along the parent chain
1618// to this point.
1619//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001620// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001621// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1622// node may have child nodes too.
1623//
1624// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1625// child until hitting a node with no children (which is an export node or
1626// else the trie is malformed). On the way down, each node is pushed on the
1627// stack ivar. If there is no more ways down, it pops up one and tries to go
1628// down a sibling path until a childless node is reached.
1629void ExportEntry::moveNext() {
1630 if (Stack.empty() || !Stack.back().IsExportNode) {
1631 Malformed = true;
1632 moveToEnd();
1633 return;
1634 }
1635
1636 Stack.pop_back();
1637 while (!Stack.empty()) {
1638 NodeState &Top = Stack.back();
1639 if (Top.NextChildIndex < Top.ChildCount) {
1640 pushDownUntilBottom();
1641 // Now at the next export node.
1642 return;
1643 } else {
1644 if (Top.IsExportNode) {
1645 // This node has no children but is itself an export node.
1646 CumulativeString.resize(Top.ParentStringLength);
1647 return;
1648 }
1649 Stack.pop_back();
1650 }
1651 }
1652 Done = true;
1653}
1654
1655iterator_range<export_iterator>
1656MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1657 ExportEntry Start(Trie);
1658 Start.moveToFirst();
1659
1660 ExportEntry Finish(Trie);
1661 Finish.moveToEnd();
1662
1663 return iterator_range<export_iterator>(export_iterator(Start),
1664 export_iterator(Finish));
1665}
1666
1667iterator_range<export_iterator> MachOObjectFile::exports() const {
1668 return exports(getDyldInfoExportsTrie());
1669}
1670
1671
Nick Kledzikac431442014-09-12 21:34:15 +00001672MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1673 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1674 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1675 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1676
1677void MachORebaseEntry::moveToFirst() {
1678 Ptr = Opcodes.begin();
1679 moveNext();
1680}
1681
1682void MachORebaseEntry::moveToEnd() {
1683 Ptr = Opcodes.end();
1684 RemainingLoopCount = 0;
1685 Done = true;
1686}
1687
1688void MachORebaseEntry::moveNext() {
1689 // If in the middle of some loop, move to next rebasing in loop.
1690 SegmentOffset += AdvanceAmount;
1691 if (RemainingLoopCount) {
1692 --RemainingLoopCount;
1693 return;
1694 }
1695 if (Ptr == Opcodes.end()) {
1696 Done = true;
1697 return;
1698 }
1699 bool More = true;
1700 while (More && !Malformed) {
1701 // Parse next opcode and set up next loop.
1702 uint8_t Byte = *Ptr++;
1703 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1704 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1705 switch (Opcode) {
1706 case MachO::REBASE_OPCODE_DONE:
1707 More = false;
1708 Done = true;
1709 moveToEnd();
1710 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1711 break;
1712 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1713 RebaseType = ImmValue;
1714 DEBUG_WITH_TYPE(
1715 "mach-o-rebase",
1716 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1717 << "RebaseType=" << (int) RebaseType << "\n");
1718 break;
1719 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1720 SegmentIndex = ImmValue;
1721 SegmentOffset = readULEB128();
1722 DEBUG_WITH_TYPE(
1723 "mach-o-rebase",
1724 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1725 << "SegmentIndex=" << SegmentIndex << ", "
1726 << format("SegmentOffset=0x%06X", SegmentOffset)
1727 << "\n");
1728 break;
1729 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1730 SegmentOffset += readULEB128();
1731 DEBUG_WITH_TYPE("mach-o-rebase",
1732 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1733 << format("SegmentOffset=0x%06X",
1734 SegmentOffset) << "\n");
1735 break;
1736 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1737 SegmentOffset += ImmValue * PointerSize;
1738 DEBUG_WITH_TYPE("mach-o-rebase",
1739 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1740 << format("SegmentOffset=0x%06X",
1741 SegmentOffset) << "\n");
1742 break;
1743 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1744 AdvanceAmount = PointerSize;
1745 RemainingLoopCount = ImmValue - 1;
1746 DEBUG_WITH_TYPE(
1747 "mach-o-rebase",
1748 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1749 << format("SegmentOffset=0x%06X", SegmentOffset)
1750 << ", AdvanceAmount=" << AdvanceAmount
1751 << ", RemainingLoopCount=" << RemainingLoopCount
1752 << "\n");
1753 return;
1754 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1755 AdvanceAmount = PointerSize;
1756 RemainingLoopCount = readULEB128() - 1;
1757 DEBUG_WITH_TYPE(
1758 "mach-o-rebase",
1759 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1760 << format("SegmentOffset=0x%06X", SegmentOffset)
1761 << ", AdvanceAmount=" << AdvanceAmount
1762 << ", RemainingLoopCount=" << RemainingLoopCount
1763 << "\n");
1764 return;
1765 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1766 AdvanceAmount = readULEB128() + PointerSize;
1767 RemainingLoopCount = 0;
1768 DEBUG_WITH_TYPE(
1769 "mach-o-rebase",
1770 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1771 << format("SegmentOffset=0x%06X", SegmentOffset)
1772 << ", AdvanceAmount=" << AdvanceAmount
1773 << ", RemainingLoopCount=" << RemainingLoopCount
1774 << "\n");
1775 return;
1776 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1777 RemainingLoopCount = readULEB128() - 1;
1778 AdvanceAmount = readULEB128() + PointerSize;
1779 DEBUG_WITH_TYPE(
1780 "mach-o-rebase",
1781 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1782 << format("SegmentOffset=0x%06X", SegmentOffset)
1783 << ", AdvanceAmount=" << AdvanceAmount
1784 << ", RemainingLoopCount=" << RemainingLoopCount
1785 << "\n");
1786 return;
1787 default:
1788 Malformed = true;
1789 }
1790 }
1791}
1792
1793uint64_t MachORebaseEntry::readULEB128() {
1794 unsigned Count;
1795 uint64_t Result = decodeULEB128(Ptr, &Count);
1796 Ptr += Count;
1797 if (Ptr > Opcodes.end()) {
1798 Ptr = Opcodes.end();
1799 Malformed = true;
1800 }
1801 return Result;
1802}
1803
1804uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1805
1806uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1807
1808StringRef MachORebaseEntry::typeName() const {
1809 switch (RebaseType) {
1810 case MachO::REBASE_TYPE_POINTER:
1811 return "pointer";
1812 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1813 return "text abs32";
1814 case MachO::REBASE_TYPE_TEXT_PCREL32:
1815 return "text rel32";
1816 }
1817 return "unknown";
1818}
1819
1820bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1821 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1822 return (Ptr == Other.Ptr) &&
1823 (RemainingLoopCount == Other.RemainingLoopCount) &&
1824 (Done == Other.Done);
1825}
1826
1827iterator_range<rebase_iterator>
1828MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1829 MachORebaseEntry Start(Opcodes, is64);
1830 Start.moveToFirst();
1831
1832 MachORebaseEntry Finish(Opcodes, is64);
1833 Finish.moveToEnd();
1834
1835 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1836 rebase_iterator(Finish));
1837}
1838
1839iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1840 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1841}
1842
Nick Kledzik56ebef42014-09-16 01:41:51 +00001843
1844MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1845 Kind BK)
1846 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1847 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1848 BindType(0), PointerSize(is64Bit ? 8 : 4),
1849 TableKind(BK), Malformed(false), Done(false) {}
1850
1851void MachOBindEntry::moveToFirst() {
1852 Ptr = Opcodes.begin();
1853 moveNext();
1854}
1855
1856void MachOBindEntry::moveToEnd() {
1857 Ptr = Opcodes.end();
1858 RemainingLoopCount = 0;
1859 Done = true;
1860}
1861
1862void MachOBindEntry::moveNext() {
1863 // If in the middle of some loop, move to next binding in loop.
1864 SegmentOffset += AdvanceAmount;
1865 if (RemainingLoopCount) {
1866 --RemainingLoopCount;
1867 return;
1868 }
1869 if (Ptr == Opcodes.end()) {
1870 Done = true;
1871 return;
1872 }
1873 bool More = true;
1874 while (More && !Malformed) {
1875 // Parse next opcode and set up next loop.
1876 uint8_t Byte = *Ptr++;
1877 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1878 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1879 int8_t SignExtended;
1880 const uint8_t *SymStart;
1881 switch (Opcode) {
1882 case MachO::BIND_OPCODE_DONE:
1883 if (TableKind == Kind::Lazy) {
1884 // Lazying bindings have a DONE opcode between entries. Need to ignore
1885 // it to advance to next entry. But need not if this is last entry.
1886 bool NotLastEntry = false;
1887 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1888 if (*P) {
1889 NotLastEntry = true;
1890 }
1891 }
1892 if (NotLastEntry)
1893 break;
1894 }
1895 More = false;
1896 Done = true;
1897 moveToEnd();
1898 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1899 break;
1900 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1901 Ordinal = ImmValue;
1902 DEBUG_WITH_TYPE(
1903 "mach-o-bind",
1904 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1905 << "Ordinal=" << Ordinal << "\n");
1906 break;
1907 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1908 Ordinal = readULEB128();
1909 DEBUG_WITH_TYPE(
1910 "mach-o-bind",
1911 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1912 << "Ordinal=" << Ordinal << "\n");
1913 break;
1914 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1915 if (ImmValue) {
1916 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1917 Ordinal = SignExtended;
1918 } else
1919 Ordinal = 0;
1920 DEBUG_WITH_TYPE(
1921 "mach-o-bind",
1922 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1923 << "Ordinal=" << Ordinal << "\n");
1924 break;
1925 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1926 Flags = ImmValue;
1927 SymStart = Ptr;
1928 while (*Ptr) {
1929 ++Ptr;
1930 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001931 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1932 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001933 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001934 DEBUG_WITH_TYPE(
1935 "mach-o-bind",
1936 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1937 << "SymbolName=" << SymbolName << "\n");
1938 if (TableKind == Kind::Weak) {
1939 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1940 return;
1941 }
1942 break;
1943 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1944 BindType = ImmValue;
1945 DEBUG_WITH_TYPE(
1946 "mach-o-bind",
1947 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1948 << "BindType=" << (int)BindType << "\n");
1949 break;
1950 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1951 Addend = readSLEB128();
1952 if (TableKind == Kind::Lazy)
1953 Malformed = true;
1954 DEBUG_WITH_TYPE(
1955 "mach-o-bind",
1956 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1957 << "Addend=" << Addend << "\n");
1958 break;
1959 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1960 SegmentIndex = ImmValue;
1961 SegmentOffset = readULEB128();
1962 DEBUG_WITH_TYPE(
1963 "mach-o-bind",
1964 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1965 << "SegmentIndex=" << SegmentIndex << ", "
1966 << format("SegmentOffset=0x%06X", SegmentOffset)
1967 << "\n");
1968 break;
1969 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1970 SegmentOffset += readULEB128();
1971 DEBUG_WITH_TYPE("mach-o-bind",
1972 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1973 << format("SegmentOffset=0x%06X",
1974 SegmentOffset) << "\n");
1975 break;
1976 case MachO::BIND_OPCODE_DO_BIND:
1977 AdvanceAmount = PointerSize;
1978 RemainingLoopCount = 0;
1979 DEBUG_WITH_TYPE("mach-o-bind",
1980 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1981 << format("SegmentOffset=0x%06X",
1982 SegmentOffset) << "\n");
1983 return;
1984 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001985 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001986 RemainingLoopCount = 0;
1987 if (TableKind == Kind::Lazy)
1988 Malformed = true;
1989 DEBUG_WITH_TYPE(
1990 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001991 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001992 << format("SegmentOffset=0x%06X", SegmentOffset)
1993 << ", AdvanceAmount=" << AdvanceAmount
1994 << ", RemainingLoopCount=" << RemainingLoopCount
1995 << "\n");
1996 return;
1997 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001998 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001999 RemainingLoopCount = 0;
2000 if (TableKind == Kind::Lazy)
2001 Malformed = true;
2002 DEBUG_WITH_TYPE("mach-o-bind",
2003 llvm::dbgs()
2004 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2005 << format("SegmentOffset=0x%06X",
2006 SegmentOffset) << "\n");
2007 return;
2008 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2009 RemainingLoopCount = readULEB128() - 1;
2010 AdvanceAmount = readULEB128() + PointerSize;
2011 if (TableKind == Kind::Lazy)
2012 Malformed = true;
2013 DEBUG_WITH_TYPE(
2014 "mach-o-bind",
2015 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2016 << format("SegmentOffset=0x%06X", SegmentOffset)
2017 << ", AdvanceAmount=" << AdvanceAmount
2018 << ", RemainingLoopCount=" << RemainingLoopCount
2019 << "\n");
2020 return;
2021 default:
2022 Malformed = true;
2023 }
2024 }
2025}
2026
2027uint64_t MachOBindEntry::readULEB128() {
2028 unsigned Count;
2029 uint64_t Result = decodeULEB128(Ptr, &Count);
2030 Ptr += Count;
2031 if (Ptr > Opcodes.end()) {
2032 Ptr = Opcodes.end();
2033 Malformed = true;
2034 }
2035 return Result;
2036}
2037
2038int64_t MachOBindEntry::readSLEB128() {
2039 unsigned Count;
2040 int64_t Result = decodeSLEB128(Ptr, &Count);
2041 Ptr += Count;
2042 if (Ptr > Opcodes.end()) {
2043 Ptr = Opcodes.end();
2044 Malformed = true;
2045 }
2046 return Result;
2047}
2048
2049
2050uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2051
2052uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2053
2054StringRef MachOBindEntry::typeName() const {
2055 switch (BindType) {
2056 case MachO::BIND_TYPE_POINTER:
2057 return "pointer";
2058 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2059 return "text abs32";
2060 case MachO::BIND_TYPE_TEXT_PCREL32:
2061 return "text rel32";
2062 }
2063 return "unknown";
2064}
2065
2066StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2067
2068int64_t MachOBindEntry::addend() const { return Addend; }
2069
2070uint32_t MachOBindEntry::flags() const { return Flags; }
2071
2072int MachOBindEntry::ordinal() const { return Ordinal; }
2073
2074bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2075 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2076 return (Ptr == Other.Ptr) &&
2077 (RemainingLoopCount == Other.RemainingLoopCount) &&
2078 (Done == Other.Done);
2079}
2080
2081iterator_range<bind_iterator>
2082MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2083 MachOBindEntry::Kind BKind) {
2084 MachOBindEntry Start(Opcodes, is64, BKind);
2085 Start.moveToFirst();
2086
2087 MachOBindEntry Finish(Opcodes, is64, BKind);
2088 Finish.moveToEnd();
2089
2090 return iterator_range<bind_iterator>(bind_iterator(Start),
2091 bind_iterator(Finish));
2092}
2093
2094iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2095 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2096 MachOBindEntry::Kind::Regular);
2097}
2098
2099iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2100 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2101 MachOBindEntry::Kind::Lazy);
2102}
2103
2104iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2105 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2106 MachOBindEntry::Kind::Weak);
2107}
2108
Rafael Espindola56f976f2013-04-18 18:08:55 +00002109StringRef
2110MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2111 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2112 return parseSegmentOrSectionName(Raw.data());
2113}
2114
2115ArrayRef<char>
2116MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002117 const section_base *Base =
2118 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002119 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002120}
2121
2122ArrayRef<char>
2123MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002124 const section_base *Base =
2125 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002126 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002127}
2128
2129bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002130MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002131 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002132 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002133 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002134 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002135}
2136
Eric Christopher1d62c252013-07-22 22:25:07 +00002137unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002138 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002139 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002140 return RE.r_word1 & 0xffffff;
2141 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002142}
2143
Eric Christopher1d62c252013-07-22 22:25:07 +00002144bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002145 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002146 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002147 return (RE.r_word1 >> 27) & 1;
2148 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002149}
2150
Eric Christopher1d62c252013-07-22 22:25:07 +00002151bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002152 const MachO::any_relocation_info &RE) const {
2153 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002154}
2155
Eric Christopher1d62c252013-07-22 22:25:07 +00002156uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002157 const MachO::any_relocation_info &RE) const {
2158 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002159}
2160
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002161uint32_t MachOObjectFile::getScatteredRelocationType(
2162 const MachO::any_relocation_info &RE) const {
2163 return (RE.r_word0 >> 24) & 0xf;
2164}
2165
Eric Christopher1d62c252013-07-22 22:25:07 +00002166unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002167 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002168 if (isRelocationScattered(RE))
2169 return getScatteredRelocationAddress(RE);
2170 return getPlainRelocationAddress(RE);
2171}
2172
Charles Davis8bdfafd2013-09-01 04:28:48 +00002173unsigned MachOObjectFile::getAnyRelocationPCRel(
2174 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002175 if (isRelocationScattered(RE))
2176 return getScatteredRelocationPCRel(this, RE);
2177 return getPlainRelocationPCRel(this, RE);
2178}
2179
Eric Christopher1d62c252013-07-22 22:25:07 +00002180unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002181 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002182 if (isRelocationScattered(RE))
2183 return getScatteredRelocationLength(RE);
2184 return getPlainRelocationLength(this, RE);
2185}
2186
2187unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002188MachOObjectFile::getAnyRelocationType(
2189 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002190 if (isRelocationScattered(RE))
2191 return getScatteredRelocationType(RE);
2192 return getPlainRelocationType(this, RE);
2193}
2194
Rafael Espindola52501032013-04-30 15:40:54 +00002195SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00002196MachOObjectFile::getRelocationSection(
2197 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002198 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002199 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002200 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2201 DataRefImpl DRI;
2202 DRI.d.a = SecNum;
2203 return SectionRef(DRI, this);
2204}
2205
Rafael Espindola56f976f2013-04-18 18:08:55 +00002206MachOObjectFile::LoadCommandInfo
2207MachOObjectFile::getFirstLoadCommandInfo() const {
2208 MachOObjectFile::LoadCommandInfo Load;
2209
Charles Davis8bdfafd2013-09-01 04:28:48 +00002210 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2211 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002212 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002213 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002214 return Load;
2215}
2216
2217MachOObjectFile::LoadCommandInfo
2218MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2219 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002220 Next.Ptr = L.Ptr + L.C.cmdsize;
2221 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002222 return Next;
2223}
2224
Charles Davis8bdfafd2013-09-01 04:28:48 +00002225MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2226 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002227}
2228
Charles Davis8bdfafd2013-09-01 04:28:48 +00002229MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2230 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002231}
2232
Charles Davis8bdfafd2013-09-01 04:28:48 +00002233MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002234 unsigned Index) const {
2235 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002236 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002237}
2238
Charles Davis8bdfafd2013-09-01 04:28:48 +00002239MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2240 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002241 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002242 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002243}
2244
Charles Davis8bdfafd2013-09-01 04:28:48 +00002245MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002246MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002247 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002248 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002249}
2250
Charles Davis8bdfafd2013-09-01 04:28:48 +00002251MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002252MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002253 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002254 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002255}
2256
Charles Davis8bdfafd2013-09-01 04:28:48 +00002257MachO::linkedit_data_command
2258MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2259 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002260}
2261
Charles Davis8bdfafd2013-09-01 04:28:48 +00002262MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002263MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002264 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002265}
2266
Charles Davis8bdfafd2013-09-01 04:28:48 +00002267MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002268MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002269 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002270}
2271
Charles Davis8bdfafd2013-09-01 04:28:48 +00002272MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002273MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002274 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002275}
2276
Jim Grosbach448334a2014-03-18 22:09:05 +00002277MachO::version_min_command
2278MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2279 return getStruct<MachO::version_min_command>(this, L.Ptr);
2280}
2281
Tim Northover8f9590b2014-06-30 14:40:57 +00002282MachO::dylib_command
2283MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2284 return getStruct<MachO::dylib_command>(this, L.Ptr);
2285}
2286
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002287MachO::dyld_info_command
2288MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2289 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2290}
2291
2292MachO::dylinker_command
2293MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2294 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2295}
2296
2297MachO::uuid_command
2298MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2299 return getStruct<MachO::uuid_command>(this, L.Ptr);
2300}
2301
2302MachO::source_version_command
2303MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2304 return getStruct<MachO::source_version_command>(this, L.Ptr);
2305}
2306
2307MachO::entry_point_command
2308MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2309 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2310}
2311
Tim Northover8f9590b2014-06-30 14:40:57 +00002312
Charles Davis8bdfafd2013-09-01 04:28:48 +00002313MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002314MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002315 DataRefImpl Sec;
2316 Sec.d.a = Rel.d.a;
2317 uint32_t Offset;
2318 if (is64Bit()) {
2319 MachO::section_64 Sect = getSection64(Sec);
2320 Offset = Sect.reloff;
2321 } else {
2322 MachO::section Sect = getSection(Sec);
2323 Offset = Sect.reloff;
2324 }
2325
2326 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2327 getPtr(this, Offset)) + Rel.d.b;
2328 return getStruct<MachO::any_relocation_info>(
2329 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002330}
2331
Charles Davis8bdfafd2013-09-01 04:28:48 +00002332MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002333MachOObjectFile::getDice(DataRefImpl Rel) const {
2334 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002335 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002336}
2337
Charles Davis8bdfafd2013-09-01 04:28:48 +00002338MachO::mach_header MachOObjectFile::getHeader() const {
2339 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002340}
2341
Charles Davis8bdfafd2013-09-01 04:28:48 +00002342MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2343 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002344}
2345
Charles Davis8bdfafd2013-09-01 04:28:48 +00002346uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2347 const MachO::dysymtab_command &DLC,
2348 unsigned Index) const {
2349 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2350 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002351}
2352
Charles Davis8bdfafd2013-09-01 04:28:48 +00002353MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002354MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2355 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002356 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2357 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002358}
2359
Charles Davis8bdfafd2013-09-01 04:28:48 +00002360MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002361 if (SymtabLoadCmd)
2362 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2363
2364 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2365 MachO::symtab_command Cmd;
2366 Cmd.cmd = MachO::LC_SYMTAB;
2367 Cmd.cmdsize = sizeof(MachO::symtab_command);
2368 Cmd.symoff = 0;
2369 Cmd.nsyms = 0;
2370 Cmd.stroff = 0;
2371 Cmd.strsize = 0;
2372 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002373}
2374
Charles Davis8bdfafd2013-09-01 04:28:48 +00002375MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002376 if (DysymtabLoadCmd)
2377 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2378
2379 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2380 MachO::dysymtab_command Cmd;
2381 Cmd.cmd = MachO::LC_DYSYMTAB;
2382 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2383 Cmd.ilocalsym = 0;
2384 Cmd.nlocalsym = 0;
2385 Cmd.iextdefsym = 0;
2386 Cmd.nextdefsym = 0;
2387 Cmd.iundefsym = 0;
2388 Cmd.nundefsym = 0;
2389 Cmd.tocoff = 0;
2390 Cmd.ntoc = 0;
2391 Cmd.modtaboff = 0;
2392 Cmd.nmodtab = 0;
2393 Cmd.extrefsymoff = 0;
2394 Cmd.nextrefsyms = 0;
2395 Cmd.indirectsymoff = 0;
2396 Cmd.nindirectsyms = 0;
2397 Cmd.extreloff = 0;
2398 Cmd.nextrel = 0;
2399 Cmd.locreloff = 0;
2400 Cmd.nlocrel = 0;
2401 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002402}
2403
Charles Davis8bdfafd2013-09-01 04:28:48 +00002404MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002405MachOObjectFile::getDataInCodeLoadCommand() const {
2406 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002407 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002408
2409 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002410 MachO::linkedit_data_command Cmd;
2411 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2412 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2413 Cmd.dataoff = 0;
2414 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002415 return Cmd;
2416}
2417
Nick Kledzikd04bc352014-08-30 00:20:14 +00002418ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2419 if (!DyldInfoLoadCmd)
2420 return ArrayRef<uint8_t>();
2421
2422 MachO::dyld_info_command DyldInfo
2423 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2424 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2425 getPtr(this, DyldInfo.rebase_off));
2426 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2427}
2428
2429ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2430 if (!DyldInfoLoadCmd)
2431 return ArrayRef<uint8_t>();
2432
2433 MachO::dyld_info_command DyldInfo
2434 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2435 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2436 getPtr(this, DyldInfo.bind_off));
2437 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2438}
2439
2440ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2441 if (!DyldInfoLoadCmd)
2442 return ArrayRef<uint8_t>();
2443
2444 MachO::dyld_info_command DyldInfo
2445 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2446 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2447 getPtr(this, DyldInfo.weak_bind_off));
2448 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2449}
2450
2451ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2452 if (!DyldInfoLoadCmd)
2453 return ArrayRef<uint8_t>();
2454
2455 MachO::dyld_info_command DyldInfo
2456 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2457 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2458 getPtr(this, DyldInfo.lazy_bind_off));
2459 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2460}
2461
2462ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2463 if (!DyldInfoLoadCmd)
2464 return ArrayRef<uint8_t>();
2465
2466 MachO::dyld_info_command DyldInfo
2467 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2468 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2469 getPtr(this, DyldInfo.export_off));
2470 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2471}
2472
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002473ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2474 if (!UuidLoadCmd)
2475 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002476 // Returning a pointer is fine as uuid doesn't need endian swapping.
2477 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2478 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002479}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002480
Rafael Espindola6e040c02013-04-26 20:07:33 +00002481StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002482 MachO::symtab_command S = getSymtabLoadCommand();
2483 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002484}
2485
Rafael Espindola56f976f2013-04-18 18:08:55 +00002486bool MachOObjectFile::is64Bit() const {
2487 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002488 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002489}
2490
2491void MachOObjectFile::ReadULEB128s(uint64_t Index,
2492 SmallVectorImpl<uint64_t> &Out) const {
2493 DataExtractor extractor(ObjectFile::getData(), true, 0);
2494
2495 uint32_t offset = Index;
2496 uint64_t data = 0;
2497 while (uint64_t delta = extractor.getULEB128(&offset)) {
2498 data += delta;
2499 Out.push_back(data);
2500 }
2501}
2502
Rafael Espindolac66d7612014-08-17 19:09:37 +00002503bool MachOObjectFile::isRelocatableObject() const {
2504 return getHeader().filetype == MachO::MH_OBJECT;
2505}
2506
Rafael Espindola437b0d52014-07-31 03:12:45 +00002507ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002508ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2509 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002510 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002511 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002512 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002513 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002514 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002515 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002516 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002517 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002518 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002519 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002520 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002521 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002522
Rafael Espindola692410e2014-01-21 23:06:54 +00002523 if (EC)
2524 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002525 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002526}
2527