blob: e4769762be44ccb6f5359dbb829bda5088ed102b [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;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000239 if (LoadCommandCount == 0)
240 return;
241
Charles Davis8bdfafd2013-09-01 04:28:48 +0000242 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
243 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000244
245 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000246 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000247 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000248 // Multiple symbol tables
249 if (SymtabLoadCmd) {
250 EC = object_error::parse_failed;
251 return;
252 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000253 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000254 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000255 // Multiple dynamic symbol tables
256 if (DysymtabLoadCmd) {
257 EC = object_error::parse_failed;
258 return;
259 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000260 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000261 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000262 // Multiple data in code tables
263 if (DataInCodeLoadCmd) {
264 EC = object_error::parse_failed;
265 return;
266 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000267 DataInCodeLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000268 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
269 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000270 // Multiple dyldinfo load commands
271 if (DyldInfoLoadCmd) {
272 EC = object_error::parse_failed;
273 return;
274 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000275 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000276 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000277 // Multiple UUID load commands
278 if (UuidLoadCmd) {
279 EC = object_error::parse_failed;
280 return;
281 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000282 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000283 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000284 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
285 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000286 const char *Sec = getSectionPtr(this, Load, J);
287 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000288 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000289 if (isPageZeroSegment(this, Load))
290 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000291 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
292 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
293 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
294 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
295 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
296 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000297 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000298
299 if (I == LoadCommandCount - 1)
300 break;
301 else
302 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000303 }
304}
305
Rafael Espindola5e812af2014-01-30 02:49:50 +0000306void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000307 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000308 sizeof(MachO::nlist_64) :
309 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000310 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000311}
312
Rafael Espindola3acea392014-06-12 21:46:39 +0000313std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
314 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000315 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000316 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000317 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000318 Res = StringRef(Start);
319 return object_error::success;
320}
321
Rafael Espindola0e77a942014-12-10 20:46:55 +0000322unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
323 DataRefImpl DRI = Sec.getRawDataRefImpl();
324 uint32_t Flags = getSectionFlags(this, DRI);
325 return Flags & MachO::SECTION_TYPE;
326}
327
Kevin Enderby980b2582014-06-05 21:21:57 +0000328// getIndirectName() returns the name of the alias'ed symbol who's string table
329// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000330std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
331 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000332 StringRef StringTable = getStringTableData();
333 uint64_t NValue;
334 if (is64Bit()) {
335 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
336 NValue = Entry.n_value;
337 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
338 return object_error::parse_failed;
339 } else {
340 MachO::nlist Entry = getSymbolTableEntry(Symb);
341 NValue = Entry.n_value;
342 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
343 return object_error::parse_failed;
344 }
345 if (NValue >= StringTable.size())
346 return object_error::parse_failed;
347 const char *Start = &StringTable.data()[NValue];
348 Res = StringRef(Start);
349 return object_error::success;
350}
351
Rafael Espindola3acea392014-06-12 21:46:39 +0000352std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
353 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000354 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000355 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000356 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
357 Entry.n_value == 0)
358 Res = UnknownAddressOrSize;
359 else
360 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000361 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000362 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000363 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
364 Entry.n_value == 0)
365 Res = UnknownAddressOrSize;
366 else
367 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000368 }
369 return object_error::success;
370}
371
Rafael Espindola3acea392014-06-12 21:46:39 +0000372std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
373 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000374 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000375 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000376 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000377 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000378 } else {
379 Result = 0;
380 }
381 return object_error::success;
382}
383
Rafael Espindola3acea392014-06-12 21:46:39 +0000384std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
385 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000386 uint64_t BeginOffset;
387 uint64_t EndOffset = 0;
388 uint8_t SectionIndex;
389
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000391 uint64_t Value;
392 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000393 if (Value == UnknownAddressOrSize) {
394 Result = UnknownAddressOrSize;
395 return object_error::success;
396 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000397
398 BeginOffset = Value;
399
Charles Davis8bdfafd2013-09-01 04:28:48 +0000400 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000401 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000402 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000403 if (flags & SymbolRef::SF_Common)
404 Result = Value;
405 else
406 Result = UnknownAddressOrSize;
407 return object_error::success;
408 }
409 // Unfortunately symbols are unsorted so we need to touch all
410 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000411 for (const SymbolRef &Symbol : symbols()) {
412 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000413 Entry = getSymbolTableEntryBase(this, DRI);
414 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000415 if (Value == UnknownAddressOrSize)
416 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000417 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000418 if (!EndOffset || Value < EndOffset)
419 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000420 }
421 if (!EndOffset) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000422 DataRefImpl Sec;
423 Sec.d.a = SectionIndex-1;
Rafael Espindola80291272014-10-08 15:28:58 +0000424 uint64_t Size = getSectionSize(Sec);
425 EndOffset = getSectionAddress(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000426 EndOffset += Size;
427 }
428 Result = EndOffset - BeginOffset;
429 return object_error::success;
430}
431
Rafael Espindola3acea392014-06-12 21:46:39 +0000432std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
433 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000434 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000435 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000436
437 Res = SymbolRef::ST_Other;
438
439 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000440 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000441 Res = SymbolRef::ST_Debug;
442 return object_error::success;
443 }
444
Charles Davis74ec8b02013-08-27 05:00:13 +0000445 switch (n_type & MachO::N_TYPE) {
446 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000447 Res = SymbolRef::ST_Unknown;
448 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000449 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000450 Res = SymbolRef::ST_Function;
451 break;
452 }
453 return object_error::success;
454}
455
Rafael Espindola20122a42014-01-31 20:57:12 +0000456uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000457 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000458
Charles Davis8bdfafd2013-09-01 04:28:48 +0000459 uint8_t MachOType = Entry.n_type;
460 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000461
Rafael Espindola20122a42014-01-31 20:57:12 +0000462 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000463
Charles Davis74ec8b02013-08-27 05:00:13 +0000464 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000465 Result |= SymbolRef::SF_Undefined;
466
Tim Northovereaef0742014-05-30 13:22:59 +0000467 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
468 Result |= SymbolRef::SF_Indirect;
469
Rafael Espindolaa1356322013-11-02 05:03:24 +0000470 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000471 Result |= SymbolRef::SF_FormatSpecific;
472
Charles Davis74ec8b02013-08-27 05:00:13 +0000473 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000474 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000475 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000476 uint64_t Value;
477 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000478 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000479 Result |= SymbolRef::SF_Common;
480 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000481 }
482
Charles Davis74ec8b02013-08-27 05:00:13 +0000483 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000484 Result |= SymbolRef::SF_Weak;
485
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000486 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
487 Result |= SymbolRef::SF_Thumb;
488
Charles Davis74ec8b02013-08-27 05:00:13 +0000489 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000490 Result |= SymbolRef::SF_Absolute;
491
Rafael Espindola20122a42014-01-31 20:57:12 +0000492 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000493}
494
Rafael Espindola3acea392014-06-12 21:46:39 +0000495std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
496 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000497 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000498 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000499
500 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000501 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000502 } else {
503 DataRefImpl DRI;
504 DRI.d.a = index - 1;
505 Res = section_iterator(SectionRef(DRI, this));
506 }
507
508 return object_error::success;
509}
510
Rafael Espindola5e812af2014-01-30 02:49:50 +0000511void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000512 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000513}
514
Rafael Espindola3acea392014-06-12 21:46:39 +0000515std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
516 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000517 ArrayRef<char> Raw = getSectionRawName(Sec);
518 Result = parseSegmentOrSectionName(Raw.data());
519 return object_error::success;
520}
521
Rafael Espindola80291272014-10-08 15:28:58 +0000522uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
523 if (is64Bit())
524 return getSection64(Sec).addr;
525 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000526}
527
Rafael Espindola80291272014-10-08 15:28:58 +0000528uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
529 if (is64Bit())
530 return getSection64(Sec).size;
531 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000532}
533
Rafael Espindola3acea392014-06-12 21:46:39 +0000534std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
535 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000536 uint32_t Offset;
537 uint64_t Size;
538
539 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000540 MachO::section_64 Sect = getSection64(Sec);
541 Offset = Sect.offset;
542 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000543 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000544 MachO::section Sect = getSection(Sec);
545 Offset = Sect.offset;
546 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000547 }
548
549 Res = this->getData().substr(Offset, Size);
550 return object_error::success;
551}
552
Rafael Espindola80291272014-10-08 15:28:58 +0000553uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000554 uint32_t Align;
555 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000556 MachO::section_64 Sect = getSection64(Sec);
557 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000558 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000559 MachO::section Sect = getSection(Sec);
560 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000561 }
562
Rafael Espindola80291272014-10-08 15:28:58 +0000563 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000564}
565
Rafael Espindola80291272014-10-08 15:28:58 +0000566bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000567 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000568 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000569}
570
Rafael Espindola80291272014-10-08 15:28:58 +0000571bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000572 uint32_t Flags = getSectionFlags(this, Sec);
573 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000574 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
575 !(SectionType == MachO::S_ZEROFILL ||
576 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000577}
578
Rafael Espindola80291272014-10-08 15:28:58 +0000579bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000580 uint32_t Flags = getSectionFlags(this, Sec);
581 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000582 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
583 (SectionType == MachO::S_ZEROFILL ||
584 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000585}
586
Rafael Espindola80291272014-10-08 15:28:58 +0000587bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000588 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000589 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000590}
591
Rafael Espindola80291272014-10-08 15:28:58 +0000592bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
593 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000594 SymbolRef::Type ST;
595 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000596 if (ST == SymbolRef::ST_Unknown)
597 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000598
Rafael Espindola80291272014-10-08 15:28:58 +0000599 uint64_t SectBegin = getSectionAddress(Sec);
600 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000601 SectEnd += SectBegin;
602
603 uint64_t SymAddr;
604 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000605 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000606}
607
Rui Ueyamabc654b12013-09-27 21:47:05 +0000608relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000609 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000610 Ret.d.a = Sec.d.a;
611 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000612 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000613}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000614
Rafael Espindola56f976f2013-04-18 18:08:55 +0000615relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000616MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000617 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000618 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000619 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000620 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000621 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000622 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000623 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000624 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000625
Rafael Espindola56f976f2013-04-18 18:08:55 +0000626 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000627 Ret.d.a = Sec.d.a;
628 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000629 return relocation_iterator(RelocationRef(Ret, this));
630}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000631
Rafael Espindola5e812af2014-01-30 02:49:50 +0000632void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000633 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000634}
Owen Anderson171f4852011-10-24 23:20:07 +0000635
Rafael Espindola3acea392014-06-12 21:46:39 +0000636std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
637 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000638 uint64_t Offset;
639 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000640
641 DataRefImpl Sec;
642 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000643 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000644 Res = SecAddress + Offset;
645 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000646}
647
Rafael Espindola3acea392014-06-12 21:46:39 +0000648std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
649 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000650 assert(getHeader().filetype == MachO::MH_OBJECT &&
651 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000652 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000653 Res = getAnyRelocationAddress(RE);
654 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000655}
656
Rafael Espindola806f0062013-06-05 01:33:53 +0000657symbol_iterator
658MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000659 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000660 if (isRelocationScattered(RE))
661 return symbol_end();
662
Rafael Espindola56f976f2013-04-18 18:08:55 +0000663 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
664 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000665 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000666 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000667
Charles Davis8bdfafd2013-09-01 04:28:48 +0000668 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000669 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000670 sizeof(MachO::nlist_64) :
671 sizeof(MachO::nlist);
672 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000673 DataRefImpl Sym;
674 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000675 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000676}
677
Rafael Espindola3acea392014-06-12 21:46:39 +0000678std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
679 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000680 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000681 Res = getAnyRelocationType(RE);
682 return object_error::success;
683}
684
Rafael Espindola3acea392014-06-12 21:46:39 +0000685std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000686MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
687 SmallVectorImpl<char> &Result) const {
688 StringRef res;
689 uint64_t RType;
690 getRelocationType(Rel, RType);
691
692 unsigned Arch = this->getArch();
693
694 switch (Arch) {
695 case Triple::x86: {
696 static const char *const Table[] = {
697 "GENERIC_RELOC_VANILLA",
698 "GENERIC_RELOC_PAIR",
699 "GENERIC_RELOC_SECTDIFF",
700 "GENERIC_RELOC_PB_LA_PTR",
701 "GENERIC_RELOC_LOCAL_SECTDIFF",
702 "GENERIC_RELOC_TLV" };
703
Eric Christopher13250cb2013-12-06 02:33:38 +0000704 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000705 res = "Unknown";
706 else
707 res = Table[RType];
708 break;
709 }
710 case Triple::x86_64: {
711 static const char *const Table[] = {
712 "X86_64_RELOC_UNSIGNED",
713 "X86_64_RELOC_SIGNED",
714 "X86_64_RELOC_BRANCH",
715 "X86_64_RELOC_GOT_LOAD",
716 "X86_64_RELOC_GOT",
717 "X86_64_RELOC_SUBTRACTOR",
718 "X86_64_RELOC_SIGNED_1",
719 "X86_64_RELOC_SIGNED_2",
720 "X86_64_RELOC_SIGNED_4",
721 "X86_64_RELOC_TLV" };
722
723 if (RType > 9)
724 res = "Unknown";
725 else
726 res = Table[RType];
727 break;
728 }
729 case Triple::arm: {
730 static const char *const Table[] = {
731 "ARM_RELOC_VANILLA",
732 "ARM_RELOC_PAIR",
733 "ARM_RELOC_SECTDIFF",
734 "ARM_RELOC_LOCAL_SECTDIFF",
735 "ARM_RELOC_PB_LA_PTR",
736 "ARM_RELOC_BR24",
737 "ARM_THUMB_RELOC_BR22",
738 "ARM_THUMB_32BIT_BRANCH",
739 "ARM_RELOC_HALF",
740 "ARM_RELOC_HALF_SECTDIFF" };
741
742 if (RType > 9)
743 res = "Unknown";
744 else
745 res = Table[RType];
746 break;
747 }
Tim Northover00ed9962014-03-29 10:18:08 +0000748 case Triple::aarch64: {
749 static const char *const Table[] = {
750 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
751 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
752 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
753 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
754 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
755 "ARM64_RELOC_ADDEND"
756 };
757
758 if (RType >= array_lengthof(Table))
759 res = "Unknown";
760 else
761 res = Table[RType];
762 break;
763 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000764 case Triple::ppc: {
765 static const char *const Table[] = {
766 "PPC_RELOC_VANILLA",
767 "PPC_RELOC_PAIR",
768 "PPC_RELOC_BR14",
769 "PPC_RELOC_BR24",
770 "PPC_RELOC_HI16",
771 "PPC_RELOC_LO16",
772 "PPC_RELOC_HA16",
773 "PPC_RELOC_LO14",
774 "PPC_RELOC_SECTDIFF",
775 "PPC_RELOC_PB_LA_PTR",
776 "PPC_RELOC_HI16_SECTDIFF",
777 "PPC_RELOC_LO16_SECTDIFF",
778 "PPC_RELOC_HA16_SECTDIFF",
779 "PPC_RELOC_JBSR",
780 "PPC_RELOC_LO14_SECTDIFF",
781 "PPC_RELOC_LOCAL_SECTDIFF" };
782
Eric Christopher13250cb2013-12-06 02:33:38 +0000783 if (RType > 15)
784 res = "Unknown";
785 else
786 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000787 break;
788 }
789 case Triple::UnknownArch:
790 res = "Unknown";
791 break;
792 }
793 Result.append(res.begin(), res.end());
794 return object_error::success;
795}
796
Rafael Espindola3acea392014-06-12 21:46:39 +0000797std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000798MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000799 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000800 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000801
Rafael Espindola56f976f2013-04-18 18:08:55 +0000802 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000803
Alp Tokere69170a2014-06-26 22:52:05 +0000804 std::string fmtbuf;
805 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000806 unsigned Type = this->getAnyRelocationType(RE);
807 bool IsPCRel = this->getAnyRelocationPCRel(RE);
808
809 // Determine any addends that should be displayed with the relocation.
810 // These require decoding the relocation type, which is triple-specific.
811
812 // X86_64 has entirely custom relocation types.
813 if (Arch == Triple::x86_64) {
814 bool isPCRel = getAnyRelocationPCRel(RE);
815
816 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000817 case MachO::X86_64_RELOC_GOT_LOAD:
818 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000819 printRelocationTargetName(this, RE, fmt);
820 fmt << "@GOT";
821 if (isPCRel) fmt << "PCREL";
822 break;
823 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000824 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000825 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000826 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000827 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000828
Charles Davis8bdfafd2013-09-01 04:28:48 +0000829 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000830 // X86_64_RELOC_UNSIGNED.
831 // NOTE: Scattered relocations don't exist on x86_64.
832 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000833 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000834 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
835 "X86_64_RELOC_SUBTRACTOR.");
836
Charles Davis8bdfafd2013-09-01 04:28:48 +0000837 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
838 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000839 printRelocationTargetName(this, RENext, fmt);
840 fmt << "-";
841 printRelocationTargetName(this, RE, fmt);
842 break;
843 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000844 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000845 printRelocationTargetName(this, RE, fmt);
846 fmt << "@TLV";
847 if (isPCRel) fmt << "P";
848 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000849 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000850 printRelocationTargetName(this, RE, fmt);
851 fmt << "-1";
852 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000853 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000854 printRelocationTargetName(this, RE, fmt);
855 fmt << "-2";
856 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000857 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000858 printRelocationTargetName(this, RE, fmt);
859 fmt << "-4";
860 break;
861 default:
862 printRelocationTargetName(this, RE, fmt);
863 break;
864 }
865 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000866 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
867 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000868 // Generic relocation types...
869 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000870 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000871 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000872 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000873 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000874 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000875 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000876
877 // X86 sect diff's must be followed by a relocation of type
878 // GENERIC_RELOC_PAIR.
879 unsigned RType = getAnyRelocationType(RENext);
880
Charles Davis8bdfafd2013-09-01 04:28:48 +0000881 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000882 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
883 "GENERIC_RELOC_SECTDIFF.");
884
885 printRelocationTargetName(this, RE, fmt);
886 fmt << "-";
887 printRelocationTargetName(this, RENext, fmt);
888 break;
889 }
890 }
891
David Fangb88cdf62013-08-08 20:14:40 +0000892 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000893 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000894 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000895 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000896 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000897 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000898
899 // X86 sect diff's must be followed by a relocation of type
900 // GENERIC_RELOC_PAIR.
901 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000902 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000903 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
904 "GENERIC_RELOC_LOCAL_SECTDIFF.");
905
906 printRelocationTargetName(this, RE, fmt);
907 fmt << "-";
908 printRelocationTargetName(this, RENext, fmt);
909 break;
910 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000911 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000912 printRelocationTargetName(this, RE, fmt);
913 fmt << "@TLV";
914 if (IsPCRel) fmt << "P";
915 break;
916 }
917 default:
918 printRelocationTargetName(this, RE, fmt);
919 }
920 } else { // ARM-specific relocations
921 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000922 case MachO::ARM_RELOC_HALF:
923 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000924 // Half relocations steal a bit from the length field to encode
925 // whether this is an upper16 or a lower16 relocation.
926 bool isUpper = getAnyRelocationLength(RE) >> 1;
927
928 if (isUpper)
929 fmt << ":upper16:(";
930 else
931 fmt << ":lower16:(";
932 printRelocationTargetName(this, RE, fmt);
933
934 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000935 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000936 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000937
938 // ARM half relocs must be followed by a relocation of type
939 // ARM_RELOC_PAIR.
940 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000941 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000942 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000943 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000944
945 // NOTE: The half of the target virtual address is stashed in the
946 // address field of the secondary relocation, but we can't reverse
947 // engineer the constant offset from it without decoding the movw/movt
948 // instruction to find the other half in its immediate field.
949
950 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
951 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000952 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000953 fmt << "-";
954 printRelocationTargetName(this, RENext, fmt);
955 }
956
957 fmt << ")";
958 break;
959 }
960 default: {
961 printRelocationTargetName(this, RE, fmt);
962 }
963 }
964 }
965 } else
966 printRelocationTargetName(this, RE, fmt);
967
Alp Tokere69170a2014-06-26 22:52:05 +0000968 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000969 Result.append(fmtbuf.begin(), fmtbuf.end());
970 return object_error::success;
971}
972
Rafael Espindola3acea392014-06-12 21:46:39 +0000973std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
974 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000975 unsigned Arch = getArch();
976 uint64_t Type;
977 getRelocationType(Rel, Type);
978
979 Result = false;
980
981 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
982 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000983 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000984 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000985 } else if (Arch == Triple::x86_64) {
986 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000987 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000988 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000989 DataRefImpl RelPrev = Rel;
990 RelPrev.d.a--;
991 uint64_t PrevType;
992 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000993 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000994 Result = true;
995 }
996 }
997
998 return object_error::success;
999}
1000
Kevin Enderby980b2582014-06-05 21:21:57 +00001001//
1002// guessLibraryShortName() is passed a name of a dynamic library and returns a
1003// guess on what the short name is. Then name is returned as a substring of the
1004// StringRef Name passed in. The name of the dynamic library is recognized as
1005// a framework if it has one of the two following forms:
1006// Foo.framework/Versions/A/Foo
1007// Foo.framework/Foo
1008// Where A and Foo can be any string. And may contain a trailing suffix
1009// starting with an underbar. If the Name is recognized as a framework then
1010// isFramework is set to true else it is set to false. If the Name has a
1011// suffix then Suffix is set to the substring in Name that contains the suffix
1012// else it is set to a NULL StringRef.
1013//
1014// The Name of the dynamic library is recognized as a library name if it has
1015// one of the two following forms:
1016// libFoo.A.dylib
1017// libFoo.dylib
1018// The library may have a suffix trailing the name Foo of the form:
1019// libFoo_profile.A.dylib
1020// libFoo_profile.dylib
1021//
1022// The Name of the dynamic library is also recognized as a library name if it
1023// has the following form:
1024// Foo.qtx
1025//
1026// If the Name of the dynamic library is none of the forms above then a NULL
1027// StringRef is returned.
1028//
1029StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1030 bool &isFramework,
1031 StringRef &Suffix) {
1032 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1033 size_t a, b, c, d, Idx;
1034
1035 isFramework = false;
1036 Suffix = StringRef();
1037
1038 // Pull off the last component and make Foo point to it
1039 a = Name.rfind('/');
1040 if (a == Name.npos || a == 0)
1041 goto guess_library;
1042 Foo = Name.slice(a+1, Name.npos);
1043
1044 // Look for a suffix starting with a '_'
1045 Idx = Foo.rfind('_');
1046 if (Idx != Foo.npos && Foo.size() >= 2) {
1047 Suffix = Foo.slice(Idx, Foo.npos);
1048 Foo = Foo.slice(0, Idx);
1049 }
1050
1051 // First look for the form Foo.framework/Foo
1052 b = Name.rfind('/', a);
1053 if (b == Name.npos)
1054 Idx = 0;
1055 else
1056 Idx = b+1;
1057 F = Name.slice(Idx, Idx + Foo.size());
1058 DotFramework = Name.slice(Idx + Foo.size(),
1059 Idx + Foo.size() + sizeof(".framework/")-1);
1060 if (F == Foo && DotFramework == ".framework/") {
1061 isFramework = true;
1062 return Foo;
1063 }
1064
1065 // Next look for the form Foo.framework/Versions/A/Foo
1066 if (b == Name.npos)
1067 goto guess_library;
1068 c = Name.rfind('/', b);
1069 if (c == Name.npos || c == 0)
1070 goto guess_library;
1071 V = Name.slice(c+1, Name.npos);
1072 if (!V.startswith("Versions/"))
1073 goto guess_library;
1074 d = Name.rfind('/', c);
1075 if (d == Name.npos)
1076 Idx = 0;
1077 else
1078 Idx = d+1;
1079 F = Name.slice(Idx, Idx + Foo.size());
1080 DotFramework = Name.slice(Idx + Foo.size(),
1081 Idx + Foo.size() + sizeof(".framework/")-1);
1082 if (F == Foo && DotFramework == ".framework/") {
1083 isFramework = true;
1084 return Foo;
1085 }
1086
1087guess_library:
1088 // pull off the suffix after the "." and make a point to it
1089 a = Name.rfind('.');
1090 if (a == Name.npos || a == 0)
1091 return StringRef();
1092 Dylib = Name.slice(a, Name.npos);
1093 if (Dylib != ".dylib")
1094 goto guess_qtx;
1095
1096 // First pull off the version letter for the form Foo.A.dylib if any.
1097 if (a >= 3) {
1098 Dot = Name.slice(a-2, a-1);
1099 if (Dot == ".")
1100 a = a - 2;
1101 }
1102
1103 b = Name.rfind('/', a);
1104 if (b == Name.npos)
1105 b = 0;
1106 else
1107 b = b+1;
1108 // ignore any suffix after an underbar like Foo_profile.A.dylib
1109 Idx = Name.find('_', b);
1110 if (Idx != Name.npos && Idx != b) {
1111 Lib = Name.slice(b, Idx);
1112 Suffix = Name.slice(Idx, a);
1113 }
1114 else
1115 Lib = Name.slice(b, a);
1116 // There are incorrect library names of the form:
1117 // libATS.A_profile.dylib so check for these.
1118 if (Lib.size() >= 3) {
1119 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1120 if (Dot == ".")
1121 Lib = Lib.slice(0, Lib.size()-2);
1122 }
1123 return Lib;
1124
1125guess_qtx:
1126 Qtx = Name.slice(a, Name.npos);
1127 if (Qtx != ".qtx")
1128 return StringRef();
1129 b = Name.rfind('/', a);
1130 if (b == Name.npos)
1131 Lib = Name.slice(0, a);
1132 else
1133 Lib = Name.slice(b+1, a);
1134 // There are library names of the form: QT.A.qtx so check for these.
1135 if (Lib.size() >= 3) {
1136 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1137 if (Dot == ".")
1138 Lib = Lib.slice(0, Lib.size()-2);
1139 }
1140 return Lib;
1141}
1142
1143// getLibraryShortNameByIndex() is used to get the short name of the library
1144// for an undefined symbol in a linked Mach-O binary that was linked with the
1145// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1146// It is passed the index (0 - based) of the library as translated from
1147// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001148std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001149 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001150 if (Index >= Libraries.size())
1151 return object_error::parse_failed;
1152
Kevin Enderby980b2582014-06-05 21:21:57 +00001153 // If the cache of LibrariesShortNames is not built up do that first for
1154 // all the Libraries.
1155 if (LibrariesShortNames.size() == 0) {
1156 for (unsigned i = 0; i < Libraries.size(); i++) {
1157 MachO::dylib_command D =
1158 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001159 if (D.dylib.name >= D.cmdsize)
1160 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001161 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001162 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001163 if (D.dylib.name+Name.size() >= D.cmdsize)
1164 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001165 StringRef Suffix;
1166 bool isFramework;
1167 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001168 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001169 LibrariesShortNames.push_back(Name);
1170 else
1171 LibrariesShortNames.push_back(shortName);
1172 }
1173 }
1174
1175 Res = LibrariesShortNames[Index];
1176 return object_error::success;
1177}
1178
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001179basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001180 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001181}
1182
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001183basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001184 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001185 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001186 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001187
Charles Davis8bdfafd2013-09-01 04:28:48 +00001188 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001189 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001190 sizeof(MachO::nlist_64) :
1191 sizeof(MachO::nlist);
1192 unsigned Offset = Symtab.symoff +
1193 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001194 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001195 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001196}
1197
Lang Hames36072da2014-05-12 21:39:59 +00001198basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1199 DataRefImpl DRI;
1200 if (!SymtabLoadCmd)
1201 return basic_symbol_iterator(SymbolRef(DRI, this));
1202
1203 MachO::symtab_command Symtab = getSymtabLoadCommand();
1204 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1205 unsigned SymbolTableEntrySize =
1206 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1207 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1208 DRI.p += Index * SymbolTableEntrySize;
1209 return basic_symbol_iterator(SymbolRef(DRI, this));
1210}
1211
Rafael Espindolab5155a52014-02-10 20:24:04 +00001212section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001213 DataRefImpl DRI;
1214 return section_iterator(SectionRef(DRI, this));
1215}
1216
Rafael Espindolab5155a52014-02-10 20:24:04 +00001217section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001218 DataRefImpl DRI;
1219 DRI.d.a = Sections.size();
1220 return section_iterator(SectionRef(DRI, this));
1221}
1222
Rafael Espindola56f976f2013-04-18 18:08:55 +00001223uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001224 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001225}
1226
Rafael Espindola56f976f2013-04-18 18:08:55 +00001227StringRef MachOObjectFile::getFileFormatName() const {
1228 unsigned CPUType = getCPUType(this);
1229 if (!is64Bit()) {
1230 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001231 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001232 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001233 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001234 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001235 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001236 return "Mach-O 32-bit ppc";
1237 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001238 return "Mach-O 32-bit unknown";
1239 }
1240 }
1241
Rafael Espindola56f976f2013-04-18 18:08:55 +00001242 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001243 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001244 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001245 case llvm::MachO::CPU_TYPE_ARM64:
1246 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001247 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001248 return "Mach-O 64-bit ppc64";
1249 default:
1250 return "Mach-O 64-bit unknown";
1251 }
1252}
1253
Alexey Samsonove6388e62013-06-18 15:03:28 +00001254Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1255 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001256 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001257 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001258 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001259 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001260 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001261 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001262 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001263 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001264 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001265 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001266 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001267 return Triple::ppc64;
1268 default:
1269 return Triple::UnknownArch;
1270 }
1271}
1272
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001273Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1274 const char **McpuDefault) {
1275 if (McpuDefault)
1276 *McpuDefault = nullptr;
1277
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001278 switch (CPUType) {
1279 case MachO::CPU_TYPE_I386:
1280 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1281 case MachO::CPU_SUBTYPE_I386_ALL:
1282 return Triple("i386-apple-darwin");
1283 default:
1284 return Triple();
1285 }
1286 case MachO::CPU_TYPE_X86_64:
1287 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1288 case MachO::CPU_SUBTYPE_X86_64_ALL:
1289 return Triple("x86_64-apple-darwin");
1290 case MachO::CPU_SUBTYPE_X86_64_H:
1291 return Triple("x86_64h-apple-darwin");
1292 default:
1293 return Triple();
1294 }
1295 case MachO::CPU_TYPE_ARM:
1296 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1297 case MachO::CPU_SUBTYPE_ARM_V4T:
1298 return Triple("armv4t-apple-darwin");
1299 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1300 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001301 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1302 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001303 case MachO::CPU_SUBTYPE_ARM_V6:
1304 return Triple("armv6-apple-darwin");
1305 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001306 if (McpuDefault)
1307 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001308 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001309 case MachO::CPU_SUBTYPE_ARM_V7:
1310 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001311 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001312 if (McpuDefault)
1313 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001314 return Triple("armv7em-apple-darwin");
1315 case MachO::CPU_SUBTYPE_ARM_V7K:
1316 return Triple("armv7k-apple-darwin");
1317 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001318 if (McpuDefault)
1319 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001320 return Triple("armv7m-apple-darwin");
1321 case MachO::CPU_SUBTYPE_ARM_V7S:
1322 return Triple("armv7s-apple-darwin");
1323 default:
1324 return Triple();
1325 }
1326 case MachO::CPU_TYPE_ARM64:
1327 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1328 case MachO::CPU_SUBTYPE_ARM64_ALL:
1329 return Triple("arm64-apple-darwin");
1330 default:
1331 return Triple();
1332 }
1333 case MachO::CPU_TYPE_POWERPC:
1334 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1335 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1336 return Triple("ppc-apple-darwin");
1337 default:
1338 return Triple();
1339 }
1340 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001341 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001342 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1343 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001344 default:
1345 return Triple();
1346 }
1347 default:
1348 return Triple();
1349 }
1350}
1351
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001352Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1353 const char **McpuDefault) {
1354 if (McpuDefault)
1355 *McpuDefault = nullptr;
1356
1357 switch (CPUType) {
1358 case MachO::CPU_TYPE_ARM:
1359 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1360 case MachO::CPU_SUBTYPE_ARM_V4T:
1361 return Triple("thumbv4t-apple-darwin");
1362 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1363 return Triple("thumbv5e-apple-darwin");
1364 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1365 return Triple("xscale-apple-darwin");
1366 case MachO::CPU_SUBTYPE_ARM_V6:
1367 return Triple("thumbv6-apple-darwin");
1368 case MachO::CPU_SUBTYPE_ARM_V6M:
1369 if (McpuDefault)
1370 *McpuDefault = "cortex-m0";
1371 return Triple("thumbv6m-apple-darwin");
1372 case MachO::CPU_SUBTYPE_ARM_V7:
1373 return Triple("thumbv7-apple-darwin");
1374 case MachO::CPU_SUBTYPE_ARM_V7EM:
1375 if (McpuDefault)
1376 *McpuDefault = "cortex-m4";
1377 return Triple("thumbv7em-apple-darwin");
1378 case MachO::CPU_SUBTYPE_ARM_V7K:
1379 return Triple("thumbv7k-apple-darwin");
1380 case MachO::CPU_SUBTYPE_ARM_V7M:
1381 if (McpuDefault)
1382 *McpuDefault = "cortex-m3";
1383 return Triple("thumbv7m-apple-darwin");
1384 case MachO::CPU_SUBTYPE_ARM_V7S:
1385 return Triple("thumbv7s-apple-darwin");
1386 default:
1387 return Triple();
1388 }
1389 default:
1390 return Triple();
1391 }
1392}
1393
1394Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1395 const char **McpuDefault,
1396 Triple *ThumbTriple) {
1397 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1398 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1399 McpuDefault);
1400 return T;
1401}
1402
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001403Triple MachOObjectFile::getHostArch() {
1404 return Triple(sys::getDefaultTargetTriple());
1405}
1406
Rafael Espindola72318b42014-08-08 16:30:17 +00001407bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1408 return StringSwitch<bool>(ArchFlag)
1409 .Case("i386", true)
1410 .Case("x86_64", true)
1411 .Case("x86_64h", true)
1412 .Case("armv4t", true)
1413 .Case("arm", true)
1414 .Case("armv5e", true)
1415 .Case("armv6", true)
1416 .Case("armv6m", true)
1417 .Case("armv7em", true)
1418 .Case("armv7k", true)
1419 .Case("armv7m", true)
1420 .Case("armv7s", true)
1421 .Case("arm64", true)
1422 .Case("ppc", true)
1423 .Case("ppc64", true)
1424 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001425}
1426
Alexey Samsonove6388e62013-06-18 15:03:28 +00001427unsigned MachOObjectFile::getArch() const {
1428 return getArch(getCPUType(this));
1429}
1430
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001431Triple MachOObjectFile::getArch(const char **McpuDefault,
1432 Triple *ThumbTriple) const {
1433 Triple T;
1434 if (is64Bit()) {
1435 MachO::mach_header_64 H_64;
1436 H_64 = getHeader64();
1437 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1438 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1439 McpuDefault);
1440 } else {
1441 MachO::mach_header H;
1442 H = getHeader();
1443 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1444 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1445 McpuDefault);
1446 }
1447 return T;
1448}
1449
Rui Ueyamabc654b12013-09-27 21:47:05 +00001450relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001451 DataRefImpl DRI;
1452 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001453 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001454}
1455
Rui Ueyamabc654b12013-09-27 21:47:05 +00001456relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001457 DataRefImpl DRI;
1458 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001459 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001460}
1461
Kevin Enderby273ae012013-06-06 17:20:50 +00001462dice_iterator MachOObjectFile::begin_dices() const {
1463 DataRefImpl DRI;
1464 if (!DataInCodeLoadCmd)
1465 return dice_iterator(DiceRef(DRI, this));
1466
Charles Davis8bdfafd2013-09-01 04:28:48 +00001467 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1468 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001469 return dice_iterator(DiceRef(DRI, this));
1470}
1471
1472dice_iterator MachOObjectFile::end_dices() const {
1473 DataRefImpl DRI;
1474 if (!DataInCodeLoadCmd)
1475 return dice_iterator(DiceRef(DRI, this));
1476
Charles Davis8bdfafd2013-09-01 04:28:48 +00001477 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1478 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001479 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1480 return dice_iterator(DiceRef(DRI, this));
1481}
1482
Nick Kledzikd04bc352014-08-30 00:20:14 +00001483ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1484 : Trie(T), Malformed(false), Done(false) { }
1485
1486void ExportEntry::moveToFirst() {
1487 pushNode(0);
1488 pushDownUntilBottom();
1489}
1490
1491void ExportEntry::moveToEnd() {
1492 Stack.clear();
1493 Done = true;
1494}
1495
1496bool ExportEntry::operator==(const ExportEntry &Other) const {
1497 // Common case, one at end, other iterating from begin.
1498 if (Done || Other.Done)
1499 return (Done == Other.Done);
1500 // Not equal if different stack sizes.
1501 if (Stack.size() != Other.Stack.size())
1502 return false;
1503 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001504 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001505 return false;
1506 // Equal if all nodes in both stacks match.
1507 for (unsigned i=0; i < Stack.size(); ++i) {
1508 if (Stack[i].Start != Other.Stack[i].Start)
1509 return false;
1510 }
1511 return true;
1512}
1513
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001514uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1515 unsigned Count;
1516 uint64_t Result = decodeULEB128(Ptr, &Count);
1517 Ptr += Count;
1518 if (Ptr > Trie.end()) {
1519 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001520 Malformed = true;
1521 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001522 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001523}
1524
1525StringRef ExportEntry::name() const {
1526 return CumulativeString.str();
1527}
1528
1529uint64_t ExportEntry::flags() const {
1530 return Stack.back().Flags;
1531}
1532
1533uint64_t ExportEntry::address() const {
1534 return Stack.back().Address;
1535}
1536
1537uint64_t ExportEntry::other() const {
1538 return Stack.back().Other;
1539}
1540
1541StringRef ExportEntry::otherName() const {
1542 const char* ImportName = Stack.back().ImportName;
1543 if (ImportName)
1544 return StringRef(ImportName);
1545 return StringRef();
1546}
1547
1548uint32_t ExportEntry::nodeOffset() const {
1549 return Stack.back().Start - Trie.begin();
1550}
1551
1552ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1553 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1554 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1555 ParentStringLength(0), IsExportNode(false) {
1556}
1557
1558void ExportEntry::pushNode(uint64_t offset) {
1559 const uint8_t *Ptr = Trie.begin() + offset;
1560 NodeState State(Ptr);
1561 uint64_t ExportInfoSize = readULEB128(State.Current);
1562 State.IsExportNode = (ExportInfoSize != 0);
1563 const uint8_t* Children = State.Current + ExportInfoSize;
1564 if (State.IsExportNode) {
1565 State.Flags = readULEB128(State.Current);
1566 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1567 State.Address = 0;
1568 State.Other = readULEB128(State.Current); // dylib ordinal
1569 State.ImportName = reinterpret_cast<const char*>(State.Current);
1570 } else {
1571 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001572 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1573 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001574 }
1575 }
1576 State.ChildCount = *Children;
1577 State.Current = Children + 1;
1578 State.NextChildIndex = 0;
1579 State.ParentStringLength = CumulativeString.size();
1580 Stack.push_back(State);
1581}
1582
1583void ExportEntry::pushDownUntilBottom() {
1584 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1585 NodeState &Top = Stack.back();
1586 CumulativeString.resize(Top.ParentStringLength);
1587 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001588 char C = *Top.Current;
1589 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001590 }
1591 Top.Current += 1;
1592 uint64_t childNodeIndex = readULEB128(Top.Current);
1593 Top.NextChildIndex += 1;
1594 pushNode(childNodeIndex);
1595 }
1596 if (!Stack.back().IsExportNode) {
1597 Malformed = true;
1598 moveToEnd();
1599 }
1600}
1601
1602// We have a trie data structure and need a way to walk it that is compatible
1603// with the C++ iterator model. The solution is a non-recursive depth first
1604// traversal where the iterator contains a stack of parent nodes along with a
1605// string that is the accumulation of all edge strings along the parent chain
1606// to this point.
1607//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001608// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001609// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1610// node may have child nodes too.
1611//
1612// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1613// child until hitting a node with no children (which is an export node or
1614// else the trie is malformed). On the way down, each node is pushed on the
1615// stack ivar. If there is no more ways down, it pops up one and tries to go
1616// down a sibling path until a childless node is reached.
1617void ExportEntry::moveNext() {
1618 if (Stack.empty() || !Stack.back().IsExportNode) {
1619 Malformed = true;
1620 moveToEnd();
1621 return;
1622 }
1623
1624 Stack.pop_back();
1625 while (!Stack.empty()) {
1626 NodeState &Top = Stack.back();
1627 if (Top.NextChildIndex < Top.ChildCount) {
1628 pushDownUntilBottom();
1629 // Now at the next export node.
1630 return;
1631 } else {
1632 if (Top.IsExportNode) {
1633 // This node has no children but is itself an export node.
1634 CumulativeString.resize(Top.ParentStringLength);
1635 return;
1636 }
1637 Stack.pop_back();
1638 }
1639 }
1640 Done = true;
1641}
1642
1643iterator_range<export_iterator>
1644MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1645 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001646 if (Trie.size() == 0)
1647 Start.moveToEnd();
1648 else
1649 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001650
1651 ExportEntry Finish(Trie);
1652 Finish.moveToEnd();
1653
1654 return iterator_range<export_iterator>(export_iterator(Start),
1655 export_iterator(Finish));
1656}
1657
1658iterator_range<export_iterator> MachOObjectFile::exports() const {
1659 return exports(getDyldInfoExportsTrie());
1660}
1661
1662
Nick Kledzikac431442014-09-12 21:34:15 +00001663MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1664 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1665 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1666 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1667
1668void MachORebaseEntry::moveToFirst() {
1669 Ptr = Opcodes.begin();
1670 moveNext();
1671}
1672
1673void MachORebaseEntry::moveToEnd() {
1674 Ptr = Opcodes.end();
1675 RemainingLoopCount = 0;
1676 Done = true;
1677}
1678
1679void MachORebaseEntry::moveNext() {
1680 // If in the middle of some loop, move to next rebasing in loop.
1681 SegmentOffset += AdvanceAmount;
1682 if (RemainingLoopCount) {
1683 --RemainingLoopCount;
1684 return;
1685 }
1686 if (Ptr == Opcodes.end()) {
1687 Done = true;
1688 return;
1689 }
1690 bool More = true;
1691 while (More && !Malformed) {
1692 // Parse next opcode and set up next loop.
1693 uint8_t Byte = *Ptr++;
1694 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1695 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1696 switch (Opcode) {
1697 case MachO::REBASE_OPCODE_DONE:
1698 More = false;
1699 Done = true;
1700 moveToEnd();
1701 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1702 break;
1703 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1704 RebaseType = ImmValue;
1705 DEBUG_WITH_TYPE(
1706 "mach-o-rebase",
1707 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1708 << "RebaseType=" << (int) RebaseType << "\n");
1709 break;
1710 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1711 SegmentIndex = ImmValue;
1712 SegmentOffset = readULEB128();
1713 DEBUG_WITH_TYPE(
1714 "mach-o-rebase",
1715 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1716 << "SegmentIndex=" << SegmentIndex << ", "
1717 << format("SegmentOffset=0x%06X", SegmentOffset)
1718 << "\n");
1719 break;
1720 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1721 SegmentOffset += readULEB128();
1722 DEBUG_WITH_TYPE("mach-o-rebase",
1723 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1724 << format("SegmentOffset=0x%06X",
1725 SegmentOffset) << "\n");
1726 break;
1727 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1728 SegmentOffset += ImmValue * PointerSize;
1729 DEBUG_WITH_TYPE("mach-o-rebase",
1730 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1731 << format("SegmentOffset=0x%06X",
1732 SegmentOffset) << "\n");
1733 break;
1734 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1735 AdvanceAmount = PointerSize;
1736 RemainingLoopCount = ImmValue - 1;
1737 DEBUG_WITH_TYPE(
1738 "mach-o-rebase",
1739 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1740 << format("SegmentOffset=0x%06X", SegmentOffset)
1741 << ", AdvanceAmount=" << AdvanceAmount
1742 << ", RemainingLoopCount=" << RemainingLoopCount
1743 << "\n");
1744 return;
1745 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1746 AdvanceAmount = PointerSize;
1747 RemainingLoopCount = readULEB128() - 1;
1748 DEBUG_WITH_TYPE(
1749 "mach-o-rebase",
1750 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1751 << format("SegmentOffset=0x%06X", SegmentOffset)
1752 << ", AdvanceAmount=" << AdvanceAmount
1753 << ", RemainingLoopCount=" << RemainingLoopCount
1754 << "\n");
1755 return;
1756 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1757 AdvanceAmount = readULEB128() + PointerSize;
1758 RemainingLoopCount = 0;
1759 DEBUG_WITH_TYPE(
1760 "mach-o-rebase",
1761 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1762 << format("SegmentOffset=0x%06X", SegmentOffset)
1763 << ", AdvanceAmount=" << AdvanceAmount
1764 << ", RemainingLoopCount=" << RemainingLoopCount
1765 << "\n");
1766 return;
1767 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1768 RemainingLoopCount = readULEB128() - 1;
1769 AdvanceAmount = readULEB128() + PointerSize;
1770 DEBUG_WITH_TYPE(
1771 "mach-o-rebase",
1772 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1773 << format("SegmentOffset=0x%06X", SegmentOffset)
1774 << ", AdvanceAmount=" << AdvanceAmount
1775 << ", RemainingLoopCount=" << RemainingLoopCount
1776 << "\n");
1777 return;
1778 default:
1779 Malformed = true;
1780 }
1781 }
1782}
1783
1784uint64_t MachORebaseEntry::readULEB128() {
1785 unsigned Count;
1786 uint64_t Result = decodeULEB128(Ptr, &Count);
1787 Ptr += Count;
1788 if (Ptr > Opcodes.end()) {
1789 Ptr = Opcodes.end();
1790 Malformed = true;
1791 }
1792 return Result;
1793}
1794
1795uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1796
1797uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1798
1799StringRef MachORebaseEntry::typeName() const {
1800 switch (RebaseType) {
1801 case MachO::REBASE_TYPE_POINTER:
1802 return "pointer";
1803 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1804 return "text abs32";
1805 case MachO::REBASE_TYPE_TEXT_PCREL32:
1806 return "text rel32";
1807 }
1808 return "unknown";
1809}
1810
1811bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1812 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1813 return (Ptr == Other.Ptr) &&
1814 (RemainingLoopCount == Other.RemainingLoopCount) &&
1815 (Done == Other.Done);
1816}
1817
1818iterator_range<rebase_iterator>
1819MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1820 MachORebaseEntry Start(Opcodes, is64);
1821 Start.moveToFirst();
1822
1823 MachORebaseEntry Finish(Opcodes, is64);
1824 Finish.moveToEnd();
1825
1826 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1827 rebase_iterator(Finish));
1828}
1829
1830iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1831 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1832}
1833
Nick Kledzik56ebef42014-09-16 01:41:51 +00001834
1835MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1836 Kind BK)
1837 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1838 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1839 BindType(0), PointerSize(is64Bit ? 8 : 4),
1840 TableKind(BK), Malformed(false), Done(false) {}
1841
1842void MachOBindEntry::moveToFirst() {
1843 Ptr = Opcodes.begin();
1844 moveNext();
1845}
1846
1847void MachOBindEntry::moveToEnd() {
1848 Ptr = Opcodes.end();
1849 RemainingLoopCount = 0;
1850 Done = true;
1851}
1852
1853void MachOBindEntry::moveNext() {
1854 // If in the middle of some loop, move to next binding in loop.
1855 SegmentOffset += AdvanceAmount;
1856 if (RemainingLoopCount) {
1857 --RemainingLoopCount;
1858 return;
1859 }
1860 if (Ptr == Opcodes.end()) {
1861 Done = true;
1862 return;
1863 }
1864 bool More = true;
1865 while (More && !Malformed) {
1866 // Parse next opcode and set up next loop.
1867 uint8_t Byte = *Ptr++;
1868 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1869 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1870 int8_t SignExtended;
1871 const uint8_t *SymStart;
1872 switch (Opcode) {
1873 case MachO::BIND_OPCODE_DONE:
1874 if (TableKind == Kind::Lazy) {
1875 // Lazying bindings have a DONE opcode between entries. Need to ignore
1876 // it to advance to next entry. But need not if this is last entry.
1877 bool NotLastEntry = false;
1878 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1879 if (*P) {
1880 NotLastEntry = true;
1881 }
1882 }
1883 if (NotLastEntry)
1884 break;
1885 }
1886 More = false;
1887 Done = true;
1888 moveToEnd();
1889 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1890 break;
1891 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1892 Ordinal = ImmValue;
1893 DEBUG_WITH_TYPE(
1894 "mach-o-bind",
1895 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1896 << "Ordinal=" << Ordinal << "\n");
1897 break;
1898 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1899 Ordinal = readULEB128();
1900 DEBUG_WITH_TYPE(
1901 "mach-o-bind",
1902 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1903 << "Ordinal=" << Ordinal << "\n");
1904 break;
1905 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1906 if (ImmValue) {
1907 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1908 Ordinal = SignExtended;
1909 } else
1910 Ordinal = 0;
1911 DEBUG_WITH_TYPE(
1912 "mach-o-bind",
1913 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1914 << "Ordinal=" << Ordinal << "\n");
1915 break;
1916 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1917 Flags = ImmValue;
1918 SymStart = Ptr;
1919 while (*Ptr) {
1920 ++Ptr;
1921 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001922 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1923 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001924 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001925 DEBUG_WITH_TYPE(
1926 "mach-o-bind",
1927 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1928 << "SymbolName=" << SymbolName << "\n");
1929 if (TableKind == Kind::Weak) {
1930 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1931 return;
1932 }
1933 break;
1934 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1935 BindType = ImmValue;
1936 DEBUG_WITH_TYPE(
1937 "mach-o-bind",
1938 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1939 << "BindType=" << (int)BindType << "\n");
1940 break;
1941 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1942 Addend = readSLEB128();
1943 if (TableKind == Kind::Lazy)
1944 Malformed = true;
1945 DEBUG_WITH_TYPE(
1946 "mach-o-bind",
1947 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1948 << "Addend=" << Addend << "\n");
1949 break;
1950 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1951 SegmentIndex = ImmValue;
1952 SegmentOffset = readULEB128();
1953 DEBUG_WITH_TYPE(
1954 "mach-o-bind",
1955 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1956 << "SegmentIndex=" << SegmentIndex << ", "
1957 << format("SegmentOffset=0x%06X", SegmentOffset)
1958 << "\n");
1959 break;
1960 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1961 SegmentOffset += readULEB128();
1962 DEBUG_WITH_TYPE("mach-o-bind",
1963 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1964 << format("SegmentOffset=0x%06X",
1965 SegmentOffset) << "\n");
1966 break;
1967 case MachO::BIND_OPCODE_DO_BIND:
1968 AdvanceAmount = PointerSize;
1969 RemainingLoopCount = 0;
1970 DEBUG_WITH_TYPE("mach-o-bind",
1971 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1972 << format("SegmentOffset=0x%06X",
1973 SegmentOffset) << "\n");
1974 return;
1975 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001976 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001977 RemainingLoopCount = 0;
1978 if (TableKind == Kind::Lazy)
1979 Malformed = true;
1980 DEBUG_WITH_TYPE(
1981 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001982 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001983 << format("SegmentOffset=0x%06X", SegmentOffset)
1984 << ", AdvanceAmount=" << AdvanceAmount
1985 << ", RemainingLoopCount=" << RemainingLoopCount
1986 << "\n");
1987 return;
1988 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001989 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001990 RemainingLoopCount = 0;
1991 if (TableKind == Kind::Lazy)
1992 Malformed = true;
1993 DEBUG_WITH_TYPE("mach-o-bind",
1994 llvm::dbgs()
1995 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1996 << format("SegmentOffset=0x%06X",
1997 SegmentOffset) << "\n");
1998 return;
1999 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2000 RemainingLoopCount = readULEB128() - 1;
2001 AdvanceAmount = readULEB128() + PointerSize;
2002 if (TableKind == Kind::Lazy)
2003 Malformed = true;
2004 DEBUG_WITH_TYPE(
2005 "mach-o-bind",
2006 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2007 << format("SegmentOffset=0x%06X", SegmentOffset)
2008 << ", AdvanceAmount=" << AdvanceAmount
2009 << ", RemainingLoopCount=" << RemainingLoopCount
2010 << "\n");
2011 return;
2012 default:
2013 Malformed = true;
2014 }
2015 }
2016}
2017
2018uint64_t MachOBindEntry::readULEB128() {
2019 unsigned Count;
2020 uint64_t Result = decodeULEB128(Ptr, &Count);
2021 Ptr += Count;
2022 if (Ptr > Opcodes.end()) {
2023 Ptr = Opcodes.end();
2024 Malformed = true;
2025 }
2026 return Result;
2027}
2028
2029int64_t MachOBindEntry::readSLEB128() {
2030 unsigned Count;
2031 int64_t Result = decodeSLEB128(Ptr, &Count);
2032 Ptr += Count;
2033 if (Ptr > Opcodes.end()) {
2034 Ptr = Opcodes.end();
2035 Malformed = true;
2036 }
2037 return Result;
2038}
2039
2040
2041uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2042
2043uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2044
2045StringRef MachOBindEntry::typeName() const {
2046 switch (BindType) {
2047 case MachO::BIND_TYPE_POINTER:
2048 return "pointer";
2049 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2050 return "text abs32";
2051 case MachO::BIND_TYPE_TEXT_PCREL32:
2052 return "text rel32";
2053 }
2054 return "unknown";
2055}
2056
2057StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2058
2059int64_t MachOBindEntry::addend() const { return Addend; }
2060
2061uint32_t MachOBindEntry::flags() const { return Flags; }
2062
2063int MachOBindEntry::ordinal() const { return Ordinal; }
2064
2065bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2066 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2067 return (Ptr == Other.Ptr) &&
2068 (RemainingLoopCount == Other.RemainingLoopCount) &&
2069 (Done == Other.Done);
2070}
2071
2072iterator_range<bind_iterator>
2073MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2074 MachOBindEntry::Kind BKind) {
2075 MachOBindEntry Start(Opcodes, is64, BKind);
2076 Start.moveToFirst();
2077
2078 MachOBindEntry Finish(Opcodes, is64, BKind);
2079 Finish.moveToEnd();
2080
2081 return iterator_range<bind_iterator>(bind_iterator(Start),
2082 bind_iterator(Finish));
2083}
2084
2085iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2086 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2087 MachOBindEntry::Kind::Regular);
2088}
2089
2090iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2091 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2092 MachOBindEntry::Kind::Lazy);
2093}
2094
2095iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2096 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2097 MachOBindEntry::Kind::Weak);
2098}
2099
Rafael Espindola56f976f2013-04-18 18:08:55 +00002100StringRef
2101MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2102 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2103 return parseSegmentOrSectionName(Raw.data());
2104}
2105
2106ArrayRef<char>
2107MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002108 const section_base *Base =
2109 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002110 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002111}
2112
2113ArrayRef<char>
2114MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002115 const section_base *Base =
2116 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002117 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002118}
2119
2120bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002121MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002122 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002123 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002124 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002125 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002126}
2127
Eric Christopher1d62c252013-07-22 22:25:07 +00002128unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002129 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002130 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002131 return RE.r_word1 & 0xffffff;
2132 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002133}
2134
Eric Christopher1d62c252013-07-22 22:25:07 +00002135bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002136 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002137 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002138 return (RE.r_word1 >> 27) & 1;
2139 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002140}
2141
Eric Christopher1d62c252013-07-22 22:25:07 +00002142bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002143 const MachO::any_relocation_info &RE) const {
2144 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002145}
2146
Eric Christopher1d62c252013-07-22 22:25:07 +00002147uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002148 const MachO::any_relocation_info &RE) const {
2149 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002150}
2151
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002152uint32_t MachOObjectFile::getScatteredRelocationType(
2153 const MachO::any_relocation_info &RE) const {
2154 return (RE.r_word0 >> 24) & 0xf;
2155}
2156
Eric Christopher1d62c252013-07-22 22:25:07 +00002157unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002158 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002159 if (isRelocationScattered(RE))
2160 return getScatteredRelocationAddress(RE);
2161 return getPlainRelocationAddress(RE);
2162}
2163
Charles Davis8bdfafd2013-09-01 04:28:48 +00002164unsigned MachOObjectFile::getAnyRelocationPCRel(
2165 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002166 if (isRelocationScattered(RE))
2167 return getScatteredRelocationPCRel(this, RE);
2168 return getPlainRelocationPCRel(this, RE);
2169}
2170
Eric Christopher1d62c252013-07-22 22:25:07 +00002171unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002172 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002173 if (isRelocationScattered(RE))
2174 return getScatteredRelocationLength(RE);
2175 return getPlainRelocationLength(this, RE);
2176}
2177
2178unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002179MachOObjectFile::getAnyRelocationType(
2180 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002181 if (isRelocationScattered(RE))
2182 return getScatteredRelocationType(RE);
2183 return getPlainRelocationType(this, RE);
2184}
2185
Rafael Espindola52501032013-04-30 15:40:54 +00002186SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00002187MachOObjectFile::getRelocationSection(
2188 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002189 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002190 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002191 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2192 DataRefImpl DRI;
2193 DRI.d.a = SecNum;
2194 return SectionRef(DRI, this);
2195}
2196
Rafael Espindola56f976f2013-04-18 18:08:55 +00002197MachOObjectFile::LoadCommandInfo
2198MachOObjectFile::getFirstLoadCommandInfo() const {
2199 MachOObjectFile::LoadCommandInfo Load;
2200
Charles Davis8bdfafd2013-09-01 04:28:48 +00002201 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2202 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002203 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002204 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002205 return Load;
2206}
2207
2208MachOObjectFile::LoadCommandInfo
2209MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2210 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002211 Next.Ptr = L.Ptr + L.C.cmdsize;
2212 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002213 return Next;
2214}
2215
Charles Davis8bdfafd2013-09-01 04:28:48 +00002216MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2217 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002218}
2219
Charles Davis8bdfafd2013-09-01 04:28:48 +00002220MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2221 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002222}
2223
Charles Davis8bdfafd2013-09-01 04:28:48 +00002224MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002225 unsigned Index) const {
2226 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002227 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002228}
2229
Charles Davis8bdfafd2013-09-01 04:28:48 +00002230MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2231 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002232 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002233 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002234}
2235
Charles Davis8bdfafd2013-09-01 04:28:48 +00002236MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002237MachOObjectFile::getSymbolTableEntry(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>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002240}
2241
Charles Davis8bdfafd2013-09-01 04:28:48 +00002242MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002243MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002244 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002245 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002246}
2247
Charles Davis8bdfafd2013-09-01 04:28:48 +00002248MachO::linkedit_data_command
2249MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2250 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002251}
2252
Charles Davis8bdfafd2013-09-01 04:28:48 +00002253MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002254MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002255 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002256}
2257
Charles Davis8bdfafd2013-09-01 04:28:48 +00002258MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002259MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002260 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002261}
2262
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002263MachO::linker_option_command
2264MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2265 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002266}
2267
Jim Grosbach448334a2014-03-18 22:09:05 +00002268MachO::version_min_command
2269MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2270 return getStruct<MachO::version_min_command>(this, L.Ptr);
2271}
2272
Tim Northover8f9590b2014-06-30 14:40:57 +00002273MachO::dylib_command
2274MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2275 return getStruct<MachO::dylib_command>(this, L.Ptr);
2276}
2277
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002278MachO::dyld_info_command
2279MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2280 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2281}
2282
2283MachO::dylinker_command
2284MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2285 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2286}
2287
2288MachO::uuid_command
2289MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2290 return getStruct<MachO::uuid_command>(this, L.Ptr);
2291}
2292
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002293MachO::rpath_command
2294MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2295 return getStruct<MachO::rpath_command>(this, L.Ptr);
2296}
2297
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002298MachO::source_version_command
2299MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2300 return getStruct<MachO::source_version_command>(this, L.Ptr);
2301}
2302
2303MachO::entry_point_command
2304MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2305 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2306}
2307
Kevin Enderby0804f4672014-12-16 23:25:52 +00002308MachO::encryption_info_command
2309MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2310 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2311}
2312
Kevin Enderby57538292014-12-17 01:01:30 +00002313MachO::encryption_info_command_64
2314MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2315 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2316}
2317
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002318MachO::sub_framework_command
2319MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2320 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2321}
Tim Northover8f9590b2014-06-30 14:40:57 +00002322
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002323MachO::sub_umbrella_command
2324MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2325 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2326}
2327
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002328MachO::sub_library_command
2329MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2330 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2331}
2332
Kevin Enderby186eac32014-12-19 21:06:24 +00002333MachO::sub_client_command
2334MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2335 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2336}
2337
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002338MachO::routines_command
2339MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2340 return getStruct<MachO::routines_command>(this, L.Ptr);
2341}
2342
2343MachO::routines_command_64
2344MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2345 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2346}
2347
Kevin Enderby48ef5342014-12-23 22:56:39 +00002348MachO::thread_command
2349MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2350 return getStruct<MachO::thread_command>(this, L.Ptr);
2351}
2352
Charles Davis8bdfafd2013-09-01 04:28:48 +00002353MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002354MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002355 DataRefImpl Sec;
2356 Sec.d.a = Rel.d.a;
2357 uint32_t Offset;
2358 if (is64Bit()) {
2359 MachO::section_64 Sect = getSection64(Sec);
2360 Offset = Sect.reloff;
2361 } else {
2362 MachO::section Sect = getSection(Sec);
2363 Offset = Sect.reloff;
2364 }
2365
2366 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2367 getPtr(this, Offset)) + Rel.d.b;
2368 return getStruct<MachO::any_relocation_info>(
2369 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002370}
2371
Charles Davis8bdfafd2013-09-01 04:28:48 +00002372MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002373MachOObjectFile::getDice(DataRefImpl Rel) const {
2374 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002375 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002376}
2377
Charles Davis8bdfafd2013-09-01 04:28:48 +00002378MachO::mach_header MachOObjectFile::getHeader() const {
2379 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002380}
2381
Charles Davis8bdfafd2013-09-01 04:28:48 +00002382MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2383 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002384}
2385
Charles Davis8bdfafd2013-09-01 04:28:48 +00002386uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2387 const MachO::dysymtab_command &DLC,
2388 unsigned Index) const {
2389 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2390 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002391}
2392
Charles Davis8bdfafd2013-09-01 04:28:48 +00002393MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002394MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2395 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002396 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2397 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002398}
2399
Charles Davis8bdfafd2013-09-01 04:28:48 +00002400MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002401 if (SymtabLoadCmd)
2402 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2403
2404 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2405 MachO::symtab_command Cmd;
2406 Cmd.cmd = MachO::LC_SYMTAB;
2407 Cmd.cmdsize = sizeof(MachO::symtab_command);
2408 Cmd.symoff = 0;
2409 Cmd.nsyms = 0;
2410 Cmd.stroff = 0;
2411 Cmd.strsize = 0;
2412 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002413}
2414
Charles Davis8bdfafd2013-09-01 04:28:48 +00002415MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002416 if (DysymtabLoadCmd)
2417 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2418
2419 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2420 MachO::dysymtab_command Cmd;
2421 Cmd.cmd = MachO::LC_DYSYMTAB;
2422 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2423 Cmd.ilocalsym = 0;
2424 Cmd.nlocalsym = 0;
2425 Cmd.iextdefsym = 0;
2426 Cmd.nextdefsym = 0;
2427 Cmd.iundefsym = 0;
2428 Cmd.nundefsym = 0;
2429 Cmd.tocoff = 0;
2430 Cmd.ntoc = 0;
2431 Cmd.modtaboff = 0;
2432 Cmd.nmodtab = 0;
2433 Cmd.extrefsymoff = 0;
2434 Cmd.nextrefsyms = 0;
2435 Cmd.indirectsymoff = 0;
2436 Cmd.nindirectsyms = 0;
2437 Cmd.extreloff = 0;
2438 Cmd.nextrel = 0;
2439 Cmd.locreloff = 0;
2440 Cmd.nlocrel = 0;
2441 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002442}
2443
Charles Davis8bdfafd2013-09-01 04:28:48 +00002444MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002445MachOObjectFile::getDataInCodeLoadCommand() const {
2446 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002447 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002448
2449 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002450 MachO::linkedit_data_command Cmd;
2451 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2452 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2453 Cmd.dataoff = 0;
2454 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002455 return Cmd;
2456}
2457
Nick Kledzikd04bc352014-08-30 00:20:14 +00002458ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2459 if (!DyldInfoLoadCmd)
2460 return ArrayRef<uint8_t>();
2461
2462 MachO::dyld_info_command DyldInfo
2463 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2464 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2465 getPtr(this, DyldInfo.rebase_off));
2466 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2467}
2468
2469ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2470 if (!DyldInfoLoadCmd)
2471 return ArrayRef<uint8_t>();
2472
2473 MachO::dyld_info_command DyldInfo
2474 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2475 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2476 getPtr(this, DyldInfo.bind_off));
2477 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2478}
2479
2480ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2481 if (!DyldInfoLoadCmd)
2482 return ArrayRef<uint8_t>();
2483
2484 MachO::dyld_info_command DyldInfo
2485 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2486 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2487 getPtr(this, DyldInfo.weak_bind_off));
2488 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2489}
2490
2491ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2492 if (!DyldInfoLoadCmd)
2493 return ArrayRef<uint8_t>();
2494
2495 MachO::dyld_info_command DyldInfo
2496 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2497 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2498 getPtr(this, DyldInfo.lazy_bind_off));
2499 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2500}
2501
2502ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2503 if (!DyldInfoLoadCmd)
2504 return ArrayRef<uint8_t>();
2505
2506 MachO::dyld_info_command DyldInfo
2507 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2508 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2509 getPtr(this, DyldInfo.export_off));
2510 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2511}
2512
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002513ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2514 if (!UuidLoadCmd)
2515 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002516 // Returning a pointer is fine as uuid doesn't need endian swapping.
2517 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2518 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002519}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002520
Rafael Espindola6e040c02013-04-26 20:07:33 +00002521StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002522 MachO::symtab_command S = getSymtabLoadCommand();
2523 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002524}
2525
Rafael Espindola56f976f2013-04-18 18:08:55 +00002526bool MachOObjectFile::is64Bit() const {
2527 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002528 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002529}
2530
2531void MachOObjectFile::ReadULEB128s(uint64_t Index,
2532 SmallVectorImpl<uint64_t> &Out) const {
2533 DataExtractor extractor(ObjectFile::getData(), true, 0);
2534
2535 uint32_t offset = Index;
2536 uint64_t data = 0;
2537 while (uint64_t delta = extractor.getULEB128(&offset)) {
2538 data += delta;
2539 Out.push_back(data);
2540 }
2541}
2542
Rafael Espindolac66d7612014-08-17 19:09:37 +00002543bool MachOObjectFile::isRelocatableObject() const {
2544 return getHeader().filetype == MachO::MH_OBJECT;
2545}
2546
Rafael Espindola437b0d52014-07-31 03:12:45 +00002547ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002548ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2549 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002550 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002551 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002552 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002553 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002554 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002555 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002556 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002557 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002558 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002559 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002560 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002561 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002562
Rafael Espindola692410e2014-01-21 23:06:54 +00002563 if (EC)
2564 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002565 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002566}
2567