blob: 678728e1de784872420011a0fa073c932d67e0d1 [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
Charles Davis8bdfafd2013-09-01 04:28:48 +0000222static unsigned
223getScatteredRelocationType(const MachO::any_relocation_info &RE) {
224 return (RE.r_word0 >> 24) & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000225}
226
227static uint32_t getSectionFlags(const MachOObjectFile *O,
228 DataRefImpl Sec) {
229 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000230 MachO::section_64 Sect = O->getSection64(Sec);
231 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000232 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000233 MachO::section Sect = O->getSection(Sec);
234 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000235}
236
Rafael Espindola48af1c22014-08-19 18:44:46 +0000237MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
238 bool Is64bits, std::error_code &EC)
239 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000240 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Nick Kledzik56ebef42014-09-16 01:41:51 +0000241 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000242 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000243 uint32_t LoadCommandCount = this->getHeader().ncmds;
244 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
245 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000246
247 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000248 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000249 if (Load.C.cmd == MachO::LC_SYMTAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000250 assert(!SymtabLoadCmd && "Multiple symbol tables");
251 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000252 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000253 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
254 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000255 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby273ae012013-06-06 17:20:50 +0000256 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
257 DataInCodeLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000258 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
259 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
260 assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");
261 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000262 } else if (Load.C.cmd == MachO::LC_UUID) {
263 assert(!UuidLoadCmd && "Multiple UUID load commands");
264 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000265 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000266 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
267 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000268 const char *Sec = getSectionPtr(this, Load, J);
269 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000270 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000271 if (isPageZeroSegment(this, Load))
272 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000273 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
274 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
275 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
276 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
277 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
278 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000279 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000280
281 if (I == LoadCommandCount - 1)
282 break;
283 else
284 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000285 }
286}
287
Rafael Espindola5e812af2014-01-30 02:49:50 +0000288void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000289 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000290 sizeof(MachO::nlist_64) :
291 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000292 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000293}
294
Rafael Espindola3acea392014-06-12 21:46:39 +0000295std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
296 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000297 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000298 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000299 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000300 Res = StringRef(Start);
301 return object_error::success;
302}
303
Kevin Enderby980b2582014-06-05 21:21:57 +0000304// getIndirectName() returns the name of the alias'ed symbol who's string table
305// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000306std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
307 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000308 StringRef StringTable = getStringTableData();
309 uint64_t NValue;
310 if (is64Bit()) {
311 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
312 NValue = Entry.n_value;
313 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
314 return object_error::parse_failed;
315 } else {
316 MachO::nlist Entry = getSymbolTableEntry(Symb);
317 NValue = Entry.n_value;
318 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
319 return object_error::parse_failed;
320 }
321 if (NValue >= StringTable.size())
322 return object_error::parse_failed;
323 const char *Start = &StringTable.data()[NValue];
324 Res = StringRef(Start);
325 return object_error::success;
326}
327
Rafael Espindola3acea392014-06-12 21:46:39 +0000328std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
329 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000330 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000331 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000332 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
333 Entry.n_value == 0)
334 Res = UnknownAddressOrSize;
335 else
336 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000337 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000338 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000339 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
340 Entry.n_value == 0)
341 Res = UnknownAddressOrSize;
342 else
343 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000344 }
345 return object_error::success;
346}
347
Rafael Espindola3acea392014-06-12 21:46:39 +0000348std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
349 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000350 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000351 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000352 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000353 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000354 } else {
355 Result = 0;
356 }
357 return object_error::success;
358}
359
Rafael Espindola3acea392014-06-12 21:46:39 +0000360std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
361 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000362 uint64_t BeginOffset;
363 uint64_t EndOffset = 0;
364 uint8_t SectionIndex;
365
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000366 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000367 uint64_t Value;
368 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000369 if (Value == UnknownAddressOrSize) {
370 Result = UnknownAddressOrSize;
371 return object_error::success;
372 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000373
374 BeginOffset = Value;
375
Charles Davis8bdfafd2013-09-01 04:28:48 +0000376 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000377 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000378 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000379 if (flags & SymbolRef::SF_Common)
380 Result = Value;
381 else
382 Result = UnknownAddressOrSize;
383 return object_error::success;
384 }
385 // Unfortunately symbols are unsorted so we need to touch all
386 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000387 for (const SymbolRef &Symbol : symbols()) {
388 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000389 Entry = getSymbolTableEntryBase(this, DRI);
390 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000391 if (Value == UnknownAddressOrSize)
392 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000393 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000394 if (!EndOffset || Value < EndOffset)
395 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000396 }
397 if (!EndOffset) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000398 DataRefImpl Sec;
399 Sec.d.a = SectionIndex-1;
Rafael Espindola80291272014-10-08 15:28:58 +0000400 uint64_t Size = getSectionSize(Sec);
401 EndOffset = getSectionAddress(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000402 EndOffset += Size;
403 }
404 Result = EndOffset - BeginOffset;
405 return object_error::success;
406}
407
Rafael Espindola3acea392014-06-12 21:46:39 +0000408std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
409 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000411 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000412
413 Res = SymbolRef::ST_Other;
414
415 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000416 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000417 Res = SymbolRef::ST_Debug;
418 return object_error::success;
419 }
420
Charles Davis74ec8b02013-08-27 05:00:13 +0000421 switch (n_type & MachO::N_TYPE) {
422 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000423 Res = SymbolRef::ST_Unknown;
424 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000425 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000426 Res = SymbolRef::ST_Function;
427 break;
428 }
429 return object_error::success;
430}
431
Rafael Espindola20122a42014-01-31 20:57:12 +0000432uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000433 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000434
Charles Davis8bdfafd2013-09-01 04:28:48 +0000435 uint8_t MachOType = Entry.n_type;
436 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437
Rafael Espindola20122a42014-01-31 20:57:12 +0000438 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000439
Charles Davis74ec8b02013-08-27 05:00:13 +0000440 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000441 Result |= SymbolRef::SF_Undefined;
442
Tim Northovereaef0742014-05-30 13:22:59 +0000443 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
444 Result |= SymbolRef::SF_Indirect;
445
Rafael Espindolaa1356322013-11-02 05:03:24 +0000446 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000447 Result |= SymbolRef::SF_FormatSpecific;
448
Charles Davis74ec8b02013-08-27 05:00:13 +0000449 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000450 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000451 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000452 uint64_t Value;
453 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000454 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000455 Result |= SymbolRef::SF_Common;
456 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000457 }
458
Charles Davis74ec8b02013-08-27 05:00:13 +0000459 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000460 Result |= SymbolRef::SF_Weak;
461
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000462 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
463 Result |= SymbolRef::SF_Thumb;
464
Charles Davis74ec8b02013-08-27 05:00:13 +0000465 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000466 Result |= SymbolRef::SF_Absolute;
467
Rafael Espindola20122a42014-01-31 20:57:12 +0000468 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000469}
470
Rafael Espindola3acea392014-06-12 21:46:39 +0000471std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
472 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000473 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000474 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000475
476 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000477 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000478 } else {
479 DataRefImpl DRI;
480 DRI.d.a = index - 1;
481 Res = section_iterator(SectionRef(DRI, this));
482 }
483
484 return object_error::success;
485}
486
Rafael Espindola5e812af2014-01-30 02:49:50 +0000487void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000488 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000489}
490
Rafael Espindola3acea392014-06-12 21:46:39 +0000491std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
492 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000493 ArrayRef<char> Raw = getSectionRawName(Sec);
494 Result = parseSegmentOrSectionName(Raw.data());
495 return object_error::success;
496}
497
Rafael Espindola80291272014-10-08 15:28:58 +0000498uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
499 if (is64Bit())
500 return getSection64(Sec).addr;
501 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000502}
503
Rafael Espindola80291272014-10-08 15:28:58 +0000504uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
505 if (is64Bit())
506 return getSection64(Sec).size;
507 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000508}
509
Rafael Espindola3acea392014-06-12 21:46:39 +0000510std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
511 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000512 uint32_t Offset;
513 uint64_t Size;
514
515 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000516 MachO::section_64 Sect = getSection64(Sec);
517 Offset = Sect.offset;
518 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000519 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000520 MachO::section Sect = getSection(Sec);
521 Offset = Sect.offset;
522 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000523 }
524
525 Res = this->getData().substr(Offset, Size);
526 return object_error::success;
527}
528
Rafael Espindola80291272014-10-08 15:28:58 +0000529uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000530 uint32_t Align;
531 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000532 MachO::section_64 Sect = getSection64(Sec);
533 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000534 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000535 MachO::section Sect = getSection(Sec);
536 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537 }
538
Rafael Espindola80291272014-10-08 15:28:58 +0000539 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000540}
541
Rafael Espindola80291272014-10-08 15:28:58 +0000542bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000543 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000544 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000545}
546
Rafael Espindola80291272014-10-08 15:28:58 +0000547bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000548 uint32_t Flags = getSectionFlags(this, Sec);
549 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000550 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
551 !(SectionType == MachO::S_ZEROFILL ||
552 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000553}
554
Rafael Espindola80291272014-10-08 15:28:58 +0000555bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000556 uint32_t Flags = getSectionFlags(this, Sec);
557 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000558 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
559 (SectionType == MachO::S_ZEROFILL ||
560 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000561}
562
Rafael Espindola80291272014-10-08 15:28:58 +0000563bool MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sect) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000564 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000565 return true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000566}
567
Rafael Espindola80291272014-10-08 15:28:58 +0000568bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000569 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000570 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000571}
572
Rafael Espindola80291272014-10-08 15:28:58 +0000573bool MachOObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000574 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis74ec8b02013-08-27 05:00:13 +0000575 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000576 return SectionType == MachO::S_ZEROFILL ||
577 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000578}
579
Rafael Espindola80291272014-10-08 15:28:58 +0000580bool MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000581 // Consider using the code from isSectionText to look for __const sections.
582 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
583 // to use section attributes to distinguish code from data.
584
585 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000586 return false;
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000587}
588
Rafael Espindola80291272014-10-08 15:28:58 +0000589bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
590 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000591 SymbolRef::Type ST;
592 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000593 if (ST == SymbolRef::ST_Unknown)
594 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000595
Rafael Espindola80291272014-10-08 15:28:58 +0000596 uint64_t SectBegin = getSectionAddress(Sec);
597 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000598 SectEnd += SectBegin;
599
600 uint64_t SymAddr;
601 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000602 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000603}
604
Rui Ueyamabc654b12013-09-27 21:47:05 +0000605relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000606 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000607 Ret.d.a = Sec.d.a;
608 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000609 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000610}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000611
Rafael Espindola56f976f2013-04-18 18:08:55 +0000612relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000613MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000614 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000615 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000616 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000617 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000618 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000619 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000620 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000621 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000622
Rafael Espindola56f976f2013-04-18 18:08:55 +0000623 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000624 Ret.d.a = Sec.d.a;
625 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000626 return relocation_iterator(RelocationRef(Ret, this));
627}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000628
Rafael Espindola5e812af2014-01-30 02:49:50 +0000629void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000630 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000631}
Owen Anderson171f4852011-10-24 23:20:07 +0000632
Rafael Espindola3acea392014-06-12 21:46:39 +0000633std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
634 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000635 uint64_t Offset;
636 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000637
638 DataRefImpl Sec;
639 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000640 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000641 Res = SecAddress + Offset;
642 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000643}
644
Rafael Espindola3acea392014-06-12 21:46:39 +0000645std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
646 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000647 assert(getHeader().filetype == MachO::MH_OBJECT &&
648 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000649 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000650 Res = getAnyRelocationAddress(RE);
651 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000652}
653
Rafael Espindola806f0062013-06-05 01:33:53 +0000654symbol_iterator
655MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000656 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000657 if (isRelocationScattered(RE))
658 return symbol_end();
659
Rafael Espindola56f976f2013-04-18 18:08:55 +0000660 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
661 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000662 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000663 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000664
Charles Davis8bdfafd2013-09-01 04:28:48 +0000665 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000666 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000667 sizeof(MachO::nlist_64) :
668 sizeof(MachO::nlist);
669 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000670 DataRefImpl Sym;
671 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000672 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000673}
674
Rafael Espindola3acea392014-06-12 21:46:39 +0000675std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
676 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000677 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000678 Res = getAnyRelocationType(RE);
679 return object_error::success;
680}
681
Rafael Espindola3acea392014-06-12 21:46:39 +0000682std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000683MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
684 SmallVectorImpl<char> &Result) const {
685 StringRef res;
686 uint64_t RType;
687 getRelocationType(Rel, RType);
688
689 unsigned Arch = this->getArch();
690
691 switch (Arch) {
692 case Triple::x86: {
693 static const char *const Table[] = {
694 "GENERIC_RELOC_VANILLA",
695 "GENERIC_RELOC_PAIR",
696 "GENERIC_RELOC_SECTDIFF",
697 "GENERIC_RELOC_PB_LA_PTR",
698 "GENERIC_RELOC_LOCAL_SECTDIFF",
699 "GENERIC_RELOC_TLV" };
700
Eric Christopher13250cb2013-12-06 02:33:38 +0000701 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000702 res = "Unknown";
703 else
704 res = Table[RType];
705 break;
706 }
707 case Triple::x86_64: {
708 static const char *const Table[] = {
709 "X86_64_RELOC_UNSIGNED",
710 "X86_64_RELOC_SIGNED",
711 "X86_64_RELOC_BRANCH",
712 "X86_64_RELOC_GOT_LOAD",
713 "X86_64_RELOC_GOT",
714 "X86_64_RELOC_SUBTRACTOR",
715 "X86_64_RELOC_SIGNED_1",
716 "X86_64_RELOC_SIGNED_2",
717 "X86_64_RELOC_SIGNED_4",
718 "X86_64_RELOC_TLV" };
719
720 if (RType > 9)
721 res = "Unknown";
722 else
723 res = Table[RType];
724 break;
725 }
726 case Triple::arm: {
727 static const char *const Table[] = {
728 "ARM_RELOC_VANILLA",
729 "ARM_RELOC_PAIR",
730 "ARM_RELOC_SECTDIFF",
731 "ARM_RELOC_LOCAL_SECTDIFF",
732 "ARM_RELOC_PB_LA_PTR",
733 "ARM_RELOC_BR24",
734 "ARM_THUMB_RELOC_BR22",
735 "ARM_THUMB_32BIT_BRANCH",
736 "ARM_RELOC_HALF",
737 "ARM_RELOC_HALF_SECTDIFF" };
738
739 if (RType > 9)
740 res = "Unknown";
741 else
742 res = Table[RType];
743 break;
744 }
Tim Northover00ed9962014-03-29 10:18:08 +0000745 case Triple::aarch64: {
746 static const char *const Table[] = {
747 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
748 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
749 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
750 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
751 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
752 "ARM64_RELOC_ADDEND"
753 };
754
755 if (RType >= array_lengthof(Table))
756 res = "Unknown";
757 else
758 res = Table[RType];
759 break;
760 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000761 case Triple::ppc: {
762 static const char *const Table[] = {
763 "PPC_RELOC_VANILLA",
764 "PPC_RELOC_PAIR",
765 "PPC_RELOC_BR14",
766 "PPC_RELOC_BR24",
767 "PPC_RELOC_HI16",
768 "PPC_RELOC_LO16",
769 "PPC_RELOC_HA16",
770 "PPC_RELOC_LO14",
771 "PPC_RELOC_SECTDIFF",
772 "PPC_RELOC_PB_LA_PTR",
773 "PPC_RELOC_HI16_SECTDIFF",
774 "PPC_RELOC_LO16_SECTDIFF",
775 "PPC_RELOC_HA16_SECTDIFF",
776 "PPC_RELOC_JBSR",
777 "PPC_RELOC_LO14_SECTDIFF",
778 "PPC_RELOC_LOCAL_SECTDIFF" };
779
Eric Christopher13250cb2013-12-06 02:33:38 +0000780 if (RType > 15)
781 res = "Unknown";
782 else
783 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000784 break;
785 }
786 case Triple::UnknownArch:
787 res = "Unknown";
788 break;
789 }
790 Result.append(res.begin(), res.end());
791 return object_error::success;
792}
793
Rafael Espindola3acea392014-06-12 21:46:39 +0000794std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000795MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000796 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000797 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000798
Rafael Espindola56f976f2013-04-18 18:08:55 +0000799 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000800
Alp Tokere69170a2014-06-26 22:52:05 +0000801 std::string fmtbuf;
802 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000803 unsigned Type = this->getAnyRelocationType(RE);
804 bool IsPCRel = this->getAnyRelocationPCRel(RE);
805
806 // Determine any addends that should be displayed with the relocation.
807 // These require decoding the relocation type, which is triple-specific.
808
809 // X86_64 has entirely custom relocation types.
810 if (Arch == Triple::x86_64) {
811 bool isPCRel = getAnyRelocationPCRel(RE);
812
813 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000814 case MachO::X86_64_RELOC_GOT_LOAD:
815 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000816 printRelocationTargetName(this, RE, fmt);
817 fmt << "@GOT";
818 if (isPCRel) fmt << "PCREL";
819 break;
820 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000821 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000822 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000823 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000824 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000825
Charles Davis8bdfafd2013-09-01 04:28:48 +0000826 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000827 // X86_64_RELOC_UNSIGNED.
828 // NOTE: Scattered relocations don't exist on x86_64.
829 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000830 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000831 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
832 "X86_64_RELOC_SUBTRACTOR.");
833
Charles Davis8bdfafd2013-09-01 04:28:48 +0000834 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
835 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000836 printRelocationTargetName(this, RENext, fmt);
837 fmt << "-";
838 printRelocationTargetName(this, RE, fmt);
839 break;
840 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000841 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000842 printRelocationTargetName(this, RE, fmt);
843 fmt << "@TLV";
844 if (isPCRel) fmt << "P";
845 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000846 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000847 printRelocationTargetName(this, RE, fmt);
848 fmt << "-1";
849 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000850 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000851 printRelocationTargetName(this, RE, fmt);
852 fmt << "-2";
853 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000854 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000855 printRelocationTargetName(this, RE, fmt);
856 fmt << "-4";
857 break;
858 default:
859 printRelocationTargetName(this, RE, fmt);
860 break;
861 }
862 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000863 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
864 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000865 // Generic relocation types...
866 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000867 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000868 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000869 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000870 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000871 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000872 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000873
874 // X86 sect diff's must be followed by a relocation of type
875 // GENERIC_RELOC_PAIR.
876 unsigned RType = getAnyRelocationType(RENext);
877
Charles Davis8bdfafd2013-09-01 04:28:48 +0000878 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000879 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
880 "GENERIC_RELOC_SECTDIFF.");
881
882 printRelocationTargetName(this, RE, fmt);
883 fmt << "-";
884 printRelocationTargetName(this, RENext, fmt);
885 break;
886 }
887 }
888
David Fangb88cdf62013-08-08 20:14:40 +0000889 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000890 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000891 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000892 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000893 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000894 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000895
896 // X86 sect diff's must be followed by a relocation of type
897 // GENERIC_RELOC_PAIR.
898 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000899 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000900 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
901 "GENERIC_RELOC_LOCAL_SECTDIFF.");
902
903 printRelocationTargetName(this, RE, fmt);
904 fmt << "-";
905 printRelocationTargetName(this, RENext, fmt);
906 break;
907 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000908 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000909 printRelocationTargetName(this, RE, fmt);
910 fmt << "@TLV";
911 if (IsPCRel) fmt << "P";
912 break;
913 }
914 default:
915 printRelocationTargetName(this, RE, fmt);
916 }
917 } else { // ARM-specific relocations
918 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000919 case MachO::ARM_RELOC_HALF:
920 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000921 // Half relocations steal a bit from the length field to encode
922 // whether this is an upper16 or a lower16 relocation.
923 bool isUpper = getAnyRelocationLength(RE) >> 1;
924
925 if (isUpper)
926 fmt << ":upper16:(";
927 else
928 fmt << ":lower16:(";
929 printRelocationTargetName(this, RE, fmt);
930
931 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000932 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000933 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000934
935 // ARM half relocs must be followed by a relocation of type
936 // ARM_RELOC_PAIR.
937 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000938 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000939 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000940 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000941
942 // NOTE: The half of the target virtual address is stashed in the
943 // address field of the secondary relocation, but we can't reverse
944 // engineer the constant offset from it without decoding the movw/movt
945 // instruction to find the other half in its immediate field.
946
947 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
948 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000949 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000950 fmt << "-";
951 printRelocationTargetName(this, RENext, fmt);
952 }
953
954 fmt << ")";
955 break;
956 }
957 default: {
958 printRelocationTargetName(this, RE, fmt);
959 }
960 }
961 }
962 } else
963 printRelocationTargetName(this, RE, fmt);
964
Alp Tokere69170a2014-06-26 22:52:05 +0000965 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000966 Result.append(fmtbuf.begin(), fmtbuf.end());
967 return object_error::success;
968}
969
Rafael Espindola3acea392014-06-12 21:46:39 +0000970std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
971 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000972 unsigned Arch = getArch();
973 uint64_t Type;
974 getRelocationType(Rel, Type);
975
976 Result = false;
977
978 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
979 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000980 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000981 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000982 } else if (Arch == Triple::x86_64) {
983 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000984 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000985 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000986 DataRefImpl RelPrev = Rel;
987 RelPrev.d.a--;
988 uint64_t PrevType;
989 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000990 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000991 Result = true;
992 }
993 }
994
995 return object_error::success;
996}
997
Kevin Enderby980b2582014-06-05 21:21:57 +0000998//
999// guessLibraryShortName() is passed a name of a dynamic library and returns a
1000// guess on what the short name is. Then name is returned as a substring of the
1001// StringRef Name passed in. The name of the dynamic library is recognized as
1002// a framework if it has one of the two following forms:
1003// Foo.framework/Versions/A/Foo
1004// Foo.framework/Foo
1005// Where A and Foo can be any string. And may contain a trailing suffix
1006// starting with an underbar. If the Name is recognized as a framework then
1007// isFramework is set to true else it is set to false. If the Name has a
1008// suffix then Suffix is set to the substring in Name that contains the suffix
1009// else it is set to a NULL StringRef.
1010//
1011// The Name of the dynamic library is recognized as a library name if it has
1012// one of the two following forms:
1013// libFoo.A.dylib
1014// libFoo.dylib
1015// The library may have a suffix trailing the name Foo of the form:
1016// libFoo_profile.A.dylib
1017// libFoo_profile.dylib
1018//
1019// The Name of the dynamic library is also recognized as a library name if it
1020// has the following form:
1021// Foo.qtx
1022//
1023// If the Name of the dynamic library is none of the forms above then a NULL
1024// StringRef is returned.
1025//
1026StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1027 bool &isFramework,
1028 StringRef &Suffix) {
1029 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1030 size_t a, b, c, d, Idx;
1031
1032 isFramework = false;
1033 Suffix = StringRef();
1034
1035 // Pull off the last component and make Foo point to it
1036 a = Name.rfind('/');
1037 if (a == Name.npos || a == 0)
1038 goto guess_library;
1039 Foo = Name.slice(a+1, Name.npos);
1040
1041 // Look for a suffix starting with a '_'
1042 Idx = Foo.rfind('_');
1043 if (Idx != Foo.npos && Foo.size() >= 2) {
1044 Suffix = Foo.slice(Idx, Foo.npos);
1045 Foo = Foo.slice(0, Idx);
1046 }
1047
1048 // First look for the form Foo.framework/Foo
1049 b = Name.rfind('/', a);
1050 if (b == Name.npos)
1051 Idx = 0;
1052 else
1053 Idx = b+1;
1054 F = Name.slice(Idx, Idx + Foo.size());
1055 DotFramework = Name.slice(Idx + Foo.size(),
1056 Idx + Foo.size() + sizeof(".framework/")-1);
1057 if (F == Foo && DotFramework == ".framework/") {
1058 isFramework = true;
1059 return Foo;
1060 }
1061
1062 // Next look for the form Foo.framework/Versions/A/Foo
1063 if (b == Name.npos)
1064 goto guess_library;
1065 c = Name.rfind('/', b);
1066 if (c == Name.npos || c == 0)
1067 goto guess_library;
1068 V = Name.slice(c+1, Name.npos);
1069 if (!V.startswith("Versions/"))
1070 goto guess_library;
1071 d = Name.rfind('/', c);
1072 if (d == Name.npos)
1073 Idx = 0;
1074 else
1075 Idx = d+1;
1076 F = Name.slice(Idx, Idx + Foo.size());
1077 DotFramework = Name.slice(Idx + Foo.size(),
1078 Idx + Foo.size() + sizeof(".framework/")-1);
1079 if (F == Foo && DotFramework == ".framework/") {
1080 isFramework = true;
1081 return Foo;
1082 }
1083
1084guess_library:
1085 // pull off the suffix after the "." and make a point to it
1086 a = Name.rfind('.');
1087 if (a == Name.npos || a == 0)
1088 return StringRef();
1089 Dylib = Name.slice(a, Name.npos);
1090 if (Dylib != ".dylib")
1091 goto guess_qtx;
1092
1093 // First pull off the version letter for the form Foo.A.dylib if any.
1094 if (a >= 3) {
1095 Dot = Name.slice(a-2, a-1);
1096 if (Dot == ".")
1097 a = a - 2;
1098 }
1099
1100 b = Name.rfind('/', a);
1101 if (b == Name.npos)
1102 b = 0;
1103 else
1104 b = b+1;
1105 // ignore any suffix after an underbar like Foo_profile.A.dylib
1106 Idx = Name.find('_', b);
1107 if (Idx != Name.npos && Idx != b) {
1108 Lib = Name.slice(b, Idx);
1109 Suffix = Name.slice(Idx, a);
1110 }
1111 else
1112 Lib = Name.slice(b, a);
1113 // There are incorrect library names of the form:
1114 // libATS.A_profile.dylib so check for these.
1115 if (Lib.size() >= 3) {
1116 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1117 if (Dot == ".")
1118 Lib = Lib.slice(0, Lib.size()-2);
1119 }
1120 return Lib;
1121
1122guess_qtx:
1123 Qtx = Name.slice(a, Name.npos);
1124 if (Qtx != ".qtx")
1125 return StringRef();
1126 b = Name.rfind('/', a);
1127 if (b == Name.npos)
1128 Lib = Name.slice(0, a);
1129 else
1130 Lib = Name.slice(b+1, a);
1131 // There are library names of the form: QT.A.qtx so check for these.
1132 if (Lib.size() >= 3) {
1133 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1134 if (Dot == ".")
1135 Lib = Lib.slice(0, Lib.size()-2);
1136 }
1137 return Lib;
1138}
1139
1140// getLibraryShortNameByIndex() is used to get the short name of the library
1141// for an undefined symbol in a linked Mach-O binary that was linked with the
1142// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1143// It is passed the index (0 - based) of the library as translated from
1144// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001145std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001146 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001147 if (Index >= Libraries.size())
1148 return object_error::parse_failed;
1149
Kevin Enderby980b2582014-06-05 21:21:57 +00001150 // If the cache of LibrariesShortNames is not built up do that first for
1151 // all the Libraries.
1152 if (LibrariesShortNames.size() == 0) {
1153 for (unsigned i = 0; i < Libraries.size(); i++) {
1154 MachO::dylib_command D =
1155 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001156 if (D.dylib.name >= D.cmdsize)
1157 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001158 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001159 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001160 if (D.dylib.name+Name.size() >= D.cmdsize)
1161 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001162 StringRef Suffix;
1163 bool isFramework;
1164 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001165 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001166 LibrariesShortNames.push_back(Name);
1167 else
1168 LibrariesShortNames.push_back(shortName);
1169 }
1170 }
1171
1172 Res = LibrariesShortNames[Index];
1173 return object_error::success;
1174}
1175
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001176basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001177 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001178}
1179
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001180basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001181 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001182 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001183 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001184
Charles Davis8bdfafd2013-09-01 04:28:48 +00001185 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001186 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001187 sizeof(MachO::nlist_64) :
1188 sizeof(MachO::nlist);
1189 unsigned Offset = Symtab.symoff +
1190 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001191 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001192 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001193}
1194
Lang Hames36072da2014-05-12 21:39:59 +00001195basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1196 DataRefImpl DRI;
1197 if (!SymtabLoadCmd)
1198 return basic_symbol_iterator(SymbolRef(DRI, this));
1199
1200 MachO::symtab_command Symtab = getSymtabLoadCommand();
1201 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1202 unsigned SymbolTableEntrySize =
1203 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1204 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1205 DRI.p += Index * SymbolTableEntrySize;
1206 return basic_symbol_iterator(SymbolRef(DRI, this));
1207}
1208
Rafael Espindolab5155a52014-02-10 20:24:04 +00001209section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001210 DataRefImpl DRI;
1211 return section_iterator(SectionRef(DRI, this));
1212}
1213
Rafael Espindolab5155a52014-02-10 20:24:04 +00001214section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001215 DataRefImpl DRI;
1216 DRI.d.a = Sections.size();
1217 return section_iterator(SectionRef(DRI, this));
1218}
1219
Rafael Espindola56f976f2013-04-18 18:08:55 +00001220uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001221 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001222}
1223
Rafael Espindola56f976f2013-04-18 18:08:55 +00001224StringRef MachOObjectFile::getFileFormatName() const {
1225 unsigned CPUType = getCPUType(this);
1226 if (!is64Bit()) {
1227 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001228 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001229 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001230 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001231 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001232 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001233 return "Mach-O 32-bit ppc";
1234 default:
Charles Davis74ec8b02013-08-27 05:00:13 +00001235 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindola56f976f2013-04-18 18:08:55 +00001236 "64-bit object file when we're not 64-bit?");
1237 return "Mach-O 32-bit unknown";
1238 }
1239 }
1240
1241 // Make sure the cpu type has the correct mask.
Charles Davis74ec8b02013-08-27 05:00:13 +00001242 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1243 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher1d62c252013-07-22 22:25:07 +00001244 "32-bit object file when we're 64-bit?");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001245
1246 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001247 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001248 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001249 case llvm::MachO::CPU_TYPE_ARM64:
1250 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001251 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001252 return "Mach-O 64-bit ppc64";
1253 default:
1254 return "Mach-O 64-bit unknown";
1255 }
1256}
1257
Alexey Samsonove6388e62013-06-18 15:03:28 +00001258Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1259 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001260 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001261 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001262 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001263 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001264 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001265 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001266 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001267 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001268 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001269 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001270 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001271 return Triple::ppc64;
1272 default:
1273 return Triple::UnknownArch;
1274 }
1275}
1276
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001277Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1278 const char **McpuDefault) {
1279 if (McpuDefault)
1280 *McpuDefault = nullptr;
1281
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001282 switch (CPUType) {
1283 case MachO::CPU_TYPE_I386:
1284 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1285 case MachO::CPU_SUBTYPE_I386_ALL:
1286 return Triple("i386-apple-darwin");
1287 default:
1288 return Triple();
1289 }
1290 case MachO::CPU_TYPE_X86_64:
1291 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1292 case MachO::CPU_SUBTYPE_X86_64_ALL:
1293 return Triple("x86_64-apple-darwin");
1294 case MachO::CPU_SUBTYPE_X86_64_H:
1295 return Triple("x86_64h-apple-darwin");
1296 default:
1297 return Triple();
1298 }
1299 case MachO::CPU_TYPE_ARM:
1300 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1301 case MachO::CPU_SUBTYPE_ARM_V4T:
1302 return Triple("armv4t-apple-darwin");
1303 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1304 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001305 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1306 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001307 case MachO::CPU_SUBTYPE_ARM_V6:
1308 return Triple("armv6-apple-darwin");
1309 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001310 if (McpuDefault)
1311 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001312 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001313 case MachO::CPU_SUBTYPE_ARM_V7:
1314 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001315 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001316 if (McpuDefault)
1317 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001318 return Triple("armv7em-apple-darwin");
1319 case MachO::CPU_SUBTYPE_ARM_V7K:
1320 return Triple("armv7k-apple-darwin");
1321 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001322 if (McpuDefault)
1323 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001324 return Triple("armv7m-apple-darwin");
1325 case MachO::CPU_SUBTYPE_ARM_V7S:
1326 return Triple("armv7s-apple-darwin");
1327 default:
1328 return Triple();
1329 }
1330 case MachO::CPU_TYPE_ARM64:
1331 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1332 case MachO::CPU_SUBTYPE_ARM64_ALL:
1333 return Triple("arm64-apple-darwin");
1334 default:
1335 return Triple();
1336 }
1337 case MachO::CPU_TYPE_POWERPC:
1338 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1339 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1340 return Triple("ppc-apple-darwin");
1341 default:
1342 return Triple();
1343 }
1344 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001345 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001346 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1347 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001348 default:
1349 return Triple();
1350 }
1351 default:
1352 return Triple();
1353 }
1354}
1355
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001356Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1357 const char **McpuDefault) {
1358 if (McpuDefault)
1359 *McpuDefault = nullptr;
1360
1361 switch (CPUType) {
1362 case MachO::CPU_TYPE_ARM:
1363 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1364 case MachO::CPU_SUBTYPE_ARM_V4T:
1365 return Triple("thumbv4t-apple-darwin");
1366 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1367 return Triple("thumbv5e-apple-darwin");
1368 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1369 return Triple("xscale-apple-darwin");
1370 case MachO::CPU_SUBTYPE_ARM_V6:
1371 return Triple("thumbv6-apple-darwin");
1372 case MachO::CPU_SUBTYPE_ARM_V6M:
1373 if (McpuDefault)
1374 *McpuDefault = "cortex-m0";
1375 return Triple("thumbv6m-apple-darwin");
1376 case MachO::CPU_SUBTYPE_ARM_V7:
1377 return Triple("thumbv7-apple-darwin");
1378 case MachO::CPU_SUBTYPE_ARM_V7EM:
1379 if (McpuDefault)
1380 *McpuDefault = "cortex-m4";
1381 return Triple("thumbv7em-apple-darwin");
1382 case MachO::CPU_SUBTYPE_ARM_V7K:
1383 return Triple("thumbv7k-apple-darwin");
1384 case MachO::CPU_SUBTYPE_ARM_V7M:
1385 if (McpuDefault)
1386 *McpuDefault = "cortex-m3";
1387 return Triple("thumbv7m-apple-darwin");
1388 case MachO::CPU_SUBTYPE_ARM_V7S:
1389 return Triple("thumbv7s-apple-darwin");
1390 default:
1391 return Triple();
1392 }
1393 default:
1394 return Triple();
1395 }
1396}
1397
1398Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1399 const char **McpuDefault,
1400 Triple *ThumbTriple) {
1401 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1402 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1403 McpuDefault);
1404 return T;
1405}
1406
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001407Triple MachOObjectFile::getHostArch() {
1408 return Triple(sys::getDefaultTargetTriple());
1409}
1410
Rafael Espindola72318b42014-08-08 16:30:17 +00001411bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1412 return StringSwitch<bool>(ArchFlag)
1413 .Case("i386", true)
1414 .Case("x86_64", true)
1415 .Case("x86_64h", true)
1416 .Case("armv4t", true)
1417 .Case("arm", true)
1418 .Case("armv5e", true)
1419 .Case("armv6", true)
1420 .Case("armv6m", true)
1421 .Case("armv7em", true)
1422 .Case("armv7k", true)
1423 .Case("armv7m", true)
1424 .Case("armv7s", true)
1425 .Case("arm64", true)
1426 .Case("ppc", true)
1427 .Case("ppc64", true)
1428 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001429}
1430
Alexey Samsonove6388e62013-06-18 15:03:28 +00001431unsigned MachOObjectFile::getArch() const {
1432 return getArch(getCPUType(this));
1433}
1434
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001435Triple MachOObjectFile::getArch(const char **McpuDefault,
1436 Triple *ThumbTriple) const {
1437 Triple T;
1438 if (is64Bit()) {
1439 MachO::mach_header_64 H_64;
1440 H_64 = getHeader64();
1441 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1442 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1443 McpuDefault);
1444 } else {
1445 MachO::mach_header H;
1446 H = getHeader();
1447 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1448 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1449 McpuDefault);
1450 }
1451 return T;
1452}
1453
Rui Ueyamabc654b12013-09-27 21:47:05 +00001454relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001455 DataRefImpl DRI;
1456 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001457 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001458}
1459
Rui Ueyamabc654b12013-09-27 21:47:05 +00001460relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001461 DataRefImpl DRI;
1462 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001463 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001464}
1465
Kevin Enderby273ae012013-06-06 17:20:50 +00001466dice_iterator MachOObjectFile::begin_dices() const {
1467 DataRefImpl DRI;
1468 if (!DataInCodeLoadCmd)
1469 return dice_iterator(DiceRef(DRI, this));
1470
Charles Davis8bdfafd2013-09-01 04:28:48 +00001471 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1472 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001473 return dice_iterator(DiceRef(DRI, this));
1474}
1475
1476dice_iterator MachOObjectFile::end_dices() const {
1477 DataRefImpl DRI;
1478 if (!DataInCodeLoadCmd)
1479 return dice_iterator(DiceRef(DRI, this));
1480
Charles Davis8bdfafd2013-09-01 04:28:48 +00001481 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1482 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001483 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1484 return dice_iterator(DiceRef(DRI, this));
1485}
1486
Nick Kledzikd04bc352014-08-30 00:20:14 +00001487ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1488 : Trie(T), Malformed(false), Done(false) { }
1489
1490void ExportEntry::moveToFirst() {
1491 pushNode(0);
1492 pushDownUntilBottom();
1493}
1494
1495void ExportEntry::moveToEnd() {
1496 Stack.clear();
1497 Done = true;
1498}
1499
1500bool ExportEntry::operator==(const ExportEntry &Other) const {
1501 // Common case, one at end, other iterating from begin.
1502 if (Done || Other.Done)
1503 return (Done == Other.Done);
1504 // Not equal if different stack sizes.
1505 if (Stack.size() != Other.Stack.size())
1506 return false;
1507 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001508 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001509 return false;
1510 // Equal if all nodes in both stacks match.
1511 for (unsigned i=0; i < Stack.size(); ++i) {
1512 if (Stack[i].Start != Other.Stack[i].Start)
1513 return false;
1514 }
1515 return true;
1516}
1517
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001518uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1519 unsigned Count;
1520 uint64_t Result = decodeULEB128(Ptr, &Count);
1521 Ptr += Count;
1522 if (Ptr > Trie.end()) {
1523 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001524 Malformed = true;
1525 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001526 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001527}
1528
1529StringRef ExportEntry::name() const {
1530 return CumulativeString.str();
1531}
1532
1533uint64_t ExportEntry::flags() const {
1534 return Stack.back().Flags;
1535}
1536
1537uint64_t ExportEntry::address() const {
1538 return Stack.back().Address;
1539}
1540
1541uint64_t ExportEntry::other() const {
1542 return Stack.back().Other;
1543}
1544
1545StringRef ExportEntry::otherName() const {
1546 const char* ImportName = Stack.back().ImportName;
1547 if (ImportName)
1548 return StringRef(ImportName);
1549 return StringRef();
1550}
1551
1552uint32_t ExportEntry::nodeOffset() const {
1553 return Stack.back().Start - Trie.begin();
1554}
1555
1556ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1557 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1558 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1559 ParentStringLength(0), IsExportNode(false) {
1560}
1561
1562void ExportEntry::pushNode(uint64_t offset) {
1563 const uint8_t *Ptr = Trie.begin() + offset;
1564 NodeState State(Ptr);
1565 uint64_t ExportInfoSize = readULEB128(State.Current);
1566 State.IsExportNode = (ExportInfoSize != 0);
1567 const uint8_t* Children = State.Current + ExportInfoSize;
1568 if (State.IsExportNode) {
1569 State.Flags = readULEB128(State.Current);
1570 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1571 State.Address = 0;
1572 State.Other = readULEB128(State.Current); // dylib ordinal
1573 State.ImportName = reinterpret_cast<const char*>(State.Current);
1574 } else {
1575 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001576 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1577 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001578 }
1579 }
1580 State.ChildCount = *Children;
1581 State.Current = Children + 1;
1582 State.NextChildIndex = 0;
1583 State.ParentStringLength = CumulativeString.size();
1584 Stack.push_back(State);
1585}
1586
1587void ExportEntry::pushDownUntilBottom() {
1588 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1589 NodeState &Top = Stack.back();
1590 CumulativeString.resize(Top.ParentStringLength);
1591 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001592 char C = *Top.Current;
1593 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001594 }
1595 Top.Current += 1;
1596 uint64_t childNodeIndex = readULEB128(Top.Current);
1597 Top.NextChildIndex += 1;
1598 pushNode(childNodeIndex);
1599 }
1600 if (!Stack.back().IsExportNode) {
1601 Malformed = true;
1602 moveToEnd();
1603 }
1604}
1605
1606// We have a trie data structure and need a way to walk it that is compatible
1607// with the C++ iterator model. The solution is a non-recursive depth first
1608// traversal where the iterator contains a stack of parent nodes along with a
1609// string that is the accumulation of all edge strings along the parent chain
1610// to this point.
1611//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001612// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001613// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1614// node may have child nodes too.
1615//
1616// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1617// child until hitting a node with no children (which is an export node or
1618// else the trie is malformed). On the way down, each node is pushed on the
1619// stack ivar. If there is no more ways down, it pops up one and tries to go
1620// down a sibling path until a childless node is reached.
1621void ExportEntry::moveNext() {
1622 if (Stack.empty() || !Stack.back().IsExportNode) {
1623 Malformed = true;
1624 moveToEnd();
1625 return;
1626 }
1627
1628 Stack.pop_back();
1629 while (!Stack.empty()) {
1630 NodeState &Top = Stack.back();
1631 if (Top.NextChildIndex < Top.ChildCount) {
1632 pushDownUntilBottom();
1633 // Now at the next export node.
1634 return;
1635 } else {
1636 if (Top.IsExportNode) {
1637 // This node has no children but is itself an export node.
1638 CumulativeString.resize(Top.ParentStringLength);
1639 return;
1640 }
1641 Stack.pop_back();
1642 }
1643 }
1644 Done = true;
1645}
1646
1647iterator_range<export_iterator>
1648MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1649 ExportEntry Start(Trie);
1650 Start.moveToFirst();
1651
1652 ExportEntry Finish(Trie);
1653 Finish.moveToEnd();
1654
1655 return iterator_range<export_iterator>(export_iterator(Start),
1656 export_iterator(Finish));
1657}
1658
1659iterator_range<export_iterator> MachOObjectFile::exports() const {
1660 return exports(getDyldInfoExportsTrie());
1661}
1662
1663
Nick Kledzikac431442014-09-12 21:34:15 +00001664MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1665 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1666 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1667 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1668
1669void MachORebaseEntry::moveToFirst() {
1670 Ptr = Opcodes.begin();
1671 moveNext();
1672}
1673
1674void MachORebaseEntry::moveToEnd() {
1675 Ptr = Opcodes.end();
1676 RemainingLoopCount = 0;
1677 Done = true;
1678}
1679
1680void MachORebaseEntry::moveNext() {
1681 // If in the middle of some loop, move to next rebasing in loop.
1682 SegmentOffset += AdvanceAmount;
1683 if (RemainingLoopCount) {
1684 --RemainingLoopCount;
1685 return;
1686 }
1687 if (Ptr == Opcodes.end()) {
1688 Done = true;
1689 return;
1690 }
1691 bool More = true;
1692 while (More && !Malformed) {
1693 // Parse next opcode and set up next loop.
1694 uint8_t Byte = *Ptr++;
1695 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1696 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1697 switch (Opcode) {
1698 case MachO::REBASE_OPCODE_DONE:
1699 More = false;
1700 Done = true;
1701 moveToEnd();
1702 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1703 break;
1704 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1705 RebaseType = ImmValue;
1706 DEBUG_WITH_TYPE(
1707 "mach-o-rebase",
1708 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1709 << "RebaseType=" << (int) RebaseType << "\n");
1710 break;
1711 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1712 SegmentIndex = ImmValue;
1713 SegmentOffset = readULEB128();
1714 DEBUG_WITH_TYPE(
1715 "mach-o-rebase",
1716 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1717 << "SegmentIndex=" << SegmentIndex << ", "
1718 << format("SegmentOffset=0x%06X", SegmentOffset)
1719 << "\n");
1720 break;
1721 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1722 SegmentOffset += readULEB128();
1723 DEBUG_WITH_TYPE("mach-o-rebase",
1724 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1725 << format("SegmentOffset=0x%06X",
1726 SegmentOffset) << "\n");
1727 break;
1728 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1729 SegmentOffset += ImmValue * PointerSize;
1730 DEBUG_WITH_TYPE("mach-o-rebase",
1731 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1732 << format("SegmentOffset=0x%06X",
1733 SegmentOffset) << "\n");
1734 break;
1735 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1736 AdvanceAmount = PointerSize;
1737 RemainingLoopCount = ImmValue - 1;
1738 DEBUG_WITH_TYPE(
1739 "mach-o-rebase",
1740 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1741 << format("SegmentOffset=0x%06X", SegmentOffset)
1742 << ", AdvanceAmount=" << AdvanceAmount
1743 << ", RemainingLoopCount=" << RemainingLoopCount
1744 << "\n");
1745 return;
1746 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1747 AdvanceAmount = PointerSize;
1748 RemainingLoopCount = readULEB128() - 1;
1749 DEBUG_WITH_TYPE(
1750 "mach-o-rebase",
1751 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1752 << format("SegmentOffset=0x%06X", SegmentOffset)
1753 << ", AdvanceAmount=" << AdvanceAmount
1754 << ", RemainingLoopCount=" << RemainingLoopCount
1755 << "\n");
1756 return;
1757 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1758 AdvanceAmount = readULEB128() + PointerSize;
1759 RemainingLoopCount = 0;
1760 DEBUG_WITH_TYPE(
1761 "mach-o-rebase",
1762 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1763 << format("SegmentOffset=0x%06X", SegmentOffset)
1764 << ", AdvanceAmount=" << AdvanceAmount
1765 << ", RemainingLoopCount=" << RemainingLoopCount
1766 << "\n");
1767 return;
1768 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1769 RemainingLoopCount = readULEB128() - 1;
1770 AdvanceAmount = readULEB128() + PointerSize;
1771 DEBUG_WITH_TYPE(
1772 "mach-o-rebase",
1773 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1774 << format("SegmentOffset=0x%06X", SegmentOffset)
1775 << ", AdvanceAmount=" << AdvanceAmount
1776 << ", RemainingLoopCount=" << RemainingLoopCount
1777 << "\n");
1778 return;
1779 default:
1780 Malformed = true;
1781 }
1782 }
1783}
1784
1785uint64_t MachORebaseEntry::readULEB128() {
1786 unsigned Count;
1787 uint64_t Result = decodeULEB128(Ptr, &Count);
1788 Ptr += Count;
1789 if (Ptr > Opcodes.end()) {
1790 Ptr = Opcodes.end();
1791 Malformed = true;
1792 }
1793 return Result;
1794}
1795
1796uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1797
1798uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1799
1800StringRef MachORebaseEntry::typeName() const {
1801 switch (RebaseType) {
1802 case MachO::REBASE_TYPE_POINTER:
1803 return "pointer";
1804 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1805 return "text abs32";
1806 case MachO::REBASE_TYPE_TEXT_PCREL32:
1807 return "text rel32";
1808 }
1809 return "unknown";
1810}
1811
1812bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1813 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1814 return (Ptr == Other.Ptr) &&
1815 (RemainingLoopCount == Other.RemainingLoopCount) &&
1816 (Done == Other.Done);
1817}
1818
1819iterator_range<rebase_iterator>
1820MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1821 MachORebaseEntry Start(Opcodes, is64);
1822 Start.moveToFirst();
1823
1824 MachORebaseEntry Finish(Opcodes, is64);
1825 Finish.moveToEnd();
1826
1827 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1828 rebase_iterator(Finish));
1829}
1830
1831iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1832 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1833}
1834
Nick Kledzik56ebef42014-09-16 01:41:51 +00001835
1836MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1837 Kind BK)
1838 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1839 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1840 BindType(0), PointerSize(is64Bit ? 8 : 4),
1841 TableKind(BK), Malformed(false), Done(false) {}
1842
1843void MachOBindEntry::moveToFirst() {
1844 Ptr = Opcodes.begin();
1845 moveNext();
1846}
1847
1848void MachOBindEntry::moveToEnd() {
1849 Ptr = Opcodes.end();
1850 RemainingLoopCount = 0;
1851 Done = true;
1852}
1853
1854void MachOBindEntry::moveNext() {
1855 // If in the middle of some loop, move to next binding in loop.
1856 SegmentOffset += AdvanceAmount;
1857 if (RemainingLoopCount) {
1858 --RemainingLoopCount;
1859 return;
1860 }
1861 if (Ptr == Opcodes.end()) {
1862 Done = true;
1863 return;
1864 }
1865 bool More = true;
1866 while (More && !Malformed) {
1867 // Parse next opcode and set up next loop.
1868 uint8_t Byte = *Ptr++;
1869 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1870 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1871 int8_t SignExtended;
1872 const uint8_t *SymStart;
1873 switch (Opcode) {
1874 case MachO::BIND_OPCODE_DONE:
1875 if (TableKind == Kind::Lazy) {
1876 // Lazying bindings have a DONE opcode between entries. Need to ignore
1877 // it to advance to next entry. But need not if this is last entry.
1878 bool NotLastEntry = false;
1879 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1880 if (*P) {
1881 NotLastEntry = true;
1882 }
1883 }
1884 if (NotLastEntry)
1885 break;
1886 }
1887 More = false;
1888 Done = true;
1889 moveToEnd();
1890 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1891 break;
1892 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1893 Ordinal = ImmValue;
1894 DEBUG_WITH_TYPE(
1895 "mach-o-bind",
1896 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1897 << "Ordinal=" << Ordinal << "\n");
1898 break;
1899 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1900 Ordinal = readULEB128();
1901 DEBUG_WITH_TYPE(
1902 "mach-o-bind",
1903 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1904 << "Ordinal=" << Ordinal << "\n");
1905 break;
1906 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1907 if (ImmValue) {
1908 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1909 Ordinal = SignExtended;
1910 } else
1911 Ordinal = 0;
1912 DEBUG_WITH_TYPE(
1913 "mach-o-bind",
1914 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1915 << "Ordinal=" << Ordinal << "\n");
1916 break;
1917 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1918 Flags = ImmValue;
1919 SymStart = Ptr;
1920 while (*Ptr) {
1921 ++Ptr;
1922 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001923 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1924 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001925 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001926 DEBUG_WITH_TYPE(
1927 "mach-o-bind",
1928 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1929 << "SymbolName=" << SymbolName << "\n");
1930 if (TableKind == Kind::Weak) {
1931 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1932 return;
1933 }
1934 break;
1935 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1936 BindType = ImmValue;
1937 DEBUG_WITH_TYPE(
1938 "mach-o-bind",
1939 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1940 << "BindType=" << (int)BindType << "\n");
1941 break;
1942 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1943 Addend = readSLEB128();
1944 if (TableKind == Kind::Lazy)
1945 Malformed = true;
1946 DEBUG_WITH_TYPE(
1947 "mach-o-bind",
1948 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1949 << "Addend=" << Addend << "\n");
1950 break;
1951 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1952 SegmentIndex = ImmValue;
1953 SegmentOffset = readULEB128();
1954 DEBUG_WITH_TYPE(
1955 "mach-o-bind",
1956 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1957 << "SegmentIndex=" << SegmentIndex << ", "
1958 << format("SegmentOffset=0x%06X", SegmentOffset)
1959 << "\n");
1960 break;
1961 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1962 SegmentOffset += readULEB128();
1963 DEBUG_WITH_TYPE("mach-o-bind",
1964 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1965 << format("SegmentOffset=0x%06X",
1966 SegmentOffset) << "\n");
1967 break;
1968 case MachO::BIND_OPCODE_DO_BIND:
1969 AdvanceAmount = PointerSize;
1970 RemainingLoopCount = 0;
1971 DEBUG_WITH_TYPE("mach-o-bind",
1972 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1973 << format("SegmentOffset=0x%06X",
1974 SegmentOffset) << "\n");
1975 return;
1976 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001977 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001978 RemainingLoopCount = 0;
1979 if (TableKind == Kind::Lazy)
1980 Malformed = true;
1981 DEBUG_WITH_TYPE(
1982 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001983 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001984 << format("SegmentOffset=0x%06X", SegmentOffset)
1985 << ", AdvanceAmount=" << AdvanceAmount
1986 << ", RemainingLoopCount=" << RemainingLoopCount
1987 << "\n");
1988 return;
1989 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001990 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001991 RemainingLoopCount = 0;
1992 if (TableKind == Kind::Lazy)
1993 Malformed = true;
1994 DEBUG_WITH_TYPE("mach-o-bind",
1995 llvm::dbgs()
1996 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1997 << format("SegmentOffset=0x%06X",
1998 SegmentOffset) << "\n");
1999 return;
2000 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2001 RemainingLoopCount = readULEB128() - 1;
2002 AdvanceAmount = readULEB128() + PointerSize;
2003 if (TableKind == Kind::Lazy)
2004 Malformed = true;
2005 DEBUG_WITH_TYPE(
2006 "mach-o-bind",
2007 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2008 << format("SegmentOffset=0x%06X", SegmentOffset)
2009 << ", AdvanceAmount=" << AdvanceAmount
2010 << ", RemainingLoopCount=" << RemainingLoopCount
2011 << "\n");
2012 return;
2013 default:
2014 Malformed = true;
2015 }
2016 }
2017}
2018
2019uint64_t MachOBindEntry::readULEB128() {
2020 unsigned Count;
2021 uint64_t Result = decodeULEB128(Ptr, &Count);
2022 Ptr += Count;
2023 if (Ptr > Opcodes.end()) {
2024 Ptr = Opcodes.end();
2025 Malformed = true;
2026 }
2027 return Result;
2028}
2029
2030int64_t MachOBindEntry::readSLEB128() {
2031 unsigned Count;
2032 int64_t Result = decodeSLEB128(Ptr, &Count);
2033 Ptr += Count;
2034 if (Ptr > Opcodes.end()) {
2035 Ptr = Opcodes.end();
2036 Malformed = true;
2037 }
2038 return Result;
2039}
2040
2041
2042uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2043
2044uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2045
2046StringRef MachOBindEntry::typeName() const {
2047 switch (BindType) {
2048 case MachO::BIND_TYPE_POINTER:
2049 return "pointer";
2050 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2051 return "text abs32";
2052 case MachO::BIND_TYPE_TEXT_PCREL32:
2053 return "text rel32";
2054 }
2055 return "unknown";
2056}
2057
2058StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2059
2060int64_t MachOBindEntry::addend() const { return Addend; }
2061
2062uint32_t MachOBindEntry::flags() const { return Flags; }
2063
2064int MachOBindEntry::ordinal() const { return Ordinal; }
2065
2066bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2067 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2068 return (Ptr == Other.Ptr) &&
2069 (RemainingLoopCount == Other.RemainingLoopCount) &&
2070 (Done == Other.Done);
2071}
2072
2073iterator_range<bind_iterator>
2074MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2075 MachOBindEntry::Kind BKind) {
2076 MachOBindEntry Start(Opcodes, is64, BKind);
2077 Start.moveToFirst();
2078
2079 MachOBindEntry Finish(Opcodes, is64, BKind);
2080 Finish.moveToEnd();
2081
2082 return iterator_range<bind_iterator>(bind_iterator(Start),
2083 bind_iterator(Finish));
2084}
2085
2086iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2087 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2088 MachOBindEntry::Kind::Regular);
2089}
2090
2091iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2092 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2093 MachOBindEntry::Kind::Lazy);
2094}
2095
2096iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2097 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2098 MachOBindEntry::Kind::Weak);
2099}
2100
Rafael Espindola56f976f2013-04-18 18:08:55 +00002101StringRef
2102MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2103 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2104 return parseSegmentOrSectionName(Raw.data());
2105}
2106
2107ArrayRef<char>
2108MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002109 const section_base *Base =
2110 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002111 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002112}
2113
2114ArrayRef<char>
2115MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002116 const section_base *Base =
2117 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002118 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002119}
2120
2121bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002122MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002123 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002124 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002125 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002126 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002127}
2128
Eric Christopher1d62c252013-07-22 22:25:07 +00002129unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002130 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002131 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002132 return RE.r_word1 & 0xffffff;
2133 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002134}
2135
Eric Christopher1d62c252013-07-22 22:25:07 +00002136bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002137 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002138 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002139 return (RE.r_word1 >> 27) & 1;
2140 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002141}
2142
Eric Christopher1d62c252013-07-22 22:25:07 +00002143bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002144 const MachO::any_relocation_info &RE) const {
2145 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002146}
2147
Eric Christopher1d62c252013-07-22 22:25:07 +00002148uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002149 const MachO::any_relocation_info &RE) const {
2150 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002151}
2152
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002153uint32_t MachOObjectFile::getScatteredRelocationType(
2154 const MachO::any_relocation_info &RE) const {
2155 return (RE.r_word0 >> 24) & 0xf;
2156}
2157
Eric Christopher1d62c252013-07-22 22:25:07 +00002158unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002159 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002160 if (isRelocationScattered(RE))
2161 return getScatteredRelocationAddress(RE);
2162 return getPlainRelocationAddress(RE);
2163}
2164
Charles Davis8bdfafd2013-09-01 04:28:48 +00002165unsigned MachOObjectFile::getAnyRelocationPCRel(
2166 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002167 if (isRelocationScattered(RE))
2168 return getScatteredRelocationPCRel(this, RE);
2169 return getPlainRelocationPCRel(this, RE);
2170}
2171
Eric Christopher1d62c252013-07-22 22:25:07 +00002172unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002173 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002174 if (isRelocationScattered(RE))
2175 return getScatteredRelocationLength(RE);
2176 return getPlainRelocationLength(this, RE);
2177}
2178
2179unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002180MachOObjectFile::getAnyRelocationType(
2181 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002182 if (isRelocationScattered(RE))
2183 return getScatteredRelocationType(RE);
2184 return getPlainRelocationType(this, RE);
2185}
2186
Rafael Espindola52501032013-04-30 15:40:54 +00002187SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00002188MachOObjectFile::getRelocationSection(
2189 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002190 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002191 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002192 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2193 DataRefImpl DRI;
2194 DRI.d.a = SecNum;
2195 return SectionRef(DRI, this);
2196}
2197
Rafael Espindola56f976f2013-04-18 18:08:55 +00002198MachOObjectFile::LoadCommandInfo
2199MachOObjectFile::getFirstLoadCommandInfo() const {
2200 MachOObjectFile::LoadCommandInfo Load;
2201
Charles Davis8bdfafd2013-09-01 04:28:48 +00002202 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2203 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002204 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002205 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002206 return Load;
2207}
2208
2209MachOObjectFile::LoadCommandInfo
2210MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2211 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002212 Next.Ptr = L.Ptr + L.C.cmdsize;
2213 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002214 return Next;
2215}
2216
Charles Davis8bdfafd2013-09-01 04:28:48 +00002217MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2218 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002219}
2220
Charles Davis8bdfafd2013-09-01 04:28:48 +00002221MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2222 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002223}
2224
Charles Davis8bdfafd2013-09-01 04:28:48 +00002225MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002226 unsigned Index) const {
2227 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002228 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002229}
2230
Charles Davis8bdfafd2013-09-01 04:28:48 +00002231MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2232 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002233 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002234 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002235}
2236
Charles Davis8bdfafd2013-09-01 04:28:48 +00002237MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002238MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002239 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002240 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002241}
2242
Charles Davis8bdfafd2013-09-01 04:28:48 +00002243MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002244MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002245 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002246 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002247}
2248
Charles Davis8bdfafd2013-09-01 04:28:48 +00002249MachO::linkedit_data_command
2250MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2251 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002252}
2253
Charles Davis8bdfafd2013-09-01 04:28:48 +00002254MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002255MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002256 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002257}
2258
Charles Davis8bdfafd2013-09-01 04:28:48 +00002259MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002260MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002261 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002262}
2263
Charles Davis8bdfafd2013-09-01 04:28:48 +00002264MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002265MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002266 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002267}
2268
Jim Grosbach448334a2014-03-18 22:09:05 +00002269MachO::version_min_command
2270MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2271 return getStruct<MachO::version_min_command>(this, L.Ptr);
2272}
2273
Tim Northover8f9590b2014-06-30 14:40:57 +00002274MachO::dylib_command
2275MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2276 return getStruct<MachO::dylib_command>(this, L.Ptr);
2277}
2278
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002279MachO::dyld_info_command
2280MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2281 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2282}
2283
2284MachO::dylinker_command
2285MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2286 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2287}
2288
2289MachO::uuid_command
2290MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2291 return getStruct<MachO::uuid_command>(this, L.Ptr);
2292}
2293
2294MachO::source_version_command
2295MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2296 return getStruct<MachO::source_version_command>(this, L.Ptr);
2297}
2298
2299MachO::entry_point_command
2300MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2301 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2302}
2303
Tim Northover8f9590b2014-06-30 14:40:57 +00002304
Charles Davis8bdfafd2013-09-01 04:28:48 +00002305MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002306MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002307 DataRefImpl Sec;
2308 Sec.d.a = Rel.d.a;
2309 uint32_t Offset;
2310 if (is64Bit()) {
2311 MachO::section_64 Sect = getSection64(Sec);
2312 Offset = Sect.reloff;
2313 } else {
2314 MachO::section Sect = getSection(Sec);
2315 Offset = Sect.reloff;
2316 }
2317
2318 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2319 getPtr(this, Offset)) + Rel.d.b;
2320 return getStruct<MachO::any_relocation_info>(
2321 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002322}
2323
Charles Davis8bdfafd2013-09-01 04:28:48 +00002324MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002325MachOObjectFile::getDice(DataRefImpl Rel) const {
2326 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002327 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002328}
2329
Charles Davis8bdfafd2013-09-01 04:28:48 +00002330MachO::mach_header MachOObjectFile::getHeader() const {
2331 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002332}
2333
Charles Davis8bdfafd2013-09-01 04:28:48 +00002334MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2335 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002336}
2337
Charles Davis8bdfafd2013-09-01 04:28:48 +00002338uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2339 const MachO::dysymtab_command &DLC,
2340 unsigned Index) const {
2341 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2342 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002343}
2344
Charles Davis8bdfafd2013-09-01 04:28:48 +00002345MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002346MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2347 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002348 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2349 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002350}
2351
Charles Davis8bdfafd2013-09-01 04:28:48 +00002352MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002353 if (SymtabLoadCmd)
2354 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2355
2356 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2357 MachO::symtab_command Cmd;
2358 Cmd.cmd = MachO::LC_SYMTAB;
2359 Cmd.cmdsize = sizeof(MachO::symtab_command);
2360 Cmd.symoff = 0;
2361 Cmd.nsyms = 0;
2362 Cmd.stroff = 0;
2363 Cmd.strsize = 0;
2364 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002365}
2366
Charles Davis8bdfafd2013-09-01 04:28:48 +00002367MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002368 if (DysymtabLoadCmd)
2369 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2370
2371 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2372 MachO::dysymtab_command Cmd;
2373 Cmd.cmd = MachO::LC_DYSYMTAB;
2374 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2375 Cmd.ilocalsym = 0;
2376 Cmd.nlocalsym = 0;
2377 Cmd.iextdefsym = 0;
2378 Cmd.nextdefsym = 0;
2379 Cmd.iundefsym = 0;
2380 Cmd.nundefsym = 0;
2381 Cmd.tocoff = 0;
2382 Cmd.ntoc = 0;
2383 Cmd.modtaboff = 0;
2384 Cmd.nmodtab = 0;
2385 Cmd.extrefsymoff = 0;
2386 Cmd.nextrefsyms = 0;
2387 Cmd.indirectsymoff = 0;
2388 Cmd.nindirectsyms = 0;
2389 Cmd.extreloff = 0;
2390 Cmd.nextrel = 0;
2391 Cmd.locreloff = 0;
2392 Cmd.nlocrel = 0;
2393 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002394}
2395
Charles Davis8bdfafd2013-09-01 04:28:48 +00002396MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002397MachOObjectFile::getDataInCodeLoadCommand() const {
2398 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002399 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002400
2401 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002402 MachO::linkedit_data_command Cmd;
2403 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2404 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2405 Cmd.dataoff = 0;
2406 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002407 return Cmd;
2408}
2409
Nick Kledzikd04bc352014-08-30 00:20:14 +00002410ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2411 if (!DyldInfoLoadCmd)
2412 return ArrayRef<uint8_t>();
2413
2414 MachO::dyld_info_command DyldInfo
2415 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2416 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2417 getPtr(this, DyldInfo.rebase_off));
2418 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2419}
2420
2421ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2422 if (!DyldInfoLoadCmd)
2423 return ArrayRef<uint8_t>();
2424
2425 MachO::dyld_info_command DyldInfo
2426 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2427 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2428 getPtr(this, DyldInfo.bind_off));
2429 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2430}
2431
2432ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2433 if (!DyldInfoLoadCmd)
2434 return ArrayRef<uint8_t>();
2435
2436 MachO::dyld_info_command DyldInfo
2437 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2438 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2439 getPtr(this, DyldInfo.weak_bind_off));
2440 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2441}
2442
2443ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2444 if (!DyldInfoLoadCmd)
2445 return ArrayRef<uint8_t>();
2446
2447 MachO::dyld_info_command DyldInfo
2448 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2449 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2450 getPtr(this, DyldInfo.lazy_bind_off));
2451 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2452}
2453
2454ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2455 if (!DyldInfoLoadCmd)
2456 return ArrayRef<uint8_t>();
2457
2458 MachO::dyld_info_command DyldInfo
2459 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2460 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2461 getPtr(this, DyldInfo.export_off));
2462 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2463}
2464
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002465ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2466 if (!UuidLoadCmd)
2467 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002468 // Returning a pointer is fine as uuid doesn't need endian swapping.
2469 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2470 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002471}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002472
Rafael Espindola6e040c02013-04-26 20:07:33 +00002473StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002474 MachO::symtab_command S = getSymtabLoadCommand();
2475 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002476}
2477
Rafael Espindola56f976f2013-04-18 18:08:55 +00002478bool MachOObjectFile::is64Bit() const {
2479 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002480 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002481}
2482
2483void MachOObjectFile::ReadULEB128s(uint64_t Index,
2484 SmallVectorImpl<uint64_t> &Out) const {
2485 DataExtractor extractor(ObjectFile::getData(), true, 0);
2486
2487 uint32_t offset = Index;
2488 uint64_t data = 0;
2489 while (uint64_t delta = extractor.getULEB128(&offset)) {
2490 data += delta;
2491 Out.push_back(data);
2492 }
2493}
2494
Rafael Espindolac66d7612014-08-17 19:09:37 +00002495bool MachOObjectFile::isRelocatableObject() const {
2496 return getHeader().filetype == MachO::MH_OBJECT;
2497}
2498
Rafael Espindola437b0d52014-07-31 03:12:45 +00002499ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002500ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2501 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002502 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002503 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002504 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002505 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002506 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002507 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002508 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002509 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002510 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002511 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002512 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002513 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002514
Rafael Espindola692410e2014-01-21 23:06:54 +00002515 if (EC)
2516 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002517 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002518}
2519