blob: 4f544074c3df8401a2a7dc1be3868256c5b785df [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
Filipe Cabecinhas40139502015-01-15 22:52:38 +000041template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000042static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000043 // Don't read before the beginning or past the end of the file
44 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
45 report_fatal_error("Malformed MachO file.");
46
Rafael Espindola3cdeb172013-04-19 13:45:05 +000047 T Cmd;
48 memcpy(&Cmd, P, sizeof(T));
49 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000050 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000051 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000052}
53
Filipe Cabecinhas40139502015-01-15 22:52:38 +000054template <typename SegmentCmd>
55static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
56 uint32_t Cmdsize) {
57 const unsigned SectionSize = sizeof(SegmentCmd);
58 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
59 S.nsects * SectionSize > Cmdsize - sizeof(S))
60 report_fatal_error(
61 "Number of sections too large for size of load command.");
62 return S.nsects;
63}
64
Rafael Espindola56f976f2013-04-18 18:08:55 +000065static uint32_t
66getSegmentLoadCommandNumSections(const MachOObjectFile *O,
67 const MachOObjectFile::LoadCommandInfo &L) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000068 if (O->is64Bit())
69 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
70 L.C.cmdsize);
71
72 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
73 L.C.cmdsize);
Rafael Espindola5ffc0792013-04-07 16:07:35 +000074}
75
Nick Kledzik56ebef42014-09-16 01:41:51 +000076static bool isPageZeroSegment(const MachOObjectFile *O,
77 const MachOObjectFile::LoadCommandInfo &L) {
78 if (O->is64Bit()) {
79 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
80 return StringRef("__PAGEZERO").equals(S.segname);
81 }
82 MachO::segment_command S = O->getSegmentLoadCommand(L);
83 return StringRef("__PAGEZERO").equals(S.segname);
84}
85
86
Rafael Espindola6e040c02013-04-26 20:07:33 +000087static const char *
88getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
89 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000090 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
91
92 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000093 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
94 sizeof(MachO::segment_command);
95 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
96 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000097
98 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000099 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +0000100}
101
Rafael Espindola56f976f2013-04-18 18:08:55 +0000102static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
103 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000104}
105
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000106static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +0000107getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000108 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000109 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000110}
111
Rafael Espindola56f976f2013-04-18 18:08:55 +0000112static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000113 if (P[15] == 0)
114 // Null terminated.
115 return P;
116 // Not null terminated, so this is a 16 char string.
117 return StringRef(P, 16);
118}
119
Rafael Espindola56f976f2013-04-18 18:08:55 +0000120// Helper to advance a section or symbol iterator multiple increments at a time.
121template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000122static void advance(T &it, size_t Val) {
123 while (Val--)
124 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000125}
126
127static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000128 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000129}
130
131static void printRelocationTargetName(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000132 const MachO::any_relocation_info &RE,
Alp Tokere69170a2014-06-26 22:52:05 +0000133 raw_string_ostream &fmt) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134 bool IsScattered = O->isRelocationScattered(RE);
135
136 // Target of a scattered relocation is an address. In the interest of
137 // generating pretty output, scan through the symbol table looking for a
138 // symbol that aligns with that address. If we find one, print it.
139 // Otherwise, we just print the hex address of the target.
140 if (IsScattered) {
141 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
142
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000143 for (const SymbolRef &Symbol : O->symbols()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000144 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000145 uint64_t Addr;
146 StringRef Name;
147
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000148 if ((ec = Symbol.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000149 report_fatal_error(ec.message());
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000150 if (Addr != Val)
151 continue;
152 if ((ec = Symbol.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000153 report_fatal_error(ec.message());
154 fmt << Name;
155 return;
156 }
157
158 // If we couldn't find a symbol that this relocation refers to, try
159 // to find a section beginning instead.
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000160 for (const SectionRef &Section : O->sections()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000161 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000162
Rafael Espindola80291272014-10-08 15:28:58 +0000163 StringRef Name;
164 uint64_t Addr = Section.getAddress();
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000165 if (Addr != Val)
166 continue;
167 if ((ec = Section.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000168 report_fatal_error(ec.message());
169 fmt << Name;
170 return;
171 }
172
173 fmt << format("0x%x", Val);
174 return;
175 }
176
177 StringRef S;
178 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000179 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000180
181 if (isExtern) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000182 symbol_iterator SI = O->symbol_begin();
Rafael Espindola5e812af2014-01-30 02:49:50 +0000183 advance(SI, Val);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000184 SI->getName(S);
185 } else {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000186 section_iterator SI = O->section_begin();
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000187 // Adjust for the fact that sections are 1-indexed.
Rafael Espindola5e812af2014-01-30 02:49:50 +0000188 advance(SI, Val - 1);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000189 SI->getName(S);
190 }
191
192 fmt << S;
193}
194
Charles Davis8bdfafd2013-09-01 04:28:48 +0000195static uint32_t
196getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
197 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000198}
199
200static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000201getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
202 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000203}
204
205static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000206 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000207 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000208 return (RE.r_word1 >> 24) & 1;
209 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000210}
211
212static bool
213getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000214 const MachO::any_relocation_info &RE) {
215 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000216}
217
218static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000219 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000220 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000221 return (RE.r_word1 >> 25) & 3;
222 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000223}
224
225static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000226getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
227 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000228}
229
230static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000231 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000232 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000233 return RE.r_word1 >> 28;
234 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000235}
236
Rafael Espindola56f976f2013-04-18 18:08:55 +0000237static uint32_t getSectionFlags(const MachOObjectFile *O,
238 DataRefImpl Sec) {
239 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000240 MachO::section_64 Sect = O->getSection64(Sec);
241 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000242 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000243 MachO::section Sect = O->getSection(Sec);
244 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000245}
246
Rafael Espindola48af1c22014-08-19 18:44:46 +0000247MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
248 bool Is64bits, std::error_code &EC)
249 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000250 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Nick Kledzik56ebef42014-09-16 01:41:51 +0000251 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000252 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000253 uint32_t LoadCommandCount = this->getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000254 if (LoadCommandCount == 0)
255 return;
256
Charles Davis8bdfafd2013-09-01 04:28:48 +0000257 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
258 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000259
260 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000261 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000262 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000263 // Multiple symbol tables
264 if (SymtabLoadCmd) {
265 EC = object_error::parse_failed;
266 return;
267 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000268 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000269 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000270 // Multiple dynamic symbol tables
271 if (DysymtabLoadCmd) {
272 EC = object_error::parse_failed;
273 return;
274 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000275 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000276 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000277 // Multiple data in code tables
278 if (DataInCodeLoadCmd) {
279 EC = object_error::parse_failed;
280 return;
281 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000282 DataInCodeLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000283 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
284 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000285 // Multiple dyldinfo load commands
286 if (DyldInfoLoadCmd) {
287 EC = object_error::parse_failed;
288 return;
289 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000290 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000291 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000292 // Multiple UUID load commands
293 if (UuidLoadCmd) {
294 EC = object_error::parse_failed;
295 return;
296 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000297 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000298 } else if (Load.C.cmd == SegmentLoadType) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +0000299 const unsigned SegmentLoadSize = this->is64Bit()
300 ? sizeof(MachO::segment_command_64)
301 : sizeof(MachO::segment_command);
302 if (Load.C.cmdsize < SegmentLoadSize)
303 report_fatal_error("Segment load command size is too small.");
304
Rafael Espindola56f976f2013-04-18 18:08:55 +0000305 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
306 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000307 const char *Sec = getSectionPtr(this, Load, J);
308 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000309 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000310 if (isPageZeroSegment(this, Load))
311 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000312 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
313 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
314 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
315 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
316 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
317 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000318 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000319
320 if (I == LoadCommandCount - 1)
321 break;
322 else
323 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000324 }
325}
326
Rafael Espindola5e812af2014-01-30 02:49:50 +0000327void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000328 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000329 sizeof(MachO::nlist_64) :
330 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000331 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000332}
333
Rafael Espindola3acea392014-06-12 21:46:39 +0000334std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
335 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000336 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000337 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000338 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000339 if (Start < getData().begin() || Start >= getData().end())
340 report_fatal_error(
341 "Symbol name entry points before beginning or past end of file.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000342 Res = StringRef(Start);
343 return object_error::success;
344}
345
Rafael Espindola0e77a942014-12-10 20:46:55 +0000346unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
347 DataRefImpl DRI = Sec.getRawDataRefImpl();
348 uint32_t Flags = getSectionFlags(this, DRI);
349 return Flags & MachO::SECTION_TYPE;
350}
351
Kevin Enderby980b2582014-06-05 21:21:57 +0000352// getIndirectName() returns the name of the alias'ed symbol who's string table
353// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000354std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
355 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000356 StringRef StringTable = getStringTableData();
357 uint64_t NValue;
358 if (is64Bit()) {
359 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
360 NValue = Entry.n_value;
361 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362 return object_error::parse_failed;
363 } else {
364 MachO::nlist Entry = getSymbolTableEntry(Symb);
365 NValue = Entry.n_value;
366 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
367 return object_error::parse_failed;
368 }
369 if (NValue >= StringTable.size())
370 return object_error::parse_failed;
371 const char *Start = &StringTable.data()[NValue];
372 Res = StringRef(Start);
373 return object_error::success;
374}
375
Rafael Espindola3acea392014-06-12 21:46:39 +0000376std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
377 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000378 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000379 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000380 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
381 Entry.n_value == 0)
382 Res = UnknownAddressOrSize;
383 else
384 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000385 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000386 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000387 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
388 Entry.n_value == 0)
389 Res = UnknownAddressOrSize;
390 else
391 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000392 }
393 return object_error::success;
394}
395
Rafael Espindola3acea392014-06-12 21:46:39 +0000396std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
397 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000398 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000399 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000400 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000401 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000402 } else {
403 Result = 0;
404 }
405 return object_error::success;
406}
407
Rafael Espindola3acea392014-06-12 21:46:39 +0000408std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
409 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000410 uint64_t BeginOffset;
411 uint64_t EndOffset = 0;
412 uint8_t SectionIndex;
413
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000414 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000415 uint64_t Value;
416 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000417 if (Value == UnknownAddressOrSize) {
418 Result = UnknownAddressOrSize;
419 return object_error::success;
420 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000421
422 BeginOffset = Value;
423
Charles Davis8bdfafd2013-09-01 04:28:48 +0000424 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000425 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000426 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000427 if (flags & SymbolRef::SF_Common)
428 Result = Value;
429 else
430 Result = UnknownAddressOrSize;
431 return object_error::success;
432 }
433 // Unfortunately symbols are unsorted so we need to touch all
434 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000435 for (const SymbolRef &Symbol : symbols()) {
436 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437 Entry = getSymbolTableEntryBase(this, DRI);
438 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000439 if (Value == UnknownAddressOrSize)
440 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000441 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000442 if (!EndOffset || Value < EndOffset)
443 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000444 }
445 if (!EndOffset) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000446 DataRefImpl Sec;
447 Sec.d.a = SectionIndex-1;
Rafael Espindola80291272014-10-08 15:28:58 +0000448 uint64_t Size = getSectionSize(Sec);
449 EndOffset = getSectionAddress(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000450 EndOffset += Size;
451 }
452 Result = EndOffset - BeginOffset;
453 return object_error::success;
454}
455
Rafael Espindola3acea392014-06-12 21:46:39 +0000456std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
457 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000458 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000459 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000460
461 Res = SymbolRef::ST_Other;
462
463 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000464 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000465 Res = SymbolRef::ST_Debug;
466 return object_error::success;
467 }
468
Charles Davis74ec8b02013-08-27 05:00:13 +0000469 switch (n_type & MachO::N_TYPE) {
470 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000471 Res = SymbolRef::ST_Unknown;
472 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000473 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000474 Res = SymbolRef::ST_Function;
475 break;
476 }
477 return object_error::success;
478}
479
Rafael Espindola20122a42014-01-31 20:57:12 +0000480uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000481 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000482
Charles Davis8bdfafd2013-09-01 04:28:48 +0000483 uint8_t MachOType = Entry.n_type;
484 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000485
Rafael Espindola20122a42014-01-31 20:57:12 +0000486 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000487
Charles Davis74ec8b02013-08-27 05:00:13 +0000488 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000489 Result |= SymbolRef::SF_Undefined;
490
Tim Northovereaef0742014-05-30 13:22:59 +0000491 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
492 Result |= SymbolRef::SF_Indirect;
493
Rafael Espindolaa1356322013-11-02 05:03:24 +0000494 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000495 Result |= SymbolRef::SF_FormatSpecific;
496
Charles Davis74ec8b02013-08-27 05:00:13 +0000497 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000498 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000499 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000500 uint64_t Value;
501 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000502 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000503 Result |= SymbolRef::SF_Common;
504 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000505
506 if (!(MachOType & MachO::N_PEXT))
507 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000508 }
509
Charles Davis74ec8b02013-08-27 05:00:13 +0000510 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000511 Result |= SymbolRef::SF_Weak;
512
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000513 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
514 Result |= SymbolRef::SF_Thumb;
515
Charles Davis74ec8b02013-08-27 05:00:13 +0000516 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000517 Result |= SymbolRef::SF_Absolute;
518
Rafael Espindola20122a42014-01-31 20:57:12 +0000519 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000520}
521
Rafael Espindola3acea392014-06-12 21:46:39 +0000522std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
523 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000524 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000525 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000526
527 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000528 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000529 } else {
530 DataRefImpl DRI;
531 DRI.d.a = index - 1;
532 Res = section_iterator(SectionRef(DRI, this));
533 }
534
535 return object_error::success;
536}
537
Rafael Espindola5e812af2014-01-30 02:49:50 +0000538void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000539 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000540}
541
Rafael Espindola3acea392014-06-12 21:46:39 +0000542std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
543 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000544 ArrayRef<char> Raw = getSectionRawName(Sec);
545 Result = parseSegmentOrSectionName(Raw.data());
546 return object_error::success;
547}
548
Rafael Espindola80291272014-10-08 15:28:58 +0000549uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
550 if (is64Bit())
551 return getSection64(Sec).addr;
552 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000553}
554
Rafael Espindola80291272014-10-08 15:28:58 +0000555uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
556 if (is64Bit())
557 return getSection64(Sec).size;
558 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000559}
560
Rafael Espindola3acea392014-06-12 21:46:39 +0000561std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
562 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000563 uint32_t Offset;
564 uint64_t Size;
565
566 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000567 MachO::section_64 Sect = getSection64(Sec);
568 Offset = Sect.offset;
569 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000570 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000571 MachO::section Sect = getSection(Sec);
572 Offset = Sect.offset;
573 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000574 }
575
576 Res = this->getData().substr(Offset, Size);
577 return object_error::success;
578}
579
Rafael Espindola80291272014-10-08 15:28:58 +0000580uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000581 uint32_t Align;
582 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000583 MachO::section_64 Sect = getSection64(Sec);
584 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000585 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000586 MachO::section Sect = getSection(Sec);
587 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000588 }
589
Rafael Espindola80291272014-10-08 15:28:58 +0000590 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000591}
592
Rafael Espindola80291272014-10-08 15:28:58 +0000593bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000594 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000595 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000596}
597
Rafael Espindola80291272014-10-08 15:28:58 +0000598bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000599 uint32_t Flags = getSectionFlags(this, Sec);
600 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000601 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
602 !(SectionType == MachO::S_ZEROFILL ||
603 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000604}
605
Rafael Espindola80291272014-10-08 15:28:58 +0000606bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000607 uint32_t Flags = getSectionFlags(this, Sec);
608 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000609 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
610 (SectionType == MachO::S_ZEROFILL ||
611 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000612}
613
Rafael Espindola80291272014-10-08 15:28:58 +0000614bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000615 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000616 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000617}
618
Rafael Espindola80291272014-10-08 15:28:58 +0000619bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
620 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000621 SymbolRef::Type ST;
622 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000623 if (ST == SymbolRef::ST_Unknown)
624 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000625
Rafael Espindola80291272014-10-08 15:28:58 +0000626 uint64_t SectBegin = getSectionAddress(Sec);
627 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000628 SectEnd += SectBegin;
629
630 uint64_t SymAddr;
631 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000632 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000633}
634
Rui Ueyamabc654b12013-09-27 21:47:05 +0000635relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000636 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000637 Ret.d.a = Sec.d.a;
638 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000639 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000640}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000641
Rafael Espindola56f976f2013-04-18 18:08:55 +0000642relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000643MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000644 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000645 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000646 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000647 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000648 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000649 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000650 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000651 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000652
Rafael Espindola56f976f2013-04-18 18:08:55 +0000653 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000654 Ret.d.a = Sec.d.a;
655 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000656 return relocation_iterator(RelocationRef(Ret, this));
657}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000658
Rafael Espindola5e812af2014-01-30 02:49:50 +0000659void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000660 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000661}
Owen Anderson171f4852011-10-24 23:20:07 +0000662
Rafael Espindola3acea392014-06-12 21:46:39 +0000663std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
664 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000665 uint64_t Offset;
666 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000667
668 DataRefImpl Sec;
669 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000670 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000671 Res = SecAddress + Offset;
672 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000673}
674
Rafael Espindola3acea392014-06-12 21:46:39 +0000675std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
676 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000677 assert(getHeader().filetype == MachO::MH_OBJECT &&
678 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000679 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000680 Res = getAnyRelocationAddress(RE);
681 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000682}
683
Rafael Espindola806f0062013-06-05 01:33:53 +0000684symbol_iterator
685MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000686 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000687 if (isRelocationScattered(RE))
688 return symbol_end();
689
Rafael Espindola56f976f2013-04-18 18:08:55 +0000690 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
691 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000692 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000693 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000694
Charles Davis8bdfafd2013-09-01 04:28:48 +0000695 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000696 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000697 sizeof(MachO::nlist_64) :
698 sizeof(MachO::nlist);
699 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000700 DataRefImpl Sym;
701 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000702 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000703}
704
Rafael Espindola3acea392014-06-12 21:46:39 +0000705std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
706 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000707 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000708 Res = getAnyRelocationType(RE);
709 return object_error::success;
710}
711
Rafael Espindola3acea392014-06-12 21:46:39 +0000712std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000713MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
714 SmallVectorImpl<char> &Result) const {
715 StringRef res;
716 uint64_t RType;
717 getRelocationType(Rel, RType);
718
719 unsigned Arch = this->getArch();
720
721 switch (Arch) {
722 case Triple::x86: {
723 static const char *const Table[] = {
724 "GENERIC_RELOC_VANILLA",
725 "GENERIC_RELOC_PAIR",
726 "GENERIC_RELOC_SECTDIFF",
727 "GENERIC_RELOC_PB_LA_PTR",
728 "GENERIC_RELOC_LOCAL_SECTDIFF",
729 "GENERIC_RELOC_TLV" };
730
Eric Christopher13250cb2013-12-06 02:33:38 +0000731 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000732 res = "Unknown";
733 else
734 res = Table[RType];
735 break;
736 }
737 case Triple::x86_64: {
738 static const char *const Table[] = {
739 "X86_64_RELOC_UNSIGNED",
740 "X86_64_RELOC_SIGNED",
741 "X86_64_RELOC_BRANCH",
742 "X86_64_RELOC_GOT_LOAD",
743 "X86_64_RELOC_GOT",
744 "X86_64_RELOC_SUBTRACTOR",
745 "X86_64_RELOC_SIGNED_1",
746 "X86_64_RELOC_SIGNED_2",
747 "X86_64_RELOC_SIGNED_4",
748 "X86_64_RELOC_TLV" };
749
750 if (RType > 9)
751 res = "Unknown";
752 else
753 res = Table[RType];
754 break;
755 }
756 case Triple::arm: {
757 static const char *const Table[] = {
758 "ARM_RELOC_VANILLA",
759 "ARM_RELOC_PAIR",
760 "ARM_RELOC_SECTDIFF",
761 "ARM_RELOC_LOCAL_SECTDIFF",
762 "ARM_RELOC_PB_LA_PTR",
763 "ARM_RELOC_BR24",
764 "ARM_THUMB_RELOC_BR22",
765 "ARM_THUMB_32BIT_BRANCH",
766 "ARM_RELOC_HALF",
767 "ARM_RELOC_HALF_SECTDIFF" };
768
769 if (RType > 9)
770 res = "Unknown";
771 else
772 res = Table[RType];
773 break;
774 }
Tim Northover00ed9962014-03-29 10:18:08 +0000775 case Triple::aarch64: {
776 static const char *const Table[] = {
777 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
778 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
779 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
780 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
781 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
782 "ARM64_RELOC_ADDEND"
783 };
784
785 if (RType >= array_lengthof(Table))
786 res = "Unknown";
787 else
788 res = Table[RType];
789 break;
790 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000791 case Triple::ppc: {
792 static const char *const Table[] = {
793 "PPC_RELOC_VANILLA",
794 "PPC_RELOC_PAIR",
795 "PPC_RELOC_BR14",
796 "PPC_RELOC_BR24",
797 "PPC_RELOC_HI16",
798 "PPC_RELOC_LO16",
799 "PPC_RELOC_HA16",
800 "PPC_RELOC_LO14",
801 "PPC_RELOC_SECTDIFF",
802 "PPC_RELOC_PB_LA_PTR",
803 "PPC_RELOC_HI16_SECTDIFF",
804 "PPC_RELOC_LO16_SECTDIFF",
805 "PPC_RELOC_HA16_SECTDIFF",
806 "PPC_RELOC_JBSR",
807 "PPC_RELOC_LO14_SECTDIFF",
808 "PPC_RELOC_LOCAL_SECTDIFF" };
809
Eric Christopher13250cb2013-12-06 02:33:38 +0000810 if (RType > 15)
811 res = "Unknown";
812 else
813 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000814 break;
815 }
816 case Triple::UnknownArch:
817 res = "Unknown";
818 break;
819 }
820 Result.append(res.begin(), res.end());
821 return object_error::success;
822}
823
Rafael Espindola3acea392014-06-12 21:46:39 +0000824std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000825MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000826 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000827 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000828
Rafael Espindola56f976f2013-04-18 18:08:55 +0000829 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000830
Alp Tokere69170a2014-06-26 22:52:05 +0000831 std::string fmtbuf;
832 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000833 unsigned Type = this->getAnyRelocationType(RE);
834 bool IsPCRel = this->getAnyRelocationPCRel(RE);
835
836 // Determine any addends that should be displayed with the relocation.
837 // These require decoding the relocation type, which is triple-specific.
838
839 // X86_64 has entirely custom relocation types.
840 if (Arch == Triple::x86_64) {
841 bool isPCRel = getAnyRelocationPCRel(RE);
842
843 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000844 case MachO::X86_64_RELOC_GOT_LOAD:
845 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000846 printRelocationTargetName(this, RE, fmt);
847 fmt << "@GOT";
848 if (isPCRel) fmt << "PCREL";
849 break;
850 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000851 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000852 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000853 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000854 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000855
Charles Davis8bdfafd2013-09-01 04:28:48 +0000856 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000857 // X86_64_RELOC_UNSIGNED.
858 // NOTE: Scattered relocations don't exist on x86_64.
859 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000860 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000861 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
862 "X86_64_RELOC_SUBTRACTOR.");
863
Charles Davis8bdfafd2013-09-01 04:28:48 +0000864 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
865 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000866 printRelocationTargetName(this, RENext, fmt);
867 fmt << "-";
868 printRelocationTargetName(this, RE, fmt);
869 break;
870 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000871 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000872 printRelocationTargetName(this, RE, fmt);
873 fmt << "@TLV";
874 if (isPCRel) fmt << "P";
875 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000876 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000877 printRelocationTargetName(this, RE, fmt);
878 fmt << "-1";
879 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000880 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000881 printRelocationTargetName(this, RE, fmt);
882 fmt << "-2";
883 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000884 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000885 printRelocationTargetName(this, RE, fmt);
886 fmt << "-4";
887 break;
888 default:
889 printRelocationTargetName(this, RE, fmt);
890 break;
891 }
892 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000893 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
894 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000895 // Generic relocation types...
896 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000897 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000898 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000899 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000900 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000901 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000902 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000903
904 // X86 sect diff's must be followed by a relocation of type
905 // GENERIC_RELOC_PAIR.
906 unsigned RType = getAnyRelocationType(RENext);
907
Charles Davis8bdfafd2013-09-01 04:28:48 +0000908 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000909 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
910 "GENERIC_RELOC_SECTDIFF.");
911
912 printRelocationTargetName(this, RE, fmt);
913 fmt << "-";
914 printRelocationTargetName(this, RENext, fmt);
915 break;
916 }
917 }
918
David Fangb88cdf62013-08-08 20:14:40 +0000919 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000920 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000921 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000922 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000923 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000924 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000925
926 // X86 sect diff's must be followed by a relocation of type
927 // GENERIC_RELOC_PAIR.
928 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000929 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000930 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
931 "GENERIC_RELOC_LOCAL_SECTDIFF.");
932
933 printRelocationTargetName(this, RE, fmt);
934 fmt << "-";
935 printRelocationTargetName(this, RENext, fmt);
936 break;
937 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000938 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000939 printRelocationTargetName(this, RE, fmt);
940 fmt << "@TLV";
941 if (IsPCRel) fmt << "P";
942 break;
943 }
944 default:
945 printRelocationTargetName(this, RE, fmt);
946 }
947 } else { // ARM-specific relocations
948 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000949 case MachO::ARM_RELOC_HALF:
950 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000951 // Half relocations steal a bit from the length field to encode
952 // whether this is an upper16 or a lower16 relocation.
953 bool isUpper = getAnyRelocationLength(RE) >> 1;
954
955 if (isUpper)
956 fmt << ":upper16:(";
957 else
958 fmt << ":lower16:(";
959 printRelocationTargetName(this, RE, fmt);
960
961 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000962 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000963 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000964
965 // ARM half relocs must be followed by a relocation of type
966 // ARM_RELOC_PAIR.
967 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000968 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000969 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000970 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000971
972 // NOTE: The half of the target virtual address is stashed in the
973 // address field of the secondary relocation, but we can't reverse
974 // engineer the constant offset from it without decoding the movw/movt
975 // instruction to find the other half in its immediate field.
976
977 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
978 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000979 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000980 fmt << "-";
981 printRelocationTargetName(this, RENext, fmt);
982 }
983
984 fmt << ")";
985 break;
986 }
987 default: {
988 printRelocationTargetName(this, RE, fmt);
989 }
990 }
991 }
992 } else
993 printRelocationTargetName(this, RE, fmt);
994
Alp Tokere69170a2014-06-26 22:52:05 +0000995 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000996 Result.append(fmtbuf.begin(), fmtbuf.end());
997 return object_error::success;
998}
999
Rafael Espindola3acea392014-06-12 21:46:39 +00001000std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1001 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001002 unsigned Arch = getArch();
1003 uint64_t Type;
1004 getRelocationType(Rel, Type);
1005
1006 Result = false;
1007
1008 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1009 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +00001010 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001011 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001012 } else if (Arch == Triple::x86_64) {
1013 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +00001014 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001015 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001016 DataRefImpl RelPrev = Rel;
1017 RelPrev.d.a--;
1018 uint64_t PrevType;
1019 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001020 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001021 Result = true;
1022 }
1023 }
1024
1025 return object_error::success;
1026}
1027
Kevin Enderby980b2582014-06-05 21:21:57 +00001028//
1029// guessLibraryShortName() is passed a name of a dynamic library and returns a
1030// guess on what the short name is. Then name is returned as a substring of the
1031// StringRef Name passed in. The name of the dynamic library is recognized as
1032// a framework if it has one of the two following forms:
1033// Foo.framework/Versions/A/Foo
1034// Foo.framework/Foo
1035// Where A and Foo can be any string. And may contain a trailing suffix
1036// starting with an underbar. If the Name is recognized as a framework then
1037// isFramework is set to true else it is set to false. If the Name has a
1038// suffix then Suffix is set to the substring in Name that contains the suffix
1039// else it is set to a NULL StringRef.
1040//
1041// The Name of the dynamic library is recognized as a library name if it has
1042// one of the two following forms:
1043// libFoo.A.dylib
1044// libFoo.dylib
1045// The library may have a suffix trailing the name Foo of the form:
1046// libFoo_profile.A.dylib
1047// libFoo_profile.dylib
1048//
1049// The Name of the dynamic library is also recognized as a library name if it
1050// has the following form:
1051// Foo.qtx
1052//
1053// If the Name of the dynamic library is none of the forms above then a NULL
1054// StringRef is returned.
1055//
1056StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1057 bool &isFramework,
1058 StringRef &Suffix) {
1059 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1060 size_t a, b, c, d, Idx;
1061
1062 isFramework = false;
1063 Suffix = StringRef();
1064
1065 // Pull off the last component and make Foo point to it
1066 a = Name.rfind('/');
1067 if (a == Name.npos || a == 0)
1068 goto guess_library;
1069 Foo = Name.slice(a+1, Name.npos);
1070
1071 // Look for a suffix starting with a '_'
1072 Idx = Foo.rfind('_');
1073 if (Idx != Foo.npos && Foo.size() >= 2) {
1074 Suffix = Foo.slice(Idx, Foo.npos);
1075 Foo = Foo.slice(0, Idx);
1076 }
1077
1078 // First look for the form Foo.framework/Foo
1079 b = Name.rfind('/', a);
1080 if (b == Name.npos)
1081 Idx = 0;
1082 else
1083 Idx = b+1;
1084 F = Name.slice(Idx, Idx + Foo.size());
1085 DotFramework = Name.slice(Idx + Foo.size(),
1086 Idx + Foo.size() + sizeof(".framework/")-1);
1087 if (F == Foo && DotFramework == ".framework/") {
1088 isFramework = true;
1089 return Foo;
1090 }
1091
1092 // Next look for the form Foo.framework/Versions/A/Foo
1093 if (b == Name.npos)
1094 goto guess_library;
1095 c = Name.rfind('/', b);
1096 if (c == Name.npos || c == 0)
1097 goto guess_library;
1098 V = Name.slice(c+1, Name.npos);
1099 if (!V.startswith("Versions/"))
1100 goto guess_library;
1101 d = Name.rfind('/', c);
1102 if (d == Name.npos)
1103 Idx = 0;
1104 else
1105 Idx = d+1;
1106 F = Name.slice(Idx, Idx + Foo.size());
1107 DotFramework = Name.slice(Idx + Foo.size(),
1108 Idx + Foo.size() + sizeof(".framework/")-1);
1109 if (F == Foo && DotFramework == ".framework/") {
1110 isFramework = true;
1111 return Foo;
1112 }
1113
1114guess_library:
1115 // pull off the suffix after the "." and make a point to it
1116 a = Name.rfind('.');
1117 if (a == Name.npos || a == 0)
1118 return StringRef();
1119 Dylib = Name.slice(a, Name.npos);
1120 if (Dylib != ".dylib")
1121 goto guess_qtx;
1122
1123 // First pull off the version letter for the form Foo.A.dylib if any.
1124 if (a >= 3) {
1125 Dot = Name.slice(a-2, a-1);
1126 if (Dot == ".")
1127 a = a - 2;
1128 }
1129
1130 b = Name.rfind('/', a);
1131 if (b == Name.npos)
1132 b = 0;
1133 else
1134 b = b+1;
1135 // ignore any suffix after an underbar like Foo_profile.A.dylib
1136 Idx = Name.find('_', b);
1137 if (Idx != Name.npos && Idx != b) {
1138 Lib = Name.slice(b, Idx);
1139 Suffix = Name.slice(Idx, a);
1140 }
1141 else
1142 Lib = Name.slice(b, a);
1143 // There are incorrect library names of the form:
1144 // libATS.A_profile.dylib so check for these.
1145 if (Lib.size() >= 3) {
1146 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1147 if (Dot == ".")
1148 Lib = Lib.slice(0, Lib.size()-2);
1149 }
1150 return Lib;
1151
1152guess_qtx:
1153 Qtx = Name.slice(a, Name.npos);
1154 if (Qtx != ".qtx")
1155 return StringRef();
1156 b = Name.rfind('/', a);
1157 if (b == Name.npos)
1158 Lib = Name.slice(0, a);
1159 else
1160 Lib = Name.slice(b+1, a);
1161 // There are library names of the form: QT.A.qtx so check for these.
1162 if (Lib.size() >= 3) {
1163 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1164 if (Dot == ".")
1165 Lib = Lib.slice(0, Lib.size()-2);
1166 }
1167 return Lib;
1168}
1169
1170// getLibraryShortNameByIndex() is used to get the short name of the library
1171// for an undefined symbol in a linked Mach-O binary that was linked with the
1172// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1173// It is passed the index (0 - based) of the library as translated from
1174// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001175std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001176 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001177 if (Index >= Libraries.size())
1178 return object_error::parse_failed;
1179
Kevin Enderby980b2582014-06-05 21:21:57 +00001180 // If the cache of LibrariesShortNames is not built up do that first for
1181 // all the Libraries.
1182 if (LibrariesShortNames.size() == 0) {
1183 for (unsigned i = 0; i < Libraries.size(); i++) {
1184 MachO::dylib_command D =
1185 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001186 if (D.dylib.name >= D.cmdsize)
1187 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001188 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001189 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001190 if (D.dylib.name+Name.size() >= D.cmdsize)
1191 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001192 StringRef Suffix;
1193 bool isFramework;
1194 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001195 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001196 LibrariesShortNames.push_back(Name);
1197 else
1198 LibrariesShortNames.push_back(shortName);
1199 }
1200 }
1201
1202 Res = LibrariesShortNames[Index];
1203 return object_error::success;
1204}
1205
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001206basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001207 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001208}
1209
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001210basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001211 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001212 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001213 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001214
Charles Davis8bdfafd2013-09-01 04:28:48 +00001215 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001216 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001217 sizeof(MachO::nlist_64) :
1218 sizeof(MachO::nlist);
1219 unsigned Offset = Symtab.symoff +
1220 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001221 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001222 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001223}
1224
Lang Hames36072da2014-05-12 21:39:59 +00001225basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1226 DataRefImpl DRI;
1227 if (!SymtabLoadCmd)
1228 return basic_symbol_iterator(SymbolRef(DRI, this));
1229
1230 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001231 if (Index >= Symtab.nsyms)
1232 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001233 unsigned SymbolTableEntrySize =
1234 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1235 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1236 DRI.p += Index * SymbolTableEntrySize;
1237 return basic_symbol_iterator(SymbolRef(DRI, this));
1238}
1239
Rafael Espindolab5155a52014-02-10 20:24:04 +00001240section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001241 DataRefImpl DRI;
1242 return section_iterator(SectionRef(DRI, this));
1243}
1244
Rafael Espindolab5155a52014-02-10 20:24:04 +00001245section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001246 DataRefImpl DRI;
1247 DRI.d.a = Sections.size();
1248 return section_iterator(SectionRef(DRI, this));
1249}
1250
Rafael Espindola56f976f2013-04-18 18:08:55 +00001251uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001252 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001253}
1254
Rafael Espindola56f976f2013-04-18 18:08:55 +00001255StringRef MachOObjectFile::getFileFormatName() const {
1256 unsigned CPUType = getCPUType(this);
1257 if (!is64Bit()) {
1258 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001259 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001260 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001261 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001262 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001263 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001264 return "Mach-O 32-bit ppc";
1265 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001266 return "Mach-O 32-bit unknown";
1267 }
1268 }
1269
Rafael Espindola56f976f2013-04-18 18:08:55 +00001270 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001271 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001272 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001273 case llvm::MachO::CPU_TYPE_ARM64:
1274 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001275 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001276 return "Mach-O 64-bit ppc64";
1277 default:
1278 return "Mach-O 64-bit unknown";
1279 }
1280}
1281
Alexey Samsonove6388e62013-06-18 15:03:28 +00001282Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1283 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001284 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001285 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001286 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001287 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001288 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001289 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001290 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001291 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001292 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001293 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001294 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001295 return Triple::ppc64;
1296 default:
1297 return Triple::UnknownArch;
1298 }
1299}
1300
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001301Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1302 const char **McpuDefault) {
1303 if (McpuDefault)
1304 *McpuDefault = nullptr;
1305
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001306 switch (CPUType) {
1307 case MachO::CPU_TYPE_I386:
1308 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1309 case MachO::CPU_SUBTYPE_I386_ALL:
1310 return Triple("i386-apple-darwin");
1311 default:
1312 return Triple();
1313 }
1314 case MachO::CPU_TYPE_X86_64:
1315 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1316 case MachO::CPU_SUBTYPE_X86_64_ALL:
1317 return Triple("x86_64-apple-darwin");
1318 case MachO::CPU_SUBTYPE_X86_64_H:
1319 return Triple("x86_64h-apple-darwin");
1320 default:
1321 return Triple();
1322 }
1323 case MachO::CPU_TYPE_ARM:
1324 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1325 case MachO::CPU_SUBTYPE_ARM_V4T:
1326 return Triple("armv4t-apple-darwin");
1327 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1328 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001329 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1330 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001331 case MachO::CPU_SUBTYPE_ARM_V6:
1332 return Triple("armv6-apple-darwin");
1333 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001334 if (McpuDefault)
1335 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001336 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001337 case MachO::CPU_SUBTYPE_ARM_V7:
1338 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001339 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001340 if (McpuDefault)
1341 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001342 return Triple("armv7em-apple-darwin");
1343 case MachO::CPU_SUBTYPE_ARM_V7K:
1344 return Triple("armv7k-apple-darwin");
1345 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001346 if (McpuDefault)
1347 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001348 return Triple("armv7m-apple-darwin");
1349 case MachO::CPU_SUBTYPE_ARM_V7S:
1350 return Triple("armv7s-apple-darwin");
1351 default:
1352 return Triple();
1353 }
1354 case MachO::CPU_TYPE_ARM64:
1355 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1356 case MachO::CPU_SUBTYPE_ARM64_ALL:
1357 return Triple("arm64-apple-darwin");
1358 default:
1359 return Triple();
1360 }
1361 case MachO::CPU_TYPE_POWERPC:
1362 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1363 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1364 return Triple("ppc-apple-darwin");
1365 default:
1366 return Triple();
1367 }
1368 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001369 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001370 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1371 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001372 default:
1373 return Triple();
1374 }
1375 default:
1376 return Triple();
1377 }
1378}
1379
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001380Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1381 const char **McpuDefault) {
1382 if (McpuDefault)
1383 *McpuDefault = nullptr;
1384
1385 switch (CPUType) {
1386 case MachO::CPU_TYPE_ARM:
1387 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1388 case MachO::CPU_SUBTYPE_ARM_V4T:
1389 return Triple("thumbv4t-apple-darwin");
1390 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1391 return Triple("thumbv5e-apple-darwin");
1392 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1393 return Triple("xscale-apple-darwin");
1394 case MachO::CPU_SUBTYPE_ARM_V6:
1395 return Triple("thumbv6-apple-darwin");
1396 case MachO::CPU_SUBTYPE_ARM_V6M:
1397 if (McpuDefault)
1398 *McpuDefault = "cortex-m0";
1399 return Triple("thumbv6m-apple-darwin");
1400 case MachO::CPU_SUBTYPE_ARM_V7:
1401 return Triple("thumbv7-apple-darwin");
1402 case MachO::CPU_SUBTYPE_ARM_V7EM:
1403 if (McpuDefault)
1404 *McpuDefault = "cortex-m4";
1405 return Triple("thumbv7em-apple-darwin");
1406 case MachO::CPU_SUBTYPE_ARM_V7K:
1407 return Triple("thumbv7k-apple-darwin");
1408 case MachO::CPU_SUBTYPE_ARM_V7M:
1409 if (McpuDefault)
1410 *McpuDefault = "cortex-m3";
1411 return Triple("thumbv7m-apple-darwin");
1412 case MachO::CPU_SUBTYPE_ARM_V7S:
1413 return Triple("thumbv7s-apple-darwin");
1414 default:
1415 return Triple();
1416 }
1417 default:
1418 return Triple();
1419 }
1420}
1421
1422Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1423 const char **McpuDefault,
1424 Triple *ThumbTriple) {
1425 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1426 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1427 McpuDefault);
1428 return T;
1429}
1430
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001431Triple MachOObjectFile::getHostArch() {
1432 return Triple(sys::getDefaultTargetTriple());
1433}
1434
Rafael Espindola72318b42014-08-08 16:30:17 +00001435bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1436 return StringSwitch<bool>(ArchFlag)
1437 .Case("i386", true)
1438 .Case("x86_64", true)
1439 .Case("x86_64h", true)
1440 .Case("armv4t", true)
1441 .Case("arm", true)
1442 .Case("armv5e", true)
1443 .Case("armv6", true)
1444 .Case("armv6m", true)
1445 .Case("armv7em", true)
1446 .Case("armv7k", true)
1447 .Case("armv7m", true)
1448 .Case("armv7s", true)
1449 .Case("arm64", true)
1450 .Case("ppc", true)
1451 .Case("ppc64", true)
1452 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001453}
1454
Alexey Samsonove6388e62013-06-18 15:03:28 +00001455unsigned MachOObjectFile::getArch() const {
1456 return getArch(getCPUType(this));
1457}
1458
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001459Triple MachOObjectFile::getArch(const char **McpuDefault,
1460 Triple *ThumbTriple) const {
1461 Triple T;
1462 if (is64Bit()) {
1463 MachO::mach_header_64 H_64;
1464 H_64 = getHeader64();
1465 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1466 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1467 McpuDefault);
1468 } else {
1469 MachO::mach_header H;
1470 H = getHeader();
1471 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1472 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1473 McpuDefault);
1474 }
1475 return T;
1476}
1477
Rui Ueyamabc654b12013-09-27 21:47:05 +00001478relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001479 DataRefImpl DRI;
1480 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001481 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001482}
1483
Rui Ueyamabc654b12013-09-27 21:47:05 +00001484relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001485 DataRefImpl DRI;
1486 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001487 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001488}
1489
Kevin Enderby273ae012013-06-06 17:20:50 +00001490dice_iterator MachOObjectFile::begin_dices() const {
1491 DataRefImpl DRI;
1492 if (!DataInCodeLoadCmd)
1493 return dice_iterator(DiceRef(DRI, this));
1494
Charles Davis8bdfafd2013-09-01 04:28:48 +00001495 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1496 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001497 return dice_iterator(DiceRef(DRI, this));
1498}
1499
1500dice_iterator MachOObjectFile::end_dices() const {
1501 DataRefImpl DRI;
1502 if (!DataInCodeLoadCmd)
1503 return dice_iterator(DiceRef(DRI, this));
1504
Charles Davis8bdfafd2013-09-01 04:28:48 +00001505 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1506 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001507 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1508 return dice_iterator(DiceRef(DRI, this));
1509}
1510
Nick Kledzikd04bc352014-08-30 00:20:14 +00001511ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1512 : Trie(T), Malformed(false), Done(false) { }
1513
1514void ExportEntry::moveToFirst() {
1515 pushNode(0);
1516 pushDownUntilBottom();
1517}
1518
1519void ExportEntry::moveToEnd() {
1520 Stack.clear();
1521 Done = true;
1522}
1523
1524bool ExportEntry::operator==(const ExportEntry &Other) const {
1525 // Common case, one at end, other iterating from begin.
1526 if (Done || Other.Done)
1527 return (Done == Other.Done);
1528 // Not equal if different stack sizes.
1529 if (Stack.size() != Other.Stack.size())
1530 return false;
1531 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001532 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001533 return false;
1534 // Equal if all nodes in both stacks match.
1535 for (unsigned i=0; i < Stack.size(); ++i) {
1536 if (Stack[i].Start != Other.Stack[i].Start)
1537 return false;
1538 }
1539 return true;
1540}
1541
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001542uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1543 unsigned Count;
1544 uint64_t Result = decodeULEB128(Ptr, &Count);
1545 Ptr += Count;
1546 if (Ptr > Trie.end()) {
1547 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001548 Malformed = true;
1549 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001550 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001551}
1552
1553StringRef ExportEntry::name() const {
1554 return CumulativeString.str();
1555}
1556
1557uint64_t ExportEntry::flags() const {
1558 return Stack.back().Flags;
1559}
1560
1561uint64_t ExportEntry::address() const {
1562 return Stack.back().Address;
1563}
1564
1565uint64_t ExportEntry::other() const {
1566 return Stack.back().Other;
1567}
1568
1569StringRef ExportEntry::otherName() const {
1570 const char* ImportName = Stack.back().ImportName;
1571 if (ImportName)
1572 return StringRef(ImportName);
1573 return StringRef();
1574}
1575
1576uint32_t ExportEntry::nodeOffset() const {
1577 return Stack.back().Start - Trie.begin();
1578}
1579
1580ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1581 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1582 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1583 ParentStringLength(0), IsExportNode(false) {
1584}
1585
1586void ExportEntry::pushNode(uint64_t offset) {
1587 const uint8_t *Ptr = Trie.begin() + offset;
1588 NodeState State(Ptr);
1589 uint64_t ExportInfoSize = readULEB128(State.Current);
1590 State.IsExportNode = (ExportInfoSize != 0);
1591 const uint8_t* Children = State.Current + ExportInfoSize;
1592 if (State.IsExportNode) {
1593 State.Flags = readULEB128(State.Current);
1594 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1595 State.Address = 0;
1596 State.Other = readULEB128(State.Current); // dylib ordinal
1597 State.ImportName = reinterpret_cast<const char*>(State.Current);
1598 } else {
1599 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001600 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1601 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001602 }
1603 }
1604 State.ChildCount = *Children;
1605 State.Current = Children + 1;
1606 State.NextChildIndex = 0;
1607 State.ParentStringLength = CumulativeString.size();
1608 Stack.push_back(State);
1609}
1610
1611void ExportEntry::pushDownUntilBottom() {
1612 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1613 NodeState &Top = Stack.back();
1614 CumulativeString.resize(Top.ParentStringLength);
1615 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001616 char C = *Top.Current;
1617 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001618 }
1619 Top.Current += 1;
1620 uint64_t childNodeIndex = readULEB128(Top.Current);
1621 Top.NextChildIndex += 1;
1622 pushNode(childNodeIndex);
1623 }
1624 if (!Stack.back().IsExportNode) {
1625 Malformed = true;
1626 moveToEnd();
1627 }
1628}
1629
1630// We have a trie data structure and need a way to walk it that is compatible
1631// with the C++ iterator model. The solution is a non-recursive depth first
1632// traversal where the iterator contains a stack of parent nodes along with a
1633// string that is the accumulation of all edge strings along the parent chain
1634// to this point.
1635//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001636// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001637// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1638// node may have child nodes too.
1639//
1640// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1641// child until hitting a node with no children (which is an export node or
1642// else the trie is malformed). On the way down, each node is pushed on the
1643// stack ivar. If there is no more ways down, it pops up one and tries to go
1644// down a sibling path until a childless node is reached.
1645void ExportEntry::moveNext() {
1646 if (Stack.empty() || !Stack.back().IsExportNode) {
1647 Malformed = true;
1648 moveToEnd();
1649 return;
1650 }
1651
1652 Stack.pop_back();
1653 while (!Stack.empty()) {
1654 NodeState &Top = Stack.back();
1655 if (Top.NextChildIndex < Top.ChildCount) {
1656 pushDownUntilBottom();
1657 // Now at the next export node.
1658 return;
1659 } else {
1660 if (Top.IsExportNode) {
1661 // This node has no children but is itself an export node.
1662 CumulativeString.resize(Top.ParentStringLength);
1663 return;
1664 }
1665 Stack.pop_back();
1666 }
1667 }
1668 Done = true;
1669}
1670
1671iterator_range<export_iterator>
1672MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1673 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001674 if (Trie.size() == 0)
1675 Start.moveToEnd();
1676 else
1677 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001678
1679 ExportEntry Finish(Trie);
1680 Finish.moveToEnd();
1681
1682 return iterator_range<export_iterator>(export_iterator(Start),
1683 export_iterator(Finish));
1684}
1685
1686iterator_range<export_iterator> MachOObjectFile::exports() const {
1687 return exports(getDyldInfoExportsTrie());
1688}
1689
1690
Nick Kledzikac431442014-09-12 21:34:15 +00001691MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1692 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1693 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1694 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1695
1696void MachORebaseEntry::moveToFirst() {
1697 Ptr = Opcodes.begin();
1698 moveNext();
1699}
1700
1701void MachORebaseEntry::moveToEnd() {
1702 Ptr = Opcodes.end();
1703 RemainingLoopCount = 0;
1704 Done = true;
1705}
1706
1707void MachORebaseEntry::moveNext() {
1708 // If in the middle of some loop, move to next rebasing in loop.
1709 SegmentOffset += AdvanceAmount;
1710 if (RemainingLoopCount) {
1711 --RemainingLoopCount;
1712 return;
1713 }
1714 if (Ptr == Opcodes.end()) {
1715 Done = true;
1716 return;
1717 }
1718 bool More = true;
1719 while (More && !Malformed) {
1720 // Parse next opcode and set up next loop.
1721 uint8_t Byte = *Ptr++;
1722 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1723 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1724 switch (Opcode) {
1725 case MachO::REBASE_OPCODE_DONE:
1726 More = false;
1727 Done = true;
1728 moveToEnd();
1729 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1730 break;
1731 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1732 RebaseType = ImmValue;
1733 DEBUG_WITH_TYPE(
1734 "mach-o-rebase",
1735 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1736 << "RebaseType=" << (int) RebaseType << "\n");
1737 break;
1738 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1739 SegmentIndex = ImmValue;
1740 SegmentOffset = readULEB128();
1741 DEBUG_WITH_TYPE(
1742 "mach-o-rebase",
1743 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1744 << "SegmentIndex=" << SegmentIndex << ", "
1745 << format("SegmentOffset=0x%06X", SegmentOffset)
1746 << "\n");
1747 break;
1748 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1749 SegmentOffset += readULEB128();
1750 DEBUG_WITH_TYPE("mach-o-rebase",
1751 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1752 << format("SegmentOffset=0x%06X",
1753 SegmentOffset) << "\n");
1754 break;
1755 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1756 SegmentOffset += ImmValue * PointerSize;
1757 DEBUG_WITH_TYPE("mach-o-rebase",
1758 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1759 << format("SegmentOffset=0x%06X",
1760 SegmentOffset) << "\n");
1761 break;
1762 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1763 AdvanceAmount = PointerSize;
1764 RemainingLoopCount = ImmValue - 1;
1765 DEBUG_WITH_TYPE(
1766 "mach-o-rebase",
1767 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1768 << format("SegmentOffset=0x%06X", SegmentOffset)
1769 << ", AdvanceAmount=" << AdvanceAmount
1770 << ", RemainingLoopCount=" << RemainingLoopCount
1771 << "\n");
1772 return;
1773 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1774 AdvanceAmount = PointerSize;
1775 RemainingLoopCount = readULEB128() - 1;
1776 DEBUG_WITH_TYPE(
1777 "mach-o-rebase",
1778 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1779 << format("SegmentOffset=0x%06X", SegmentOffset)
1780 << ", AdvanceAmount=" << AdvanceAmount
1781 << ", RemainingLoopCount=" << RemainingLoopCount
1782 << "\n");
1783 return;
1784 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1785 AdvanceAmount = readULEB128() + PointerSize;
1786 RemainingLoopCount = 0;
1787 DEBUG_WITH_TYPE(
1788 "mach-o-rebase",
1789 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1790 << format("SegmentOffset=0x%06X", SegmentOffset)
1791 << ", AdvanceAmount=" << AdvanceAmount
1792 << ", RemainingLoopCount=" << RemainingLoopCount
1793 << "\n");
1794 return;
1795 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1796 RemainingLoopCount = readULEB128() - 1;
1797 AdvanceAmount = readULEB128() + PointerSize;
1798 DEBUG_WITH_TYPE(
1799 "mach-o-rebase",
1800 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1801 << format("SegmentOffset=0x%06X", SegmentOffset)
1802 << ", AdvanceAmount=" << AdvanceAmount
1803 << ", RemainingLoopCount=" << RemainingLoopCount
1804 << "\n");
1805 return;
1806 default:
1807 Malformed = true;
1808 }
1809 }
1810}
1811
1812uint64_t MachORebaseEntry::readULEB128() {
1813 unsigned Count;
1814 uint64_t Result = decodeULEB128(Ptr, &Count);
1815 Ptr += Count;
1816 if (Ptr > Opcodes.end()) {
1817 Ptr = Opcodes.end();
1818 Malformed = true;
1819 }
1820 return Result;
1821}
1822
1823uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1824
1825uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1826
1827StringRef MachORebaseEntry::typeName() const {
1828 switch (RebaseType) {
1829 case MachO::REBASE_TYPE_POINTER:
1830 return "pointer";
1831 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1832 return "text abs32";
1833 case MachO::REBASE_TYPE_TEXT_PCREL32:
1834 return "text rel32";
1835 }
1836 return "unknown";
1837}
1838
1839bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1840 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1841 return (Ptr == Other.Ptr) &&
1842 (RemainingLoopCount == Other.RemainingLoopCount) &&
1843 (Done == Other.Done);
1844}
1845
1846iterator_range<rebase_iterator>
1847MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1848 MachORebaseEntry Start(Opcodes, is64);
1849 Start.moveToFirst();
1850
1851 MachORebaseEntry Finish(Opcodes, is64);
1852 Finish.moveToEnd();
1853
1854 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1855 rebase_iterator(Finish));
1856}
1857
1858iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1859 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1860}
1861
Nick Kledzik56ebef42014-09-16 01:41:51 +00001862
1863MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1864 Kind BK)
1865 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1866 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1867 BindType(0), PointerSize(is64Bit ? 8 : 4),
1868 TableKind(BK), Malformed(false), Done(false) {}
1869
1870void MachOBindEntry::moveToFirst() {
1871 Ptr = Opcodes.begin();
1872 moveNext();
1873}
1874
1875void MachOBindEntry::moveToEnd() {
1876 Ptr = Opcodes.end();
1877 RemainingLoopCount = 0;
1878 Done = true;
1879}
1880
1881void MachOBindEntry::moveNext() {
1882 // If in the middle of some loop, move to next binding in loop.
1883 SegmentOffset += AdvanceAmount;
1884 if (RemainingLoopCount) {
1885 --RemainingLoopCount;
1886 return;
1887 }
1888 if (Ptr == Opcodes.end()) {
1889 Done = true;
1890 return;
1891 }
1892 bool More = true;
1893 while (More && !Malformed) {
1894 // Parse next opcode and set up next loop.
1895 uint8_t Byte = *Ptr++;
1896 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1897 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1898 int8_t SignExtended;
1899 const uint8_t *SymStart;
1900 switch (Opcode) {
1901 case MachO::BIND_OPCODE_DONE:
1902 if (TableKind == Kind::Lazy) {
1903 // Lazying bindings have a DONE opcode between entries. Need to ignore
1904 // it to advance to next entry. But need not if this is last entry.
1905 bool NotLastEntry = false;
1906 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1907 if (*P) {
1908 NotLastEntry = true;
1909 }
1910 }
1911 if (NotLastEntry)
1912 break;
1913 }
1914 More = false;
1915 Done = true;
1916 moveToEnd();
1917 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1918 break;
1919 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1920 Ordinal = ImmValue;
1921 DEBUG_WITH_TYPE(
1922 "mach-o-bind",
1923 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1924 << "Ordinal=" << Ordinal << "\n");
1925 break;
1926 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1927 Ordinal = readULEB128();
1928 DEBUG_WITH_TYPE(
1929 "mach-o-bind",
1930 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1931 << "Ordinal=" << Ordinal << "\n");
1932 break;
1933 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1934 if (ImmValue) {
1935 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1936 Ordinal = SignExtended;
1937 } else
1938 Ordinal = 0;
1939 DEBUG_WITH_TYPE(
1940 "mach-o-bind",
1941 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1942 << "Ordinal=" << Ordinal << "\n");
1943 break;
1944 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1945 Flags = ImmValue;
1946 SymStart = Ptr;
1947 while (*Ptr) {
1948 ++Ptr;
1949 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001950 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1951 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001952 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001953 DEBUG_WITH_TYPE(
1954 "mach-o-bind",
1955 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1956 << "SymbolName=" << SymbolName << "\n");
1957 if (TableKind == Kind::Weak) {
1958 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1959 return;
1960 }
1961 break;
1962 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1963 BindType = ImmValue;
1964 DEBUG_WITH_TYPE(
1965 "mach-o-bind",
1966 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1967 << "BindType=" << (int)BindType << "\n");
1968 break;
1969 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1970 Addend = readSLEB128();
1971 if (TableKind == Kind::Lazy)
1972 Malformed = true;
1973 DEBUG_WITH_TYPE(
1974 "mach-o-bind",
1975 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1976 << "Addend=" << Addend << "\n");
1977 break;
1978 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1979 SegmentIndex = ImmValue;
1980 SegmentOffset = readULEB128();
1981 DEBUG_WITH_TYPE(
1982 "mach-o-bind",
1983 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1984 << "SegmentIndex=" << SegmentIndex << ", "
1985 << format("SegmentOffset=0x%06X", SegmentOffset)
1986 << "\n");
1987 break;
1988 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1989 SegmentOffset += readULEB128();
1990 DEBUG_WITH_TYPE("mach-o-bind",
1991 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1992 << format("SegmentOffset=0x%06X",
1993 SegmentOffset) << "\n");
1994 break;
1995 case MachO::BIND_OPCODE_DO_BIND:
1996 AdvanceAmount = PointerSize;
1997 RemainingLoopCount = 0;
1998 DEBUG_WITH_TYPE("mach-o-bind",
1999 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2000 << format("SegmentOffset=0x%06X",
2001 SegmentOffset) << "\n");
2002 return;
2003 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002004 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002005 RemainingLoopCount = 0;
2006 if (TableKind == Kind::Lazy)
2007 Malformed = true;
2008 DEBUG_WITH_TYPE(
2009 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002010 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00002011 << format("SegmentOffset=0x%06X", SegmentOffset)
2012 << ", AdvanceAmount=" << AdvanceAmount
2013 << ", RemainingLoopCount=" << RemainingLoopCount
2014 << "\n");
2015 return;
2016 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002017 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002018 RemainingLoopCount = 0;
2019 if (TableKind == Kind::Lazy)
2020 Malformed = true;
2021 DEBUG_WITH_TYPE("mach-o-bind",
2022 llvm::dbgs()
2023 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2024 << format("SegmentOffset=0x%06X",
2025 SegmentOffset) << "\n");
2026 return;
2027 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2028 RemainingLoopCount = readULEB128() - 1;
2029 AdvanceAmount = readULEB128() + PointerSize;
2030 if (TableKind == Kind::Lazy)
2031 Malformed = true;
2032 DEBUG_WITH_TYPE(
2033 "mach-o-bind",
2034 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2035 << format("SegmentOffset=0x%06X", SegmentOffset)
2036 << ", AdvanceAmount=" << AdvanceAmount
2037 << ", RemainingLoopCount=" << RemainingLoopCount
2038 << "\n");
2039 return;
2040 default:
2041 Malformed = true;
2042 }
2043 }
2044}
2045
2046uint64_t MachOBindEntry::readULEB128() {
2047 unsigned Count;
2048 uint64_t Result = decodeULEB128(Ptr, &Count);
2049 Ptr += Count;
2050 if (Ptr > Opcodes.end()) {
2051 Ptr = Opcodes.end();
2052 Malformed = true;
2053 }
2054 return Result;
2055}
2056
2057int64_t MachOBindEntry::readSLEB128() {
2058 unsigned Count;
2059 int64_t Result = decodeSLEB128(Ptr, &Count);
2060 Ptr += Count;
2061 if (Ptr > Opcodes.end()) {
2062 Ptr = Opcodes.end();
2063 Malformed = true;
2064 }
2065 return Result;
2066}
2067
2068
2069uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2070
2071uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2072
2073StringRef MachOBindEntry::typeName() const {
2074 switch (BindType) {
2075 case MachO::BIND_TYPE_POINTER:
2076 return "pointer";
2077 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2078 return "text abs32";
2079 case MachO::BIND_TYPE_TEXT_PCREL32:
2080 return "text rel32";
2081 }
2082 return "unknown";
2083}
2084
2085StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2086
2087int64_t MachOBindEntry::addend() const { return Addend; }
2088
2089uint32_t MachOBindEntry::flags() const { return Flags; }
2090
2091int MachOBindEntry::ordinal() const { return Ordinal; }
2092
2093bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2094 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2095 return (Ptr == Other.Ptr) &&
2096 (RemainingLoopCount == Other.RemainingLoopCount) &&
2097 (Done == Other.Done);
2098}
2099
2100iterator_range<bind_iterator>
2101MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2102 MachOBindEntry::Kind BKind) {
2103 MachOBindEntry Start(Opcodes, is64, BKind);
2104 Start.moveToFirst();
2105
2106 MachOBindEntry Finish(Opcodes, is64, BKind);
2107 Finish.moveToEnd();
2108
2109 return iterator_range<bind_iterator>(bind_iterator(Start),
2110 bind_iterator(Finish));
2111}
2112
2113iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2114 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2115 MachOBindEntry::Kind::Regular);
2116}
2117
2118iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2119 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2120 MachOBindEntry::Kind::Lazy);
2121}
2122
2123iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2124 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2125 MachOBindEntry::Kind::Weak);
2126}
2127
Rafael Espindola56f976f2013-04-18 18:08:55 +00002128StringRef
2129MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2130 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2131 return parseSegmentOrSectionName(Raw.data());
2132}
2133
2134ArrayRef<char>
2135MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002136 if (Sec.d.a >= Sections.size())
2137 report_fatal_error("getSectionRawName: Invalid section index");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002138 const section_base *Base =
2139 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002140 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002141}
2142
2143ArrayRef<char>
2144MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002145 if (Sec.d.a >= Sections.size())
2146 report_fatal_error("getSectionRawFinalSegmentName: Invalid section index");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002147 const section_base *Base =
2148 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002149 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002150}
2151
2152bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002153MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002154 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002155 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002156 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002157 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002158}
2159
Eric Christopher1d62c252013-07-22 22:25:07 +00002160unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002161 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002162 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002163 return RE.r_word1 & 0xffffff;
2164 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002165}
2166
Eric Christopher1d62c252013-07-22 22:25:07 +00002167bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002168 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002169 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002170 return (RE.r_word1 >> 27) & 1;
2171 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002172}
2173
Eric Christopher1d62c252013-07-22 22:25:07 +00002174bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002175 const MachO::any_relocation_info &RE) const {
2176 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002177}
2178
Eric Christopher1d62c252013-07-22 22:25:07 +00002179uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002180 const MachO::any_relocation_info &RE) const {
2181 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002182}
2183
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002184uint32_t MachOObjectFile::getScatteredRelocationType(
2185 const MachO::any_relocation_info &RE) const {
2186 return (RE.r_word0 >> 24) & 0xf;
2187}
2188
Eric Christopher1d62c252013-07-22 22:25:07 +00002189unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002190 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002191 if (isRelocationScattered(RE))
2192 return getScatteredRelocationAddress(RE);
2193 return getPlainRelocationAddress(RE);
2194}
2195
Charles Davis8bdfafd2013-09-01 04:28:48 +00002196unsigned MachOObjectFile::getAnyRelocationPCRel(
2197 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002198 if (isRelocationScattered(RE))
2199 return getScatteredRelocationPCRel(this, RE);
2200 return getPlainRelocationPCRel(this, RE);
2201}
2202
Eric Christopher1d62c252013-07-22 22:25:07 +00002203unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002204 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002205 if (isRelocationScattered(RE))
2206 return getScatteredRelocationLength(RE);
2207 return getPlainRelocationLength(this, RE);
2208}
2209
2210unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002211MachOObjectFile::getAnyRelocationType(
2212 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002213 if (isRelocationScattered(RE))
2214 return getScatteredRelocationType(RE);
2215 return getPlainRelocationType(this, RE);
2216}
2217
Rafael Espindola52501032013-04-30 15:40:54 +00002218SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00002219MachOObjectFile::getRelocationSection(
2220 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002221 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002222 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002223 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2224 DataRefImpl DRI;
2225 DRI.d.a = SecNum;
2226 return SectionRef(DRI, this);
2227}
2228
Rafael Espindola56f976f2013-04-18 18:08:55 +00002229MachOObjectFile::LoadCommandInfo
2230MachOObjectFile::getFirstLoadCommandInfo() const {
2231 MachOObjectFile::LoadCommandInfo Load;
2232
Charles Davis8bdfafd2013-09-01 04:28:48 +00002233 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2234 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002235 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002236 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002237 if (Load.C.cmdsize < 8)
2238 report_fatal_error("Load command with size < 8 bytes.");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002239 return Load;
2240}
2241
2242MachOObjectFile::LoadCommandInfo
2243MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2244 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002245 Next.Ptr = L.Ptr + L.C.cmdsize;
2246 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002247 if (Next.C.cmdsize < 8)
2248 report_fatal_error("Load command with size < 8 bytes.");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002249 return Next;
2250}
2251
Charles Davis8bdfafd2013-09-01 04:28:48 +00002252MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002253 // TODO: What if Sections.size() == 0?
2254 if (DRI.d.a >= Sections.size())
2255 report_fatal_error("getSection: Invalid section index.");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002256 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002257}
2258
Charles Davis8bdfafd2013-09-01 04:28:48 +00002259MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002260 // TODO: What if Sections.size() == 0?
2261 if (DRI.d.a >= Sections.size())
2262 report_fatal_error("getSection64: Invalid section index.");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002263 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002264}
2265
Charles Davis8bdfafd2013-09-01 04:28:48 +00002266MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002267 unsigned Index) const {
2268 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002269 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002270}
2271
Charles Davis8bdfafd2013-09-01 04:28:48 +00002272MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2273 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002274 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002275 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002276}
2277
Charles Davis8bdfafd2013-09-01 04:28:48 +00002278MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002279MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002280 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002281 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002282}
2283
Charles Davis8bdfafd2013-09-01 04:28:48 +00002284MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002285MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002286 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002287 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002288}
2289
Charles Davis8bdfafd2013-09-01 04:28:48 +00002290MachO::linkedit_data_command
2291MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2292 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002293}
2294
Charles Davis8bdfafd2013-09-01 04:28:48 +00002295MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002296MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002297 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002298}
2299
Charles Davis8bdfafd2013-09-01 04:28:48 +00002300MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002301MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002302 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002303}
2304
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002305MachO::linker_option_command
2306MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2307 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002308}
2309
Jim Grosbach448334a2014-03-18 22:09:05 +00002310MachO::version_min_command
2311MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2312 return getStruct<MachO::version_min_command>(this, L.Ptr);
2313}
2314
Tim Northover8f9590b2014-06-30 14:40:57 +00002315MachO::dylib_command
2316MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2317 return getStruct<MachO::dylib_command>(this, L.Ptr);
2318}
2319
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002320MachO::dyld_info_command
2321MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2322 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2323}
2324
2325MachO::dylinker_command
2326MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2327 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2328}
2329
2330MachO::uuid_command
2331MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2332 return getStruct<MachO::uuid_command>(this, L.Ptr);
2333}
2334
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002335MachO::rpath_command
2336MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2337 return getStruct<MachO::rpath_command>(this, L.Ptr);
2338}
2339
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002340MachO::source_version_command
2341MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2342 return getStruct<MachO::source_version_command>(this, L.Ptr);
2343}
2344
2345MachO::entry_point_command
2346MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2347 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2348}
2349
Kevin Enderby0804f4672014-12-16 23:25:52 +00002350MachO::encryption_info_command
2351MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2352 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2353}
2354
Kevin Enderby57538292014-12-17 01:01:30 +00002355MachO::encryption_info_command_64
2356MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2357 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2358}
2359
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002360MachO::sub_framework_command
2361MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2362 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2363}
Tim Northover8f9590b2014-06-30 14:40:57 +00002364
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002365MachO::sub_umbrella_command
2366MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2367 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2368}
2369
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002370MachO::sub_library_command
2371MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2372 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2373}
2374
Kevin Enderby186eac32014-12-19 21:06:24 +00002375MachO::sub_client_command
2376MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2377 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2378}
2379
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002380MachO::routines_command
2381MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2382 return getStruct<MachO::routines_command>(this, L.Ptr);
2383}
2384
2385MachO::routines_command_64
2386MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2387 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2388}
2389
Kevin Enderby48ef5342014-12-23 22:56:39 +00002390MachO::thread_command
2391MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2392 return getStruct<MachO::thread_command>(this, L.Ptr);
2393}
2394
Charles Davis8bdfafd2013-09-01 04:28:48 +00002395MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002396MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002397 DataRefImpl Sec;
2398 Sec.d.a = Rel.d.a;
2399 uint32_t Offset;
2400 if (is64Bit()) {
2401 MachO::section_64 Sect = getSection64(Sec);
2402 Offset = Sect.reloff;
2403 } else {
2404 MachO::section Sect = getSection(Sec);
2405 Offset = Sect.reloff;
2406 }
2407
2408 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2409 getPtr(this, Offset)) + Rel.d.b;
2410 return getStruct<MachO::any_relocation_info>(
2411 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002412}
2413
Charles Davis8bdfafd2013-09-01 04:28:48 +00002414MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002415MachOObjectFile::getDice(DataRefImpl Rel) const {
2416 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002417 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002418}
2419
Charles Davis8bdfafd2013-09-01 04:28:48 +00002420MachO::mach_header MachOObjectFile::getHeader() const {
2421 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002422}
2423
Charles Davis8bdfafd2013-09-01 04:28:48 +00002424MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2425 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002426}
2427
Charles Davis8bdfafd2013-09-01 04:28:48 +00002428uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2429 const MachO::dysymtab_command &DLC,
2430 unsigned Index) const {
2431 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2432 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002433}
2434
Charles Davis8bdfafd2013-09-01 04:28:48 +00002435MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002436MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2437 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002438 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2439 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002440}
2441
Charles Davis8bdfafd2013-09-01 04:28:48 +00002442MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002443 if (SymtabLoadCmd)
2444 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2445
2446 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2447 MachO::symtab_command Cmd;
2448 Cmd.cmd = MachO::LC_SYMTAB;
2449 Cmd.cmdsize = sizeof(MachO::symtab_command);
2450 Cmd.symoff = 0;
2451 Cmd.nsyms = 0;
2452 Cmd.stroff = 0;
2453 Cmd.strsize = 0;
2454 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002455}
2456
Charles Davis8bdfafd2013-09-01 04:28:48 +00002457MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002458 if (DysymtabLoadCmd)
2459 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2460
2461 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2462 MachO::dysymtab_command Cmd;
2463 Cmd.cmd = MachO::LC_DYSYMTAB;
2464 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2465 Cmd.ilocalsym = 0;
2466 Cmd.nlocalsym = 0;
2467 Cmd.iextdefsym = 0;
2468 Cmd.nextdefsym = 0;
2469 Cmd.iundefsym = 0;
2470 Cmd.nundefsym = 0;
2471 Cmd.tocoff = 0;
2472 Cmd.ntoc = 0;
2473 Cmd.modtaboff = 0;
2474 Cmd.nmodtab = 0;
2475 Cmd.extrefsymoff = 0;
2476 Cmd.nextrefsyms = 0;
2477 Cmd.indirectsymoff = 0;
2478 Cmd.nindirectsyms = 0;
2479 Cmd.extreloff = 0;
2480 Cmd.nextrel = 0;
2481 Cmd.locreloff = 0;
2482 Cmd.nlocrel = 0;
2483 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002484}
2485
Charles Davis8bdfafd2013-09-01 04:28:48 +00002486MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002487MachOObjectFile::getDataInCodeLoadCommand() const {
2488 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002489 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002490
2491 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002492 MachO::linkedit_data_command Cmd;
2493 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2494 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2495 Cmd.dataoff = 0;
2496 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002497 return Cmd;
2498}
2499
Nick Kledzikd04bc352014-08-30 00:20:14 +00002500ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2501 if (!DyldInfoLoadCmd)
2502 return ArrayRef<uint8_t>();
2503
2504 MachO::dyld_info_command DyldInfo
2505 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2506 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2507 getPtr(this, DyldInfo.rebase_off));
2508 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2509}
2510
2511ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2512 if (!DyldInfoLoadCmd)
2513 return ArrayRef<uint8_t>();
2514
2515 MachO::dyld_info_command DyldInfo
2516 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2517 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2518 getPtr(this, DyldInfo.bind_off));
2519 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2520}
2521
2522ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2523 if (!DyldInfoLoadCmd)
2524 return ArrayRef<uint8_t>();
2525
2526 MachO::dyld_info_command DyldInfo
2527 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2528 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2529 getPtr(this, DyldInfo.weak_bind_off));
2530 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2531}
2532
2533ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2534 if (!DyldInfoLoadCmd)
2535 return ArrayRef<uint8_t>();
2536
2537 MachO::dyld_info_command DyldInfo
2538 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2539 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2540 getPtr(this, DyldInfo.lazy_bind_off));
2541 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2542}
2543
2544ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2545 if (!DyldInfoLoadCmd)
2546 return ArrayRef<uint8_t>();
2547
2548 MachO::dyld_info_command DyldInfo
2549 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2550 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2551 getPtr(this, DyldInfo.export_off));
2552 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2553}
2554
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002555ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2556 if (!UuidLoadCmd)
2557 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002558 // Returning a pointer is fine as uuid doesn't need endian swapping.
2559 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2560 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002561}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002562
Rafael Espindola6e040c02013-04-26 20:07:33 +00002563StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002564 MachO::symtab_command S = getSymtabLoadCommand();
2565 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002566}
2567
Rafael Espindola56f976f2013-04-18 18:08:55 +00002568bool MachOObjectFile::is64Bit() const {
2569 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002570 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002571}
2572
2573void MachOObjectFile::ReadULEB128s(uint64_t Index,
2574 SmallVectorImpl<uint64_t> &Out) const {
2575 DataExtractor extractor(ObjectFile::getData(), true, 0);
2576
2577 uint32_t offset = Index;
2578 uint64_t data = 0;
2579 while (uint64_t delta = extractor.getULEB128(&offset)) {
2580 data += delta;
2581 Out.push_back(data);
2582 }
2583}
2584
Rafael Espindolac66d7612014-08-17 19:09:37 +00002585bool MachOObjectFile::isRelocatableObject() const {
2586 return getHeader().filetype == MachO::MH_OBJECT;
2587}
2588
Rafael Espindola437b0d52014-07-31 03:12:45 +00002589ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002590ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2591 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002592 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002593 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002594 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002595 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002596 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002597 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002598 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002599 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002600 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002601 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002602 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002603 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002604
Rafael Espindola692410e2014-01-21 23:06:54 +00002605 if (EC)
2606 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002607 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002608}
2609