blob: 79f8100649881b2e9458616dd9011b3baf6e1a7a [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),
Kevin Enderby9a509442015-01-27 21:28:24 +0000251 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
252 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
253 HasPageZeroSegment(false) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000254 uint32_t LoadCommandCount = this->getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000255 if (LoadCommandCount == 0)
256 return;
257
Charles Davis8bdfafd2013-09-01 04:28:48 +0000258 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
259 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000260
261 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000262 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000263 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000264 // Multiple symbol tables
265 if (SymtabLoadCmd) {
266 EC = object_error::parse_failed;
267 return;
268 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000269 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000270 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000271 // Multiple dynamic symbol tables
272 if (DysymtabLoadCmd) {
273 EC = object_error::parse_failed;
274 return;
275 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000276 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000277 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000278 // Multiple data in code tables
279 if (DataInCodeLoadCmd) {
280 EC = object_error::parse_failed;
281 return;
282 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000283 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000284 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
285 // Multiple linker optimization hint tables
286 if (LinkOptHintsLoadCmd) {
287 EC = object_error::parse_failed;
288 return;
289 }
290 LinkOptHintsLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000291 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
292 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000293 // Multiple dyldinfo load commands
294 if (DyldInfoLoadCmd) {
295 EC = object_error::parse_failed;
296 return;
297 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000298 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000299 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000300 // Multiple UUID load commands
301 if (UuidLoadCmd) {
302 EC = object_error::parse_failed;
303 return;
304 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000305 UuidLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000306 } else if (Load.C.cmd == SegmentLoadType) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +0000307 const unsigned SegmentLoadSize = this->is64Bit()
308 ? sizeof(MachO::segment_command_64)
309 : sizeof(MachO::segment_command);
310 if (Load.C.cmdsize < SegmentLoadSize)
311 report_fatal_error("Segment load command size is too small.");
312
Rafael Espindola56f976f2013-04-18 18:08:55 +0000313 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
314 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000315 const char *Sec = getSectionPtr(this, Load, J);
316 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000317 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000318 if (isPageZeroSegment(this, Load))
319 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000320 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
321 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
322 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
323 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
324 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
325 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000326 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000327
328 if (I == LoadCommandCount - 1)
329 break;
330 else
331 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000332 }
333}
334
Rafael Espindola5e812af2014-01-30 02:49:50 +0000335void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000336 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000337 sizeof(MachO::nlist_64) :
338 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000339 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000340}
341
Rafael Espindola3acea392014-06-12 21:46:39 +0000342std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
343 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000344 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000345 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000346 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000347 if (Start < getData().begin() || Start >= getData().end())
348 report_fatal_error(
349 "Symbol name entry points before beginning or past end of file.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000350 Res = StringRef(Start);
351 return object_error::success;
352}
353
Rafael Espindola0e77a942014-12-10 20:46:55 +0000354unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
355 DataRefImpl DRI = Sec.getRawDataRefImpl();
356 uint32_t Flags = getSectionFlags(this, DRI);
357 return Flags & MachO::SECTION_TYPE;
358}
359
Kevin Enderby980b2582014-06-05 21:21:57 +0000360// getIndirectName() returns the name of the alias'ed symbol who's string table
361// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000362std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
363 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000364 StringRef StringTable = getStringTableData();
365 uint64_t NValue;
366 if (is64Bit()) {
367 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
368 NValue = Entry.n_value;
369 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
370 return object_error::parse_failed;
371 } else {
372 MachO::nlist Entry = getSymbolTableEntry(Symb);
373 NValue = Entry.n_value;
374 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
375 return object_error::parse_failed;
376 }
377 if (NValue >= StringTable.size())
378 return object_error::parse_failed;
379 const char *Start = &StringTable.data()[NValue];
380 Res = StringRef(Start);
381 return object_error::success;
382}
383
Rafael Espindola3acea392014-06-12 21:46:39 +0000384std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
385 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000386 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000387 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000388 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
389 Entry.n_value == 0)
390 Res = UnknownAddressOrSize;
391 else
392 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000393 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000394 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000395 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
396 Entry.n_value == 0)
397 Res = UnknownAddressOrSize;
398 else
399 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000400 }
401 return object_error::success;
402}
403
Rafael Espindola3acea392014-06-12 21:46:39 +0000404std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
405 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000406 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000407 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000408 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000409 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000410 } else {
411 Result = 0;
412 }
413 return object_error::success;
414}
415
Rafael Espindola3acea392014-06-12 21:46:39 +0000416std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
417 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000418 uint64_t Value;
419 getSymbolAddress(DRI, Value);
Rafael Espindola62a07cb2015-05-22 15:43:00 +0000420 uint32_t flags = getSymbolFlags(DRI);
421 if (flags & SymbolRef::SF_Common)
422 Result = Value;
423 else
Kevin Enderby1b985af2014-05-20 23:04:47 +0000424 Result = UnknownAddressOrSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000425 return object_error::success;
426}
427
Rafael Espindola3acea392014-06-12 21:46:39 +0000428std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
429 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000430 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000431 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000432
433 Res = SymbolRef::ST_Other;
434
435 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000436 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437 Res = SymbolRef::ST_Debug;
438 return object_error::success;
439 }
440
Charles Davis74ec8b02013-08-27 05:00:13 +0000441 switch (n_type & MachO::N_TYPE) {
442 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000443 Res = SymbolRef::ST_Unknown;
444 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000445 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000446 Res = SymbolRef::ST_Function;
447 break;
448 }
449 return object_error::success;
450}
451
Rafael Espindola20122a42014-01-31 20:57:12 +0000452uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000453 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000454
Charles Davis8bdfafd2013-09-01 04:28:48 +0000455 uint8_t MachOType = Entry.n_type;
456 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000457
Rafael Espindola20122a42014-01-31 20:57:12 +0000458 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000459
Charles Davis74ec8b02013-08-27 05:00:13 +0000460 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000461 Result |= SymbolRef::SF_Undefined;
462
Tim Northovereaef0742014-05-30 13:22:59 +0000463 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
464 Result |= SymbolRef::SF_Indirect;
465
Rafael Espindolaa1356322013-11-02 05:03:24 +0000466 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000467 Result |= SymbolRef::SF_FormatSpecific;
468
Charles Davis74ec8b02013-08-27 05:00:13 +0000469 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000470 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000471 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000472 uint64_t Value;
473 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000474 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000475 Result |= SymbolRef::SF_Common;
476 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000477
478 if (!(MachOType & MachO::N_PEXT))
479 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000480 }
481
Charles Davis74ec8b02013-08-27 05:00:13 +0000482 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000483 Result |= SymbolRef::SF_Weak;
484
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000485 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
486 Result |= SymbolRef::SF_Thumb;
487
Charles Davis74ec8b02013-08-27 05:00:13 +0000488 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000489 Result |= SymbolRef::SF_Absolute;
490
Rafael Espindola20122a42014-01-31 20:57:12 +0000491 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000492}
493
Rafael Espindola3acea392014-06-12 21:46:39 +0000494std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
495 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000496 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000497 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000498
499 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000500 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000501 } else {
502 DataRefImpl DRI;
503 DRI.d.a = index - 1;
Rafael Espindola0d85d102015-05-22 14:59:27 +0000504 if (DRI.d.a >= Sections.size())
505 report_fatal_error("getSymbolSection: Invalid section index.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000506 Res = section_iterator(SectionRef(DRI, this));
507 }
508
509 return object_error::success;
510}
511
Rafael Espindola5e812af2014-01-30 02:49:50 +0000512void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000513 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000514}
515
Rafael Espindola3acea392014-06-12 21:46:39 +0000516std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
517 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000518 ArrayRef<char> Raw = getSectionRawName(Sec);
519 Result = parseSegmentOrSectionName(Raw.data());
520 return object_error::success;
521}
522
Rafael Espindola80291272014-10-08 15:28:58 +0000523uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
524 if (is64Bit())
525 return getSection64(Sec).addr;
526 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000527}
528
Rafael Espindola80291272014-10-08 15:28:58 +0000529uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
530 if (is64Bit())
531 return getSection64(Sec).size;
532 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000533}
534
Rafael Espindola3acea392014-06-12 21:46:39 +0000535std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
536 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537 uint32_t Offset;
538 uint64_t Size;
539
540 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000541 MachO::section_64 Sect = getSection64(Sec);
542 Offset = Sect.offset;
543 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000544 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000545 MachO::section Sect = getSection(Sec);
546 Offset = Sect.offset;
547 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000548 }
549
550 Res = this->getData().substr(Offset, Size);
551 return object_error::success;
552}
553
Rafael Espindola80291272014-10-08 15:28:58 +0000554uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000555 uint32_t Align;
556 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000557 MachO::section_64 Sect = getSection64(Sec);
558 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000559 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000560 MachO::section Sect = getSection(Sec);
561 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000562 }
563
Rafael Espindola80291272014-10-08 15:28:58 +0000564 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000565}
566
Rafael Espindola80291272014-10-08 15:28:58 +0000567bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000568 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000569 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000570}
571
Rafael Espindola80291272014-10-08 15:28:58 +0000572bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000573 uint32_t Flags = getSectionFlags(this, Sec);
574 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000575 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
576 !(SectionType == MachO::S_ZEROFILL ||
577 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000578}
579
Rafael Espindola80291272014-10-08 15:28:58 +0000580bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000581 uint32_t Flags = getSectionFlags(this, Sec);
582 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000583 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
584 (SectionType == MachO::S_ZEROFILL ||
585 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000586}
587
Rafael Espindola80291272014-10-08 15:28:58 +0000588bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000589 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000590 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000591}
592
Rafael Espindola80291272014-10-08 15:28:58 +0000593bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
594 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000595 SymbolRef::Type ST;
596 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000597 if (ST == SymbolRef::ST_Unknown)
598 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000599
Rafael Espindola80291272014-10-08 15:28:58 +0000600 uint64_t SectBegin = getSectionAddress(Sec);
601 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000602 SectEnd += SectBegin;
603
604 uint64_t SymAddr;
605 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000606 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000607}
608
Rui Ueyamabc654b12013-09-27 21:47:05 +0000609relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000610 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000611 Ret.d.a = Sec.d.a;
612 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000613 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000614}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000615
Rafael Espindola56f976f2013-04-18 18:08:55 +0000616relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000617MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000618 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000619 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000620 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000621 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000622 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000623 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000624 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000625 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000626
Rafael Espindola56f976f2013-04-18 18:08:55 +0000627 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000628 Ret.d.a = Sec.d.a;
629 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000630 return relocation_iterator(RelocationRef(Ret, this));
631}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000632
Rafael Espindola5e812af2014-01-30 02:49:50 +0000633void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000634 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000635}
Owen Anderson171f4852011-10-24 23:20:07 +0000636
Rafael Espindola3acea392014-06-12 21:46:39 +0000637std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
638 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000639 uint64_t Offset;
640 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000641
642 DataRefImpl Sec;
643 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000644 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000645 Res = SecAddress + Offset;
646 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000647}
648
Rafael Espindola3acea392014-06-12 21:46:39 +0000649std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
650 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000651 assert(getHeader().filetype == MachO::MH_OBJECT &&
652 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000653 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000654 Res = getAnyRelocationAddress(RE);
655 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000656}
657
Rafael Espindola806f0062013-06-05 01:33:53 +0000658symbol_iterator
659MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000660 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000661 if (isRelocationScattered(RE))
662 return symbol_end();
663
Rafael Espindola56f976f2013-04-18 18:08:55 +0000664 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
665 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000666 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000667 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000668
Charles Davis8bdfafd2013-09-01 04:28:48 +0000669 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000670 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000671 sizeof(MachO::nlist_64) :
672 sizeof(MachO::nlist);
673 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000674 DataRefImpl Sym;
675 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000676 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000677}
678
Keno Fischerc780e8e2015-05-21 21:24:32 +0000679section_iterator
680MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
681 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
682}
683
Rafael Espindola3acea392014-06-12 21:46:39 +0000684std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
685 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000686 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000687 Res = getAnyRelocationType(RE);
688 return object_error::success;
689}
690
Rafael Espindola3acea392014-06-12 21:46:39 +0000691std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000692MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
693 SmallVectorImpl<char> &Result) const {
694 StringRef res;
695 uint64_t RType;
696 getRelocationType(Rel, RType);
697
698 unsigned Arch = this->getArch();
699
700 switch (Arch) {
701 case Triple::x86: {
702 static const char *const Table[] = {
703 "GENERIC_RELOC_VANILLA",
704 "GENERIC_RELOC_PAIR",
705 "GENERIC_RELOC_SECTDIFF",
706 "GENERIC_RELOC_PB_LA_PTR",
707 "GENERIC_RELOC_LOCAL_SECTDIFF",
708 "GENERIC_RELOC_TLV" };
709
Eric Christopher13250cb2013-12-06 02:33:38 +0000710 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000711 res = "Unknown";
712 else
713 res = Table[RType];
714 break;
715 }
716 case Triple::x86_64: {
717 static const char *const Table[] = {
718 "X86_64_RELOC_UNSIGNED",
719 "X86_64_RELOC_SIGNED",
720 "X86_64_RELOC_BRANCH",
721 "X86_64_RELOC_GOT_LOAD",
722 "X86_64_RELOC_GOT",
723 "X86_64_RELOC_SUBTRACTOR",
724 "X86_64_RELOC_SIGNED_1",
725 "X86_64_RELOC_SIGNED_2",
726 "X86_64_RELOC_SIGNED_4",
727 "X86_64_RELOC_TLV" };
728
729 if (RType > 9)
730 res = "Unknown";
731 else
732 res = Table[RType];
733 break;
734 }
735 case Triple::arm: {
736 static const char *const Table[] = {
737 "ARM_RELOC_VANILLA",
738 "ARM_RELOC_PAIR",
739 "ARM_RELOC_SECTDIFF",
740 "ARM_RELOC_LOCAL_SECTDIFF",
741 "ARM_RELOC_PB_LA_PTR",
742 "ARM_RELOC_BR24",
743 "ARM_THUMB_RELOC_BR22",
744 "ARM_THUMB_32BIT_BRANCH",
745 "ARM_RELOC_HALF",
746 "ARM_RELOC_HALF_SECTDIFF" };
747
748 if (RType > 9)
749 res = "Unknown";
750 else
751 res = Table[RType];
752 break;
753 }
Tim Northover00ed9962014-03-29 10:18:08 +0000754 case Triple::aarch64: {
755 static const char *const Table[] = {
756 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
757 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
758 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
759 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
760 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
761 "ARM64_RELOC_ADDEND"
762 };
763
764 if (RType >= array_lengthof(Table))
765 res = "Unknown";
766 else
767 res = Table[RType];
768 break;
769 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000770 case Triple::ppc: {
771 static const char *const Table[] = {
772 "PPC_RELOC_VANILLA",
773 "PPC_RELOC_PAIR",
774 "PPC_RELOC_BR14",
775 "PPC_RELOC_BR24",
776 "PPC_RELOC_HI16",
777 "PPC_RELOC_LO16",
778 "PPC_RELOC_HA16",
779 "PPC_RELOC_LO14",
780 "PPC_RELOC_SECTDIFF",
781 "PPC_RELOC_PB_LA_PTR",
782 "PPC_RELOC_HI16_SECTDIFF",
783 "PPC_RELOC_LO16_SECTDIFF",
784 "PPC_RELOC_HA16_SECTDIFF",
785 "PPC_RELOC_JBSR",
786 "PPC_RELOC_LO14_SECTDIFF",
787 "PPC_RELOC_LOCAL_SECTDIFF" };
788
Eric Christopher13250cb2013-12-06 02:33:38 +0000789 if (RType > 15)
790 res = "Unknown";
791 else
792 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000793 break;
794 }
795 case Triple::UnknownArch:
796 res = "Unknown";
797 break;
798 }
799 Result.append(res.begin(), res.end());
800 return object_error::success;
801}
802
Rafael Espindola3acea392014-06-12 21:46:39 +0000803std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000804MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000805 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000806 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000807
Rafael Espindola56f976f2013-04-18 18:08:55 +0000808 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000809
Alp Tokere69170a2014-06-26 22:52:05 +0000810 std::string fmtbuf;
811 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000812 unsigned Type = this->getAnyRelocationType(RE);
813 bool IsPCRel = this->getAnyRelocationPCRel(RE);
814
815 // Determine any addends that should be displayed with the relocation.
816 // These require decoding the relocation type, which is triple-specific.
817
818 // X86_64 has entirely custom relocation types.
819 if (Arch == Triple::x86_64) {
820 bool isPCRel = getAnyRelocationPCRel(RE);
821
822 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000823 case MachO::X86_64_RELOC_GOT_LOAD:
824 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000825 printRelocationTargetName(this, RE, fmt);
826 fmt << "@GOT";
827 if (isPCRel) fmt << "PCREL";
828 break;
829 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000830 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000831 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000832 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000833 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000834
Charles Davis8bdfafd2013-09-01 04:28:48 +0000835 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000836 // X86_64_RELOC_UNSIGNED.
837 // NOTE: Scattered relocations don't exist on x86_64.
838 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000839 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000840 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
841 "X86_64_RELOC_SUBTRACTOR.");
842
Charles Davis8bdfafd2013-09-01 04:28:48 +0000843 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
844 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000845 printRelocationTargetName(this, RENext, fmt);
846 fmt << "-";
847 printRelocationTargetName(this, RE, fmt);
848 break;
849 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000850 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000851 printRelocationTargetName(this, RE, fmt);
852 fmt << "@TLV";
853 if (isPCRel) fmt << "P";
854 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000855 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000856 printRelocationTargetName(this, RE, fmt);
857 fmt << "-1";
858 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000859 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000860 printRelocationTargetName(this, RE, fmt);
861 fmt << "-2";
862 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000863 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000864 printRelocationTargetName(this, RE, fmt);
865 fmt << "-4";
866 break;
867 default:
868 printRelocationTargetName(this, RE, fmt);
869 break;
870 }
871 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000872 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
873 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000874 // Generic relocation types...
875 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000876 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000877 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000878 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000879 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000880 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000881 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000882
883 // X86 sect diff's must be followed by a relocation of type
884 // GENERIC_RELOC_PAIR.
885 unsigned RType = getAnyRelocationType(RENext);
886
Charles Davis8bdfafd2013-09-01 04:28:48 +0000887 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000888 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
889 "GENERIC_RELOC_SECTDIFF.");
890
891 printRelocationTargetName(this, RE, fmt);
892 fmt << "-";
893 printRelocationTargetName(this, RENext, fmt);
894 break;
895 }
896 }
897
David Fangb88cdf62013-08-08 20:14:40 +0000898 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000899 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000900 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000901 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000902 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000903 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000904
905 // X86 sect diff's must be followed by a relocation of type
906 // GENERIC_RELOC_PAIR.
907 unsigned RType = getAnyRelocationType(RENext);
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_LOCAL_SECTDIFF.");
911
912 printRelocationTargetName(this, RE, fmt);
913 fmt << "-";
914 printRelocationTargetName(this, RENext, fmt);
915 break;
916 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000917 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000918 printRelocationTargetName(this, RE, fmt);
919 fmt << "@TLV";
920 if (IsPCRel) fmt << "P";
921 break;
922 }
923 default:
924 printRelocationTargetName(this, RE, fmt);
925 }
926 } else { // ARM-specific relocations
927 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000928 case MachO::ARM_RELOC_HALF:
929 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000930 // Half relocations steal a bit from the length field to encode
931 // whether this is an upper16 or a lower16 relocation.
932 bool isUpper = getAnyRelocationLength(RE) >> 1;
933
934 if (isUpper)
935 fmt << ":upper16:(";
936 else
937 fmt << ":lower16:(";
938 printRelocationTargetName(this, RE, fmt);
939
940 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000941 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000942 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000943
944 // ARM half relocs must be followed by a relocation of type
945 // ARM_RELOC_PAIR.
946 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000947 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000948 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000949 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000950
951 // NOTE: The half of the target virtual address is stashed in the
952 // address field of the secondary relocation, but we can't reverse
953 // engineer the constant offset from it without decoding the movw/movt
954 // instruction to find the other half in its immediate field.
955
956 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
957 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000958 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000959 fmt << "-";
960 printRelocationTargetName(this, RENext, fmt);
961 }
962
963 fmt << ")";
964 break;
965 }
966 default: {
967 printRelocationTargetName(this, RE, fmt);
968 }
969 }
970 }
971 } else
972 printRelocationTargetName(this, RE, fmt);
973
Alp Tokere69170a2014-06-26 22:52:05 +0000974 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000975 Result.append(fmtbuf.begin(), fmtbuf.end());
976 return object_error::success;
977}
978
Rafael Espindola3acea392014-06-12 21:46:39 +0000979std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
980 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000981 unsigned Arch = getArch();
982 uint64_t Type;
983 getRelocationType(Rel, Type);
984
985 Result = false;
986
987 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
988 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000989 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000990 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000991 } else if (Arch == Triple::x86_64) {
992 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000993 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000994 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000995 DataRefImpl RelPrev = Rel;
996 RelPrev.d.a--;
997 uint64_t PrevType;
998 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000999 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001000 Result = true;
1001 }
1002 }
1003
1004 return object_error::success;
1005}
1006
Kevin Enderby980b2582014-06-05 21:21:57 +00001007//
1008// guessLibraryShortName() is passed a name of a dynamic library and returns a
1009// guess on what the short name is. Then name is returned as a substring of the
1010// StringRef Name passed in. The name of the dynamic library is recognized as
1011// a framework if it has one of the two following forms:
1012// Foo.framework/Versions/A/Foo
1013// Foo.framework/Foo
1014// Where A and Foo can be any string. And may contain a trailing suffix
1015// starting with an underbar. If the Name is recognized as a framework then
1016// isFramework is set to true else it is set to false. If the Name has a
1017// suffix then Suffix is set to the substring in Name that contains the suffix
1018// else it is set to a NULL StringRef.
1019//
1020// The Name of the dynamic library is recognized as a library name if it has
1021// one of the two following forms:
1022// libFoo.A.dylib
1023// libFoo.dylib
1024// The library may have a suffix trailing the name Foo of the form:
1025// libFoo_profile.A.dylib
1026// libFoo_profile.dylib
1027//
1028// The Name of the dynamic library is also recognized as a library name if it
1029// has the following form:
1030// Foo.qtx
1031//
1032// If the Name of the dynamic library is none of the forms above then a NULL
1033// StringRef is returned.
1034//
1035StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1036 bool &isFramework,
1037 StringRef &Suffix) {
1038 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1039 size_t a, b, c, d, Idx;
1040
1041 isFramework = false;
1042 Suffix = StringRef();
1043
1044 // Pull off the last component and make Foo point to it
1045 a = Name.rfind('/');
1046 if (a == Name.npos || a == 0)
1047 goto guess_library;
1048 Foo = Name.slice(a+1, Name.npos);
1049
1050 // Look for a suffix starting with a '_'
1051 Idx = Foo.rfind('_');
1052 if (Idx != Foo.npos && Foo.size() >= 2) {
1053 Suffix = Foo.slice(Idx, Foo.npos);
1054 Foo = Foo.slice(0, Idx);
1055 }
1056
1057 // First look for the form Foo.framework/Foo
1058 b = Name.rfind('/', a);
1059 if (b == Name.npos)
1060 Idx = 0;
1061 else
1062 Idx = b+1;
1063 F = Name.slice(Idx, Idx + Foo.size());
1064 DotFramework = Name.slice(Idx + Foo.size(),
1065 Idx + Foo.size() + sizeof(".framework/")-1);
1066 if (F == Foo && DotFramework == ".framework/") {
1067 isFramework = true;
1068 return Foo;
1069 }
1070
1071 // Next look for the form Foo.framework/Versions/A/Foo
1072 if (b == Name.npos)
1073 goto guess_library;
1074 c = Name.rfind('/', b);
1075 if (c == Name.npos || c == 0)
1076 goto guess_library;
1077 V = Name.slice(c+1, Name.npos);
1078 if (!V.startswith("Versions/"))
1079 goto guess_library;
1080 d = Name.rfind('/', c);
1081 if (d == Name.npos)
1082 Idx = 0;
1083 else
1084 Idx = d+1;
1085 F = Name.slice(Idx, Idx + Foo.size());
1086 DotFramework = Name.slice(Idx + Foo.size(),
1087 Idx + Foo.size() + sizeof(".framework/")-1);
1088 if (F == Foo && DotFramework == ".framework/") {
1089 isFramework = true;
1090 return Foo;
1091 }
1092
1093guess_library:
1094 // pull off the suffix after the "." and make a point to it
1095 a = Name.rfind('.');
1096 if (a == Name.npos || a == 0)
1097 return StringRef();
1098 Dylib = Name.slice(a, Name.npos);
1099 if (Dylib != ".dylib")
1100 goto guess_qtx;
1101
1102 // First pull off the version letter for the form Foo.A.dylib if any.
1103 if (a >= 3) {
1104 Dot = Name.slice(a-2, a-1);
1105 if (Dot == ".")
1106 a = a - 2;
1107 }
1108
1109 b = Name.rfind('/', a);
1110 if (b == Name.npos)
1111 b = 0;
1112 else
1113 b = b+1;
1114 // ignore any suffix after an underbar like Foo_profile.A.dylib
1115 Idx = Name.find('_', b);
1116 if (Idx != Name.npos && Idx != b) {
1117 Lib = Name.slice(b, Idx);
1118 Suffix = Name.slice(Idx, a);
1119 }
1120 else
1121 Lib = Name.slice(b, a);
1122 // There are incorrect library names of the form:
1123 // libATS.A_profile.dylib so check for these.
1124 if (Lib.size() >= 3) {
1125 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1126 if (Dot == ".")
1127 Lib = Lib.slice(0, Lib.size()-2);
1128 }
1129 return Lib;
1130
1131guess_qtx:
1132 Qtx = Name.slice(a, Name.npos);
1133 if (Qtx != ".qtx")
1134 return StringRef();
1135 b = Name.rfind('/', a);
1136 if (b == Name.npos)
1137 Lib = Name.slice(0, a);
1138 else
1139 Lib = Name.slice(b+1, a);
1140 // There are library names of the form: QT.A.qtx so check for these.
1141 if (Lib.size() >= 3) {
1142 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1143 if (Dot == ".")
1144 Lib = Lib.slice(0, Lib.size()-2);
1145 }
1146 return Lib;
1147}
1148
1149// getLibraryShortNameByIndex() is used to get the short name of the library
1150// for an undefined symbol in a linked Mach-O binary that was linked with the
1151// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1152// It is passed the index (0 - based) of the library as translated from
1153// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001154std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001155 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001156 if (Index >= Libraries.size())
1157 return object_error::parse_failed;
1158
Kevin Enderby980b2582014-06-05 21:21:57 +00001159 // If the cache of LibrariesShortNames is not built up do that first for
1160 // all the Libraries.
1161 if (LibrariesShortNames.size() == 0) {
1162 for (unsigned i = 0; i < Libraries.size(); i++) {
1163 MachO::dylib_command D =
1164 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001165 if (D.dylib.name >= D.cmdsize)
1166 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001167 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001168 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001169 if (D.dylib.name+Name.size() >= D.cmdsize)
1170 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001171 StringRef Suffix;
1172 bool isFramework;
1173 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001174 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001175 LibrariesShortNames.push_back(Name);
1176 else
1177 LibrariesShortNames.push_back(shortName);
1178 }
1179 }
1180
1181 Res = LibrariesShortNames[Index];
1182 return object_error::success;
1183}
1184
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001185basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001186 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001187}
1188
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001189basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001190 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001191 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001192 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001193
Charles Davis8bdfafd2013-09-01 04:28:48 +00001194 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001195 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001196 sizeof(MachO::nlist_64) :
1197 sizeof(MachO::nlist);
1198 unsigned Offset = Symtab.symoff +
1199 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001200 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001201 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001202}
1203
Lang Hames36072da2014-05-12 21:39:59 +00001204basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1205 DataRefImpl DRI;
1206 if (!SymtabLoadCmd)
1207 return basic_symbol_iterator(SymbolRef(DRI, this));
1208
1209 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001210 if (Index >= Symtab.nsyms)
1211 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001212 unsigned SymbolTableEntrySize =
1213 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1214 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1215 DRI.p += Index * SymbolTableEntrySize;
1216 return basic_symbol_iterator(SymbolRef(DRI, this));
1217}
1218
Rafael Espindolab5155a52014-02-10 20:24:04 +00001219section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001220 DataRefImpl DRI;
1221 return section_iterator(SectionRef(DRI, this));
1222}
1223
Rafael Espindolab5155a52014-02-10 20:24:04 +00001224section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001225 DataRefImpl DRI;
1226 DRI.d.a = Sections.size();
1227 return section_iterator(SectionRef(DRI, this));
1228}
1229
Rafael Espindola56f976f2013-04-18 18:08:55 +00001230uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001231 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001232}
1233
Rafael Espindola56f976f2013-04-18 18:08:55 +00001234StringRef MachOObjectFile::getFileFormatName() const {
1235 unsigned CPUType = getCPUType(this);
1236 if (!is64Bit()) {
1237 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001238 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001239 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001240 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001241 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001242 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001243 return "Mach-O 32-bit ppc";
1244 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001245 return "Mach-O 32-bit unknown";
1246 }
1247 }
1248
Rafael Espindola56f976f2013-04-18 18:08:55 +00001249 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001250 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001251 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001252 case llvm::MachO::CPU_TYPE_ARM64:
1253 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001254 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001255 return "Mach-O 64-bit ppc64";
1256 default:
1257 return "Mach-O 64-bit unknown";
1258 }
1259}
1260
Alexey Samsonove6388e62013-06-18 15:03:28 +00001261Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1262 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001263 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001264 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001265 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001266 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001267 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001268 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001269 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001270 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001271 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001272 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001273 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001274 return Triple::ppc64;
1275 default:
1276 return Triple::UnknownArch;
1277 }
1278}
1279
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001280Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1281 const char **McpuDefault) {
1282 if (McpuDefault)
1283 *McpuDefault = nullptr;
1284
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001285 switch (CPUType) {
1286 case MachO::CPU_TYPE_I386:
1287 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1288 case MachO::CPU_SUBTYPE_I386_ALL:
1289 return Triple("i386-apple-darwin");
1290 default:
1291 return Triple();
1292 }
1293 case MachO::CPU_TYPE_X86_64:
1294 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1295 case MachO::CPU_SUBTYPE_X86_64_ALL:
1296 return Triple("x86_64-apple-darwin");
1297 case MachO::CPU_SUBTYPE_X86_64_H:
1298 return Triple("x86_64h-apple-darwin");
1299 default:
1300 return Triple();
1301 }
1302 case MachO::CPU_TYPE_ARM:
1303 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1304 case MachO::CPU_SUBTYPE_ARM_V4T:
1305 return Triple("armv4t-apple-darwin");
1306 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1307 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001308 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1309 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001310 case MachO::CPU_SUBTYPE_ARM_V6:
1311 return Triple("armv6-apple-darwin");
1312 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001313 if (McpuDefault)
1314 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001315 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001316 case MachO::CPU_SUBTYPE_ARM_V7:
1317 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001318 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001319 if (McpuDefault)
1320 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001321 return Triple("armv7em-apple-darwin");
1322 case MachO::CPU_SUBTYPE_ARM_V7K:
1323 return Triple("armv7k-apple-darwin");
1324 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001325 if (McpuDefault)
1326 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001327 return Triple("armv7m-apple-darwin");
1328 case MachO::CPU_SUBTYPE_ARM_V7S:
1329 return Triple("armv7s-apple-darwin");
1330 default:
1331 return Triple();
1332 }
1333 case MachO::CPU_TYPE_ARM64:
1334 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1335 case MachO::CPU_SUBTYPE_ARM64_ALL:
1336 return Triple("arm64-apple-darwin");
1337 default:
1338 return Triple();
1339 }
1340 case MachO::CPU_TYPE_POWERPC:
1341 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1342 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1343 return Triple("ppc-apple-darwin");
1344 default:
1345 return Triple();
1346 }
1347 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001348 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001349 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1350 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001351 default:
1352 return Triple();
1353 }
1354 default:
1355 return Triple();
1356 }
1357}
1358
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001359Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1360 const char **McpuDefault) {
1361 if (McpuDefault)
1362 *McpuDefault = nullptr;
1363
1364 switch (CPUType) {
1365 case MachO::CPU_TYPE_ARM:
1366 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1367 case MachO::CPU_SUBTYPE_ARM_V4T:
1368 return Triple("thumbv4t-apple-darwin");
1369 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1370 return Triple("thumbv5e-apple-darwin");
1371 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1372 return Triple("xscale-apple-darwin");
1373 case MachO::CPU_SUBTYPE_ARM_V6:
1374 return Triple("thumbv6-apple-darwin");
1375 case MachO::CPU_SUBTYPE_ARM_V6M:
1376 if (McpuDefault)
1377 *McpuDefault = "cortex-m0";
1378 return Triple("thumbv6m-apple-darwin");
1379 case MachO::CPU_SUBTYPE_ARM_V7:
1380 return Triple("thumbv7-apple-darwin");
1381 case MachO::CPU_SUBTYPE_ARM_V7EM:
1382 if (McpuDefault)
1383 *McpuDefault = "cortex-m4";
1384 return Triple("thumbv7em-apple-darwin");
1385 case MachO::CPU_SUBTYPE_ARM_V7K:
1386 return Triple("thumbv7k-apple-darwin");
1387 case MachO::CPU_SUBTYPE_ARM_V7M:
1388 if (McpuDefault)
1389 *McpuDefault = "cortex-m3";
1390 return Triple("thumbv7m-apple-darwin");
1391 case MachO::CPU_SUBTYPE_ARM_V7S:
1392 return Triple("thumbv7s-apple-darwin");
1393 default:
1394 return Triple();
1395 }
1396 default:
1397 return Triple();
1398 }
1399}
1400
1401Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1402 const char **McpuDefault,
1403 Triple *ThumbTriple) {
1404 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1405 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1406 McpuDefault);
1407 return T;
1408}
1409
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001410Triple MachOObjectFile::getHostArch() {
1411 return Triple(sys::getDefaultTargetTriple());
1412}
1413
Rafael Espindola72318b42014-08-08 16:30:17 +00001414bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1415 return StringSwitch<bool>(ArchFlag)
1416 .Case("i386", true)
1417 .Case("x86_64", true)
1418 .Case("x86_64h", true)
1419 .Case("armv4t", true)
1420 .Case("arm", true)
1421 .Case("armv5e", true)
1422 .Case("armv6", true)
1423 .Case("armv6m", true)
1424 .Case("armv7em", true)
1425 .Case("armv7k", true)
1426 .Case("armv7m", true)
1427 .Case("armv7s", true)
1428 .Case("arm64", true)
1429 .Case("ppc", true)
1430 .Case("ppc64", true)
1431 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001432}
1433
Alexey Samsonove6388e62013-06-18 15:03:28 +00001434unsigned MachOObjectFile::getArch() const {
1435 return getArch(getCPUType(this));
1436}
1437
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001438Triple MachOObjectFile::getArch(const char **McpuDefault,
1439 Triple *ThumbTriple) const {
1440 Triple T;
1441 if (is64Bit()) {
1442 MachO::mach_header_64 H_64;
1443 H_64 = getHeader64();
1444 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1445 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1446 McpuDefault);
1447 } else {
1448 MachO::mach_header H;
1449 H = getHeader();
1450 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1451 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1452 McpuDefault);
1453 }
1454 return T;
1455}
1456
Rui Ueyamabc654b12013-09-27 21:47:05 +00001457relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001458 DataRefImpl DRI;
1459 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001460 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001461}
1462
Rui Ueyamabc654b12013-09-27 21:47:05 +00001463relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001464 DataRefImpl DRI;
1465 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001466 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001467}
1468
Kevin Enderby273ae012013-06-06 17:20:50 +00001469dice_iterator MachOObjectFile::begin_dices() const {
1470 DataRefImpl DRI;
1471 if (!DataInCodeLoadCmd)
1472 return dice_iterator(DiceRef(DRI, this));
1473
Charles Davis8bdfafd2013-09-01 04:28:48 +00001474 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1475 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001476 return dice_iterator(DiceRef(DRI, this));
1477}
1478
1479dice_iterator MachOObjectFile::end_dices() const {
1480 DataRefImpl DRI;
1481 if (!DataInCodeLoadCmd)
1482 return dice_iterator(DiceRef(DRI, this));
1483
Charles Davis8bdfafd2013-09-01 04:28:48 +00001484 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1485 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001486 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1487 return dice_iterator(DiceRef(DRI, this));
1488}
1489
Nick Kledzikd04bc352014-08-30 00:20:14 +00001490ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1491 : Trie(T), Malformed(false), Done(false) { }
1492
1493void ExportEntry::moveToFirst() {
1494 pushNode(0);
1495 pushDownUntilBottom();
1496}
1497
1498void ExportEntry::moveToEnd() {
1499 Stack.clear();
1500 Done = true;
1501}
1502
1503bool ExportEntry::operator==(const ExportEntry &Other) const {
1504 // Common case, one at end, other iterating from begin.
1505 if (Done || Other.Done)
1506 return (Done == Other.Done);
1507 // Not equal if different stack sizes.
1508 if (Stack.size() != Other.Stack.size())
1509 return false;
1510 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001511 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001512 return false;
1513 // Equal if all nodes in both stacks match.
1514 for (unsigned i=0; i < Stack.size(); ++i) {
1515 if (Stack[i].Start != Other.Stack[i].Start)
1516 return false;
1517 }
1518 return true;
1519}
1520
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001521uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1522 unsigned Count;
1523 uint64_t Result = decodeULEB128(Ptr, &Count);
1524 Ptr += Count;
1525 if (Ptr > Trie.end()) {
1526 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001527 Malformed = true;
1528 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001529 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001530}
1531
1532StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001533 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001534}
1535
1536uint64_t ExportEntry::flags() const {
1537 return Stack.back().Flags;
1538}
1539
1540uint64_t ExportEntry::address() const {
1541 return Stack.back().Address;
1542}
1543
1544uint64_t ExportEntry::other() const {
1545 return Stack.back().Other;
1546}
1547
1548StringRef ExportEntry::otherName() const {
1549 const char* ImportName = Stack.back().ImportName;
1550 if (ImportName)
1551 return StringRef(ImportName);
1552 return StringRef();
1553}
1554
1555uint32_t ExportEntry::nodeOffset() const {
1556 return Stack.back().Start - Trie.begin();
1557}
1558
1559ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1560 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1561 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1562 ParentStringLength(0), IsExportNode(false) {
1563}
1564
1565void ExportEntry::pushNode(uint64_t offset) {
1566 const uint8_t *Ptr = Trie.begin() + offset;
1567 NodeState State(Ptr);
1568 uint64_t ExportInfoSize = readULEB128(State.Current);
1569 State.IsExportNode = (ExportInfoSize != 0);
1570 const uint8_t* Children = State.Current + ExportInfoSize;
1571 if (State.IsExportNode) {
1572 State.Flags = readULEB128(State.Current);
1573 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1574 State.Address = 0;
1575 State.Other = readULEB128(State.Current); // dylib ordinal
1576 State.ImportName = reinterpret_cast<const char*>(State.Current);
1577 } else {
1578 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001579 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1580 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001581 }
1582 }
1583 State.ChildCount = *Children;
1584 State.Current = Children + 1;
1585 State.NextChildIndex = 0;
1586 State.ParentStringLength = CumulativeString.size();
1587 Stack.push_back(State);
1588}
1589
1590void ExportEntry::pushDownUntilBottom() {
1591 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1592 NodeState &Top = Stack.back();
1593 CumulativeString.resize(Top.ParentStringLength);
1594 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001595 char C = *Top.Current;
1596 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001597 }
1598 Top.Current += 1;
1599 uint64_t childNodeIndex = readULEB128(Top.Current);
1600 Top.NextChildIndex += 1;
1601 pushNode(childNodeIndex);
1602 }
1603 if (!Stack.back().IsExportNode) {
1604 Malformed = true;
1605 moveToEnd();
1606 }
1607}
1608
1609// We have a trie data structure and need a way to walk it that is compatible
1610// with the C++ iterator model. The solution is a non-recursive depth first
1611// traversal where the iterator contains a stack of parent nodes along with a
1612// string that is the accumulation of all edge strings along the parent chain
1613// to this point.
1614//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001615// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001616// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1617// node may have child nodes too.
1618//
1619// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1620// child until hitting a node with no children (which is an export node or
1621// else the trie is malformed). On the way down, each node is pushed on the
1622// stack ivar. If there is no more ways down, it pops up one and tries to go
1623// down a sibling path until a childless node is reached.
1624void ExportEntry::moveNext() {
1625 if (Stack.empty() || !Stack.back().IsExportNode) {
1626 Malformed = true;
1627 moveToEnd();
1628 return;
1629 }
1630
1631 Stack.pop_back();
1632 while (!Stack.empty()) {
1633 NodeState &Top = Stack.back();
1634 if (Top.NextChildIndex < Top.ChildCount) {
1635 pushDownUntilBottom();
1636 // Now at the next export node.
1637 return;
1638 } else {
1639 if (Top.IsExportNode) {
1640 // This node has no children but is itself an export node.
1641 CumulativeString.resize(Top.ParentStringLength);
1642 return;
1643 }
1644 Stack.pop_back();
1645 }
1646 }
1647 Done = true;
1648}
1649
1650iterator_range<export_iterator>
1651MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1652 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001653 if (Trie.size() == 0)
1654 Start.moveToEnd();
1655 else
1656 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001657
1658 ExportEntry Finish(Trie);
1659 Finish.moveToEnd();
1660
1661 return iterator_range<export_iterator>(export_iterator(Start),
1662 export_iterator(Finish));
1663}
1664
1665iterator_range<export_iterator> MachOObjectFile::exports() const {
1666 return exports(getDyldInfoExportsTrie());
1667}
1668
1669
Nick Kledzikac431442014-09-12 21:34:15 +00001670MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1671 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1672 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1673 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1674
1675void MachORebaseEntry::moveToFirst() {
1676 Ptr = Opcodes.begin();
1677 moveNext();
1678}
1679
1680void MachORebaseEntry::moveToEnd() {
1681 Ptr = Opcodes.end();
1682 RemainingLoopCount = 0;
1683 Done = true;
1684}
1685
1686void MachORebaseEntry::moveNext() {
1687 // If in the middle of some loop, move to next rebasing in loop.
1688 SegmentOffset += AdvanceAmount;
1689 if (RemainingLoopCount) {
1690 --RemainingLoopCount;
1691 return;
1692 }
1693 if (Ptr == Opcodes.end()) {
1694 Done = true;
1695 return;
1696 }
1697 bool More = true;
1698 while (More && !Malformed) {
1699 // Parse next opcode and set up next loop.
1700 uint8_t Byte = *Ptr++;
1701 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1702 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1703 switch (Opcode) {
1704 case MachO::REBASE_OPCODE_DONE:
1705 More = false;
1706 Done = true;
1707 moveToEnd();
1708 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1709 break;
1710 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1711 RebaseType = ImmValue;
1712 DEBUG_WITH_TYPE(
1713 "mach-o-rebase",
1714 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1715 << "RebaseType=" << (int) RebaseType << "\n");
1716 break;
1717 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1718 SegmentIndex = ImmValue;
1719 SegmentOffset = readULEB128();
1720 DEBUG_WITH_TYPE(
1721 "mach-o-rebase",
1722 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1723 << "SegmentIndex=" << SegmentIndex << ", "
1724 << format("SegmentOffset=0x%06X", SegmentOffset)
1725 << "\n");
1726 break;
1727 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1728 SegmentOffset += readULEB128();
1729 DEBUG_WITH_TYPE("mach-o-rebase",
1730 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1731 << format("SegmentOffset=0x%06X",
1732 SegmentOffset) << "\n");
1733 break;
1734 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1735 SegmentOffset += ImmValue * PointerSize;
1736 DEBUG_WITH_TYPE("mach-o-rebase",
1737 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1738 << format("SegmentOffset=0x%06X",
1739 SegmentOffset) << "\n");
1740 break;
1741 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1742 AdvanceAmount = PointerSize;
1743 RemainingLoopCount = ImmValue - 1;
1744 DEBUG_WITH_TYPE(
1745 "mach-o-rebase",
1746 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1747 << format("SegmentOffset=0x%06X", SegmentOffset)
1748 << ", AdvanceAmount=" << AdvanceAmount
1749 << ", RemainingLoopCount=" << RemainingLoopCount
1750 << "\n");
1751 return;
1752 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1753 AdvanceAmount = PointerSize;
1754 RemainingLoopCount = readULEB128() - 1;
1755 DEBUG_WITH_TYPE(
1756 "mach-o-rebase",
1757 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1758 << format("SegmentOffset=0x%06X", SegmentOffset)
1759 << ", AdvanceAmount=" << AdvanceAmount
1760 << ", RemainingLoopCount=" << RemainingLoopCount
1761 << "\n");
1762 return;
1763 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1764 AdvanceAmount = readULEB128() + PointerSize;
1765 RemainingLoopCount = 0;
1766 DEBUG_WITH_TYPE(
1767 "mach-o-rebase",
1768 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1769 << format("SegmentOffset=0x%06X", SegmentOffset)
1770 << ", AdvanceAmount=" << AdvanceAmount
1771 << ", RemainingLoopCount=" << RemainingLoopCount
1772 << "\n");
1773 return;
1774 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1775 RemainingLoopCount = readULEB128() - 1;
1776 AdvanceAmount = readULEB128() + PointerSize;
1777 DEBUG_WITH_TYPE(
1778 "mach-o-rebase",
1779 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1780 << format("SegmentOffset=0x%06X", SegmentOffset)
1781 << ", AdvanceAmount=" << AdvanceAmount
1782 << ", RemainingLoopCount=" << RemainingLoopCount
1783 << "\n");
1784 return;
1785 default:
1786 Malformed = true;
1787 }
1788 }
1789}
1790
1791uint64_t MachORebaseEntry::readULEB128() {
1792 unsigned Count;
1793 uint64_t Result = decodeULEB128(Ptr, &Count);
1794 Ptr += Count;
1795 if (Ptr > Opcodes.end()) {
1796 Ptr = Opcodes.end();
1797 Malformed = true;
1798 }
1799 return Result;
1800}
1801
1802uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1803
1804uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1805
1806StringRef MachORebaseEntry::typeName() const {
1807 switch (RebaseType) {
1808 case MachO::REBASE_TYPE_POINTER:
1809 return "pointer";
1810 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1811 return "text abs32";
1812 case MachO::REBASE_TYPE_TEXT_PCREL32:
1813 return "text rel32";
1814 }
1815 return "unknown";
1816}
1817
1818bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1819 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1820 return (Ptr == Other.Ptr) &&
1821 (RemainingLoopCount == Other.RemainingLoopCount) &&
1822 (Done == Other.Done);
1823}
1824
1825iterator_range<rebase_iterator>
1826MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1827 MachORebaseEntry Start(Opcodes, is64);
1828 Start.moveToFirst();
1829
1830 MachORebaseEntry Finish(Opcodes, is64);
1831 Finish.moveToEnd();
1832
1833 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1834 rebase_iterator(Finish));
1835}
1836
1837iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1838 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1839}
1840
Nick Kledzik56ebef42014-09-16 01:41:51 +00001841
1842MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1843 Kind BK)
1844 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1845 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1846 BindType(0), PointerSize(is64Bit ? 8 : 4),
1847 TableKind(BK), Malformed(false), Done(false) {}
1848
1849void MachOBindEntry::moveToFirst() {
1850 Ptr = Opcodes.begin();
1851 moveNext();
1852}
1853
1854void MachOBindEntry::moveToEnd() {
1855 Ptr = Opcodes.end();
1856 RemainingLoopCount = 0;
1857 Done = true;
1858}
1859
1860void MachOBindEntry::moveNext() {
1861 // If in the middle of some loop, move to next binding in loop.
1862 SegmentOffset += AdvanceAmount;
1863 if (RemainingLoopCount) {
1864 --RemainingLoopCount;
1865 return;
1866 }
1867 if (Ptr == Opcodes.end()) {
1868 Done = true;
1869 return;
1870 }
1871 bool More = true;
1872 while (More && !Malformed) {
1873 // Parse next opcode and set up next loop.
1874 uint8_t Byte = *Ptr++;
1875 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1876 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1877 int8_t SignExtended;
1878 const uint8_t *SymStart;
1879 switch (Opcode) {
1880 case MachO::BIND_OPCODE_DONE:
1881 if (TableKind == Kind::Lazy) {
1882 // Lazying bindings have a DONE opcode between entries. Need to ignore
1883 // it to advance to next entry. But need not if this is last entry.
1884 bool NotLastEntry = false;
1885 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1886 if (*P) {
1887 NotLastEntry = true;
1888 }
1889 }
1890 if (NotLastEntry)
1891 break;
1892 }
1893 More = false;
1894 Done = true;
1895 moveToEnd();
1896 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1897 break;
1898 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1899 Ordinal = ImmValue;
1900 DEBUG_WITH_TYPE(
1901 "mach-o-bind",
1902 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1903 << "Ordinal=" << Ordinal << "\n");
1904 break;
1905 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1906 Ordinal = readULEB128();
1907 DEBUG_WITH_TYPE(
1908 "mach-o-bind",
1909 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1910 << "Ordinal=" << Ordinal << "\n");
1911 break;
1912 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1913 if (ImmValue) {
1914 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1915 Ordinal = SignExtended;
1916 } else
1917 Ordinal = 0;
1918 DEBUG_WITH_TYPE(
1919 "mach-o-bind",
1920 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1921 << "Ordinal=" << Ordinal << "\n");
1922 break;
1923 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1924 Flags = ImmValue;
1925 SymStart = Ptr;
1926 while (*Ptr) {
1927 ++Ptr;
1928 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001929 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1930 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001931 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001932 DEBUG_WITH_TYPE(
1933 "mach-o-bind",
1934 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1935 << "SymbolName=" << SymbolName << "\n");
1936 if (TableKind == Kind::Weak) {
1937 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1938 return;
1939 }
1940 break;
1941 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1942 BindType = ImmValue;
1943 DEBUG_WITH_TYPE(
1944 "mach-o-bind",
1945 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1946 << "BindType=" << (int)BindType << "\n");
1947 break;
1948 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1949 Addend = readSLEB128();
1950 if (TableKind == Kind::Lazy)
1951 Malformed = true;
1952 DEBUG_WITH_TYPE(
1953 "mach-o-bind",
1954 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1955 << "Addend=" << Addend << "\n");
1956 break;
1957 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1958 SegmentIndex = ImmValue;
1959 SegmentOffset = readULEB128();
1960 DEBUG_WITH_TYPE(
1961 "mach-o-bind",
1962 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1963 << "SegmentIndex=" << SegmentIndex << ", "
1964 << format("SegmentOffset=0x%06X", SegmentOffset)
1965 << "\n");
1966 break;
1967 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1968 SegmentOffset += readULEB128();
1969 DEBUG_WITH_TYPE("mach-o-bind",
1970 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1971 << format("SegmentOffset=0x%06X",
1972 SegmentOffset) << "\n");
1973 break;
1974 case MachO::BIND_OPCODE_DO_BIND:
1975 AdvanceAmount = PointerSize;
1976 RemainingLoopCount = 0;
1977 DEBUG_WITH_TYPE("mach-o-bind",
1978 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1979 << format("SegmentOffset=0x%06X",
1980 SegmentOffset) << "\n");
1981 return;
1982 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001983 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001984 RemainingLoopCount = 0;
1985 if (TableKind == Kind::Lazy)
1986 Malformed = true;
1987 DEBUG_WITH_TYPE(
1988 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001989 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001990 << format("SegmentOffset=0x%06X", SegmentOffset)
1991 << ", AdvanceAmount=" << AdvanceAmount
1992 << ", RemainingLoopCount=" << RemainingLoopCount
1993 << "\n");
1994 return;
1995 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001996 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001997 RemainingLoopCount = 0;
1998 if (TableKind == Kind::Lazy)
1999 Malformed = true;
2000 DEBUG_WITH_TYPE("mach-o-bind",
2001 llvm::dbgs()
2002 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2003 << format("SegmentOffset=0x%06X",
2004 SegmentOffset) << "\n");
2005 return;
2006 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2007 RemainingLoopCount = readULEB128() - 1;
2008 AdvanceAmount = readULEB128() + PointerSize;
2009 if (TableKind == Kind::Lazy)
2010 Malformed = true;
2011 DEBUG_WITH_TYPE(
2012 "mach-o-bind",
2013 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2014 << format("SegmentOffset=0x%06X", SegmentOffset)
2015 << ", AdvanceAmount=" << AdvanceAmount
2016 << ", RemainingLoopCount=" << RemainingLoopCount
2017 << "\n");
2018 return;
2019 default:
2020 Malformed = true;
2021 }
2022 }
2023}
2024
2025uint64_t MachOBindEntry::readULEB128() {
2026 unsigned Count;
2027 uint64_t Result = decodeULEB128(Ptr, &Count);
2028 Ptr += Count;
2029 if (Ptr > Opcodes.end()) {
2030 Ptr = Opcodes.end();
2031 Malformed = true;
2032 }
2033 return Result;
2034}
2035
2036int64_t MachOBindEntry::readSLEB128() {
2037 unsigned Count;
2038 int64_t Result = decodeSLEB128(Ptr, &Count);
2039 Ptr += Count;
2040 if (Ptr > Opcodes.end()) {
2041 Ptr = Opcodes.end();
2042 Malformed = true;
2043 }
2044 return Result;
2045}
2046
2047
2048uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2049
2050uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2051
2052StringRef MachOBindEntry::typeName() const {
2053 switch (BindType) {
2054 case MachO::BIND_TYPE_POINTER:
2055 return "pointer";
2056 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2057 return "text abs32";
2058 case MachO::BIND_TYPE_TEXT_PCREL32:
2059 return "text rel32";
2060 }
2061 return "unknown";
2062}
2063
2064StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2065
2066int64_t MachOBindEntry::addend() const { return Addend; }
2067
2068uint32_t MachOBindEntry::flags() const { return Flags; }
2069
2070int MachOBindEntry::ordinal() const { return Ordinal; }
2071
2072bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2073 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2074 return (Ptr == Other.Ptr) &&
2075 (RemainingLoopCount == Other.RemainingLoopCount) &&
2076 (Done == Other.Done);
2077}
2078
2079iterator_range<bind_iterator>
2080MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2081 MachOBindEntry::Kind BKind) {
2082 MachOBindEntry Start(Opcodes, is64, BKind);
2083 Start.moveToFirst();
2084
2085 MachOBindEntry Finish(Opcodes, is64, BKind);
2086 Finish.moveToEnd();
2087
2088 return iterator_range<bind_iterator>(bind_iterator(Start),
2089 bind_iterator(Finish));
2090}
2091
2092iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2093 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2094 MachOBindEntry::Kind::Regular);
2095}
2096
2097iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2098 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2099 MachOBindEntry::Kind::Lazy);
2100}
2101
2102iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2103 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2104 MachOBindEntry::Kind::Weak);
2105}
2106
Rafael Espindola56f976f2013-04-18 18:08:55 +00002107StringRef
2108MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2109 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2110 return parseSegmentOrSectionName(Raw.data());
2111}
2112
2113ArrayRef<char>
2114MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002115 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002116 const section_base *Base =
2117 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002118 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002119}
2120
2121ArrayRef<char>
2122MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002123 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002124 const section_base *Base =
2125 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002126 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002127}
2128
2129bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002130MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002131 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002132 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002133 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002134 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002135}
2136
Eric Christopher1d62c252013-07-22 22:25:07 +00002137unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002138 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002139 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002140 return RE.r_word1 & 0xffffff;
2141 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002142}
2143
Eric Christopher1d62c252013-07-22 22:25:07 +00002144bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002145 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002146 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002147 return (RE.r_word1 >> 27) & 1;
2148 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002149}
2150
Eric Christopher1d62c252013-07-22 22:25:07 +00002151bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002152 const MachO::any_relocation_info &RE) const {
2153 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002154}
2155
Eric Christopher1d62c252013-07-22 22:25:07 +00002156uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002157 const MachO::any_relocation_info &RE) const {
2158 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002159}
2160
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002161uint32_t MachOObjectFile::getScatteredRelocationType(
2162 const MachO::any_relocation_info &RE) const {
2163 return (RE.r_word0 >> 24) & 0xf;
2164}
2165
Eric Christopher1d62c252013-07-22 22:25:07 +00002166unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002167 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002168 if (isRelocationScattered(RE))
2169 return getScatteredRelocationAddress(RE);
2170 return getPlainRelocationAddress(RE);
2171}
2172
Charles Davis8bdfafd2013-09-01 04:28:48 +00002173unsigned MachOObjectFile::getAnyRelocationPCRel(
2174 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002175 if (isRelocationScattered(RE))
2176 return getScatteredRelocationPCRel(this, RE);
2177 return getPlainRelocationPCRel(this, RE);
2178}
2179
Eric Christopher1d62c252013-07-22 22:25:07 +00002180unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002181 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002182 if (isRelocationScattered(RE))
2183 return getScatteredRelocationLength(RE);
2184 return getPlainRelocationLength(this, RE);
2185}
2186
2187unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002188MachOObjectFile::getAnyRelocationType(
2189 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002190 if (isRelocationScattered(RE))
2191 return getScatteredRelocationType(RE);
2192 return getPlainRelocationType(this, RE);
2193}
2194
Rafael Espindola52501032013-04-30 15:40:54 +00002195SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002196MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002197 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002198 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002199 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002200 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2201 DataRefImpl DRI;
2202 DRI.d.a = SecNum;
2203 return SectionRef(DRI, this);
2204}
2205
Rafael Espindola56f976f2013-04-18 18:08:55 +00002206MachOObjectFile::LoadCommandInfo
2207MachOObjectFile::getFirstLoadCommandInfo() const {
2208 MachOObjectFile::LoadCommandInfo Load;
2209
Charles Davis8bdfafd2013-09-01 04:28:48 +00002210 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2211 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002212 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002213 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002214 if (Load.C.cmdsize < 8)
2215 report_fatal_error("Load command with size < 8 bytes.");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002216 return Load;
2217}
2218
2219MachOObjectFile::LoadCommandInfo
2220MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2221 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002222 Next.Ptr = L.Ptr + L.C.cmdsize;
2223 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002224 if (Next.C.cmdsize < 8)
2225 report_fatal_error("Load command with size < 8 bytes.");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002226 return Next;
2227}
2228
Charles Davis8bdfafd2013-09-01 04:28:48 +00002229MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002230 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002231 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002232}
2233
Charles Davis8bdfafd2013-09-01 04:28:48 +00002234MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002235 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002236 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002237}
2238
Charles Davis8bdfafd2013-09-01 04:28:48 +00002239MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002240 unsigned Index) const {
2241 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002242 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002243}
2244
Charles Davis8bdfafd2013-09-01 04:28:48 +00002245MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2246 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002247 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002248 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002249}
2250
Charles Davis8bdfafd2013-09-01 04:28:48 +00002251MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002252MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002253 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002254 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002255}
2256
Charles Davis8bdfafd2013-09-01 04:28:48 +00002257MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002258MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002259 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002260 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002261}
2262
Charles Davis8bdfafd2013-09-01 04:28:48 +00002263MachO::linkedit_data_command
2264MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2265 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002266}
2267
Charles Davis8bdfafd2013-09-01 04:28:48 +00002268MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002269MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002270 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002271}
2272
Charles Davis8bdfafd2013-09-01 04:28:48 +00002273MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002274MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002275 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002276}
2277
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002278MachO::linker_option_command
2279MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2280 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002281}
2282
Jim Grosbach448334a2014-03-18 22:09:05 +00002283MachO::version_min_command
2284MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2285 return getStruct<MachO::version_min_command>(this, L.Ptr);
2286}
2287
Tim Northover8f9590b2014-06-30 14:40:57 +00002288MachO::dylib_command
2289MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2290 return getStruct<MachO::dylib_command>(this, L.Ptr);
2291}
2292
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002293MachO::dyld_info_command
2294MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2295 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2296}
2297
2298MachO::dylinker_command
2299MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2300 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2301}
2302
2303MachO::uuid_command
2304MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2305 return getStruct<MachO::uuid_command>(this, L.Ptr);
2306}
2307
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002308MachO::rpath_command
2309MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2310 return getStruct<MachO::rpath_command>(this, L.Ptr);
2311}
2312
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002313MachO::source_version_command
2314MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2315 return getStruct<MachO::source_version_command>(this, L.Ptr);
2316}
2317
2318MachO::entry_point_command
2319MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2320 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2321}
2322
Kevin Enderby0804f4672014-12-16 23:25:52 +00002323MachO::encryption_info_command
2324MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2325 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2326}
2327
Kevin Enderby57538292014-12-17 01:01:30 +00002328MachO::encryption_info_command_64
2329MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2330 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2331}
2332
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002333MachO::sub_framework_command
2334MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2335 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2336}
Tim Northover8f9590b2014-06-30 14:40:57 +00002337
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002338MachO::sub_umbrella_command
2339MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2340 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2341}
2342
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002343MachO::sub_library_command
2344MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2345 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2346}
2347
Kevin Enderby186eac32014-12-19 21:06:24 +00002348MachO::sub_client_command
2349MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2350 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2351}
2352
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002353MachO::routines_command
2354MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2355 return getStruct<MachO::routines_command>(this, L.Ptr);
2356}
2357
2358MachO::routines_command_64
2359MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2360 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2361}
2362
Kevin Enderby48ef5342014-12-23 22:56:39 +00002363MachO::thread_command
2364MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2365 return getStruct<MachO::thread_command>(this, L.Ptr);
2366}
2367
Charles Davis8bdfafd2013-09-01 04:28:48 +00002368MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002369MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002370 DataRefImpl Sec;
2371 Sec.d.a = Rel.d.a;
2372 uint32_t Offset;
2373 if (is64Bit()) {
2374 MachO::section_64 Sect = getSection64(Sec);
2375 Offset = Sect.reloff;
2376 } else {
2377 MachO::section Sect = getSection(Sec);
2378 Offset = Sect.reloff;
2379 }
2380
2381 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2382 getPtr(this, Offset)) + Rel.d.b;
2383 return getStruct<MachO::any_relocation_info>(
2384 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002385}
2386
Charles Davis8bdfafd2013-09-01 04:28:48 +00002387MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002388MachOObjectFile::getDice(DataRefImpl Rel) const {
2389 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002390 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002391}
2392
Charles Davis8bdfafd2013-09-01 04:28:48 +00002393MachO::mach_header MachOObjectFile::getHeader() const {
2394 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002395}
2396
Charles Davis8bdfafd2013-09-01 04:28:48 +00002397MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2398 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002399}
2400
Charles Davis8bdfafd2013-09-01 04:28:48 +00002401uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2402 const MachO::dysymtab_command &DLC,
2403 unsigned Index) const {
2404 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2405 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002406}
2407
Charles Davis8bdfafd2013-09-01 04:28:48 +00002408MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002409MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2410 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002411 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2412 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002413}
2414
Charles Davis8bdfafd2013-09-01 04:28:48 +00002415MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002416 if (SymtabLoadCmd)
2417 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2418
2419 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2420 MachO::symtab_command Cmd;
2421 Cmd.cmd = MachO::LC_SYMTAB;
2422 Cmd.cmdsize = sizeof(MachO::symtab_command);
2423 Cmd.symoff = 0;
2424 Cmd.nsyms = 0;
2425 Cmd.stroff = 0;
2426 Cmd.strsize = 0;
2427 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002428}
2429
Charles Davis8bdfafd2013-09-01 04:28:48 +00002430MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002431 if (DysymtabLoadCmd)
2432 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2433
2434 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2435 MachO::dysymtab_command Cmd;
2436 Cmd.cmd = MachO::LC_DYSYMTAB;
2437 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2438 Cmd.ilocalsym = 0;
2439 Cmd.nlocalsym = 0;
2440 Cmd.iextdefsym = 0;
2441 Cmd.nextdefsym = 0;
2442 Cmd.iundefsym = 0;
2443 Cmd.nundefsym = 0;
2444 Cmd.tocoff = 0;
2445 Cmd.ntoc = 0;
2446 Cmd.modtaboff = 0;
2447 Cmd.nmodtab = 0;
2448 Cmd.extrefsymoff = 0;
2449 Cmd.nextrefsyms = 0;
2450 Cmd.indirectsymoff = 0;
2451 Cmd.nindirectsyms = 0;
2452 Cmd.extreloff = 0;
2453 Cmd.nextrel = 0;
2454 Cmd.locreloff = 0;
2455 Cmd.nlocrel = 0;
2456 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002457}
2458
Charles Davis8bdfafd2013-09-01 04:28:48 +00002459MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002460MachOObjectFile::getDataInCodeLoadCommand() const {
2461 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002462 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002463
2464 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002465 MachO::linkedit_data_command Cmd;
2466 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2467 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2468 Cmd.dataoff = 0;
2469 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002470 return Cmd;
2471}
2472
Kevin Enderby9a509442015-01-27 21:28:24 +00002473MachO::linkedit_data_command
2474MachOObjectFile::getLinkOptHintsLoadCommand() const {
2475 if (LinkOptHintsLoadCmd)
2476 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2477
2478 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2479 // fields.
2480 MachO::linkedit_data_command Cmd;
2481 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2482 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2483 Cmd.dataoff = 0;
2484 Cmd.datasize = 0;
2485 return Cmd;
2486}
2487
Nick Kledzikd04bc352014-08-30 00:20:14 +00002488ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2489 if (!DyldInfoLoadCmd)
2490 return ArrayRef<uint8_t>();
2491
2492 MachO::dyld_info_command DyldInfo
2493 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2494 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2495 getPtr(this, DyldInfo.rebase_off));
2496 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2497}
2498
2499ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2500 if (!DyldInfoLoadCmd)
2501 return ArrayRef<uint8_t>();
2502
2503 MachO::dyld_info_command DyldInfo
2504 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2505 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2506 getPtr(this, DyldInfo.bind_off));
2507 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2508}
2509
2510ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2511 if (!DyldInfoLoadCmd)
2512 return ArrayRef<uint8_t>();
2513
2514 MachO::dyld_info_command DyldInfo
2515 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2516 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2517 getPtr(this, DyldInfo.weak_bind_off));
2518 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2519}
2520
2521ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2522 if (!DyldInfoLoadCmd)
2523 return ArrayRef<uint8_t>();
2524
2525 MachO::dyld_info_command DyldInfo
2526 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2527 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2528 getPtr(this, DyldInfo.lazy_bind_off));
2529 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2530}
2531
2532ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2533 if (!DyldInfoLoadCmd)
2534 return ArrayRef<uint8_t>();
2535
2536 MachO::dyld_info_command DyldInfo
2537 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2538 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2539 getPtr(this, DyldInfo.export_off));
2540 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2541}
2542
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002543ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2544 if (!UuidLoadCmd)
2545 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002546 // Returning a pointer is fine as uuid doesn't need endian swapping.
2547 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2548 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002549}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002550
Rafael Espindola6e040c02013-04-26 20:07:33 +00002551StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002552 MachO::symtab_command S = getSymtabLoadCommand();
2553 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002554}
2555
Rafael Espindola56f976f2013-04-18 18:08:55 +00002556bool MachOObjectFile::is64Bit() const {
2557 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002558 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002559}
2560
2561void MachOObjectFile::ReadULEB128s(uint64_t Index,
2562 SmallVectorImpl<uint64_t> &Out) const {
2563 DataExtractor extractor(ObjectFile::getData(), true, 0);
2564
2565 uint32_t offset = Index;
2566 uint64_t data = 0;
2567 while (uint64_t delta = extractor.getULEB128(&offset)) {
2568 data += delta;
2569 Out.push_back(data);
2570 }
2571}
2572
Rafael Espindolac66d7612014-08-17 19:09:37 +00002573bool MachOObjectFile::isRelocatableObject() const {
2574 return getHeader().filetype == MachO::MH_OBJECT;
2575}
2576
Rafael Espindola437b0d52014-07-31 03:12:45 +00002577ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002578ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2579 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002580 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002581 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002582 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002583 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002584 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002585 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002586 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002587 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002588 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002589 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002590 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002591 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002592
Rafael Espindola692410e2014-01-21 23:06:54 +00002593 if (EC)
2594 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002595 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002596}
2597