blob: c6815ea27d24cfd02f8289a5a872cfc10c6cf2b5 [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"
Owen Andersonbc14bd32011-10-26 20:42:54 +000020#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000021#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000022#include "llvm/Support/LEB128.h"
23#include "llvm/Support/MachO.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000024#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000025#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000026#include <cctype>
27#include <cstring>
28#include <limits>
29
30using namespace llvm;
31using namespace object;
32
Artyom Skrobov7d602f72014-07-20 12:08:28 +000033namespace {
34 struct section_base {
35 char sectname[16];
36 char segname[16];
37 };
38}
Rafael Espindola56f976f2013-04-18 18:08:55 +000039
40template<typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000041static T getStruct(const MachOObjectFile *O, const char *P) {
Rafael Espindola3cdeb172013-04-19 13:45:05 +000042 T Cmd;
43 memcpy(&Cmd, P, sizeof(T));
44 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000045 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000046 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000047}
48
Rafael Espindola56f976f2013-04-18 18:08:55 +000049static uint32_t
50getSegmentLoadCommandNumSections(const MachOObjectFile *O,
51 const MachOObjectFile::LoadCommandInfo &L) {
52 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000053 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
54 return S.nsects;
Rafael Espindola421305a2013-04-07 20:01:29 +000055 }
Charles Davis8bdfafd2013-09-01 04:28:48 +000056 MachO::segment_command S = O->getSegmentLoadCommand(L);
57 return S.nsects;
Rafael Espindola5ffc0792013-04-07 16:07:35 +000058}
59
Rafael Espindola6e040c02013-04-26 20:07:33 +000060static const char *
61getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
62 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000063 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
64
65 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000066 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
67 sizeof(MachO::segment_command);
68 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
69 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000070
71 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000072 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000073}
74
Rafael Espindola56f976f2013-04-18 18:08:55 +000075static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
76 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000077}
78
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000079static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000080getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000081 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000082 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000083}
84
Rafael Espindola56f976f2013-04-18 18:08:55 +000085static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000086 if (P[15] == 0)
87 // Null terminated.
88 return P;
89 // Not null terminated, so this is a 16 char string.
90 return StringRef(P, 16);
91}
92
Rafael Espindola56f976f2013-04-18 18:08:55 +000093// Helper to advance a section or symbol iterator multiple increments at a time.
94template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +000095static void advance(T &it, size_t Val) {
96 while (Val--)
97 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +000098}
99
100static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000101 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000102}
103
104static void printRelocationTargetName(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000105 const MachO::any_relocation_info &RE,
Alp Tokere69170a2014-06-26 22:52:05 +0000106 raw_string_ostream &fmt) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000107 bool IsScattered = O->isRelocationScattered(RE);
108
109 // Target of a scattered relocation is an address. In the interest of
110 // generating pretty output, scan through the symbol table looking for a
111 // symbol that aligns with that address. If we find one, print it.
112 // Otherwise, we just print the hex address of the target.
113 if (IsScattered) {
114 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
115
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000116 for (const SymbolRef &Symbol : O->symbols()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000117 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000118 uint64_t Addr;
119 StringRef Name;
120
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000121 if ((ec = Symbol.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000122 report_fatal_error(ec.message());
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000123 if (Addr != Val)
124 continue;
125 if ((ec = Symbol.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000126 report_fatal_error(ec.message());
127 fmt << Name;
128 return;
129 }
130
131 // If we couldn't find a symbol that this relocation refers to, try
132 // to find a section beginning instead.
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000133 for (const SectionRef &Section : O->sections()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000134 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000135 uint64_t Addr;
136 StringRef Name;
137
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000138 if ((ec = Section.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000139 report_fatal_error(ec.message());
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000140 if (Addr != Val)
141 continue;
142 if ((ec = Section.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000143 report_fatal_error(ec.message());
144 fmt << Name;
145 return;
146 }
147
148 fmt << format("0x%x", Val);
149 return;
150 }
151
152 StringRef S;
153 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000154 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000155
156 if (isExtern) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000157 symbol_iterator SI = O->symbol_begin();
Rafael Espindola5e812af2014-01-30 02:49:50 +0000158 advance(SI, Val);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159 SI->getName(S);
160 } else {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000161 section_iterator SI = O->section_begin();
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000162 // Adjust for the fact that sections are 1-indexed.
Rafael Espindola5e812af2014-01-30 02:49:50 +0000163 advance(SI, Val - 1);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000164 SI->getName(S);
165 }
166
167 fmt << S;
168}
169
Charles Davis8bdfafd2013-09-01 04:28:48 +0000170static uint32_t
171getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
172 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000173}
174
175static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000176getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
177 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000178}
179
180static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000181 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000182 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000183 return (RE.r_word1 >> 24) & 1;
184 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000185}
186
187static bool
188getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000189 const MachO::any_relocation_info &RE) {
190 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000191}
192
193static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000194 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000195 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000196 return (RE.r_word1 >> 25) & 3;
197 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000198}
199
200static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000201getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
202 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000203}
204
205static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000206 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000207 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000208 return RE.r_word1 >> 28;
209 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000210}
211
Charles Davis8bdfafd2013-09-01 04:28:48 +0000212static unsigned
213getScatteredRelocationType(const MachO::any_relocation_info &RE) {
214 return (RE.r_word0 >> 24) & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000215}
216
217static uint32_t getSectionFlags(const MachOObjectFile *O,
218 DataRefImpl Sec) {
219 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000220 MachO::section_64 Sect = O->getSection64(Sec);
221 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000222 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000223 MachO::section Sect = O->getSection(Sec);
224 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000225}
226
Rafael Espindola48af1c22014-08-19 18:44:46 +0000227MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Nick Kledzikd04bc352014-08-30 00:20:14 +0000231 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000232 uint32_t LoadCommandCount = this->getHeader().ncmds;
233 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
234 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000235
236 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000237 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000238 if (Load.C.cmd == MachO::LC_SYMTAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000239 assert(!SymtabLoadCmd && "Multiple symbol tables");
240 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000241 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000242 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
243 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000244 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby273ae012013-06-06 17:20:50 +0000245 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
246 DataInCodeLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000247 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
248 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
249 assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");
250 DyldInfoLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000251 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000252 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
253 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000254 const char *Sec = getSectionPtr(this, Load, J);
255 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000256 }
Kevin Enderby980b2582014-06-05 21:21:57 +0000257 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
258 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
259 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
260 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
261 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
262 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000263 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000264
265 if (I == LoadCommandCount - 1)
266 break;
267 else
268 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000269 }
270}
271
Rafael Espindola5e812af2014-01-30 02:49:50 +0000272void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000273 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000274 sizeof(MachO::nlist_64) :
275 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000276 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000277}
278
Rafael Espindola3acea392014-06-12 21:46:39 +0000279std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
280 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000281 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000282 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000283 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000284 Res = StringRef(Start);
285 return object_error::success;
286}
287
Kevin Enderby980b2582014-06-05 21:21:57 +0000288// getIndirectName() returns the name of the alias'ed symbol who's string table
289// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000290std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
291 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000292 StringRef StringTable = getStringTableData();
293 uint64_t NValue;
294 if (is64Bit()) {
295 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
296 NValue = Entry.n_value;
297 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
298 return object_error::parse_failed;
299 } else {
300 MachO::nlist Entry = getSymbolTableEntry(Symb);
301 NValue = Entry.n_value;
302 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
303 return object_error::parse_failed;
304 }
305 if (NValue >= StringTable.size())
306 return object_error::parse_failed;
307 const char *Start = &StringTable.data()[NValue];
308 Res = StringRef(Start);
309 return object_error::success;
310}
311
Rafael Espindola3acea392014-06-12 21:46:39 +0000312std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
313 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000314 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000315 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000316 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
317 Entry.n_value == 0)
318 Res = UnknownAddressOrSize;
319 else
320 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000321 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000322 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000323 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
324 Entry.n_value == 0)
325 Res = UnknownAddressOrSize;
326 else
327 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000328 }
329 return object_error::success;
330}
331
Rafael Espindola3acea392014-06-12 21:46:39 +0000332std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
333 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000334 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000335 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000336 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000337 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000338 } else {
339 Result = 0;
340 }
341 return object_error::success;
342}
343
Rafael Espindola3acea392014-06-12 21:46:39 +0000344std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
345 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000346 uint64_t BeginOffset;
347 uint64_t EndOffset = 0;
348 uint8_t SectionIndex;
349
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000350 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000351 uint64_t Value;
352 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000353 if (Value == UnknownAddressOrSize) {
354 Result = UnknownAddressOrSize;
355 return object_error::success;
356 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000357
358 BeginOffset = Value;
359
Charles Davis8bdfafd2013-09-01 04:28:48 +0000360 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000361 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000362 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000363 if (flags & SymbolRef::SF_Common)
364 Result = Value;
365 else
366 Result = UnknownAddressOrSize;
367 return object_error::success;
368 }
369 // Unfortunately symbols are unsorted so we need to touch all
370 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000371 for (const SymbolRef &Symbol : symbols()) {
372 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000373 Entry = getSymbolTableEntryBase(this, DRI);
374 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000375 if (Value == UnknownAddressOrSize)
376 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000377 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000378 if (!EndOffset || Value < EndOffset)
379 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000380 }
381 if (!EndOffset) {
382 uint64_t Size;
383 DataRefImpl Sec;
384 Sec.d.a = SectionIndex-1;
385 getSectionSize(Sec, Size);
386 getSectionAddress(Sec, EndOffset);
387 EndOffset += Size;
388 }
389 Result = EndOffset - BeginOffset;
390 return object_error::success;
391}
392
Rafael Espindola3acea392014-06-12 21:46:39 +0000393std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
394 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000395 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000396 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000397
398 Res = SymbolRef::ST_Other;
399
400 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000401 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000402 Res = SymbolRef::ST_Debug;
403 return object_error::success;
404 }
405
Charles Davis74ec8b02013-08-27 05:00:13 +0000406 switch (n_type & MachO::N_TYPE) {
407 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000408 Res = SymbolRef::ST_Unknown;
409 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000410 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000411 Res = SymbolRef::ST_Function;
412 break;
413 }
414 return object_error::success;
415}
416
Rafael Espindola20122a42014-01-31 20:57:12 +0000417uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000418 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000419
Charles Davis8bdfafd2013-09-01 04:28:48 +0000420 uint8_t MachOType = Entry.n_type;
421 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000422
Rafael Espindola20122a42014-01-31 20:57:12 +0000423 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000424
Charles Davis74ec8b02013-08-27 05:00:13 +0000425 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000426 Result |= SymbolRef::SF_Undefined;
427
Tim Northovereaef0742014-05-30 13:22:59 +0000428 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
429 Result |= SymbolRef::SF_Indirect;
430
Rafael Espindolaa1356322013-11-02 05:03:24 +0000431 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000432 Result |= SymbolRef::SF_FormatSpecific;
433
Charles Davis74ec8b02013-08-27 05:00:13 +0000434 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000435 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000436 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000437 uint64_t Value;
438 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000439 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000440 Result |= SymbolRef::SF_Common;
441 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000442 }
443
Charles Davis74ec8b02013-08-27 05:00:13 +0000444 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000445 Result |= SymbolRef::SF_Weak;
446
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000447 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
448 Result |= SymbolRef::SF_Thumb;
449
Charles Davis74ec8b02013-08-27 05:00:13 +0000450 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000451 Result |= SymbolRef::SF_Absolute;
452
Rafael Espindola20122a42014-01-31 20:57:12 +0000453 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000454}
455
Rafael Espindola3acea392014-06-12 21:46:39 +0000456std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
457 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000458 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000459 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000460
461 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000462 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000463 } else {
464 DataRefImpl DRI;
465 DRI.d.a = index - 1;
466 Res = section_iterator(SectionRef(DRI, this));
467 }
468
469 return object_error::success;
470}
471
Rafael Espindola5e812af2014-01-30 02:49:50 +0000472void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000473 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000474}
475
Rafael Espindola3acea392014-06-12 21:46:39 +0000476std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
477 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000478 ArrayRef<char> Raw = getSectionRawName(Sec);
479 Result = parseSegmentOrSectionName(Raw.data());
480 return object_error::success;
481}
482
Rafael Espindola3acea392014-06-12 21:46:39 +0000483std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
484 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000485 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000486 MachO::section_64 Sect = getSection64(Sec);
487 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000488 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000489 MachO::section Sect = getSection(Sec);
490 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000491 }
492 return object_error::success;
493}
494
Rafael Espindola3acea392014-06-12 21:46:39 +0000495std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
496 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000497 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000498 MachO::section_64 Sect = getSection64(Sec);
499 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000500 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000501 MachO::section Sect = getSection(Sec);
502 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000503 }
504
505 return object_error::success;
506}
507
Rafael Espindola3acea392014-06-12 21:46:39 +0000508std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
509 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000510 uint32_t Offset;
511 uint64_t Size;
512
513 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000514 MachO::section_64 Sect = getSection64(Sec);
515 Offset = Sect.offset;
516 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000517 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000518 MachO::section Sect = getSection(Sec);
519 Offset = Sect.offset;
520 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000521 }
522
523 Res = this->getData().substr(Offset, Size);
524 return object_error::success;
525}
526
Rafael Espindola3acea392014-06-12 21:46:39 +0000527std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
528 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000529 uint32_t Align;
530 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000531 MachO::section_64 Sect = getSection64(Sec);
532 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000533 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000534 MachO::section Sect = getSection(Sec);
535 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000536 }
537
538 Res = uint64_t(1) << Align;
539 return object_error::success;
540}
541
Rafael Espindola3acea392014-06-12 21:46:39 +0000542std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
543 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000544 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000545 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000546 return object_error::success;
547}
548
Rafael Espindola3acea392014-06-12 21:46:39 +0000549std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
550 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000551 uint32_t Flags = getSectionFlags(this, Sec);
552 unsigned SectionType = Flags & MachO::SECTION_TYPE;
553 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
554 !(SectionType == MachO::S_ZEROFILL ||
555 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000556 return object_error::success;
557}
558
Rafael Espindola3acea392014-06-12 21:46:39 +0000559std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
560 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000561 uint32_t Flags = getSectionFlags(this, Sec);
562 unsigned SectionType = Flags & MachO::SECTION_TYPE;
563 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
564 (SectionType == MachO::S_ZEROFILL ||
565 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000566 return object_error::success;
567}
568
Rafael Espindola3acea392014-06-12 21:46:39 +0000569std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000570MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindola137faa02013-04-24 15:14:22 +0000571 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000572 // FIXME: Unimplemented.
573 Result = true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000574 return object_error::success;
575}
576
Rafael Espindola3acea392014-06-12 21:46:39 +0000577std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
578 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000579 // FIXME: Unimplemented.
580 Result = false;
581 return object_error::success;
582}
583
Rafael Espindola3acea392014-06-12 21:46:39 +0000584std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
585 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000586 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis74ec8b02013-08-27 05:00:13 +0000587 unsigned SectionType = Flags & MachO::SECTION_TYPE;
588 Res = SectionType == MachO::S_ZEROFILL ||
589 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000590 return object_error::success;
591}
592
Rafael Espindola3acea392014-06-12 21:46:39 +0000593std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
594 bool &Result) const {
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000595 // Consider using the code from isSectionText to look for __const sections.
596 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
597 // to use section attributes to distinguish code from data.
598
599 // FIXME: Unimplemented.
600 Result = false;
601 return object_error::success;
602}
603
Rafael Espindola3acea392014-06-12 21:46:39 +0000604std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
605 DataRefImpl Symb,
606 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000607 SymbolRef::Type ST;
608 this->getSymbolType(Symb, ST);
609 if (ST == SymbolRef::ST_Unknown) {
610 Result = false;
611 return object_error::success;
612 }
613
614 uint64_t SectBegin, SectEnd;
615 getSectionAddress(Sec, SectBegin);
616 getSectionSize(Sec, SectEnd);
617 SectEnd += SectBegin;
618
619 uint64_t SymAddr;
620 getSymbolAddress(Symb, SymAddr);
621 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
622
623 return object_error::success;
624}
625
Rui Ueyamabc654b12013-09-27 21:47:05 +0000626relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000627 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000628 Ret.d.a = Sec.d.a;
629 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000630 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000631}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000632
Rafael Espindola56f976f2013-04-18 18:08:55 +0000633relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000634MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000635 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000636 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000637 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000638 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000639 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000640 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000641 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000642 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000643
Rafael Espindola56f976f2013-04-18 18:08:55 +0000644 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000645 Ret.d.a = Sec.d.a;
646 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000647 return relocation_iterator(RelocationRef(Ret, this));
648}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000649
Rafael Espindola5e812af2014-01-30 02:49:50 +0000650void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000651 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000652}
Owen Anderson171f4852011-10-24 23:20:07 +0000653
Rafael Espindola3acea392014-06-12 21:46:39 +0000654std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
655 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000656 uint64_t Offset;
657 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000658
659 DataRefImpl Sec;
660 Sec.d.a = Rel.d.a;
661 uint64_t SecAddress;
662 getSectionAddress(Sec, SecAddress);
663 Res = SecAddress + Offset;
664 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000665}
666
Rafael Espindola3acea392014-06-12 21:46:39 +0000667std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
668 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000669 assert(getHeader().filetype == MachO::MH_OBJECT &&
670 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000671 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000672 Res = getAnyRelocationAddress(RE);
673 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000674}
675
Rafael Espindola806f0062013-06-05 01:33:53 +0000676symbol_iterator
677MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000678 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000679 if (isRelocationScattered(RE))
680 return symbol_end();
681
Rafael Espindola56f976f2013-04-18 18:08:55 +0000682 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
683 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000684 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000685 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000686
Charles Davis8bdfafd2013-09-01 04:28:48 +0000687 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000688 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000689 sizeof(MachO::nlist_64) :
690 sizeof(MachO::nlist);
691 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000692 DataRefImpl Sym;
693 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000694 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000695}
696
Rafael Espindola3acea392014-06-12 21:46:39 +0000697std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
698 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000699 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000700 Res = getAnyRelocationType(RE);
701 return object_error::success;
702}
703
Rafael Espindola3acea392014-06-12 21:46:39 +0000704std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000705MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
706 SmallVectorImpl<char> &Result) const {
707 StringRef res;
708 uint64_t RType;
709 getRelocationType(Rel, RType);
710
711 unsigned Arch = this->getArch();
712
713 switch (Arch) {
714 case Triple::x86: {
715 static const char *const Table[] = {
716 "GENERIC_RELOC_VANILLA",
717 "GENERIC_RELOC_PAIR",
718 "GENERIC_RELOC_SECTDIFF",
719 "GENERIC_RELOC_PB_LA_PTR",
720 "GENERIC_RELOC_LOCAL_SECTDIFF",
721 "GENERIC_RELOC_TLV" };
722
Eric Christopher13250cb2013-12-06 02:33:38 +0000723 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000724 res = "Unknown";
725 else
726 res = Table[RType];
727 break;
728 }
729 case Triple::x86_64: {
730 static const char *const Table[] = {
731 "X86_64_RELOC_UNSIGNED",
732 "X86_64_RELOC_SIGNED",
733 "X86_64_RELOC_BRANCH",
734 "X86_64_RELOC_GOT_LOAD",
735 "X86_64_RELOC_GOT",
736 "X86_64_RELOC_SUBTRACTOR",
737 "X86_64_RELOC_SIGNED_1",
738 "X86_64_RELOC_SIGNED_2",
739 "X86_64_RELOC_SIGNED_4",
740 "X86_64_RELOC_TLV" };
741
742 if (RType > 9)
743 res = "Unknown";
744 else
745 res = Table[RType];
746 break;
747 }
748 case Triple::arm: {
749 static const char *const Table[] = {
750 "ARM_RELOC_VANILLA",
751 "ARM_RELOC_PAIR",
752 "ARM_RELOC_SECTDIFF",
753 "ARM_RELOC_LOCAL_SECTDIFF",
754 "ARM_RELOC_PB_LA_PTR",
755 "ARM_RELOC_BR24",
756 "ARM_THUMB_RELOC_BR22",
757 "ARM_THUMB_32BIT_BRANCH",
758 "ARM_RELOC_HALF",
759 "ARM_RELOC_HALF_SECTDIFF" };
760
761 if (RType > 9)
762 res = "Unknown";
763 else
764 res = Table[RType];
765 break;
766 }
Tim Northover00ed9962014-03-29 10:18:08 +0000767 case Triple::aarch64: {
768 static const char *const Table[] = {
769 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
770 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
771 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
772 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
773 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
774 "ARM64_RELOC_ADDEND"
775 };
776
777 if (RType >= array_lengthof(Table))
778 res = "Unknown";
779 else
780 res = Table[RType];
781 break;
782 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000783 case Triple::ppc: {
784 static const char *const Table[] = {
785 "PPC_RELOC_VANILLA",
786 "PPC_RELOC_PAIR",
787 "PPC_RELOC_BR14",
788 "PPC_RELOC_BR24",
789 "PPC_RELOC_HI16",
790 "PPC_RELOC_LO16",
791 "PPC_RELOC_HA16",
792 "PPC_RELOC_LO14",
793 "PPC_RELOC_SECTDIFF",
794 "PPC_RELOC_PB_LA_PTR",
795 "PPC_RELOC_HI16_SECTDIFF",
796 "PPC_RELOC_LO16_SECTDIFF",
797 "PPC_RELOC_HA16_SECTDIFF",
798 "PPC_RELOC_JBSR",
799 "PPC_RELOC_LO14_SECTDIFF",
800 "PPC_RELOC_LOCAL_SECTDIFF" };
801
Eric Christopher13250cb2013-12-06 02:33:38 +0000802 if (RType > 15)
803 res = "Unknown";
804 else
805 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000806 break;
807 }
808 case Triple::UnknownArch:
809 res = "Unknown";
810 break;
811 }
812 Result.append(res.begin(), res.end());
813 return object_error::success;
814}
815
Rafael Espindola3acea392014-06-12 21:46:39 +0000816std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000817MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000818 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000819 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000820
Rafael Espindola56f976f2013-04-18 18:08:55 +0000821 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000822
Alp Tokere69170a2014-06-26 22:52:05 +0000823 std::string fmtbuf;
824 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000825 unsigned Type = this->getAnyRelocationType(RE);
826 bool IsPCRel = this->getAnyRelocationPCRel(RE);
827
828 // Determine any addends that should be displayed with the relocation.
829 // These require decoding the relocation type, which is triple-specific.
830
831 // X86_64 has entirely custom relocation types.
832 if (Arch == Triple::x86_64) {
833 bool isPCRel = getAnyRelocationPCRel(RE);
834
835 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000836 case MachO::X86_64_RELOC_GOT_LOAD:
837 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000838 printRelocationTargetName(this, RE, fmt);
839 fmt << "@GOT";
840 if (isPCRel) fmt << "PCREL";
841 break;
842 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000843 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000844 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000845 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000846 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000847
Charles Davis8bdfafd2013-09-01 04:28:48 +0000848 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000849 // X86_64_RELOC_UNSIGNED.
850 // NOTE: Scattered relocations don't exist on x86_64.
851 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000852 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000853 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
854 "X86_64_RELOC_SUBTRACTOR.");
855
Charles Davis8bdfafd2013-09-01 04:28:48 +0000856 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
857 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000858 printRelocationTargetName(this, RENext, fmt);
859 fmt << "-";
860 printRelocationTargetName(this, RE, fmt);
861 break;
862 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000863 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000864 printRelocationTargetName(this, RE, fmt);
865 fmt << "@TLV";
866 if (isPCRel) fmt << "P";
867 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000868 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000869 printRelocationTargetName(this, RE, fmt);
870 fmt << "-1";
871 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000872 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000873 printRelocationTargetName(this, RE, fmt);
874 fmt << "-2";
875 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000876 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000877 printRelocationTargetName(this, RE, fmt);
878 fmt << "-4";
879 break;
880 default:
881 printRelocationTargetName(this, RE, fmt);
882 break;
883 }
884 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000885 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
886 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000887 // Generic relocation types...
888 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000889 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000890 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000891 case MachO::GENERIC_RELOC_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);
899
Charles Davis8bdfafd2013-09-01 04:28:48 +0000900 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000901 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
902 "GENERIC_RELOC_SECTDIFF.");
903
904 printRelocationTargetName(this, RE, fmt);
905 fmt << "-";
906 printRelocationTargetName(this, RENext, fmt);
907 break;
908 }
909 }
910
David Fangb88cdf62013-08-08 20:14:40 +0000911 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000912 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000913 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000914 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000915 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000916 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000917
918 // X86 sect diff's must be followed by a relocation of type
919 // GENERIC_RELOC_PAIR.
920 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000921 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000922 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
923 "GENERIC_RELOC_LOCAL_SECTDIFF.");
924
925 printRelocationTargetName(this, RE, fmt);
926 fmt << "-";
927 printRelocationTargetName(this, RENext, fmt);
928 break;
929 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000930 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000931 printRelocationTargetName(this, RE, fmt);
932 fmt << "@TLV";
933 if (IsPCRel) fmt << "P";
934 break;
935 }
936 default:
937 printRelocationTargetName(this, RE, fmt);
938 }
939 } else { // ARM-specific relocations
940 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000941 case MachO::ARM_RELOC_HALF:
942 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000943 // Half relocations steal a bit from the length field to encode
944 // whether this is an upper16 or a lower16 relocation.
945 bool isUpper = getAnyRelocationLength(RE) >> 1;
946
947 if (isUpper)
948 fmt << ":upper16:(";
949 else
950 fmt << ":lower16:(";
951 printRelocationTargetName(this, RE, fmt);
952
953 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000954 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000955 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000956
957 // ARM half relocs must be followed by a relocation of type
958 // ARM_RELOC_PAIR.
959 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000960 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000961 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000962 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000963
964 // NOTE: The half of the target virtual address is stashed in the
965 // address field of the secondary relocation, but we can't reverse
966 // engineer the constant offset from it without decoding the movw/movt
967 // instruction to find the other half in its immediate field.
968
969 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
970 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000971 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000972 fmt << "-";
973 printRelocationTargetName(this, RENext, fmt);
974 }
975
976 fmt << ")";
977 break;
978 }
979 default: {
980 printRelocationTargetName(this, RE, fmt);
981 }
982 }
983 }
984 } else
985 printRelocationTargetName(this, RE, fmt);
986
Alp Tokere69170a2014-06-26 22:52:05 +0000987 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000988 Result.append(fmtbuf.begin(), fmtbuf.end());
989 return object_error::success;
990}
991
Rafael Espindola3acea392014-06-12 21:46:39 +0000992std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
993 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000994 unsigned Arch = getArch();
995 uint64_t Type;
996 getRelocationType(Rel, Type);
997
998 Result = false;
999
1000 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1001 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +00001002 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001003 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001004 } else if (Arch == Triple::x86_64) {
1005 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +00001006 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001007 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001008 DataRefImpl RelPrev = Rel;
1009 RelPrev.d.a--;
1010 uint64_t PrevType;
1011 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001012 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001013 Result = true;
1014 }
1015 }
1016
1017 return object_error::success;
1018}
1019
Kevin Enderby980b2582014-06-05 21:21:57 +00001020//
1021// guessLibraryShortName() is passed a name of a dynamic library and returns a
1022// guess on what the short name is. Then name is returned as a substring of the
1023// StringRef Name passed in. The name of the dynamic library is recognized as
1024// a framework if it has one of the two following forms:
1025// Foo.framework/Versions/A/Foo
1026// Foo.framework/Foo
1027// Where A and Foo can be any string. And may contain a trailing suffix
1028// starting with an underbar. If the Name is recognized as a framework then
1029// isFramework is set to true else it is set to false. If the Name has a
1030// suffix then Suffix is set to the substring in Name that contains the suffix
1031// else it is set to a NULL StringRef.
1032//
1033// The Name of the dynamic library is recognized as a library name if it has
1034// one of the two following forms:
1035// libFoo.A.dylib
1036// libFoo.dylib
1037// The library may have a suffix trailing the name Foo of the form:
1038// libFoo_profile.A.dylib
1039// libFoo_profile.dylib
1040//
1041// The Name of the dynamic library is also recognized as a library name if it
1042// has the following form:
1043// Foo.qtx
1044//
1045// If the Name of the dynamic library is none of the forms above then a NULL
1046// StringRef is returned.
1047//
1048StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1049 bool &isFramework,
1050 StringRef &Suffix) {
1051 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1052 size_t a, b, c, d, Idx;
1053
1054 isFramework = false;
1055 Suffix = StringRef();
1056
1057 // Pull off the last component and make Foo point to it
1058 a = Name.rfind('/');
1059 if (a == Name.npos || a == 0)
1060 goto guess_library;
1061 Foo = Name.slice(a+1, Name.npos);
1062
1063 // Look for a suffix starting with a '_'
1064 Idx = Foo.rfind('_');
1065 if (Idx != Foo.npos && Foo.size() >= 2) {
1066 Suffix = Foo.slice(Idx, Foo.npos);
1067 Foo = Foo.slice(0, Idx);
1068 }
1069
1070 // First look for the form Foo.framework/Foo
1071 b = Name.rfind('/', a);
1072 if (b == Name.npos)
1073 Idx = 0;
1074 else
1075 Idx = b+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
1084 // Next look for the form Foo.framework/Versions/A/Foo
1085 if (b == Name.npos)
1086 goto guess_library;
1087 c = Name.rfind('/', b);
1088 if (c == Name.npos || c == 0)
1089 goto guess_library;
1090 V = Name.slice(c+1, Name.npos);
1091 if (!V.startswith("Versions/"))
1092 goto guess_library;
1093 d = Name.rfind('/', c);
1094 if (d == Name.npos)
1095 Idx = 0;
1096 else
1097 Idx = d+1;
1098 F = Name.slice(Idx, Idx + Foo.size());
1099 DotFramework = Name.slice(Idx + Foo.size(),
1100 Idx + Foo.size() + sizeof(".framework/")-1);
1101 if (F == Foo && DotFramework == ".framework/") {
1102 isFramework = true;
1103 return Foo;
1104 }
1105
1106guess_library:
1107 // pull off the suffix after the "." and make a point to it
1108 a = Name.rfind('.');
1109 if (a == Name.npos || a == 0)
1110 return StringRef();
1111 Dylib = Name.slice(a, Name.npos);
1112 if (Dylib != ".dylib")
1113 goto guess_qtx;
1114
1115 // First pull off the version letter for the form Foo.A.dylib if any.
1116 if (a >= 3) {
1117 Dot = Name.slice(a-2, a-1);
1118 if (Dot == ".")
1119 a = a - 2;
1120 }
1121
1122 b = Name.rfind('/', a);
1123 if (b == Name.npos)
1124 b = 0;
1125 else
1126 b = b+1;
1127 // ignore any suffix after an underbar like Foo_profile.A.dylib
1128 Idx = Name.find('_', b);
1129 if (Idx != Name.npos && Idx != b) {
1130 Lib = Name.slice(b, Idx);
1131 Suffix = Name.slice(Idx, a);
1132 }
1133 else
1134 Lib = Name.slice(b, a);
1135 // There are incorrect library names of the form:
1136 // libATS.A_profile.dylib so check for these.
1137 if (Lib.size() >= 3) {
1138 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1139 if (Dot == ".")
1140 Lib = Lib.slice(0, Lib.size()-2);
1141 }
1142 return Lib;
1143
1144guess_qtx:
1145 Qtx = Name.slice(a, Name.npos);
1146 if (Qtx != ".qtx")
1147 return StringRef();
1148 b = Name.rfind('/', a);
1149 if (b == Name.npos)
1150 Lib = Name.slice(0, a);
1151 else
1152 Lib = Name.slice(b+1, a);
1153 // There are library names of the form: QT.A.qtx so check for these.
1154 if (Lib.size() >= 3) {
1155 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1156 if (Dot == ".")
1157 Lib = Lib.slice(0, Lib.size()-2);
1158 }
1159 return Lib;
1160}
1161
1162// getLibraryShortNameByIndex() is used to get the short name of the library
1163// for an undefined symbol in a linked Mach-O binary that was linked with the
1164// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1165// It is passed the index (0 - based) of the library as translated from
1166// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001167std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001168 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001169 if (Index >= Libraries.size())
1170 return object_error::parse_failed;
1171
1172 MachO::dylib_command D =
1173 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1174 if (D.dylib.name >= D.cmdsize)
1175 return object_error::parse_failed;
1176
1177 // If the cache of LibrariesShortNames is not built up do that first for
1178 // all the Libraries.
1179 if (LibrariesShortNames.size() == 0) {
1180 for (unsigned i = 0; i < Libraries.size(); i++) {
1181 MachO::dylib_command D =
1182 getStruct<MachO::dylib_command>(this, Libraries[i]);
1183 if (D.dylib.name >= D.cmdsize) {
1184 LibrariesShortNames.push_back(StringRef());
1185 continue;
1186 }
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001187 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001188 StringRef Name = StringRef(P);
1189 StringRef Suffix;
1190 bool isFramework;
1191 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1192 if (shortName == StringRef())
1193 LibrariesShortNames.push_back(Name);
1194 else
1195 LibrariesShortNames.push_back(shortName);
1196 }
1197 }
1198
1199 Res = LibrariesShortNames[Index];
1200 return object_error::success;
1201}
1202
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001203basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001204 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001205}
1206
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001207basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001208 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001209 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001210 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001211
Charles Davis8bdfafd2013-09-01 04:28:48 +00001212 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001213 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001214 sizeof(MachO::nlist_64) :
1215 sizeof(MachO::nlist);
1216 unsigned Offset = Symtab.symoff +
1217 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001218 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001219 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001220}
1221
Lang Hames36072da2014-05-12 21:39:59 +00001222basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1223 DataRefImpl DRI;
1224 if (!SymtabLoadCmd)
1225 return basic_symbol_iterator(SymbolRef(DRI, this));
1226
1227 MachO::symtab_command Symtab = getSymtabLoadCommand();
1228 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1229 unsigned SymbolTableEntrySize =
1230 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1231 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1232 DRI.p += Index * SymbolTableEntrySize;
1233 return basic_symbol_iterator(SymbolRef(DRI, this));
1234}
1235
Rafael Espindolab5155a52014-02-10 20:24:04 +00001236section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001237 DataRefImpl DRI;
1238 return section_iterator(SectionRef(DRI, this));
1239}
1240
Rafael Espindolab5155a52014-02-10 20:24:04 +00001241section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001242 DataRefImpl DRI;
1243 DRI.d.a = Sections.size();
1244 return section_iterator(SectionRef(DRI, this));
1245}
1246
Rafael Espindola56f976f2013-04-18 18:08:55 +00001247uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001248 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001249}
1250
Rafael Espindola56f976f2013-04-18 18:08:55 +00001251StringRef MachOObjectFile::getFileFormatName() const {
1252 unsigned CPUType = getCPUType(this);
1253 if (!is64Bit()) {
1254 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001255 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001256 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001257 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001258 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001259 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001260 return "Mach-O 32-bit ppc";
1261 default:
Charles Davis74ec8b02013-08-27 05:00:13 +00001262 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindola56f976f2013-04-18 18:08:55 +00001263 "64-bit object file when we're not 64-bit?");
1264 return "Mach-O 32-bit unknown";
1265 }
1266 }
1267
1268 // Make sure the cpu type has the correct mask.
Charles Davis74ec8b02013-08-27 05:00:13 +00001269 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1270 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher1d62c252013-07-22 22:25:07 +00001271 "32-bit object file when we're 64-bit?");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001272
1273 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001274 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001275 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001276 case llvm::MachO::CPU_TYPE_ARM64:
1277 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001278 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001279 return "Mach-O 64-bit ppc64";
1280 default:
1281 return "Mach-O 64-bit unknown";
1282 }
1283}
1284
Alexey Samsonove6388e62013-06-18 15:03:28 +00001285Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1286 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001287 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001288 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001289 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001290 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001291 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001292 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001293 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001294 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001295 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001296 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001297 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001298 return Triple::ppc64;
1299 default:
1300 return Triple::UnknownArch;
1301 }
1302}
1303
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001304Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1305 const char **McpuDefault) {
1306 if (McpuDefault)
1307 *McpuDefault = nullptr;
1308
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001309 switch (CPUType) {
1310 case MachO::CPU_TYPE_I386:
1311 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1312 case MachO::CPU_SUBTYPE_I386_ALL:
1313 return Triple("i386-apple-darwin");
1314 default:
1315 return Triple();
1316 }
1317 case MachO::CPU_TYPE_X86_64:
1318 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1319 case MachO::CPU_SUBTYPE_X86_64_ALL:
1320 return Triple("x86_64-apple-darwin");
1321 case MachO::CPU_SUBTYPE_X86_64_H:
1322 return Triple("x86_64h-apple-darwin");
1323 default:
1324 return Triple();
1325 }
1326 case MachO::CPU_TYPE_ARM:
1327 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1328 case MachO::CPU_SUBTYPE_ARM_V4T:
1329 return Triple("armv4t-apple-darwin");
1330 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1331 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001332 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1333 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001334 case MachO::CPU_SUBTYPE_ARM_V6:
1335 return Triple("armv6-apple-darwin");
1336 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001337 if (McpuDefault)
1338 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001339 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001340 case MachO::CPU_SUBTYPE_ARM_V7:
1341 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001342 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001343 if (McpuDefault)
1344 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001345 return Triple("armv7em-apple-darwin");
1346 case MachO::CPU_SUBTYPE_ARM_V7K:
1347 return Triple("armv7k-apple-darwin");
1348 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001349 if (McpuDefault)
1350 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001351 return Triple("armv7m-apple-darwin");
1352 case MachO::CPU_SUBTYPE_ARM_V7S:
1353 return Triple("armv7s-apple-darwin");
1354 default:
1355 return Triple();
1356 }
1357 case MachO::CPU_TYPE_ARM64:
1358 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1359 case MachO::CPU_SUBTYPE_ARM64_ALL:
1360 return Triple("arm64-apple-darwin");
1361 default:
1362 return Triple();
1363 }
1364 case MachO::CPU_TYPE_POWERPC:
1365 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1366 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1367 return Triple("ppc-apple-darwin");
1368 default:
1369 return Triple();
1370 }
1371 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001372 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001373 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1374 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001375 default:
1376 return Triple();
1377 }
1378 default:
1379 return Triple();
1380 }
1381}
1382
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001383Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1384 const char **McpuDefault) {
1385 if (McpuDefault)
1386 *McpuDefault = nullptr;
1387
1388 switch (CPUType) {
1389 case MachO::CPU_TYPE_ARM:
1390 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1391 case MachO::CPU_SUBTYPE_ARM_V4T:
1392 return Triple("thumbv4t-apple-darwin");
1393 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1394 return Triple("thumbv5e-apple-darwin");
1395 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1396 return Triple("xscale-apple-darwin");
1397 case MachO::CPU_SUBTYPE_ARM_V6:
1398 return Triple("thumbv6-apple-darwin");
1399 case MachO::CPU_SUBTYPE_ARM_V6M:
1400 if (McpuDefault)
1401 *McpuDefault = "cortex-m0";
1402 return Triple("thumbv6m-apple-darwin");
1403 case MachO::CPU_SUBTYPE_ARM_V7:
1404 return Triple("thumbv7-apple-darwin");
1405 case MachO::CPU_SUBTYPE_ARM_V7EM:
1406 if (McpuDefault)
1407 *McpuDefault = "cortex-m4";
1408 return Triple("thumbv7em-apple-darwin");
1409 case MachO::CPU_SUBTYPE_ARM_V7K:
1410 return Triple("thumbv7k-apple-darwin");
1411 case MachO::CPU_SUBTYPE_ARM_V7M:
1412 if (McpuDefault)
1413 *McpuDefault = "cortex-m3";
1414 return Triple("thumbv7m-apple-darwin");
1415 case MachO::CPU_SUBTYPE_ARM_V7S:
1416 return Triple("thumbv7s-apple-darwin");
1417 default:
1418 return Triple();
1419 }
1420 default:
1421 return Triple();
1422 }
1423}
1424
1425Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1426 const char **McpuDefault,
1427 Triple *ThumbTriple) {
1428 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1429 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1430 McpuDefault);
1431 return T;
1432}
1433
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001434Triple MachOObjectFile::getHostArch() {
1435 return Triple(sys::getDefaultTargetTriple());
1436}
1437
Rafael Espindola72318b42014-08-08 16:30:17 +00001438bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1439 return StringSwitch<bool>(ArchFlag)
1440 .Case("i386", true)
1441 .Case("x86_64", true)
1442 .Case("x86_64h", true)
1443 .Case("armv4t", true)
1444 .Case("arm", true)
1445 .Case("armv5e", true)
1446 .Case("armv6", true)
1447 .Case("armv6m", true)
1448 .Case("armv7em", true)
1449 .Case("armv7k", true)
1450 .Case("armv7m", true)
1451 .Case("armv7s", true)
1452 .Case("arm64", true)
1453 .Case("ppc", true)
1454 .Case("ppc64", true)
1455 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001456}
1457
Alexey Samsonove6388e62013-06-18 15:03:28 +00001458unsigned MachOObjectFile::getArch() const {
1459 return getArch(getCPUType(this));
1460}
1461
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001462Triple MachOObjectFile::getArch(const char **McpuDefault,
1463 Triple *ThumbTriple) const {
1464 Triple T;
1465 if (is64Bit()) {
1466 MachO::mach_header_64 H_64;
1467 H_64 = getHeader64();
1468 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1469 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1470 McpuDefault);
1471 } else {
1472 MachO::mach_header H;
1473 H = getHeader();
1474 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1475 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1476 McpuDefault);
1477 }
1478 return T;
1479}
1480
Rui Ueyamabc654b12013-09-27 21:47:05 +00001481relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001482 DataRefImpl DRI;
1483 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001484 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001485}
1486
Rui Ueyamabc654b12013-09-27 21:47:05 +00001487relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001488 DataRefImpl DRI;
1489 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001490 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001491}
1492
Kevin Enderby273ae012013-06-06 17:20:50 +00001493dice_iterator MachOObjectFile::begin_dices() const {
1494 DataRefImpl DRI;
1495 if (!DataInCodeLoadCmd)
1496 return dice_iterator(DiceRef(DRI, this));
1497
Charles Davis8bdfafd2013-09-01 04:28:48 +00001498 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1499 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001500 return dice_iterator(DiceRef(DRI, this));
1501}
1502
1503dice_iterator MachOObjectFile::end_dices() const {
1504 DataRefImpl DRI;
1505 if (!DataInCodeLoadCmd)
1506 return dice_iterator(DiceRef(DRI, this));
1507
Charles Davis8bdfafd2013-09-01 04:28:48 +00001508 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1509 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001510 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1511 return dice_iterator(DiceRef(DRI, this));
1512}
1513
Nick Kledzikd04bc352014-08-30 00:20:14 +00001514ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1515 : Trie(T), Malformed(false), Done(false) { }
1516
1517void ExportEntry::moveToFirst() {
1518 pushNode(0);
1519 pushDownUntilBottom();
1520}
1521
1522void ExportEntry::moveToEnd() {
1523 Stack.clear();
1524 Done = true;
1525}
1526
1527bool ExportEntry::operator==(const ExportEntry &Other) const {
1528 // Common case, one at end, other iterating from begin.
1529 if (Done || Other.Done)
1530 return (Done == Other.Done);
1531 // Not equal if different stack sizes.
1532 if (Stack.size() != Other.Stack.size())
1533 return false;
1534 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001535 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001536 return false;
1537 // Equal if all nodes in both stacks match.
1538 for (unsigned i=0; i < Stack.size(); ++i) {
1539 if (Stack[i].Start != Other.Stack[i].Start)
1540 return false;
1541 }
1542 return true;
1543}
1544
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001545uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1546 unsigned Count;
1547 uint64_t Result = decodeULEB128(Ptr, &Count);
1548 Ptr += Count;
1549 if (Ptr > Trie.end()) {
1550 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001551 Malformed = true;
1552 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001553 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001554}
1555
1556StringRef ExportEntry::name() const {
1557 return CumulativeString.str();
1558}
1559
1560uint64_t ExportEntry::flags() const {
1561 return Stack.back().Flags;
1562}
1563
1564uint64_t ExportEntry::address() const {
1565 return Stack.back().Address;
1566}
1567
1568uint64_t ExportEntry::other() const {
1569 return Stack.back().Other;
1570}
1571
1572StringRef ExportEntry::otherName() const {
1573 const char* ImportName = Stack.back().ImportName;
1574 if (ImportName)
1575 return StringRef(ImportName);
1576 return StringRef();
1577}
1578
1579uint32_t ExportEntry::nodeOffset() const {
1580 return Stack.back().Start - Trie.begin();
1581}
1582
1583ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1584 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1585 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1586 ParentStringLength(0), IsExportNode(false) {
1587}
1588
1589void ExportEntry::pushNode(uint64_t offset) {
1590 const uint8_t *Ptr = Trie.begin() + offset;
1591 NodeState State(Ptr);
1592 uint64_t ExportInfoSize = readULEB128(State.Current);
1593 State.IsExportNode = (ExportInfoSize != 0);
1594 const uint8_t* Children = State.Current + ExportInfoSize;
1595 if (State.IsExportNode) {
1596 State.Flags = readULEB128(State.Current);
1597 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1598 State.Address = 0;
1599 State.Other = readULEB128(State.Current); // dylib ordinal
1600 State.ImportName = reinterpret_cast<const char*>(State.Current);
1601 } else {
1602 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001603 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1604 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001605 }
1606 }
1607 State.ChildCount = *Children;
1608 State.Current = Children + 1;
1609 State.NextChildIndex = 0;
1610 State.ParentStringLength = CumulativeString.size();
1611 Stack.push_back(State);
1612}
1613
1614void ExportEntry::pushDownUntilBottom() {
1615 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1616 NodeState &Top = Stack.back();
1617 CumulativeString.resize(Top.ParentStringLength);
1618 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001619 char C = *Top.Current;
1620 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001621 }
1622 Top.Current += 1;
1623 uint64_t childNodeIndex = readULEB128(Top.Current);
1624 Top.NextChildIndex += 1;
1625 pushNode(childNodeIndex);
1626 }
1627 if (!Stack.back().IsExportNode) {
1628 Malformed = true;
1629 moveToEnd();
1630 }
1631}
1632
1633// We have a trie data structure and need a way to walk it that is compatible
1634// with the C++ iterator model. The solution is a non-recursive depth first
1635// traversal where the iterator contains a stack of parent nodes along with a
1636// string that is the accumulation of all edge strings along the parent chain
1637// to this point.
1638//
1639// There is one “export” node for each exported symbol. But because some
1640// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1641// node may have child nodes too.
1642//
1643// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1644// child until hitting a node with no children (which is an export node or
1645// else the trie is malformed). On the way down, each node is pushed on the
1646// stack ivar. If there is no more ways down, it pops up one and tries to go
1647// down a sibling path until a childless node is reached.
1648void ExportEntry::moveNext() {
1649 if (Stack.empty() || !Stack.back().IsExportNode) {
1650 Malformed = true;
1651 moveToEnd();
1652 return;
1653 }
1654
1655 Stack.pop_back();
1656 while (!Stack.empty()) {
1657 NodeState &Top = Stack.back();
1658 if (Top.NextChildIndex < Top.ChildCount) {
1659 pushDownUntilBottom();
1660 // Now at the next export node.
1661 return;
1662 } else {
1663 if (Top.IsExportNode) {
1664 // This node has no children but is itself an export node.
1665 CumulativeString.resize(Top.ParentStringLength);
1666 return;
1667 }
1668 Stack.pop_back();
1669 }
1670 }
1671 Done = true;
1672}
1673
1674iterator_range<export_iterator>
1675MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1676 ExportEntry Start(Trie);
1677 Start.moveToFirst();
1678
1679 ExportEntry Finish(Trie);
1680 Finish.moveToEnd();
1681
1682 return iterator_range<export_iterator>(export_iterator(Start),
1683 export_iterator(Finish));
1684}
1685
1686iterator_range<export_iterator> MachOObjectFile::exports() const {
1687 return exports(getDyldInfoExportsTrie());
1688}
1689
1690
Rafael Espindola56f976f2013-04-18 18:08:55 +00001691StringRef
1692MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1693 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1694 return parseSegmentOrSectionName(Raw.data());
1695}
1696
1697ArrayRef<char>
1698MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001699 const section_base *Base =
1700 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001701 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001702}
1703
1704ArrayRef<char>
1705MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001706 const section_base *Base =
1707 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001708 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001709}
1710
1711bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001712MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001713 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001714 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001715 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001716 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001717}
1718
Eric Christopher1d62c252013-07-22 22:25:07 +00001719unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001720 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001721 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001722 return RE.r_word1 & 0xffffff;
1723 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001724}
1725
Eric Christopher1d62c252013-07-22 22:25:07 +00001726bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001727 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001728 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001729 return (RE.r_word1 >> 27) & 1;
1730 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001731}
1732
Eric Christopher1d62c252013-07-22 22:25:07 +00001733bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001734 const MachO::any_relocation_info &RE) const {
1735 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001736}
1737
Eric Christopher1d62c252013-07-22 22:25:07 +00001738uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001739 const MachO::any_relocation_info &RE) const {
1740 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001741}
1742
Eric Christopher1d62c252013-07-22 22:25:07 +00001743unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001744 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001745 if (isRelocationScattered(RE))
1746 return getScatteredRelocationAddress(RE);
1747 return getPlainRelocationAddress(RE);
1748}
1749
Charles Davis8bdfafd2013-09-01 04:28:48 +00001750unsigned MachOObjectFile::getAnyRelocationPCRel(
1751 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001752 if (isRelocationScattered(RE))
1753 return getScatteredRelocationPCRel(this, RE);
1754 return getPlainRelocationPCRel(this, RE);
1755}
1756
Eric Christopher1d62c252013-07-22 22:25:07 +00001757unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001758 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001759 if (isRelocationScattered(RE))
1760 return getScatteredRelocationLength(RE);
1761 return getPlainRelocationLength(this, RE);
1762}
1763
1764unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00001765MachOObjectFile::getAnyRelocationType(
1766 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001767 if (isRelocationScattered(RE))
1768 return getScatteredRelocationType(RE);
1769 return getPlainRelocationType(this, RE);
1770}
1771
Rafael Espindola52501032013-04-30 15:40:54 +00001772SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00001773MachOObjectFile::getRelocationSection(
1774 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00001775 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00001776 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00001777 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1778 DataRefImpl DRI;
1779 DRI.d.a = SecNum;
1780 return SectionRef(DRI, this);
1781}
1782
Rafael Espindola56f976f2013-04-18 18:08:55 +00001783MachOObjectFile::LoadCommandInfo
1784MachOObjectFile::getFirstLoadCommandInfo() const {
1785 MachOObjectFile::LoadCommandInfo Load;
1786
Charles Davis8bdfafd2013-09-01 04:28:48 +00001787 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1788 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001789 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001790 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001791 return Load;
1792}
1793
1794MachOObjectFile::LoadCommandInfo
1795MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1796 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001797 Next.Ptr = L.Ptr + L.C.cmdsize;
1798 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001799 return Next;
1800}
1801
Charles Davis8bdfafd2013-09-01 04:28:48 +00001802MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1803 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001804}
1805
Charles Davis8bdfafd2013-09-01 04:28:48 +00001806MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1807 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001808}
1809
Charles Davis8bdfafd2013-09-01 04:28:48 +00001810MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00001811 unsigned Index) const {
1812 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001813 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001814}
1815
Charles Davis8bdfafd2013-09-01 04:28:48 +00001816MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1817 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001818 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001819 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001820}
1821
Charles Davis8bdfafd2013-09-01 04:28:48 +00001822MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00001823MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001824 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001825 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001826}
1827
Charles Davis8bdfafd2013-09-01 04:28:48 +00001828MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00001829MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001830 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001831 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001832}
1833
Charles Davis8bdfafd2013-09-01 04:28:48 +00001834MachO::linkedit_data_command
1835MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1836 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001837}
1838
Charles Davis8bdfafd2013-09-01 04:28:48 +00001839MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00001840MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001841 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001842}
1843
Charles Davis8bdfafd2013-09-01 04:28:48 +00001844MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00001845MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001846 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001847}
1848
Charles Davis8bdfafd2013-09-01 04:28:48 +00001849MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00001850MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001851 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001852}
1853
Jim Grosbach448334a2014-03-18 22:09:05 +00001854MachO::version_min_command
1855MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1856 return getStruct<MachO::version_min_command>(this, L.Ptr);
1857}
1858
Tim Northover8f9590b2014-06-30 14:40:57 +00001859MachO::dylib_command
1860MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
1861 return getStruct<MachO::dylib_command>(this, L.Ptr);
1862}
1863
Kevin Enderby8ae63c12014-09-04 16:54:47 +00001864MachO::dyld_info_command
1865MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
1866 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
1867}
1868
1869MachO::dylinker_command
1870MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
1871 return getStruct<MachO::dylinker_command>(this, L.Ptr);
1872}
1873
1874MachO::uuid_command
1875MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
1876 return getStruct<MachO::uuid_command>(this, L.Ptr);
1877}
1878
1879MachO::source_version_command
1880MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
1881 return getStruct<MachO::source_version_command>(this, L.Ptr);
1882}
1883
1884MachO::entry_point_command
1885MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
1886 return getStruct<MachO::entry_point_command>(this, L.Ptr);
1887}
1888
Tim Northover8f9590b2014-06-30 14:40:57 +00001889
Charles Davis8bdfafd2013-09-01 04:28:48 +00001890MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00001891MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001892 DataRefImpl Sec;
1893 Sec.d.a = Rel.d.a;
1894 uint32_t Offset;
1895 if (is64Bit()) {
1896 MachO::section_64 Sect = getSection64(Sec);
1897 Offset = Sect.reloff;
1898 } else {
1899 MachO::section Sect = getSection(Sec);
1900 Offset = Sect.reloff;
1901 }
1902
1903 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
1904 getPtr(this, Offset)) + Rel.d.b;
1905 return getStruct<MachO::any_relocation_info>(
1906 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001907}
1908
Charles Davis8bdfafd2013-09-01 04:28:48 +00001909MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00001910MachOObjectFile::getDice(DataRefImpl Rel) const {
1911 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001912 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00001913}
1914
Charles Davis8bdfafd2013-09-01 04:28:48 +00001915MachO::mach_header MachOObjectFile::getHeader() const {
1916 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001917}
1918
Charles Davis8bdfafd2013-09-01 04:28:48 +00001919MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1920 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001921}
1922
Charles Davis8bdfafd2013-09-01 04:28:48 +00001923uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1924 const MachO::dysymtab_command &DLC,
1925 unsigned Index) const {
1926 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1927 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001928}
1929
Charles Davis8bdfafd2013-09-01 04:28:48 +00001930MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00001931MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1932 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001933 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1934 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001935}
1936
Charles Davis8bdfafd2013-09-01 04:28:48 +00001937MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1938 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001939}
1940
Charles Davis8bdfafd2013-09-01 04:28:48 +00001941MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1942 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001943}
1944
Charles Davis8bdfafd2013-09-01 04:28:48 +00001945MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00001946MachOObjectFile::getDataInCodeLoadCommand() const {
1947 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00001948 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00001949
1950 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001951 MachO::linkedit_data_command Cmd;
1952 Cmd.cmd = MachO::LC_DATA_IN_CODE;
1953 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1954 Cmd.dataoff = 0;
1955 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00001956 return Cmd;
1957}
1958
Nick Kledzikd04bc352014-08-30 00:20:14 +00001959ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
1960 if (!DyldInfoLoadCmd)
1961 return ArrayRef<uint8_t>();
1962
1963 MachO::dyld_info_command DyldInfo
1964 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
1965 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
1966 getPtr(this, DyldInfo.rebase_off));
1967 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
1968}
1969
1970ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
1971 if (!DyldInfoLoadCmd)
1972 return ArrayRef<uint8_t>();
1973
1974 MachO::dyld_info_command DyldInfo
1975 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
1976 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
1977 getPtr(this, DyldInfo.bind_off));
1978 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
1979}
1980
1981ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
1982 if (!DyldInfoLoadCmd)
1983 return ArrayRef<uint8_t>();
1984
1985 MachO::dyld_info_command DyldInfo
1986 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
1987 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
1988 getPtr(this, DyldInfo.weak_bind_off));
1989 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
1990}
1991
1992ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
1993 if (!DyldInfoLoadCmd)
1994 return ArrayRef<uint8_t>();
1995
1996 MachO::dyld_info_command DyldInfo
1997 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
1998 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
1999 getPtr(this, DyldInfo.lazy_bind_off));
2000 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2001}
2002
2003ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2004 if (!DyldInfoLoadCmd)
2005 return ArrayRef<uint8_t>();
2006
2007 MachO::dyld_info_command DyldInfo
2008 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2009 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2010 getPtr(this, DyldInfo.export_off));
2011 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2012}
2013
2014
Rafael Espindola6e040c02013-04-26 20:07:33 +00002015StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002016 MachO::symtab_command S = getSymtabLoadCommand();
2017 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002018}
2019
Rafael Espindola56f976f2013-04-18 18:08:55 +00002020bool MachOObjectFile::is64Bit() const {
2021 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002022 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002023}
2024
2025void MachOObjectFile::ReadULEB128s(uint64_t Index,
2026 SmallVectorImpl<uint64_t> &Out) const {
2027 DataExtractor extractor(ObjectFile::getData(), true, 0);
2028
2029 uint32_t offset = Index;
2030 uint64_t data = 0;
2031 while (uint64_t delta = extractor.getULEB128(&offset)) {
2032 data += delta;
2033 Out.push_back(data);
2034 }
2035}
2036
Rafael Espindolac66d7612014-08-17 19:09:37 +00002037bool MachOObjectFile::isRelocatableObject() const {
2038 return getHeader().filetype == MachO::MH_OBJECT;
2039}
2040
Rafael Espindola437b0d52014-07-31 03:12:45 +00002041ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002042ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2043 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002044 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002045 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002046 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002047 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002048 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002049 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002050 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002051 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002052 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002053 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002054 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002055 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002056
Rafael Espindola692410e2014-01-21 23:06:54 +00002057 if (EC)
2058 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002059 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002060}
2061