blob: 0e96bc7ff729cc2444a37f436a11d6fe2c3abac7 [file] [log] [blame]
Eric Christopher7b015c72011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Anderson27c579d2011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Tim Northover00ed9962014-03-29 10:18:08 +000016#include "llvm/ADT/STLExtras.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000017#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "llvm/ADT/Triple.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000019#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000020#include "llvm/Support/Debug.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000021#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000022#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000023#include "llvm/Support/LEB128.h"
24#include "llvm/Support/MachO.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000025#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000026#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000027#include <cctype>
28#include <cstring>
29#include <limits>
30
31using namespace llvm;
32using namespace object;
33
Artyom Skrobov7d602f72014-07-20 12:08:28 +000034namespace {
35 struct section_base {
36 char sectname[16];
37 char segname[16];
38 };
39}
Rafael Espindola56f976f2013-04-18 18:08:55 +000040
41template<typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000042static T getStruct(const MachOObjectFile *O, const char *P) {
Rafael Espindola3cdeb172013-04-19 13:45:05 +000043 T Cmd;
44 memcpy(&Cmd, P, sizeof(T));
45 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000046 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000047 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000048}
49
Rafael Espindola56f976f2013-04-18 18:08:55 +000050static uint32_t
51getSegmentLoadCommandNumSections(const MachOObjectFile *O,
52 const MachOObjectFile::LoadCommandInfo &L) {
53 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000054 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
55 return S.nsects;
Rafael Espindola421305a2013-04-07 20:01:29 +000056 }
Charles Davis8bdfafd2013-09-01 04:28:48 +000057 MachO::segment_command S = O->getSegmentLoadCommand(L);
58 return S.nsects;
Rafael Espindola5ffc0792013-04-07 16:07:35 +000059}
60
Nick Kledzik56ebef42014-09-16 01:41:51 +000061static bool isPageZeroSegment(const MachOObjectFile *O,
62 const MachOObjectFile::LoadCommandInfo &L) {
63 if (O->is64Bit()) {
64 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
65 return StringRef("__PAGEZERO").equals(S.segname);
66 }
67 MachO::segment_command S = O->getSegmentLoadCommand(L);
68 return StringRef("__PAGEZERO").equals(S.segname);
69}
70
71
Rafael Espindola6e040c02013-04-26 20:07:33 +000072static const char *
73getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
74 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000075 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
76
77 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000078 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
79 sizeof(MachO::segment_command);
80 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
81 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000082
83 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000084 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000085}
86
Rafael Espindola56f976f2013-04-18 18:08:55 +000087static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
88 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000089}
90
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000091static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000092getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000093 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000094 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000095}
96
Rafael Espindola56f976f2013-04-18 18:08:55 +000097static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000098 if (P[15] == 0)
99 // Null terminated.
100 return P;
101 // Not null terminated, so this is a 16 char string.
102 return StringRef(P, 16);
103}
104
Rafael Espindola56f976f2013-04-18 18:08:55 +0000105// Helper to advance a section or symbol iterator multiple increments at a time.
106template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000107static void advance(T &it, size_t Val) {
108 while (Val--)
109 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000110}
111
112static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000113 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000114}
115
116static void printRelocationTargetName(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000117 const MachO::any_relocation_info &RE,
Alp Tokere69170a2014-06-26 22:52:05 +0000118 raw_string_ostream &fmt) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000119 bool IsScattered = O->isRelocationScattered(RE);
120
121 // Target of a scattered relocation is an address. In the interest of
122 // generating pretty output, scan through the symbol table looking for a
123 // symbol that aligns with that address. If we find one, print it.
124 // Otherwise, we just print the hex address of the target.
125 if (IsScattered) {
126 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
127
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000128 for (const SymbolRef &Symbol : O->symbols()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000129 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000130 uint64_t Addr;
131 StringRef Name;
132
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000133 if ((ec = Symbol.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134 report_fatal_error(ec.message());
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000135 if (Addr != Val)
136 continue;
137 if ((ec = Symbol.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000138 report_fatal_error(ec.message());
139 fmt << Name;
140 return;
141 }
142
143 // If we couldn't find a symbol that this relocation refers to, try
144 // to find a section beginning instead.
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000145 for (const SectionRef &Section : O->sections()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000146 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000147
Rafael Espindola80291272014-10-08 15:28:58 +0000148 StringRef Name;
149 uint64_t Addr = Section.getAddress();
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000150 if (Addr != Val)
151 continue;
152 if ((ec = Section.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000153 report_fatal_error(ec.message());
154 fmt << Name;
155 return;
156 }
157
158 fmt << format("0x%x", Val);
159 return;
160 }
161
162 StringRef S;
163 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000164 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000165
166 if (isExtern) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000167 symbol_iterator SI = O->symbol_begin();
Rafael Espindola5e812af2014-01-30 02:49:50 +0000168 advance(SI, Val);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000169 SI->getName(S);
170 } else {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000171 section_iterator SI = O->section_begin();
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000172 // Adjust for the fact that sections are 1-indexed.
Rafael Espindola5e812af2014-01-30 02:49:50 +0000173 advance(SI, Val - 1);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000174 SI->getName(S);
175 }
176
177 fmt << S;
178}
179
Charles Davis8bdfafd2013-09-01 04:28:48 +0000180static uint32_t
181getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
182 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000183}
184
185static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000186getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
187 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000188}
189
190static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000191 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000192 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000193 return (RE.r_word1 >> 24) & 1;
194 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000195}
196
197static bool
198getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000199 const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000201}
202
203static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000204 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000205 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000206 return (RE.r_word1 >> 25) & 3;
207 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000208}
209
210static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000211getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000213}
214
215static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000216 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000217 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000218 return RE.r_word1 >> 28;
219 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000220}
221
Rafael Espindola56f976f2013-04-18 18:08:55 +0000222static uint32_t getSectionFlags(const MachOObjectFile *O,
223 DataRefImpl Sec) {
224 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000225 MachO::section_64 Sect = O->getSection64(Sec);
226 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000227 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000228 MachO::section Sect = O->getSection(Sec);
229 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000230}
231
Rafael Espindola48af1c22014-08-19 18:44:46 +0000232MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
233 bool Is64bits, std::error_code &EC)
234 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000235 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Nick Kledzik56ebef42014-09-16 01:41:51 +0000236 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000237 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000238 uint32_t LoadCommandCount = this->getHeader().ncmds;
239 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
240 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000241
242 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000243 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000244 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000245 // Multiple symbol tables
246 if (SymtabLoadCmd) {
247 EC = object_error::parse_failed;
248 return;
249 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000250 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000251 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000252 // Multiple dynamic symbol tables
253 if (DysymtabLoadCmd) {
254 EC = object_error::parse_failed;
255 return;
256 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000257 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000258 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000259 // Multiple data in code tables
260 if (DataInCodeLoadCmd) {
261 EC = object_error::parse_failed;
262 return;
263 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000264 DataInCodeLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000265 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
266 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000267 // Multiple dyldinfo load commands
268 if (DyldInfoLoadCmd) {
269 EC = object_error::parse_failed;
270 return;
271 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000272 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000273 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000274 // Multiple UUID load commands
275 if (UuidLoadCmd) {
276 EC = object_error::parse_failed;
277 return;
278 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000279 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000280 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000281 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
282 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000283 const char *Sec = getSectionPtr(this, Load, J);
284 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000285 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000286 if (isPageZeroSegment(this, Load))
287 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000288 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
289 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
290 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
291 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
292 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
293 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000294 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000295
296 if (I == LoadCommandCount - 1)
297 break;
298 else
299 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000300 }
301}
302
Rafael Espindola5e812af2014-01-30 02:49:50 +0000303void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000304 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000305 sizeof(MachO::nlist_64) :
306 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000307 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000308}
309
Rafael Espindola3acea392014-06-12 21:46:39 +0000310std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
311 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000312 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000313 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000314 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000315 Res = StringRef(Start);
316 return object_error::success;
317}
318
Rafael Espindola0e77a942014-12-10 20:46:55 +0000319unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
320 DataRefImpl DRI = Sec.getRawDataRefImpl();
321 uint32_t Flags = getSectionFlags(this, DRI);
322 return Flags & MachO::SECTION_TYPE;
323}
324
Kevin Enderby980b2582014-06-05 21:21:57 +0000325// getIndirectName() returns the name of the alias'ed symbol who's string table
326// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000327std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
328 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000329 StringRef StringTable = getStringTableData();
330 uint64_t NValue;
331 if (is64Bit()) {
332 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
333 NValue = Entry.n_value;
334 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
335 return object_error::parse_failed;
336 } else {
337 MachO::nlist Entry = getSymbolTableEntry(Symb);
338 NValue = Entry.n_value;
339 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
340 return object_error::parse_failed;
341 }
342 if (NValue >= StringTable.size())
343 return object_error::parse_failed;
344 const char *Start = &StringTable.data()[NValue];
345 Res = StringRef(Start);
346 return object_error::success;
347}
348
Rafael Espindola3acea392014-06-12 21:46:39 +0000349std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
350 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000351 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000352 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000353 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
354 Entry.n_value == 0)
355 Res = UnknownAddressOrSize;
356 else
357 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000358 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000359 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000360 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
361 Entry.n_value == 0)
362 Res = UnknownAddressOrSize;
363 else
364 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000365 }
366 return object_error::success;
367}
368
Rafael Espindola3acea392014-06-12 21:46:39 +0000369std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
370 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000371 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000372 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000373 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000374 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000375 } else {
376 Result = 0;
377 }
378 return object_error::success;
379}
380
Rafael Espindola3acea392014-06-12 21:46:39 +0000381std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
382 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000383 uint64_t BeginOffset;
384 uint64_t EndOffset = 0;
385 uint8_t SectionIndex;
386
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000387 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000388 uint64_t Value;
389 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000390 if (Value == UnknownAddressOrSize) {
391 Result = UnknownAddressOrSize;
392 return object_error::success;
393 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000394
395 BeginOffset = Value;
396
Charles Davis8bdfafd2013-09-01 04:28:48 +0000397 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000398 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000399 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000400 if (flags & SymbolRef::SF_Common)
401 Result = Value;
402 else
403 Result = UnknownAddressOrSize;
404 return object_error::success;
405 }
406 // Unfortunately symbols are unsorted so we need to touch all
407 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000408 for (const SymbolRef &Symbol : symbols()) {
409 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000410 Entry = getSymbolTableEntryBase(this, DRI);
411 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000412 if (Value == UnknownAddressOrSize)
413 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000414 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000415 if (!EndOffset || Value < EndOffset)
416 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000417 }
418 if (!EndOffset) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000419 DataRefImpl Sec;
420 Sec.d.a = SectionIndex-1;
Rafael Espindola80291272014-10-08 15:28:58 +0000421 uint64_t Size = getSectionSize(Sec);
422 EndOffset = getSectionAddress(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000423 EndOffset += Size;
424 }
425 Result = EndOffset - BeginOffset;
426 return object_error::success;
427}
428
Rafael Espindola3acea392014-06-12 21:46:39 +0000429std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
430 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000431 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000432 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000433
434 Res = SymbolRef::ST_Other;
435
436 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000437 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000438 Res = SymbolRef::ST_Debug;
439 return object_error::success;
440 }
441
Charles Davis74ec8b02013-08-27 05:00:13 +0000442 switch (n_type & MachO::N_TYPE) {
443 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000444 Res = SymbolRef::ST_Unknown;
445 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000446 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000447 Res = SymbolRef::ST_Function;
448 break;
449 }
450 return object_error::success;
451}
452
Rafael Espindola20122a42014-01-31 20:57:12 +0000453uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000454 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000455
Charles Davis8bdfafd2013-09-01 04:28:48 +0000456 uint8_t MachOType = Entry.n_type;
457 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000458
Rafael Espindola20122a42014-01-31 20:57:12 +0000459 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000460
Charles Davis74ec8b02013-08-27 05:00:13 +0000461 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000462 Result |= SymbolRef::SF_Undefined;
463
Tim Northovereaef0742014-05-30 13:22:59 +0000464 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
465 Result |= SymbolRef::SF_Indirect;
466
Rafael Espindolaa1356322013-11-02 05:03:24 +0000467 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000468 Result |= SymbolRef::SF_FormatSpecific;
469
Charles Davis74ec8b02013-08-27 05:00:13 +0000470 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000471 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000472 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000473 uint64_t Value;
474 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000475 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000476 Result |= SymbolRef::SF_Common;
477 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000478 }
479
Charles Davis74ec8b02013-08-27 05:00:13 +0000480 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000481 Result |= SymbolRef::SF_Weak;
482
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000483 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
484 Result |= SymbolRef::SF_Thumb;
485
Charles Davis74ec8b02013-08-27 05:00:13 +0000486 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000487 Result |= SymbolRef::SF_Absolute;
488
Rafael Espindola20122a42014-01-31 20:57:12 +0000489 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000490}
491
Rafael Espindola3acea392014-06-12 21:46:39 +0000492std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
493 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000494 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000495 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000496
497 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000498 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000499 } else {
500 DataRefImpl DRI;
501 DRI.d.a = index - 1;
502 Res = section_iterator(SectionRef(DRI, this));
503 }
504
505 return object_error::success;
506}
507
Rafael Espindola5e812af2014-01-30 02:49:50 +0000508void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000509 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000510}
511
Rafael Espindola3acea392014-06-12 21:46:39 +0000512std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
513 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000514 ArrayRef<char> Raw = getSectionRawName(Sec);
515 Result = parseSegmentOrSectionName(Raw.data());
516 return object_error::success;
517}
518
Rafael Espindola80291272014-10-08 15:28:58 +0000519uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
520 if (is64Bit())
521 return getSection64(Sec).addr;
522 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000523}
524
Rafael Espindola80291272014-10-08 15:28:58 +0000525uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
526 if (is64Bit())
527 return getSection64(Sec).size;
528 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000529}
530
Rafael Espindola3acea392014-06-12 21:46:39 +0000531std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
532 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000533 uint32_t Offset;
534 uint64_t Size;
535
536 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000537 MachO::section_64 Sect = getSection64(Sec);
538 Offset = Sect.offset;
539 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000540 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000541 MachO::section Sect = getSection(Sec);
542 Offset = Sect.offset;
543 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000544 }
545
546 Res = this->getData().substr(Offset, Size);
547 return object_error::success;
548}
549
Rafael Espindola80291272014-10-08 15:28:58 +0000550uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000551 uint32_t Align;
552 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000553 MachO::section_64 Sect = getSection64(Sec);
554 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000555 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000556 MachO::section Sect = getSection(Sec);
557 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000558 }
559
Rafael Espindola80291272014-10-08 15:28:58 +0000560 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000561}
562
Rafael Espindola80291272014-10-08 15:28:58 +0000563bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000564 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000565 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000566}
567
Rafael Espindola80291272014-10-08 15:28:58 +0000568bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000569 uint32_t Flags = getSectionFlags(this, Sec);
570 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000571 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
572 !(SectionType == MachO::S_ZEROFILL ||
573 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000574}
575
Rafael Espindola80291272014-10-08 15:28:58 +0000576bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000577 uint32_t Flags = getSectionFlags(this, Sec);
578 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000579 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
580 (SectionType == MachO::S_ZEROFILL ||
581 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000582}
583
Rafael Espindola80291272014-10-08 15:28:58 +0000584bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000585 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000586 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000587}
588
Rafael Espindola80291272014-10-08 15:28:58 +0000589bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
590 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000591 SymbolRef::Type ST;
592 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000593 if (ST == SymbolRef::ST_Unknown)
594 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000595
Rafael Espindola80291272014-10-08 15:28:58 +0000596 uint64_t SectBegin = getSectionAddress(Sec);
597 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000598 SectEnd += SectBegin;
599
600 uint64_t SymAddr;
601 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000602 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000603}
604
Rui Ueyamabc654b12013-09-27 21:47:05 +0000605relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000606 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000607 Ret.d.a = Sec.d.a;
608 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000609 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000610}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000611
Rafael Espindola56f976f2013-04-18 18:08:55 +0000612relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000613MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000614 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000615 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000616 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000617 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000618 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000619 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000620 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000621 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000622
Rafael Espindola56f976f2013-04-18 18:08:55 +0000623 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000624 Ret.d.a = Sec.d.a;
625 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000626 return relocation_iterator(RelocationRef(Ret, this));
627}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000628
Rafael Espindola5e812af2014-01-30 02:49:50 +0000629void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000630 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000631}
Owen Anderson171f4852011-10-24 23:20:07 +0000632
Rafael Espindola3acea392014-06-12 21:46:39 +0000633std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
634 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000635 uint64_t Offset;
636 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000637
638 DataRefImpl Sec;
639 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000640 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000641 Res = SecAddress + Offset;
642 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000643}
644
Rafael Espindola3acea392014-06-12 21:46:39 +0000645std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
646 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000647 assert(getHeader().filetype == MachO::MH_OBJECT &&
648 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000649 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000650 Res = getAnyRelocationAddress(RE);
651 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000652}
653
Rafael Espindola806f0062013-06-05 01:33:53 +0000654symbol_iterator
655MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000656 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000657 if (isRelocationScattered(RE))
658 return symbol_end();
659
Rafael Espindola56f976f2013-04-18 18:08:55 +0000660 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
661 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000662 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000663 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000664
Charles Davis8bdfafd2013-09-01 04:28:48 +0000665 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000666 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000667 sizeof(MachO::nlist_64) :
668 sizeof(MachO::nlist);
669 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000670 DataRefImpl Sym;
671 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000672 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000673}
674
Rafael Espindola3acea392014-06-12 21:46:39 +0000675std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
676 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000677 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000678 Res = getAnyRelocationType(RE);
679 return object_error::success;
680}
681
Rafael Espindola3acea392014-06-12 21:46:39 +0000682std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000683MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
684 SmallVectorImpl<char> &Result) const {
685 StringRef res;
686 uint64_t RType;
687 getRelocationType(Rel, RType);
688
689 unsigned Arch = this->getArch();
690
691 switch (Arch) {
692 case Triple::x86: {
693 static const char *const Table[] = {
694 "GENERIC_RELOC_VANILLA",
695 "GENERIC_RELOC_PAIR",
696 "GENERIC_RELOC_SECTDIFF",
697 "GENERIC_RELOC_PB_LA_PTR",
698 "GENERIC_RELOC_LOCAL_SECTDIFF",
699 "GENERIC_RELOC_TLV" };
700
Eric Christopher13250cb2013-12-06 02:33:38 +0000701 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000702 res = "Unknown";
703 else
704 res = Table[RType];
705 break;
706 }
707 case Triple::x86_64: {
708 static const char *const Table[] = {
709 "X86_64_RELOC_UNSIGNED",
710 "X86_64_RELOC_SIGNED",
711 "X86_64_RELOC_BRANCH",
712 "X86_64_RELOC_GOT_LOAD",
713 "X86_64_RELOC_GOT",
714 "X86_64_RELOC_SUBTRACTOR",
715 "X86_64_RELOC_SIGNED_1",
716 "X86_64_RELOC_SIGNED_2",
717 "X86_64_RELOC_SIGNED_4",
718 "X86_64_RELOC_TLV" };
719
720 if (RType > 9)
721 res = "Unknown";
722 else
723 res = Table[RType];
724 break;
725 }
726 case Triple::arm: {
727 static const char *const Table[] = {
728 "ARM_RELOC_VANILLA",
729 "ARM_RELOC_PAIR",
730 "ARM_RELOC_SECTDIFF",
731 "ARM_RELOC_LOCAL_SECTDIFF",
732 "ARM_RELOC_PB_LA_PTR",
733 "ARM_RELOC_BR24",
734 "ARM_THUMB_RELOC_BR22",
735 "ARM_THUMB_32BIT_BRANCH",
736 "ARM_RELOC_HALF",
737 "ARM_RELOC_HALF_SECTDIFF" };
738
739 if (RType > 9)
740 res = "Unknown";
741 else
742 res = Table[RType];
743 break;
744 }
Tim Northover00ed9962014-03-29 10:18:08 +0000745 case Triple::aarch64: {
746 static const char *const Table[] = {
747 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
748 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
749 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
750 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
751 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
752 "ARM64_RELOC_ADDEND"
753 };
754
755 if (RType >= array_lengthof(Table))
756 res = "Unknown";
757 else
758 res = Table[RType];
759 break;
760 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000761 case Triple::ppc: {
762 static const char *const Table[] = {
763 "PPC_RELOC_VANILLA",
764 "PPC_RELOC_PAIR",
765 "PPC_RELOC_BR14",
766 "PPC_RELOC_BR24",
767 "PPC_RELOC_HI16",
768 "PPC_RELOC_LO16",
769 "PPC_RELOC_HA16",
770 "PPC_RELOC_LO14",
771 "PPC_RELOC_SECTDIFF",
772 "PPC_RELOC_PB_LA_PTR",
773 "PPC_RELOC_HI16_SECTDIFF",
774 "PPC_RELOC_LO16_SECTDIFF",
775 "PPC_RELOC_HA16_SECTDIFF",
776 "PPC_RELOC_JBSR",
777 "PPC_RELOC_LO14_SECTDIFF",
778 "PPC_RELOC_LOCAL_SECTDIFF" };
779
Eric Christopher13250cb2013-12-06 02:33:38 +0000780 if (RType > 15)
781 res = "Unknown";
782 else
783 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000784 break;
785 }
786 case Triple::UnknownArch:
787 res = "Unknown";
788 break;
789 }
790 Result.append(res.begin(), res.end());
791 return object_error::success;
792}
793
Rafael Espindola3acea392014-06-12 21:46:39 +0000794std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000795MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000796 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000797 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000798
Rafael Espindola56f976f2013-04-18 18:08:55 +0000799 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000800
Alp Tokere69170a2014-06-26 22:52:05 +0000801 std::string fmtbuf;
802 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000803 unsigned Type = this->getAnyRelocationType(RE);
804 bool IsPCRel = this->getAnyRelocationPCRel(RE);
805
806 // Determine any addends that should be displayed with the relocation.
807 // These require decoding the relocation type, which is triple-specific.
808
809 // X86_64 has entirely custom relocation types.
810 if (Arch == Triple::x86_64) {
811 bool isPCRel = getAnyRelocationPCRel(RE);
812
813 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000814 case MachO::X86_64_RELOC_GOT_LOAD:
815 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000816 printRelocationTargetName(this, RE, fmt);
817 fmt << "@GOT";
818 if (isPCRel) fmt << "PCREL";
819 break;
820 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000821 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000822 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000823 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000824 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000825
Charles Davis8bdfafd2013-09-01 04:28:48 +0000826 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000827 // X86_64_RELOC_UNSIGNED.
828 // NOTE: Scattered relocations don't exist on x86_64.
829 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000830 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000831 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
832 "X86_64_RELOC_SUBTRACTOR.");
833
Charles Davis8bdfafd2013-09-01 04:28:48 +0000834 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
835 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000836 printRelocationTargetName(this, RENext, fmt);
837 fmt << "-";
838 printRelocationTargetName(this, RE, fmt);
839 break;
840 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000841 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000842 printRelocationTargetName(this, RE, fmt);
843 fmt << "@TLV";
844 if (isPCRel) fmt << "P";
845 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000846 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000847 printRelocationTargetName(this, RE, fmt);
848 fmt << "-1";
849 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000850 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000851 printRelocationTargetName(this, RE, fmt);
852 fmt << "-2";
853 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000854 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000855 printRelocationTargetName(this, RE, fmt);
856 fmt << "-4";
857 break;
858 default:
859 printRelocationTargetName(this, RE, fmt);
860 break;
861 }
862 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000863 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
864 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000865 // Generic relocation types...
866 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000867 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000868 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000869 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000870 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000871 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000872 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000873
874 // X86 sect diff's must be followed by a relocation of type
875 // GENERIC_RELOC_PAIR.
876 unsigned RType = getAnyRelocationType(RENext);
877
Charles Davis8bdfafd2013-09-01 04:28:48 +0000878 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000879 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
880 "GENERIC_RELOC_SECTDIFF.");
881
882 printRelocationTargetName(this, RE, fmt);
883 fmt << "-";
884 printRelocationTargetName(this, RENext, fmt);
885 break;
886 }
887 }
888
David Fangb88cdf62013-08-08 20:14:40 +0000889 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000890 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000891 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000892 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000893 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000894 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000895
896 // X86 sect diff's must be followed by a relocation of type
897 // GENERIC_RELOC_PAIR.
898 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000899 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000900 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
901 "GENERIC_RELOC_LOCAL_SECTDIFF.");
902
903 printRelocationTargetName(this, RE, fmt);
904 fmt << "-";
905 printRelocationTargetName(this, RENext, fmt);
906 break;
907 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000908 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000909 printRelocationTargetName(this, RE, fmt);
910 fmt << "@TLV";
911 if (IsPCRel) fmt << "P";
912 break;
913 }
914 default:
915 printRelocationTargetName(this, RE, fmt);
916 }
917 } else { // ARM-specific relocations
918 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000919 case MachO::ARM_RELOC_HALF:
920 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000921 // Half relocations steal a bit from the length field to encode
922 // whether this is an upper16 or a lower16 relocation.
923 bool isUpper = getAnyRelocationLength(RE) >> 1;
924
925 if (isUpper)
926 fmt << ":upper16:(";
927 else
928 fmt << ":lower16:(";
929 printRelocationTargetName(this, RE, fmt);
930
931 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000932 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000933 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000934
935 // ARM half relocs must be followed by a relocation of type
936 // ARM_RELOC_PAIR.
937 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000938 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000939 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000940 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000941
942 // NOTE: The half of the target virtual address is stashed in the
943 // address field of the secondary relocation, but we can't reverse
944 // engineer the constant offset from it without decoding the movw/movt
945 // instruction to find the other half in its immediate field.
946
947 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
948 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000949 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000950 fmt << "-";
951 printRelocationTargetName(this, RENext, fmt);
952 }
953
954 fmt << ")";
955 break;
956 }
957 default: {
958 printRelocationTargetName(this, RE, fmt);
959 }
960 }
961 }
962 } else
963 printRelocationTargetName(this, RE, fmt);
964
Alp Tokere69170a2014-06-26 22:52:05 +0000965 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000966 Result.append(fmtbuf.begin(), fmtbuf.end());
967 return object_error::success;
968}
969
Rafael Espindola3acea392014-06-12 21:46:39 +0000970std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
971 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000972 unsigned Arch = getArch();
973 uint64_t Type;
974 getRelocationType(Rel, Type);
975
976 Result = false;
977
978 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
979 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000980 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000981 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000982 } else if (Arch == Triple::x86_64) {
983 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000984 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000985 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000986 DataRefImpl RelPrev = Rel;
987 RelPrev.d.a--;
988 uint64_t PrevType;
989 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000990 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000991 Result = true;
992 }
993 }
994
995 return object_error::success;
996}
997
Kevin Enderby980b2582014-06-05 21:21:57 +0000998//
999// guessLibraryShortName() is passed a name of a dynamic library and returns a
1000// guess on what the short name is. Then name is returned as a substring of the
1001// StringRef Name passed in. The name of the dynamic library is recognized as
1002// a framework if it has one of the two following forms:
1003// Foo.framework/Versions/A/Foo
1004// Foo.framework/Foo
1005// Where A and Foo can be any string. And may contain a trailing suffix
1006// starting with an underbar. If the Name is recognized as a framework then
1007// isFramework is set to true else it is set to false. If the Name has a
1008// suffix then Suffix is set to the substring in Name that contains the suffix
1009// else it is set to a NULL StringRef.
1010//
1011// The Name of the dynamic library is recognized as a library name if it has
1012// one of the two following forms:
1013// libFoo.A.dylib
1014// libFoo.dylib
1015// The library may have a suffix trailing the name Foo of the form:
1016// libFoo_profile.A.dylib
1017// libFoo_profile.dylib
1018//
1019// The Name of the dynamic library is also recognized as a library name if it
1020// has the following form:
1021// Foo.qtx
1022//
1023// If the Name of the dynamic library is none of the forms above then a NULL
1024// StringRef is returned.
1025//
1026StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1027 bool &isFramework,
1028 StringRef &Suffix) {
1029 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1030 size_t a, b, c, d, Idx;
1031
1032 isFramework = false;
1033 Suffix = StringRef();
1034
1035 // Pull off the last component and make Foo point to it
1036 a = Name.rfind('/');
1037 if (a == Name.npos || a == 0)
1038 goto guess_library;
1039 Foo = Name.slice(a+1, Name.npos);
1040
1041 // Look for a suffix starting with a '_'
1042 Idx = Foo.rfind('_');
1043 if (Idx != Foo.npos && Foo.size() >= 2) {
1044 Suffix = Foo.slice(Idx, Foo.npos);
1045 Foo = Foo.slice(0, Idx);
1046 }
1047
1048 // First look for the form Foo.framework/Foo
1049 b = Name.rfind('/', a);
1050 if (b == Name.npos)
1051 Idx = 0;
1052 else
1053 Idx = b+1;
1054 F = Name.slice(Idx, Idx + Foo.size());
1055 DotFramework = Name.slice(Idx + Foo.size(),
1056 Idx + Foo.size() + sizeof(".framework/")-1);
1057 if (F == Foo && DotFramework == ".framework/") {
1058 isFramework = true;
1059 return Foo;
1060 }
1061
1062 // Next look for the form Foo.framework/Versions/A/Foo
1063 if (b == Name.npos)
1064 goto guess_library;
1065 c = Name.rfind('/', b);
1066 if (c == Name.npos || c == 0)
1067 goto guess_library;
1068 V = Name.slice(c+1, Name.npos);
1069 if (!V.startswith("Versions/"))
1070 goto guess_library;
1071 d = Name.rfind('/', c);
1072 if (d == Name.npos)
1073 Idx = 0;
1074 else
1075 Idx = d+1;
1076 F = Name.slice(Idx, Idx + Foo.size());
1077 DotFramework = Name.slice(Idx + Foo.size(),
1078 Idx + Foo.size() + sizeof(".framework/")-1);
1079 if (F == Foo && DotFramework == ".framework/") {
1080 isFramework = true;
1081 return Foo;
1082 }
1083
1084guess_library:
1085 // pull off the suffix after the "." and make a point to it
1086 a = Name.rfind('.');
1087 if (a == Name.npos || a == 0)
1088 return StringRef();
1089 Dylib = Name.slice(a, Name.npos);
1090 if (Dylib != ".dylib")
1091 goto guess_qtx;
1092
1093 // First pull off the version letter for the form Foo.A.dylib if any.
1094 if (a >= 3) {
1095 Dot = Name.slice(a-2, a-1);
1096 if (Dot == ".")
1097 a = a - 2;
1098 }
1099
1100 b = Name.rfind('/', a);
1101 if (b == Name.npos)
1102 b = 0;
1103 else
1104 b = b+1;
1105 // ignore any suffix after an underbar like Foo_profile.A.dylib
1106 Idx = Name.find('_', b);
1107 if (Idx != Name.npos && Idx != b) {
1108 Lib = Name.slice(b, Idx);
1109 Suffix = Name.slice(Idx, a);
1110 }
1111 else
1112 Lib = Name.slice(b, a);
1113 // There are incorrect library names of the form:
1114 // libATS.A_profile.dylib so check for these.
1115 if (Lib.size() >= 3) {
1116 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1117 if (Dot == ".")
1118 Lib = Lib.slice(0, Lib.size()-2);
1119 }
1120 return Lib;
1121
1122guess_qtx:
1123 Qtx = Name.slice(a, Name.npos);
1124 if (Qtx != ".qtx")
1125 return StringRef();
1126 b = Name.rfind('/', a);
1127 if (b == Name.npos)
1128 Lib = Name.slice(0, a);
1129 else
1130 Lib = Name.slice(b+1, a);
1131 // There are library names of the form: QT.A.qtx so check for these.
1132 if (Lib.size() >= 3) {
1133 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1134 if (Dot == ".")
1135 Lib = Lib.slice(0, Lib.size()-2);
1136 }
1137 return Lib;
1138}
1139
1140// getLibraryShortNameByIndex() is used to get the short name of the library
1141// for an undefined symbol in a linked Mach-O binary that was linked with the
1142// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1143// It is passed the index (0 - based) of the library as translated from
1144// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001145std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001146 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001147 if (Index >= Libraries.size())
1148 return object_error::parse_failed;
1149
Kevin Enderby980b2582014-06-05 21:21:57 +00001150 // If the cache of LibrariesShortNames is not built up do that first for
1151 // all the Libraries.
1152 if (LibrariesShortNames.size() == 0) {
1153 for (unsigned i = 0; i < Libraries.size(); i++) {
1154 MachO::dylib_command D =
1155 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001156 if (D.dylib.name >= D.cmdsize)
1157 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001158 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001159 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001160 if (D.dylib.name+Name.size() >= D.cmdsize)
1161 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001162 StringRef Suffix;
1163 bool isFramework;
1164 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001165 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001166 LibrariesShortNames.push_back(Name);
1167 else
1168 LibrariesShortNames.push_back(shortName);
1169 }
1170 }
1171
1172 Res = LibrariesShortNames[Index];
1173 return object_error::success;
1174}
1175
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001176basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001177 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001178}
1179
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001180basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001181 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001182 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001183 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001184
Charles Davis8bdfafd2013-09-01 04:28:48 +00001185 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001186 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001187 sizeof(MachO::nlist_64) :
1188 sizeof(MachO::nlist);
1189 unsigned Offset = Symtab.symoff +
1190 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001191 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001192 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001193}
1194
Lang Hames36072da2014-05-12 21:39:59 +00001195basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1196 DataRefImpl DRI;
1197 if (!SymtabLoadCmd)
1198 return basic_symbol_iterator(SymbolRef(DRI, this));
1199
1200 MachO::symtab_command Symtab = getSymtabLoadCommand();
1201 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1202 unsigned SymbolTableEntrySize =
1203 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1204 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1205 DRI.p += Index * SymbolTableEntrySize;
1206 return basic_symbol_iterator(SymbolRef(DRI, this));
1207}
1208
Rafael Espindolab5155a52014-02-10 20:24:04 +00001209section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001210 DataRefImpl DRI;
1211 return section_iterator(SectionRef(DRI, this));
1212}
1213
Rafael Espindolab5155a52014-02-10 20:24:04 +00001214section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001215 DataRefImpl DRI;
1216 DRI.d.a = Sections.size();
1217 return section_iterator(SectionRef(DRI, this));
1218}
1219
Rafael Espindola56f976f2013-04-18 18:08:55 +00001220uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001221 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001222}
1223
Rafael Espindola56f976f2013-04-18 18:08:55 +00001224StringRef MachOObjectFile::getFileFormatName() const {
1225 unsigned CPUType = getCPUType(this);
1226 if (!is64Bit()) {
1227 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001228 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001229 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001230 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001231 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001232 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001233 return "Mach-O 32-bit ppc";
1234 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001235 return "Mach-O 32-bit unknown";
1236 }
1237 }
1238
Rafael Espindola56f976f2013-04-18 18:08:55 +00001239 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001240 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001241 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001242 case llvm::MachO::CPU_TYPE_ARM64:
1243 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001244 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001245 return "Mach-O 64-bit ppc64";
1246 default:
1247 return "Mach-O 64-bit unknown";
1248 }
1249}
1250
Alexey Samsonove6388e62013-06-18 15:03:28 +00001251Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1252 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001253 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001254 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001255 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001256 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001257 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001258 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001259 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001260 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001261 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001262 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001263 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001264 return Triple::ppc64;
1265 default:
1266 return Triple::UnknownArch;
1267 }
1268}
1269
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001270Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1271 const char **McpuDefault) {
1272 if (McpuDefault)
1273 *McpuDefault = nullptr;
1274
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001275 switch (CPUType) {
1276 case MachO::CPU_TYPE_I386:
1277 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1278 case MachO::CPU_SUBTYPE_I386_ALL:
1279 return Triple("i386-apple-darwin");
1280 default:
1281 return Triple();
1282 }
1283 case MachO::CPU_TYPE_X86_64:
1284 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1285 case MachO::CPU_SUBTYPE_X86_64_ALL:
1286 return Triple("x86_64-apple-darwin");
1287 case MachO::CPU_SUBTYPE_X86_64_H:
1288 return Triple("x86_64h-apple-darwin");
1289 default:
1290 return Triple();
1291 }
1292 case MachO::CPU_TYPE_ARM:
1293 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1294 case MachO::CPU_SUBTYPE_ARM_V4T:
1295 return Triple("armv4t-apple-darwin");
1296 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1297 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001298 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1299 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001300 case MachO::CPU_SUBTYPE_ARM_V6:
1301 return Triple("armv6-apple-darwin");
1302 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001303 if (McpuDefault)
1304 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001305 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001306 case MachO::CPU_SUBTYPE_ARM_V7:
1307 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001308 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001309 if (McpuDefault)
1310 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001311 return Triple("armv7em-apple-darwin");
1312 case MachO::CPU_SUBTYPE_ARM_V7K:
1313 return Triple("armv7k-apple-darwin");
1314 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001315 if (McpuDefault)
1316 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001317 return Triple("armv7m-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V7S:
1319 return Triple("armv7s-apple-darwin");
1320 default:
1321 return Triple();
1322 }
1323 case MachO::CPU_TYPE_ARM64:
1324 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1325 case MachO::CPU_SUBTYPE_ARM64_ALL:
1326 return Triple("arm64-apple-darwin");
1327 default:
1328 return Triple();
1329 }
1330 case MachO::CPU_TYPE_POWERPC:
1331 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1332 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1333 return Triple("ppc-apple-darwin");
1334 default:
1335 return Triple();
1336 }
1337 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001338 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001339 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1340 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001341 default:
1342 return Triple();
1343 }
1344 default:
1345 return Triple();
1346 }
1347}
1348
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001349Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1350 const char **McpuDefault) {
1351 if (McpuDefault)
1352 *McpuDefault = nullptr;
1353
1354 switch (CPUType) {
1355 case MachO::CPU_TYPE_ARM:
1356 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1357 case MachO::CPU_SUBTYPE_ARM_V4T:
1358 return Triple("thumbv4t-apple-darwin");
1359 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1360 return Triple("thumbv5e-apple-darwin");
1361 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1362 return Triple("xscale-apple-darwin");
1363 case MachO::CPU_SUBTYPE_ARM_V6:
1364 return Triple("thumbv6-apple-darwin");
1365 case MachO::CPU_SUBTYPE_ARM_V6M:
1366 if (McpuDefault)
1367 *McpuDefault = "cortex-m0";
1368 return Triple("thumbv6m-apple-darwin");
1369 case MachO::CPU_SUBTYPE_ARM_V7:
1370 return Triple("thumbv7-apple-darwin");
1371 case MachO::CPU_SUBTYPE_ARM_V7EM:
1372 if (McpuDefault)
1373 *McpuDefault = "cortex-m4";
1374 return Triple("thumbv7em-apple-darwin");
1375 case MachO::CPU_SUBTYPE_ARM_V7K:
1376 return Triple("thumbv7k-apple-darwin");
1377 case MachO::CPU_SUBTYPE_ARM_V7M:
1378 if (McpuDefault)
1379 *McpuDefault = "cortex-m3";
1380 return Triple("thumbv7m-apple-darwin");
1381 case MachO::CPU_SUBTYPE_ARM_V7S:
1382 return Triple("thumbv7s-apple-darwin");
1383 default:
1384 return Triple();
1385 }
1386 default:
1387 return Triple();
1388 }
1389}
1390
1391Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1392 const char **McpuDefault,
1393 Triple *ThumbTriple) {
1394 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1395 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1396 McpuDefault);
1397 return T;
1398}
1399
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001400Triple MachOObjectFile::getHostArch() {
1401 return Triple(sys::getDefaultTargetTriple());
1402}
1403
Rafael Espindola72318b42014-08-08 16:30:17 +00001404bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1405 return StringSwitch<bool>(ArchFlag)
1406 .Case("i386", true)
1407 .Case("x86_64", true)
1408 .Case("x86_64h", true)
1409 .Case("armv4t", true)
1410 .Case("arm", true)
1411 .Case("armv5e", true)
1412 .Case("armv6", true)
1413 .Case("armv6m", true)
1414 .Case("armv7em", true)
1415 .Case("armv7k", true)
1416 .Case("armv7m", true)
1417 .Case("armv7s", true)
1418 .Case("arm64", true)
1419 .Case("ppc", true)
1420 .Case("ppc64", true)
1421 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001422}
1423
Alexey Samsonove6388e62013-06-18 15:03:28 +00001424unsigned MachOObjectFile::getArch() const {
1425 return getArch(getCPUType(this));
1426}
1427
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001428Triple MachOObjectFile::getArch(const char **McpuDefault,
1429 Triple *ThumbTriple) const {
1430 Triple T;
1431 if (is64Bit()) {
1432 MachO::mach_header_64 H_64;
1433 H_64 = getHeader64();
1434 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1435 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1436 McpuDefault);
1437 } else {
1438 MachO::mach_header H;
1439 H = getHeader();
1440 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1441 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1442 McpuDefault);
1443 }
1444 return T;
1445}
1446
Rui Ueyamabc654b12013-09-27 21:47:05 +00001447relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001448 DataRefImpl DRI;
1449 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001450 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001451}
1452
Rui Ueyamabc654b12013-09-27 21:47:05 +00001453relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001454 DataRefImpl DRI;
1455 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001456 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001457}
1458
Kevin Enderby273ae012013-06-06 17:20:50 +00001459dice_iterator MachOObjectFile::begin_dices() const {
1460 DataRefImpl DRI;
1461 if (!DataInCodeLoadCmd)
1462 return dice_iterator(DiceRef(DRI, this));
1463
Charles Davis8bdfafd2013-09-01 04:28:48 +00001464 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1465 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001466 return dice_iterator(DiceRef(DRI, this));
1467}
1468
1469dice_iterator MachOObjectFile::end_dices() const {
1470 DataRefImpl DRI;
1471 if (!DataInCodeLoadCmd)
1472 return dice_iterator(DiceRef(DRI, this));
1473
Charles Davis8bdfafd2013-09-01 04:28:48 +00001474 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1475 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001476 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1477 return dice_iterator(DiceRef(DRI, this));
1478}
1479
Nick Kledzikd04bc352014-08-30 00:20:14 +00001480ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1481 : Trie(T), Malformed(false), Done(false) { }
1482
1483void ExportEntry::moveToFirst() {
1484 pushNode(0);
1485 pushDownUntilBottom();
1486}
1487
1488void ExportEntry::moveToEnd() {
1489 Stack.clear();
1490 Done = true;
1491}
1492
1493bool ExportEntry::operator==(const ExportEntry &Other) const {
1494 // Common case, one at end, other iterating from begin.
1495 if (Done || Other.Done)
1496 return (Done == Other.Done);
1497 // Not equal if different stack sizes.
1498 if (Stack.size() != Other.Stack.size())
1499 return false;
1500 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001501 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001502 return false;
1503 // Equal if all nodes in both stacks match.
1504 for (unsigned i=0; i < Stack.size(); ++i) {
1505 if (Stack[i].Start != Other.Stack[i].Start)
1506 return false;
1507 }
1508 return true;
1509}
1510
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001511uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1512 unsigned Count;
1513 uint64_t Result = decodeULEB128(Ptr, &Count);
1514 Ptr += Count;
1515 if (Ptr > Trie.end()) {
1516 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001517 Malformed = true;
1518 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001519 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001520}
1521
1522StringRef ExportEntry::name() const {
1523 return CumulativeString.str();
1524}
1525
1526uint64_t ExportEntry::flags() const {
1527 return Stack.back().Flags;
1528}
1529
1530uint64_t ExportEntry::address() const {
1531 return Stack.back().Address;
1532}
1533
1534uint64_t ExportEntry::other() const {
1535 return Stack.back().Other;
1536}
1537
1538StringRef ExportEntry::otherName() const {
1539 const char* ImportName = Stack.back().ImportName;
1540 if (ImportName)
1541 return StringRef(ImportName);
1542 return StringRef();
1543}
1544
1545uint32_t ExportEntry::nodeOffset() const {
1546 return Stack.back().Start - Trie.begin();
1547}
1548
1549ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1550 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1551 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1552 ParentStringLength(0), IsExportNode(false) {
1553}
1554
1555void ExportEntry::pushNode(uint64_t offset) {
1556 const uint8_t *Ptr = Trie.begin() + offset;
1557 NodeState State(Ptr);
1558 uint64_t ExportInfoSize = readULEB128(State.Current);
1559 State.IsExportNode = (ExportInfoSize != 0);
1560 const uint8_t* Children = State.Current + ExportInfoSize;
1561 if (State.IsExportNode) {
1562 State.Flags = readULEB128(State.Current);
1563 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1564 State.Address = 0;
1565 State.Other = readULEB128(State.Current); // dylib ordinal
1566 State.ImportName = reinterpret_cast<const char*>(State.Current);
1567 } else {
1568 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001569 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1570 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001571 }
1572 }
1573 State.ChildCount = *Children;
1574 State.Current = Children + 1;
1575 State.NextChildIndex = 0;
1576 State.ParentStringLength = CumulativeString.size();
1577 Stack.push_back(State);
1578}
1579
1580void ExportEntry::pushDownUntilBottom() {
1581 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1582 NodeState &Top = Stack.back();
1583 CumulativeString.resize(Top.ParentStringLength);
1584 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001585 char C = *Top.Current;
1586 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001587 }
1588 Top.Current += 1;
1589 uint64_t childNodeIndex = readULEB128(Top.Current);
1590 Top.NextChildIndex += 1;
1591 pushNode(childNodeIndex);
1592 }
1593 if (!Stack.back().IsExportNode) {
1594 Malformed = true;
1595 moveToEnd();
1596 }
1597}
1598
1599// We have a trie data structure and need a way to walk it that is compatible
1600// with the C++ iterator model. The solution is a non-recursive depth first
1601// traversal where the iterator contains a stack of parent nodes along with a
1602// string that is the accumulation of all edge strings along the parent chain
1603// to this point.
1604//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001605// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001606// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1607// node may have child nodes too.
1608//
1609// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1610// child until hitting a node with no children (which is an export node or
1611// else the trie is malformed). On the way down, each node is pushed on the
1612// stack ivar. If there is no more ways down, it pops up one and tries to go
1613// down a sibling path until a childless node is reached.
1614void ExportEntry::moveNext() {
1615 if (Stack.empty() || !Stack.back().IsExportNode) {
1616 Malformed = true;
1617 moveToEnd();
1618 return;
1619 }
1620
1621 Stack.pop_back();
1622 while (!Stack.empty()) {
1623 NodeState &Top = Stack.back();
1624 if (Top.NextChildIndex < Top.ChildCount) {
1625 pushDownUntilBottom();
1626 // Now at the next export node.
1627 return;
1628 } else {
1629 if (Top.IsExportNode) {
1630 // This node has no children but is itself an export node.
1631 CumulativeString.resize(Top.ParentStringLength);
1632 return;
1633 }
1634 Stack.pop_back();
1635 }
1636 }
1637 Done = true;
1638}
1639
1640iterator_range<export_iterator>
1641MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1642 ExportEntry Start(Trie);
1643 Start.moveToFirst();
1644
1645 ExportEntry Finish(Trie);
1646 Finish.moveToEnd();
1647
1648 return iterator_range<export_iterator>(export_iterator(Start),
1649 export_iterator(Finish));
1650}
1651
1652iterator_range<export_iterator> MachOObjectFile::exports() const {
1653 return exports(getDyldInfoExportsTrie());
1654}
1655
1656
Nick Kledzikac431442014-09-12 21:34:15 +00001657MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1658 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1659 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1660 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1661
1662void MachORebaseEntry::moveToFirst() {
1663 Ptr = Opcodes.begin();
1664 moveNext();
1665}
1666
1667void MachORebaseEntry::moveToEnd() {
1668 Ptr = Opcodes.end();
1669 RemainingLoopCount = 0;
1670 Done = true;
1671}
1672
1673void MachORebaseEntry::moveNext() {
1674 // If in the middle of some loop, move to next rebasing in loop.
1675 SegmentOffset += AdvanceAmount;
1676 if (RemainingLoopCount) {
1677 --RemainingLoopCount;
1678 return;
1679 }
1680 if (Ptr == Opcodes.end()) {
1681 Done = true;
1682 return;
1683 }
1684 bool More = true;
1685 while (More && !Malformed) {
1686 // Parse next opcode and set up next loop.
1687 uint8_t Byte = *Ptr++;
1688 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1689 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1690 switch (Opcode) {
1691 case MachO::REBASE_OPCODE_DONE:
1692 More = false;
1693 Done = true;
1694 moveToEnd();
1695 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1696 break;
1697 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1698 RebaseType = ImmValue;
1699 DEBUG_WITH_TYPE(
1700 "mach-o-rebase",
1701 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1702 << "RebaseType=" << (int) RebaseType << "\n");
1703 break;
1704 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1705 SegmentIndex = ImmValue;
1706 SegmentOffset = readULEB128();
1707 DEBUG_WITH_TYPE(
1708 "mach-o-rebase",
1709 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1710 << "SegmentIndex=" << SegmentIndex << ", "
1711 << format("SegmentOffset=0x%06X", SegmentOffset)
1712 << "\n");
1713 break;
1714 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1715 SegmentOffset += readULEB128();
1716 DEBUG_WITH_TYPE("mach-o-rebase",
1717 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1718 << format("SegmentOffset=0x%06X",
1719 SegmentOffset) << "\n");
1720 break;
1721 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1722 SegmentOffset += ImmValue * PointerSize;
1723 DEBUG_WITH_TYPE("mach-o-rebase",
1724 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1725 << format("SegmentOffset=0x%06X",
1726 SegmentOffset) << "\n");
1727 break;
1728 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1729 AdvanceAmount = PointerSize;
1730 RemainingLoopCount = ImmValue - 1;
1731 DEBUG_WITH_TYPE(
1732 "mach-o-rebase",
1733 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1734 << format("SegmentOffset=0x%06X", SegmentOffset)
1735 << ", AdvanceAmount=" << AdvanceAmount
1736 << ", RemainingLoopCount=" << RemainingLoopCount
1737 << "\n");
1738 return;
1739 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1740 AdvanceAmount = PointerSize;
1741 RemainingLoopCount = readULEB128() - 1;
1742 DEBUG_WITH_TYPE(
1743 "mach-o-rebase",
1744 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1745 << format("SegmentOffset=0x%06X", SegmentOffset)
1746 << ", AdvanceAmount=" << AdvanceAmount
1747 << ", RemainingLoopCount=" << RemainingLoopCount
1748 << "\n");
1749 return;
1750 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1751 AdvanceAmount = readULEB128() + PointerSize;
1752 RemainingLoopCount = 0;
1753 DEBUG_WITH_TYPE(
1754 "mach-o-rebase",
1755 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1756 << format("SegmentOffset=0x%06X", SegmentOffset)
1757 << ", AdvanceAmount=" << AdvanceAmount
1758 << ", RemainingLoopCount=" << RemainingLoopCount
1759 << "\n");
1760 return;
1761 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1762 RemainingLoopCount = readULEB128() - 1;
1763 AdvanceAmount = readULEB128() + PointerSize;
1764 DEBUG_WITH_TYPE(
1765 "mach-o-rebase",
1766 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1767 << format("SegmentOffset=0x%06X", SegmentOffset)
1768 << ", AdvanceAmount=" << AdvanceAmount
1769 << ", RemainingLoopCount=" << RemainingLoopCount
1770 << "\n");
1771 return;
1772 default:
1773 Malformed = true;
1774 }
1775 }
1776}
1777
1778uint64_t MachORebaseEntry::readULEB128() {
1779 unsigned Count;
1780 uint64_t Result = decodeULEB128(Ptr, &Count);
1781 Ptr += Count;
1782 if (Ptr > Opcodes.end()) {
1783 Ptr = Opcodes.end();
1784 Malformed = true;
1785 }
1786 return Result;
1787}
1788
1789uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1790
1791uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1792
1793StringRef MachORebaseEntry::typeName() const {
1794 switch (RebaseType) {
1795 case MachO::REBASE_TYPE_POINTER:
1796 return "pointer";
1797 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1798 return "text abs32";
1799 case MachO::REBASE_TYPE_TEXT_PCREL32:
1800 return "text rel32";
1801 }
1802 return "unknown";
1803}
1804
1805bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1806 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1807 return (Ptr == Other.Ptr) &&
1808 (RemainingLoopCount == Other.RemainingLoopCount) &&
1809 (Done == Other.Done);
1810}
1811
1812iterator_range<rebase_iterator>
1813MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1814 MachORebaseEntry Start(Opcodes, is64);
1815 Start.moveToFirst();
1816
1817 MachORebaseEntry Finish(Opcodes, is64);
1818 Finish.moveToEnd();
1819
1820 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1821 rebase_iterator(Finish));
1822}
1823
1824iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1825 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1826}
1827
Nick Kledzik56ebef42014-09-16 01:41:51 +00001828
1829MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1830 Kind BK)
1831 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1832 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1833 BindType(0), PointerSize(is64Bit ? 8 : 4),
1834 TableKind(BK), Malformed(false), Done(false) {}
1835
1836void MachOBindEntry::moveToFirst() {
1837 Ptr = Opcodes.begin();
1838 moveNext();
1839}
1840
1841void MachOBindEntry::moveToEnd() {
1842 Ptr = Opcodes.end();
1843 RemainingLoopCount = 0;
1844 Done = true;
1845}
1846
1847void MachOBindEntry::moveNext() {
1848 // If in the middle of some loop, move to next binding in loop.
1849 SegmentOffset += AdvanceAmount;
1850 if (RemainingLoopCount) {
1851 --RemainingLoopCount;
1852 return;
1853 }
1854 if (Ptr == Opcodes.end()) {
1855 Done = true;
1856 return;
1857 }
1858 bool More = true;
1859 while (More && !Malformed) {
1860 // Parse next opcode and set up next loop.
1861 uint8_t Byte = *Ptr++;
1862 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1863 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1864 int8_t SignExtended;
1865 const uint8_t *SymStart;
1866 switch (Opcode) {
1867 case MachO::BIND_OPCODE_DONE:
1868 if (TableKind == Kind::Lazy) {
1869 // Lazying bindings have a DONE opcode between entries. Need to ignore
1870 // it to advance to next entry. But need not if this is last entry.
1871 bool NotLastEntry = false;
1872 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1873 if (*P) {
1874 NotLastEntry = true;
1875 }
1876 }
1877 if (NotLastEntry)
1878 break;
1879 }
1880 More = false;
1881 Done = true;
1882 moveToEnd();
1883 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1884 break;
1885 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1886 Ordinal = ImmValue;
1887 DEBUG_WITH_TYPE(
1888 "mach-o-bind",
1889 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1890 << "Ordinal=" << Ordinal << "\n");
1891 break;
1892 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1893 Ordinal = readULEB128();
1894 DEBUG_WITH_TYPE(
1895 "mach-o-bind",
1896 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1897 << "Ordinal=" << Ordinal << "\n");
1898 break;
1899 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1900 if (ImmValue) {
1901 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1902 Ordinal = SignExtended;
1903 } else
1904 Ordinal = 0;
1905 DEBUG_WITH_TYPE(
1906 "mach-o-bind",
1907 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1908 << "Ordinal=" << Ordinal << "\n");
1909 break;
1910 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1911 Flags = ImmValue;
1912 SymStart = Ptr;
1913 while (*Ptr) {
1914 ++Ptr;
1915 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001916 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1917 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001918 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001919 DEBUG_WITH_TYPE(
1920 "mach-o-bind",
1921 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1922 << "SymbolName=" << SymbolName << "\n");
1923 if (TableKind == Kind::Weak) {
1924 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1925 return;
1926 }
1927 break;
1928 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1929 BindType = ImmValue;
1930 DEBUG_WITH_TYPE(
1931 "mach-o-bind",
1932 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1933 << "BindType=" << (int)BindType << "\n");
1934 break;
1935 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1936 Addend = readSLEB128();
1937 if (TableKind == Kind::Lazy)
1938 Malformed = true;
1939 DEBUG_WITH_TYPE(
1940 "mach-o-bind",
1941 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1942 << "Addend=" << Addend << "\n");
1943 break;
1944 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1945 SegmentIndex = ImmValue;
1946 SegmentOffset = readULEB128();
1947 DEBUG_WITH_TYPE(
1948 "mach-o-bind",
1949 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1950 << "SegmentIndex=" << SegmentIndex << ", "
1951 << format("SegmentOffset=0x%06X", SegmentOffset)
1952 << "\n");
1953 break;
1954 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1955 SegmentOffset += readULEB128();
1956 DEBUG_WITH_TYPE("mach-o-bind",
1957 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1958 << format("SegmentOffset=0x%06X",
1959 SegmentOffset) << "\n");
1960 break;
1961 case MachO::BIND_OPCODE_DO_BIND:
1962 AdvanceAmount = PointerSize;
1963 RemainingLoopCount = 0;
1964 DEBUG_WITH_TYPE("mach-o-bind",
1965 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1966 << format("SegmentOffset=0x%06X",
1967 SegmentOffset) << "\n");
1968 return;
1969 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001970 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001971 RemainingLoopCount = 0;
1972 if (TableKind == Kind::Lazy)
1973 Malformed = true;
1974 DEBUG_WITH_TYPE(
1975 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001976 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001977 << format("SegmentOffset=0x%06X", SegmentOffset)
1978 << ", AdvanceAmount=" << AdvanceAmount
1979 << ", RemainingLoopCount=" << RemainingLoopCount
1980 << "\n");
1981 return;
1982 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001983 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001984 RemainingLoopCount = 0;
1985 if (TableKind == Kind::Lazy)
1986 Malformed = true;
1987 DEBUG_WITH_TYPE("mach-o-bind",
1988 llvm::dbgs()
1989 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1990 << format("SegmentOffset=0x%06X",
1991 SegmentOffset) << "\n");
1992 return;
1993 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1994 RemainingLoopCount = readULEB128() - 1;
1995 AdvanceAmount = readULEB128() + PointerSize;
1996 if (TableKind == Kind::Lazy)
1997 Malformed = true;
1998 DEBUG_WITH_TYPE(
1999 "mach-o-bind",
2000 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2001 << format("SegmentOffset=0x%06X", SegmentOffset)
2002 << ", AdvanceAmount=" << AdvanceAmount
2003 << ", RemainingLoopCount=" << RemainingLoopCount
2004 << "\n");
2005 return;
2006 default:
2007 Malformed = true;
2008 }
2009 }
2010}
2011
2012uint64_t MachOBindEntry::readULEB128() {
2013 unsigned Count;
2014 uint64_t Result = decodeULEB128(Ptr, &Count);
2015 Ptr += Count;
2016 if (Ptr > Opcodes.end()) {
2017 Ptr = Opcodes.end();
2018 Malformed = true;
2019 }
2020 return Result;
2021}
2022
2023int64_t MachOBindEntry::readSLEB128() {
2024 unsigned Count;
2025 int64_t Result = decodeSLEB128(Ptr, &Count);
2026 Ptr += Count;
2027 if (Ptr > Opcodes.end()) {
2028 Ptr = Opcodes.end();
2029 Malformed = true;
2030 }
2031 return Result;
2032}
2033
2034
2035uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2036
2037uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2038
2039StringRef MachOBindEntry::typeName() const {
2040 switch (BindType) {
2041 case MachO::BIND_TYPE_POINTER:
2042 return "pointer";
2043 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2044 return "text abs32";
2045 case MachO::BIND_TYPE_TEXT_PCREL32:
2046 return "text rel32";
2047 }
2048 return "unknown";
2049}
2050
2051StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2052
2053int64_t MachOBindEntry::addend() const { return Addend; }
2054
2055uint32_t MachOBindEntry::flags() const { return Flags; }
2056
2057int MachOBindEntry::ordinal() const { return Ordinal; }
2058
2059bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2060 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2061 return (Ptr == Other.Ptr) &&
2062 (RemainingLoopCount == Other.RemainingLoopCount) &&
2063 (Done == Other.Done);
2064}
2065
2066iterator_range<bind_iterator>
2067MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2068 MachOBindEntry::Kind BKind) {
2069 MachOBindEntry Start(Opcodes, is64, BKind);
2070 Start.moveToFirst();
2071
2072 MachOBindEntry Finish(Opcodes, is64, BKind);
2073 Finish.moveToEnd();
2074
2075 return iterator_range<bind_iterator>(bind_iterator(Start),
2076 bind_iterator(Finish));
2077}
2078
2079iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2080 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2081 MachOBindEntry::Kind::Regular);
2082}
2083
2084iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2085 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2086 MachOBindEntry::Kind::Lazy);
2087}
2088
2089iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2090 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2091 MachOBindEntry::Kind::Weak);
2092}
2093
Rafael Espindola56f976f2013-04-18 18:08:55 +00002094StringRef
2095MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2096 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2097 return parseSegmentOrSectionName(Raw.data());
2098}
2099
2100ArrayRef<char>
2101MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002102 const section_base *Base =
2103 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002104 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002105}
2106
2107ArrayRef<char>
2108MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002109 const section_base *Base =
2110 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002111 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002112}
2113
2114bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002115MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002116 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002117 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002118 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002119 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002120}
2121
Eric Christopher1d62c252013-07-22 22:25:07 +00002122unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002123 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002124 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002125 return RE.r_word1 & 0xffffff;
2126 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002127}
2128
Eric Christopher1d62c252013-07-22 22:25:07 +00002129bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002130 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002131 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002132 return (RE.r_word1 >> 27) & 1;
2133 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002134}
2135
Eric Christopher1d62c252013-07-22 22:25:07 +00002136bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002137 const MachO::any_relocation_info &RE) const {
2138 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002139}
2140
Eric Christopher1d62c252013-07-22 22:25:07 +00002141uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002142 const MachO::any_relocation_info &RE) const {
2143 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002144}
2145
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002146uint32_t MachOObjectFile::getScatteredRelocationType(
2147 const MachO::any_relocation_info &RE) const {
2148 return (RE.r_word0 >> 24) & 0xf;
2149}
2150
Eric Christopher1d62c252013-07-22 22:25:07 +00002151unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002152 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002153 if (isRelocationScattered(RE))
2154 return getScatteredRelocationAddress(RE);
2155 return getPlainRelocationAddress(RE);
2156}
2157
Charles Davis8bdfafd2013-09-01 04:28:48 +00002158unsigned MachOObjectFile::getAnyRelocationPCRel(
2159 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002160 if (isRelocationScattered(RE))
2161 return getScatteredRelocationPCRel(this, RE);
2162 return getPlainRelocationPCRel(this, RE);
2163}
2164
Eric Christopher1d62c252013-07-22 22:25:07 +00002165unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002166 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002167 if (isRelocationScattered(RE))
2168 return getScatteredRelocationLength(RE);
2169 return getPlainRelocationLength(this, RE);
2170}
2171
2172unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002173MachOObjectFile::getAnyRelocationType(
2174 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002175 if (isRelocationScattered(RE))
2176 return getScatteredRelocationType(RE);
2177 return getPlainRelocationType(this, RE);
2178}
2179
Rafael Espindola52501032013-04-30 15:40:54 +00002180SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00002181MachOObjectFile::getRelocationSection(
2182 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002183 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002184 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002185 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2186 DataRefImpl DRI;
2187 DRI.d.a = SecNum;
2188 return SectionRef(DRI, this);
2189}
2190
Rafael Espindola56f976f2013-04-18 18:08:55 +00002191MachOObjectFile::LoadCommandInfo
2192MachOObjectFile::getFirstLoadCommandInfo() const {
2193 MachOObjectFile::LoadCommandInfo Load;
2194
Charles Davis8bdfafd2013-09-01 04:28:48 +00002195 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2196 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002197 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002198 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002199 return Load;
2200}
2201
2202MachOObjectFile::LoadCommandInfo
2203MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2204 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002205 Next.Ptr = L.Ptr + L.C.cmdsize;
2206 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002207 return Next;
2208}
2209
Charles Davis8bdfafd2013-09-01 04:28:48 +00002210MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2211 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002212}
2213
Charles Davis8bdfafd2013-09-01 04:28:48 +00002214MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2215 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002216}
2217
Charles Davis8bdfafd2013-09-01 04:28:48 +00002218MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002219 unsigned Index) const {
2220 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002221 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002222}
2223
Charles Davis8bdfafd2013-09-01 04:28:48 +00002224MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2225 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002226 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002227 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002228}
2229
Charles Davis8bdfafd2013-09-01 04:28:48 +00002230MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002231MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002232 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002233 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002234}
2235
Charles Davis8bdfafd2013-09-01 04:28:48 +00002236MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002237MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002238 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002239 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002240}
2241
Charles Davis8bdfafd2013-09-01 04:28:48 +00002242MachO::linkedit_data_command
2243MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2244 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002245}
2246
Charles Davis8bdfafd2013-09-01 04:28:48 +00002247MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002248MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002249 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002250}
2251
Charles Davis8bdfafd2013-09-01 04:28:48 +00002252MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002253MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002254 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002255}
2256
Charles Davis8bdfafd2013-09-01 04:28:48 +00002257MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002258MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002259 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002260}
2261
Jim Grosbach448334a2014-03-18 22:09:05 +00002262MachO::version_min_command
2263MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2264 return getStruct<MachO::version_min_command>(this, L.Ptr);
2265}
2266
Tim Northover8f9590b2014-06-30 14:40:57 +00002267MachO::dylib_command
2268MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2269 return getStruct<MachO::dylib_command>(this, L.Ptr);
2270}
2271
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002272MachO::dyld_info_command
2273MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2274 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2275}
2276
2277MachO::dylinker_command
2278MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2279 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2280}
2281
2282MachO::uuid_command
2283MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2284 return getStruct<MachO::uuid_command>(this, L.Ptr);
2285}
2286
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002287MachO::rpath_command
2288MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2289 return getStruct<MachO::rpath_command>(this, L.Ptr);
2290}
2291
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002292MachO::source_version_command
2293MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2294 return getStruct<MachO::source_version_command>(this, L.Ptr);
2295}
2296
2297MachO::entry_point_command
2298MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2299 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2300}
2301
Kevin Enderby0804f4672014-12-16 23:25:52 +00002302MachO::encryption_info_command
2303MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2304 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2305}
2306
Kevin Enderby57538292014-12-17 01:01:30 +00002307MachO::encryption_info_command_64
2308MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2309 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2310}
2311
Tim Northover8f9590b2014-06-30 14:40:57 +00002312
Charles Davis8bdfafd2013-09-01 04:28:48 +00002313MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002314MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002315 DataRefImpl Sec;
2316 Sec.d.a = Rel.d.a;
2317 uint32_t Offset;
2318 if (is64Bit()) {
2319 MachO::section_64 Sect = getSection64(Sec);
2320 Offset = Sect.reloff;
2321 } else {
2322 MachO::section Sect = getSection(Sec);
2323 Offset = Sect.reloff;
2324 }
2325
2326 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2327 getPtr(this, Offset)) + Rel.d.b;
2328 return getStruct<MachO::any_relocation_info>(
2329 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002330}
2331
Charles Davis8bdfafd2013-09-01 04:28:48 +00002332MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002333MachOObjectFile::getDice(DataRefImpl Rel) const {
2334 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002335 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002336}
2337
Charles Davis8bdfafd2013-09-01 04:28:48 +00002338MachO::mach_header MachOObjectFile::getHeader() const {
2339 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002340}
2341
Charles Davis8bdfafd2013-09-01 04:28:48 +00002342MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2343 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002344}
2345
Charles Davis8bdfafd2013-09-01 04:28:48 +00002346uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2347 const MachO::dysymtab_command &DLC,
2348 unsigned Index) const {
2349 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2350 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002351}
2352
Charles Davis8bdfafd2013-09-01 04:28:48 +00002353MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002354MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2355 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002356 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2357 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002358}
2359
Charles Davis8bdfafd2013-09-01 04:28:48 +00002360MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002361 if (SymtabLoadCmd)
2362 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2363
2364 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2365 MachO::symtab_command Cmd;
2366 Cmd.cmd = MachO::LC_SYMTAB;
2367 Cmd.cmdsize = sizeof(MachO::symtab_command);
2368 Cmd.symoff = 0;
2369 Cmd.nsyms = 0;
2370 Cmd.stroff = 0;
2371 Cmd.strsize = 0;
2372 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002373}
2374
Charles Davis8bdfafd2013-09-01 04:28:48 +00002375MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002376 if (DysymtabLoadCmd)
2377 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2378
2379 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2380 MachO::dysymtab_command Cmd;
2381 Cmd.cmd = MachO::LC_DYSYMTAB;
2382 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2383 Cmd.ilocalsym = 0;
2384 Cmd.nlocalsym = 0;
2385 Cmd.iextdefsym = 0;
2386 Cmd.nextdefsym = 0;
2387 Cmd.iundefsym = 0;
2388 Cmd.nundefsym = 0;
2389 Cmd.tocoff = 0;
2390 Cmd.ntoc = 0;
2391 Cmd.modtaboff = 0;
2392 Cmd.nmodtab = 0;
2393 Cmd.extrefsymoff = 0;
2394 Cmd.nextrefsyms = 0;
2395 Cmd.indirectsymoff = 0;
2396 Cmd.nindirectsyms = 0;
2397 Cmd.extreloff = 0;
2398 Cmd.nextrel = 0;
2399 Cmd.locreloff = 0;
2400 Cmd.nlocrel = 0;
2401 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002402}
2403
Charles Davis8bdfafd2013-09-01 04:28:48 +00002404MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002405MachOObjectFile::getDataInCodeLoadCommand() const {
2406 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002407 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002408
2409 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002410 MachO::linkedit_data_command Cmd;
2411 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2412 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2413 Cmd.dataoff = 0;
2414 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002415 return Cmd;
2416}
2417
Nick Kledzikd04bc352014-08-30 00:20:14 +00002418ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2419 if (!DyldInfoLoadCmd)
2420 return ArrayRef<uint8_t>();
2421
2422 MachO::dyld_info_command DyldInfo
2423 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2424 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2425 getPtr(this, DyldInfo.rebase_off));
2426 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2427}
2428
2429ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2430 if (!DyldInfoLoadCmd)
2431 return ArrayRef<uint8_t>();
2432
2433 MachO::dyld_info_command DyldInfo
2434 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2435 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2436 getPtr(this, DyldInfo.bind_off));
2437 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2438}
2439
2440ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2441 if (!DyldInfoLoadCmd)
2442 return ArrayRef<uint8_t>();
2443
2444 MachO::dyld_info_command DyldInfo
2445 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2446 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2447 getPtr(this, DyldInfo.weak_bind_off));
2448 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2449}
2450
2451ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2452 if (!DyldInfoLoadCmd)
2453 return ArrayRef<uint8_t>();
2454
2455 MachO::dyld_info_command DyldInfo
2456 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2457 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2458 getPtr(this, DyldInfo.lazy_bind_off));
2459 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2460}
2461
2462ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2463 if (!DyldInfoLoadCmd)
2464 return ArrayRef<uint8_t>();
2465
2466 MachO::dyld_info_command DyldInfo
2467 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2468 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2469 getPtr(this, DyldInfo.export_off));
2470 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2471}
2472
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002473ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2474 if (!UuidLoadCmd)
2475 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002476 // Returning a pointer is fine as uuid doesn't need endian swapping.
2477 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2478 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002479}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002480
Rafael Espindola6e040c02013-04-26 20:07:33 +00002481StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002482 MachO::symtab_command S = getSymtabLoadCommand();
2483 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002484}
2485
Rafael Espindola56f976f2013-04-18 18:08:55 +00002486bool MachOObjectFile::is64Bit() const {
2487 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002488 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002489}
2490
2491void MachOObjectFile::ReadULEB128s(uint64_t Index,
2492 SmallVectorImpl<uint64_t> &Out) const {
2493 DataExtractor extractor(ObjectFile::getData(), true, 0);
2494
2495 uint32_t offset = Index;
2496 uint64_t data = 0;
2497 while (uint64_t delta = extractor.getULEB128(&offset)) {
2498 data += delta;
2499 Out.push_back(data);
2500 }
2501}
2502
Rafael Espindolac66d7612014-08-17 19:09:37 +00002503bool MachOObjectFile::isRelocatableObject() const {
2504 return getHeader().filetype == MachO::MH_OBJECT;
2505}
2506
Rafael Espindola437b0d52014-07-31 03:12:45 +00002507ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002508ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2509 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002510 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002511 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002512 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002513 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002514 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002515 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002516 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002517 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002518 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002519 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002520 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002521 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002522
Rafael Espindola692410e2014-01-21 23:06:54 +00002523 if (EC)
2524 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002525 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002526}
2527