blob: e1ace497ca2484be60d5ac125526f5a7aa00ee8e [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 Espindolaa4d224722015-05-31 23:52:50 +0000404uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000405 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000406 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000407 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000408 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000409 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000410 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000411}
412
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000413uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000414 uint64_t Value;
415 getSymbolAddress(DRI, Value);
Rafael Espindola62a07cb2015-05-22 15:43:00 +0000416 uint32_t flags = getSymbolFlags(DRI);
417 if (flags & SymbolRef::SF_Common)
Rafael Espindola5eb02e42015-06-01 00:27:26 +0000418 return Value;
419 return UnknownAddressOrSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000420}
421
Rafael Espindola3acea392014-06-12 21:46:39 +0000422std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
423 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000424 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000425 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000426
427 Res = SymbolRef::ST_Other;
428
429 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000430 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000431 Res = SymbolRef::ST_Debug;
432 return object_error::success;
433 }
434
Charles Davis74ec8b02013-08-27 05:00:13 +0000435 switch (n_type & MachO::N_TYPE) {
436 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437 Res = SymbolRef::ST_Unknown;
438 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000439 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000440 Res = SymbolRef::ST_Function;
441 break;
442 }
443 return object_error::success;
444}
445
Rafael Espindola20122a42014-01-31 20:57:12 +0000446uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000447 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000448
Charles Davis8bdfafd2013-09-01 04:28:48 +0000449 uint8_t MachOType = Entry.n_type;
450 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000451
Rafael Espindola20122a42014-01-31 20:57:12 +0000452 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000453
Charles Davis74ec8b02013-08-27 05:00:13 +0000454 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000455 Result |= SymbolRef::SF_Undefined;
456
Tim Northovereaef0742014-05-30 13:22:59 +0000457 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
458 Result |= SymbolRef::SF_Indirect;
459
Rafael Espindolaa1356322013-11-02 05:03:24 +0000460 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000461 Result |= SymbolRef::SF_FormatSpecific;
462
Charles Davis74ec8b02013-08-27 05:00:13 +0000463 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000464 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000465 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000466 uint64_t Value;
467 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000468 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000469 Result |= SymbolRef::SF_Common;
470 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000471
472 if (!(MachOType & MachO::N_PEXT))
473 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000474 }
475
Charles Davis74ec8b02013-08-27 05:00:13 +0000476 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000477 Result |= SymbolRef::SF_Weak;
478
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000479 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
480 Result |= SymbolRef::SF_Thumb;
481
Charles Davis74ec8b02013-08-27 05:00:13 +0000482 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000483 Result |= SymbolRef::SF_Absolute;
484
Rafael Espindola20122a42014-01-31 20:57:12 +0000485 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000486}
487
Rafael Espindola3acea392014-06-12 21:46:39 +0000488std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
489 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000490 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000491 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000492
493 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000494 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000495 } else {
496 DataRefImpl DRI;
497 DRI.d.a = index - 1;
Rafael Espindola0d85d102015-05-22 14:59:27 +0000498 if (DRI.d.a >= Sections.size())
499 report_fatal_error("getSymbolSection: Invalid section index.");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000500 Res = section_iterator(SectionRef(DRI, this));
501 }
502
503 return object_error::success;
504}
505
Rafael Espindola5e812af2014-01-30 02:49:50 +0000506void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000507 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000508}
509
Rafael Espindola3acea392014-06-12 21:46:39 +0000510std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
511 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000512 ArrayRef<char> Raw = getSectionRawName(Sec);
513 Result = parseSegmentOrSectionName(Raw.data());
514 return object_error::success;
515}
516
Rafael Espindola80291272014-10-08 15:28:58 +0000517uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
518 if (is64Bit())
519 return getSection64(Sec).addr;
520 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000521}
522
Rafael Espindola80291272014-10-08 15:28:58 +0000523uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
524 if (is64Bit())
525 return getSection64(Sec).size;
526 return getSection(Sec).size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000527}
528
Rafael Espindola3acea392014-06-12 21:46:39 +0000529std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
530 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000531 uint32_t Offset;
532 uint64_t Size;
533
534 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000535 MachO::section_64 Sect = getSection64(Sec);
536 Offset = Sect.offset;
537 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000538 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000539 MachO::section Sect = getSection(Sec);
540 Offset = Sect.offset;
541 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000542 }
543
544 Res = this->getData().substr(Offset, Size);
545 return object_error::success;
546}
547
Rafael Espindola80291272014-10-08 15:28:58 +0000548uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000549 uint32_t Align;
550 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000551 MachO::section_64 Sect = getSection64(Sec);
552 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000553 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000554 MachO::section Sect = getSection(Sec);
555 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000556 }
557
Rafael Espindola80291272014-10-08 15:28:58 +0000558 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000559}
560
Rafael Espindola80291272014-10-08 15:28:58 +0000561bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000562 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000563 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000564}
565
Rafael Espindola80291272014-10-08 15:28:58 +0000566bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000567 uint32_t Flags = getSectionFlags(this, Sec);
568 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000569 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
570 !(SectionType == MachO::S_ZEROFILL ||
571 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000572}
573
Rafael Espindola80291272014-10-08 15:28:58 +0000574bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000575 uint32_t Flags = getSectionFlags(this, Sec);
576 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000577 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
578 (SectionType == MachO::S_ZEROFILL ||
579 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000580}
581
Rafael Espindola80291272014-10-08 15:28:58 +0000582bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000583 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000584 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000585}
586
Rafael Espindola80291272014-10-08 15:28:58 +0000587bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
588 DataRefImpl Symb) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000589 SymbolRef::Type ST;
590 this->getSymbolType(Symb, ST);
Rafael Espindola80291272014-10-08 15:28:58 +0000591 if (ST == SymbolRef::ST_Unknown)
592 return false;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000593
Rafael Espindola80291272014-10-08 15:28:58 +0000594 uint64_t SectBegin = getSectionAddress(Sec);
595 uint64_t SectEnd = getSectionSize(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000596 SectEnd += SectBegin;
597
598 uint64_t SymAddr;
599 getSymbolAddress(Symb, SymAddr);
Rafael Espindola80291272014-10-08 15:28:58 +0000600 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000601}
602
Rui Ueyamabc654b12013-09-27 21:47:05 +0000603relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000604 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000605 Ret.d.a = Sec.d.a;
606 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000607 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000608}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000609
Rafael Espindola56f976f2013-04-18 18:08:55 +0000610relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000611MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000612 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000613 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000614 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000615 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000616 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000617 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000618 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000619 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000620
Rafael Espindola56f976f2013-04-18 18:08:55 +0000621 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000622 Ret.d.a = Sec.d.a;
623 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000624 return relocation_iterator(RelocationRef(Ret, this));
625}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000626
Rafael Espindola5e812af2014-01-30 02:49:50 +0000627void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000628 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000629}
Owen Anderson171f4852011-10-24 23:20:07 +0000630
Rafael Espindola3acea392014-06-12 21:46:39 +0000631std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
632 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000633 uint64_t Offset;
634 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000635
636 DataRefImpl Sec;
637 Sec.d.a = Rel.d.a;
Rafael Espindola80291272014-10-08 15:28:58 +0000638 uint64_t SecAddress = getSectionAddress(Sec);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000639 Res = SecAddress + Offset;
640 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000641}
642
Rafael Espindola3acea392014-06-12 21:46:39 +0000643std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
644 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000645 assert(getHeader().filetype == MachO::MH_OBJECT &&
646 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000647 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000648 Res = getAnyRelocationAddress(RE);
649 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000650}
651
Rafael Espindola806f0062013-06-05 01:33:53 +0000652symbol_iterator
653MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000654 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000655 if (isRelocationScattered(RE))
656 return symbol_end();
657
Rafael Espindola56f976f2013-04-18 18:08:55 +0000658 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
659 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000660 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000661 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000662
Charles Davis8bdfafd2013-09-01 04:28:48 +0000663 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000664 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000665 sizeof(MachO::nlist_64) :
666 sizeof(MachO::nlist);
667 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000668 DataRefImpl Sym;
669 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000670 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000671}
672
Keno Fischerc780e8e2015-05-21 21:24:32 +0000673section_iterator
674MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
675 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
676}
677
Rafael Espindola3acea392014-06-12 21:46:39 +0000678std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
679 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000680 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000681 Res = getAnyRelocationType(RE);
682 return object_error::success;
683}
684
Rafael Espindola3acea392014-06-12 21:46:39 +0000685std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000686MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
687 SmallVectorImpl<char> &Result) const {
688 StringRef res;
689 uint64_t RType;
690 getRelocationType(Rel, RType);
691
692 unsigned Arch = this->getArch();
693
694 switch (Arch) {
695 case Triple::x86: {
696 static const char *const Table[] = {
697 "GENERIC_RELOC_VANILLA",
698 "GENERIC_RELOC_PAIR",
699 "GENERIC_RELOC_SECTDIFF",
700 "GENERIC_RELOC_PB_LA_PTR",
701 "GENERIC_RELOC_LOCAL_SECTDIFF",
702 "GENERIC_RELOC_TLV" };
703
Eric Christopher13250cb2013-12-06 02:33:38 +0000704 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000705 res = "Unknown";
706 else
707 res = Table[RType];
708 break;
709 }
710 case Triple::x86_64: {
711 static const char *const Table[] = {
712 "X86_64_RELOC_UNSIGNED",
713 "X86_64_RELOC_SIGNED",
714 "X86_64_RELOC_BRANCH",
715 "X86_64_RELOC_GOT_LOAD",
716 "X86_64_RELOC_GOT",
717 "X86_64_RELOC_SUBTRACTOR",
718 "X86_64_RELOC_SIGNED_1",
719 "X86_64_RELOC_SIGNED_2",
720 "X86_64_RELOC_SIGNED_4",
721 "X86_64_RELOC_TLV" };
722
723 if (RType > 9)
724 res = "Unknown";
725 else
726 res = Table[RType];
727 break;
728 }
729 case Triple::arm: {
730 static const char *const Table[] = {
731 "ARM_RELOC_VANILLA",
732 "ARM_RELOC_PAIR",
733 "ARM_RELOC_SECTDIFF",
734 "ARM_RELOC_LOCAL_SECTDIFF",
735 "ARM_RELOC_PB_LA_PTR",
736 "ARM_RELOC_BR24",
737 "ARM_THUMB_RELOC_BR22",
738 "ARM_THUMB_32BIT_BRANCH",
739 "ARM_RELOC_HALF",
740 "ARM_RELOC_HALF_SECTDIFF" };
741
742 if (RType > 9)
743 res = "Unknown";
744 else
745 res = Table[RType];
746 break;
747 }
Tim Northover00ed9962014-03-29 10:18:08 +0000748 case Triple::aarch64: {
749 static const char *const Table[] = {
750 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
751 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
752 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
753 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
754 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
755 "ARM64_RELOC_ADDEND"
756 };
757
758 if (RType >= array_lengthof(Table))
759 res = "Unknown";
760 else
761 res = Table[RType];
762 break;
763 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000764 case Triple::ppc: {
765 static const char *const Table[] = {
766 "PPC_RELOC_VANILLA",
767 "PPC_RELOC_PAIR",
768 "PPC_RELOC_BR14",
769 "PPC_RELOC_BR24",
770 "PPC_RELOC_HI16",
771 "PPC_RELOC_LO16",
772 "PPC_RELOC_HA16",
773 "PPC_RELOC_LO14",
774 "PPC_RELOC_SECTDIFF",
775 "PPC_RELOC_PB_LA_PTR",
776 "PPC_RELOC_HI16_SECTDIFF",
777 "PPC_RELOC_LO16_SECTDIFF",
778 "PPC_RELOC_HA16_SECTDIFF",
779 "PPC_RELOC_JBSR",
780 "PPC_RELOC_LO14_SECTDIFF",
781 "PPC_RELOC_LOCAL_SECTDIFF" };
782
Eric Christopher13250cb2013-12-06 02:33:38 +0000783 if (RType > 15)
784 res = "Unknown";
785 else
786 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000787 break;
788 }
789 case Triple::UnknownArch:
790 res = "Unknown";
791 break;
792 }
793 Result.append(res.begin(), res.end());
794 return object_error::success;
795}
796
Rafael Espindola3acea392014-06-12 21:46:39 +0000797std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000798MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000799 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000800 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000801
Rafael Espindola56f976f2013-04-18 18:08:55 +0000802 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000803
Alp Tokere69170a2014-06-26 22:52:05 +0000804 std::string fmtbuf;
805 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000806 unsigned Type = this->getAnyRelocationType(RE);
807 bool IsPCRel = this->getAnyRelocationPCRel(RE);
808
809 // Determine any addends that should be displayed with the relocation.
810 // These require decoding the relocation type, which is triple-specific.
811
812 // X86_64 has entirely custom relocation types.
813 if (Arch == Triple::x86_64) {
814 bool isPCRel = getAnyRelocationPCRel(RE);
815
816 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000817 case MachO::X86_64_RELOC_GOT_LOAD:
818 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000819 printRelocationTargetName(this, RE, fmt);
820 fmt << "@GOT";
821 if (isPCRel) fmt << "PCREL";
822 break;
823 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000824 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000825 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000826 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000827 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000828
Charles Davis8bdfafd2013-09-01 04:28:48 +0000829 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000830 // X86_64_RELOC_UNSIGNED.
831 // NOTE: Scattered relocations don't exist on x86_64.
832 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000833 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000834 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
835 "X86_64_RELOC_SUBTRACTOR.");
836
Charles Davis8bdfafd2013-09-01 04:28:48 +0000837 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
838 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000839 printRelocationTargetName(this, RENext, fmt);
840 fmt << "-";
841 printRelocationTargetName(this, RE, fmt);
842 break;
843 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000844 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000845 printRelocationTargetName(this, RE, fmt);
846 fmt << "@TLV";
847 if (isPCRel) fmt << "P";
848 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000849 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000850 printRelocationTargetName(this, RE, fmt);
851 fmt << "-1";
852 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000853 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000854 printRelocationTargetName(this, RE, fmt);
855 fmt << "-2";
856 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000857 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000858 printRelocationTargetName(this, RE, fmt);
859 fmt << "-4";
860 break;
861 default:
862 printRelocationTargetName(this, RE, fmt);
863 break;
864 }
865 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000866 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
867 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000868 // Generic relocation types...
869 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000870 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000871 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000872 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000873 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000874 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000875 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000876
877 // X86 sect diff's must be followed by a relocation of type
878 // GENERIC_RELOC_PAIR.
879 unsigned RType = getAnyRelocationType(RENext);
880
Charles Davis8bdfafd2013-09-01 04:28:48 +0000881 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000882 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
883 "GENERIC_RELOC_SECTDIFF.");
884
885 printRelocationTargetName(this, RE, fmt);
886 fmt << "-";
887 printRelocationTargetName(this, RENext, fmt);
888 break;
889 }
890 }
891
David Fangb88cdf62013-08-08 20:14:40 +0000892 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000893 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000894 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000895 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000896 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000897 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000898
899 // X86 sect diff's must be followed by a relocation of type
900 // GENERIC_RELOC_PAIR.
901 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000902 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000903 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
904 "GENERIC_RELOC_LOCAL_SECTDIFF.");
905
906 printRelocationTargetName(this, RE, fmt);
907 fmt << "-";
908 printRelocationTargetName(this, RENext, fmt);
909 break;
910 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000911 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000912 printRelocationTargetName(this, RE, fmt);
913 fmt << "@TLV";
914 if (IsPCRel) fmt << "P";
915 break;
916 }
917 default:
918 printRelocationTargetName(this, RE, fmt);
919 }
920 } else { // ARM-specific relocations
921 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000922 case MachO::ARM_RELOC_HALF:
923 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000924 // Half relocations steal a bit from the length field to encode
925 // whether this is an upper16 or a lower16 relocation.
926 bool isUpper = getAnyRelocationLength(RE) >> 1;
927
928 if (isUpper)
929 fmt << ":upper16:(";
930 else
931 fmt << ":lower16:(";
932 printRelocationTargetName(this, RE, fmt);
933
934 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000935 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000936 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000937
938 // ARM half relocs must be followed by a relocation of type
939 // ARM_RELOC_PAIR.
940 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000941 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000942 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000943 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000944
945 // NOTE: The half of the target virtual address is stashed in the
946 // address field of the secondary relocation, but we can't reverse
947 // engineer the constant offset from it without decoding the movw/movt
948 // instruction to find the other half in its immediate field.
949
950 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
951 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000952 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000953 fmt << "-";
954 printRelocationTargetName(this, RENext, fmt);
955 }
956
957 fmt << ")";
958 break;
959 }
960 default: {
961 printRelocationTargetName(this, RE, fmt);
962 }
963 }
964 }
965 } else
966 printRelocationTargetName(this, RE, fmt);
967
Alp Tokere69170a2014-06-26 22:52:05 +0000968 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000969 Result.append(fmtbuf.begin(), fmtbuf.end());
970 return object_error::success;
971}
972
Rafael Espindola3acea392014-06-12 21:46:39 +0000973std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
974 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000975 unsigned Arch = getArch();
976 uint64_t Type;
977 getRelocationType(Rel, Type);
978
979 Result = false;
980
981 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
982 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000983 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000984 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000985 } else if (Arch == Triple::x86_64) {
986 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000987 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000988 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000989 DataRefImpl RelPrev = Rel;
990 RelPrev.d.a--;
991 uint64_t PrevType;
992 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000993 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000994 Result = true;
995 }
996 }
997
998 return object_error::success;
999}
1000
Keno Fischer281b6942015-05-30 19:44:53 +00001001uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
1002 MachO::any_relocation_info RE = getRelocation(Rel);
1003 return getAnyRelocationLength(RE);
1004}
1005
Kevin Enderby980b2582014-06-05 21:21:57 +00001006//
1007// guessLibraryShortName() is passed a name of a dynamic library and returns a
1008// guess on what the short name is. Then name is returned as a substring of the
1009// StringRef Name passed in. The name of the dynamic library is recognized as
1010// a framework if it has one of the two following forms:
1011// Foo.framework/Versions/A/Foo
1012// Foo.framework/Foo
1013// Where A and Foo can be any string. And may contain a trailing suffix
1014// starting with an underbar. If the Name is recognized as a framework then
1015// isFramework is set to true else it is set to false. If the Name has a
1016// suffix then Suffix is set to the substring in Name that contains the suffix
1017// else it is set to a NULL StringRef.
1018//
1019// The Name of the dynamic library is recognized as a library name if it has
1020// one of the two following forms:
1021// libFoo.A.dylib
1022// libFoo.dylib
1023// The library may have a suffix trailing the name Foo of the form:
1024// libFoo_profile.A.dylib
1025// libFoo_profile.dylib
1026//
1027// The Name of the dynamic library is also recognized as a library name if it
1028// has the following form:
1029// Foo.qtx
1030//
1031// If the Name of the dynamic library is none of the forms above then a NULL
1032// StringRef is returned.
1033//
1034StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1035 bool &isFramework,
1036 StringRef &Suffix) {
1037 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1038 size_t a, b, c, d, Idx;
1039
1040 isFramework = false;
1041 Suffix = StringRef();
1042
1043 // Pull off the last component and make Foo point to it
1044 a = Name.rfind('/');
1045 if (a == Name.npos || a == 0)
1046 goto guess_library;
1047 Foo = Name.slice(a+1, Name.npos);
1048
1049 // Look for a suffix starting with a '_'
1050 Idx = Foo.rfind('_');
1051 if (Idx != Foo.npos && Foo.size() >= 2) {
1052 Suffix = Foo.slice(Idx, Foo.npos);
1053 Foo = Foo.slice(0, Idx);
1054 }
1055
1056 // First look for the form Foo.framework/Foo
1057 b = Name.rfind('/', a);
1058 if (b == Name.npos)
1059 Idx = 0;
1060 else
1061 Idx = b+1;
1062 F = Name.slice(Idx, Idx + Foo.size());
1063 DotFramework = Name.slice(Idx + Foo.size(),
1064 Idx + Foo.size() + sizeof(".framework/")-1);
1065 if (F == Foo && DotFramework == ".framework/") {
1066 isFramework = true;
1067 return Foo;
1068 }
1069
1070 // Next look for the form Foo.framework/Versions/A/Foo
1071 if (b == Name.npos)
1072 goto guess_library;
1073 c = Name.rfind('/', b);
1074 if (c == Name.npos || c == 0)
1075 goto guess_library;
1076 V = Name.slice(c+1, Name.npos);
1077 if (!V.startswith("Versions/"))
1078 goto guess_library;
1079 d = Name.rfind('/', c);
1080 if (d == Name.npos)
1081 Idx = 0;
1082 else
1083 Idx = d+1;
1084 F = Name.slice(Idx, Idx + Foo.size());
1085 DotFramework = Name.slice(Idx + Foo.size(),
1086 Idx + Foo.size() + sizeof(".framework/")-1);
1087 if (F == Foo && DotFramework == ".framework/") {
1088 isFramework = true;
1089 return Foo;
1090 }
1091
1092guess_library:
1093 // pull off the suffix after the "." and make a point to it
1094 a = Name.rfind('.');
1095 if (a == Name.npos || a == 0)
1096 return StringRef();
1097 Dylib = Name.slice(a, Name.npos);
1098 if (Dylib != ".dylib")
1099 goto guess_qtx;
1100
1101 // First pull off the version letter for the form Foo.A.dylib if any.
1102 if (a >= 3) {
1103 Dot = Name.slice(a-2, a-1);
1104 if (Dot == ".")
1105 a = a - 2;
1106 }
1107
1108 b = Name.rfind('/', a);
1109 if (b == Name.npos)
1110 b = 0;
1111 else
1112 b = b+1;
1113 // ignore any suffix after an underbar like Foo_profile.A.dylib
1114 Idx = Name.find('_', b);
1115 if (Idx != Name.npos && Idx != b) {
1116 Lib = Name.slice(b, Idx);
1117 Suffix = Name.slice(Idx, a);
1118 }
1119 else
1120 Lib = Name.slice(b, a);
1121 // There are incorrect library names of the form:
1122 // libATS.A_profile.dylib so check for these.
1123 if (Lib.size() >= 3) {
1124 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1125 if (Dot == ".")
1126 Lib = Lib.slice(0, Lib.size()-2);
1127 }
1128 return Lib;
1129
1130guess_qtx:
1131 Qtx = Name.slice(a, Name.npos);
1132 if (Qtx != ".qtx")
1133 return StringRef();
1134 b = Name.rfind('/', a);
1135 if (b == Name.npos)
1136 Lib = Name.slice(0, a);
1137 else
1138 Lib = Name.slice(b+1, a);
1139 // There are library names of the form: QT.A.qtx so check for these.
1140 if (Lib.size() >= 3) {
1141 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1142 if (Dot == ".")
1143 Lib = Lib.slice(0, Lib.size()-2);
1144 }
1145 return Lib;
1146}
1147
1148// getLibraryShortNameByIndex() is used to get the short name of the library
1149// for an undefined symbol in a linked Mach-O binary that was linked with the
1150// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1151// It is passed the index (0 - based) of the library as translated from
1152// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001153std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001154 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001155 if (Index >= Libraries.size())
1156 return object_error::parse_failed;
1157
Kevin Enderby980b2582014-06-05 21:21:57 +00001158 // If the cache of LibrariesShortNames is not built up do that first for
1159 // all the Libraries.
1160 if (LibrariesShortNames.size() == 0) {
1161 for (unsigned i = 0; i < Libraries.size(); i++) {
1162 MachO::dylib_command D =
1163 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001164 if (D.dylib.name >= D.cmdsize)
1165 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001166 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001167 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001168 if (D.dylib.name+Name.size() >= D.cmdsize)
1169 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001170 StringRef Suffix;
1171 bool isFramework;
1172 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001173 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001174 LibrariesShortNames.push_back(Name);
1175 else
1176 LibrariesShortNames.push_back(shortName);
1177 }
1178 }
1179
1180 Res = LibrariesShortNames[Index];
1181 return object_error::success;
1182}
1183
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001184basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001185 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001186}
1187
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001188basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001189 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001190 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001191 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001192
Charles Davis8bdfafd2013-09-01 04:28:48 +00001193 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001194 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001195 sizeof(MachO::nlist_64) :
1196 sizeof(MachO::nlist);
1197 unsigned Offset = Symtab.symoff +
1198 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001199 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001200 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001201}
1202
Lang Hames36072da2014-05-12 21:39:59 +00001203basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1204 DataRefImpl DRI;
1205 if (!SymtabLoadCmd)
1206 return basic_symbol_iterator(SymbolRef(DRI, this));
1207
1208 MachO::symtab_command Symtab = getSymtabLoadCommand();
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001209 if (Index >= Symtab.nsyms)
1210 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001211 unsigned SymbolTableEntrySize =
1212 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1213 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1214 DRI.p += Index * SymbolTableEntrySize;
1215 return basic_symbol_iterator(SymbolRef(DRI, this));
1216}
1217
Rafael Espindolab5155a52014-02-10 20:24:04 +00001218section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001219 DataRefImpl DRI;
1220 return section_iterator(SectionRef(DRI, this));
1221}
1222
Rafael Espindolab5155a52014-02-10 20:24:04 +00001223section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001224 DataRefImpl DRI;
1225 DRI.d.a = Sections.size();
1226 return section_iterator(SectionRef(DRI, this));
1227}
1228
Rafael Espindola56f976f2013-04-18 18:08:55 +00001229uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001230 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001231}
1232
Rafael Espindola56f976f2013-04-18 18:08:55 +00001233StringRef MachOObjectFile::getFileFormatName() const {
1234 unsigned CPUType = getCPUType(this);
1235 if (!is64Bit()) {
1236 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001237 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001238 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001239 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001240 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001241 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001242 return "Mach-O 32-bit ppc";
1243 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001244 return "Mach-O 32-bit unknown";
1245 }
1246 }
1247
Rafael Espindola56f976f2013-04-18 18:08:55 +00001248 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001249 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001250 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001251 case llvm::MachO::CPU_TYPE_ARM64:
1252 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001253 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001254 return "Mach-O 64-bit ppc64";
1255 default:
1256 return "Mach-O 64-bit unknown";
1257 }
1258}
1259
Alexey Samsonove6388e62013-06-18 15:03:28 +00001260Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1261 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001262 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001263 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001264 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001265 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001266 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001267 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001268 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001269 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001270 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001271 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001272 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001273 return Triple::ppc64;
1274 default:
1275 return Triple::UnknownArch;
1276 }
1277}
1278
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001279Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1280 const char **McpuDefault) {
1281 if (McpuDefault)
1282 *McpuDefault = nullptr;
1283
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001284 switch (CPUType) {
1285 case MachO::CPU_TYPE_I386:
1286 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1287 case MachO::CPU_SUBTYPE_I386_ALL:
1288 return Triple("i386-apple-darwin");
1289 default:
1290 return Triple();
1291 }
1292 case MachO::CPU_TYPE_X86_64:
1293 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1294 case MachO::CPU_SUBTYPE_X86_64_ALL:
1295 return Triple("x86_64-apple-darwin");
1296 case MachO::CPU_SUBTYPE_X86_64_H:
1297 return Triple("x86_64h-apple-darwin");
1298 default:
1299 return Triple();
1300 }
1301 case MachO::CPU_TYPE_ARM:
1302 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1303 case MachO::CPU_SUBTYPE_ARM_V4T:
1304 return Triple("armv4t-apple-darwin");
1305 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1306 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001307 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1308 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001309 case MachO::CPU_SUBTYPE_ARM_V6:
1310 return Triple("armv6-apple-darwin");
1311 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001312 if (McpuDefault)
1313 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001314 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001315 case MachO::CPU_SUBTYPE_ARM_V7:
1316 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001317 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001318 if (McpuDefault)
1319 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001320 return Triple("armv7em-apple-darwin");
1321 case MachO::CPU_SUBTYPE_ARM_V7K:
1322 return Triple("armv7k-apple-darwin");
1323 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001324 if (McpuDefault)
1325 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001326 return Triple("armv7m-apple-darwin");
1327 case MachO::CPU_SUBTYPE_ARM_V7S:
1328 return Triple("armv7s-apple-darwin");
1329 default:
1330 return Triple();
1331 }
1332 case MachO::CPU_TYPE_ARM64:
1333 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1334 case MachO::CPU_SUBTYPE_ARM64_ALL:
1335 return Triple("arm64-apple-darwin");
1336 default:
1337 return Triple();
1338 }
1339 case MachO::CPU_TYPE_POWERPC:
1340 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1341 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1342 return Triple("ppc-apple-darwin");
1343 default:
1344 return Triple();
1345 }
1346 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001347 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001348 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1349 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001350 default:
1351 return Triple();
1352 }
1353 default:
1354 return Triple();
1355 }
1356}
1357
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001358Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1359 const char **McpuDefault) {
1360 if (McpuDefault)
1361 *McpuDefault = nullptr;
1362
1363 switch (CPUType) {
1364 case MachO::CPU_TYPE_ARM:
1365 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1366 case MachO::CPU_SUBTYPE_ARM_V4T:
1367 return Triple("thumbv4t-apple-darwin");
1368 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1369 return Triple("thumbv5e-apple-darwin");
1370 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1371 return Triple("xscale-apple-darwin");
1372 case MachO::CPU_SUBTYPE_ARM_V6:
1373 return Triple("thumbv6-apple-darwin");
1374 case MachO::CPU_SUBTYPE_ARM_V6M:
1375 if (McpuDefault)
1376 *McpuDefault = "cortex-m0";
1377 return Triple("thumbv6m-apple-darwin");
1378 case MachO::CPU_SUBTYPE_ARM_V7:
1379 return Triple("thumbv7-apple-darwin");
1380 case MachO::CPU_SUBTYPE_ARM_V7EM:
1381 if (McpuDefault)
1382 *McpuDefault = "cortex-m4";
1383 return Triple("thumbv7em-apple-darwin");
1384 case MachO::CPU_SUBTYPE_ARM_V7K:
1385 return Triple("thumbv7k-apple-darwin");
1386 case MachO::CPU_SUBTYPE_ARM_V7M:
1387 if (McpuDefault)
1388 *McpuDefault = "cortex-m3";
1389 return Triple("thumbv7m-apple-darwin");
1390 case MachO::CPU_SUBTYPE_ARM_V7S:
1391 return Triple("thumbv7s-apple-darwin");
1392 default:
1393 return Triple();
1394 }
1395 default:
1396 return Triple();
1397 }
1398}
1399
1400Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1401 const char **McpuDefault,
1402 Triple *ThumbTriple) {
1403 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1404 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1405 McpuDefault);
1406 return T;
1407}
1408
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001409Triple MachOObjectFile::getHostArch() {
1410 return Triple(sys::getDefaultTargetTriple());
1411}
1412
Rafael Espindola72318b42014-08-08 16:30:17 +00001413bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1414 return StringSwitch<bool>(ArchFlag)
1415 .Case("i386", true)
1416 .Case("x86_64", true)
1417 .Case("x86_64h", true)
1418 .Case("armv4t", true)
1419 .Case("arm", true)
1420 .Case("armv5e", true)
1421 .Case("armv6", true)
1422 .Case("armv6m", true)
1423 .Case("armv7em", true)
1424 .Case("armv7k", true)
1425 .Case("armv7m", true)
1426 .Case("armv7s", true)
1427 .Case("arm64", true)
1428 .Case("ppc", true)
1429 .Case("ppc64", true)
1430 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001431}
1432
Alexey Samsonove6388e62013-06-18 15:03:28 +00001433unsigned MachOObjectFile::getArch() const {
1434 return getArch(getCPUType(this));
1435}
1436
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001437Triple MachOObjectFile::getArch(const char **McpuDefault,
1438 Triple *ThumbTriple) const {
1439 Triple T;
1440 if (is64Bit()) {
1441 MachO::mach_header_64 H_64;
1442 H_64 = getHeader64();
1443 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1444 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1445 McpuDefault);
1446 } else {
1447 MachO::mach_header H;
1448 H = getHeader();
1449 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1450 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1451 McpuDefault);
1452 }
1453 return T;
1454}
1455
Rui Ueyamabc654b12013-09-27 21:47:05 +00001456relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001457 DataRefImpl DRI;
1458 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001459 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001460}
1461
Rui Ueyamabc654b12013-09-27 21:47:05 +00001462relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001463 DataRefImpl DRI;
1464 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001465 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001466}
1467
Kevin Enderby273ae012013-06-06 17:20:50 +00001468dice_iterator MachOObjectFile::begin_dices() const {
1469 DataRefImpl DRI;
1470 if (!DataInCodeLoadCmd)
1471 return dice_iterator(DiceRef(DRI, this));
1472
Charles Davis8bdfafd2013-09-01 04:28:48 +00001473 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1474 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001475 return dice_iterator(DiceRef(DRI, this));
1476}
1477
1478dice_iterator MachOObjectFile::end_dices() const {
1479 DataRefImpl DRI;
1480 if (!DataInCodeLoadCmd)
1481 return dice_iterator(DiceRef(DRI, this));
1482
Charles Davis8bdfafd2013-09-01 04:28:48 +00001483 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1484 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001485 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1486 return dice_iterator(DiceRef(DRI, this));
1487}
1488
Nick Kledzikd04bc352014-08-30 00:20:14 +00001489ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1490 : Trie(T), Malformed(false), Done(false) { }
1491
1492void ExportEntry::moveToFirst() {
1493 pushNode(0);
1494 pushDownUntilBottom();
1495}
1496
1497void ExportEntry::moveToEnd() {
1498 Stack.clear();
1499 Done = true;
1500}
1501
1502bool ExportEntry::operator==(const ExportEntry &Other) const {
1503 // Common case, one at end, other iterating from begin.
1504 if (Done || Other.Done)
1505 return (Done == Other.Done);
1506 // Not equal if different stack sizes.
1507 if (Stack.size() != Other.Stack.size())
1508 return false;
1509 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001510 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001511 return false;
1512 // Equal if all nodes in both stacks match.
1513 for (unsigned i=0; i < Stack.size(); ++i) {
1514 if (Stack[i].Start != Other.Stack[i].Start)
1515 return false;
1516 }
1517 return true;
1518}
1519
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001520uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1521 unsigned Count;
1522 uint64_t Result = decodeULEB128(Ptr, &Count);
1523 Ptr += Count;
1524 if (Ptr > Trie.end()) {
1525 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001526 Malformed = true;
1527 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001528 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001529}
1530
1531StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001532 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001533}
1534
1535uint64_t ExportEntry::flags() const {
1536 return Stack.back().Flags;
1537}
1538
1539uint64_t ExportEntry::address() const {
1540 return Stack.back().Address;
1541}
1542
1543uint64_t ExportEntry::other() const {
1544 return Stack.back().Other;
1545}
1546
1547StringRef ExportEntry::otherName() const {
1548 const char* ImportName = Stack.back().ImportName;
1549 if (ImportName)
1550 return StringRef(ImportName);
1551 return StringRef();
1552}
1553
1554uint32_t ExportEntry::nodeOffset() const {
1555 return Stack.back().Start - Trie.begin();
1556}
1557
1558ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1559 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1560 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1561 ParentStringLength(0), IsExportNode(false) {
1562}
1563
1564void ExportEntry::pushNode(uint64_t offset) {
1565 const uint8_t *Ptr = Trie.begin() + offset;
1566 NodeState State(Ptr);
1567 uint64_t ExportInfoSize = readULEB128(State.Current);
1568 State.IsExportNode = (ExportInfoSize != 0);
1569 const uint8_t* Children = State.Current + ExportInfoSize;
1570 if (State.IsExportNode) {
1571 State.Flags = readULEB128(State.Current);
1572 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1573 State.Address = 0;
1574 State.Other = readULEB128(State.Current); // dylib ordinal
1575 State.ImportName = reinterpret_cast<const char*>(State.Current);
1576 } else {
1577 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001578 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1579 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001580 }
1581 }
1582 State.ChildCount = *Children;
1583 State.Current = Children + 1;
1584 State.NextChildIndex = 0;
1585 State.ParentStringLength = CumulativeString.size();
1586 Stack.push_back(State);
1587}
1588
1589void ExportEntry::pushDownUntilBottom() {
1590 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1591 NodeState &Top = Stack.back();
1592 CumulativeString.resize(Top.ParentStringLength);
1593 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001594 char C = *Top.Current;
1595 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001596 }
1597 Top.Current += 1;
1598 uint64_t childNodeIndex = readULEB128(Top.Current);
1599 Top.NextChildIndex += 1;
1600 pushNode(childNodeIndex);
1601 }
1602 if (!Stack.back().IsExportNode) {
1603 Malformed = true;
1604 moveToEnd();
1605 }
1606}
1607
1608// We have a trie data structure and need a way to walk it that is compatible
1609// with the C++ iterator model. The solution is a non-recursive depth first
1610// traversal where the iterator contains a stack of parent nodes along with a
1611// string that is the accumulation of all edge strings along the parent chain
1612// to this point.
1613//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001614// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001615// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1616// node may have child nodes too.
1617//
1618// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1619// child until hitting a node with no children (which is an export node or
1620// else the trie is malformed). On the way down, each node is pushed on the
1621// stack ivar. If there is no more ways down, it pops up one and tries to go
1622// down a sibling path until a childless node is reached.
1623void ExportEntry::moveNext() {
1624 if (Stack.empty() || !Stack.back().IsExportNode) {
1625 Malformed = true;
1626 moveToEnd();
1627 return;
1628 }
1629
1630 Stack.pop_back();
1631 while (!Stack.empty()) {
1632 NodeState &Top = Stack.back();
1633 if (Top.NextChildIndex < Top.ChildCount) {
1634 pushDownUntilBottom();
1635 // Now at the next export node.
1636 return;
1637 } else {
1638 if (Top.IsExportNode) {
1639 // This node has no children but is itself an export node.
1640 CumulativeString.resize(Top.ParentStringLength);
1641 return;
1642 }
1643 Stack.pop_back();
1644 }
1645 }
1646 Done = true;
1647}
1648
1649iterator_range<export_iterator>
1650MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1651 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001652 if (Trie.size() == 0)
1653 Start.moveToEnd();
1654 else
1655 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001656
1657 ExportEntry Finish(Trie);
1658 Finish.moveToEnd();
1659
1660 return iterator_range<export_iterator>(export_iterator(Start),
1661 export_iterator(Finish));
1662}
1663
1664iterator_range<export_iterator> MachOObjectFile::exports() const {
1665 return exports(getDyldInfoExportsTrie());
1666}
1667
1668
Nick Kledzikac431442014-09-12 21:34:15 +00001669MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1670 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1671 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1672 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1673
1674void MachORebaseEntry::moveToFirst() {
1675 Ptr = Opcodes.begin();
1676 moveNext();
1677}
1678
1679void MachORebaseEntry::moveToEnd() {
1680 Ptr = Opcodes.end();
1681 RemainingLoopCount = 0;
1682 Done = true;
1683}
1684
1685void MachORebaseEntry::moveNext() {
1686 // If in the middle of some loop, move to next rebasing in loop.
1687 SegmentOffset += AdvanceAmount;
1688 if (RemainingLoopCount) {
1689 --RemainingLoopCount;
1690 return;
1691 }
1692 if (Ptr == Opcodes.end()) {
1693 Done = true;
1694 return;
1695 }
1696 bool More = true;
1697 while (More && !Malformed) {
1698 // Parse next opcode and set up next loop.
1699 uint8_t Byte = *Ptr++;
1700 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1701 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1702 switch (Opcode) {
1703 case MachO::REBASE_OPCODE_DONE:
1704 More = false;
1705 Done = true;
1706 moveToEnd();
1707 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1708 break;
1709 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1710 RebaseType = ImmValue;
1711 DEBUG_WITH_TYPE(
1712 "mach-o-rebase",
1713 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1714 << "RebaseType=" << (int) RebaseType << "\n");
1715 break;
1716 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1717 SegmentIndex = ImmValue;
1718 SegmentOffset = readULEB128();
1719 DEBUG_WITH_TYPE(
1720 "mach-o-rebase",
1721 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1722 << "SegmentIndex=" << SegmentIndex << ", "
1723 << format("SegmentOffset=0x%06X", SegmentOffset)
1724 << "\n");
1725 break;
1726 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1727 SegmentOffset += readULEB128();
1728 DEBUG_WITH_TYPE("mach-o-rebase",
1729 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1730 << format("SegmentOffset=0x%06X",
1731 SegmentOffset) << "\n");
1732 break;
1733 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1734 SegmentOffset += ImmValue * PointerSize;
1735 DEBUG_WITH_TYPE("mach-o-rebase",
1736 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1737 << format("SegmentOffset=0x%06X",
1738 SegmentOffset) << "\n");
1739 break;
1740 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1741 AdvanceAmount = PointerSize;
1742 RemainingLoopCount = ImmValue - 1;
1743 DEBUG_WITH_TYPE(
1744 "mach-o-rebase",
1745 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1746 << format("SegmentOffset=0x%06X", SegmentOffset)
1747 << ", AdvanceAmount=" << AdvanceAmount
1748 << ", RemainingLoopCount=" << RemainingLoopCount
1749 << "\n");
1750 return;
1751 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1752 AdvanceAmount = PointerSize;
1753 RemainingLoopCount = readULEB128() - 1;
1754 DEBUG_WITH_TYPE(
1755 "mach-o-rebase",
1756 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1757 << format("SegmentOffset=0x%06X", SegmentOffset)
1758 << ", AdvanceAmount=" << AdvanceAmount
1759 << ", RemainingLoopCount=" << RemainingLoopCount
1760 << "\n");
1761 return;
1762 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1763 AdvanceAmount = readULEB128() + PointerSize;
1764 RemainingLoopCount = 0;
1765 DEBUG_WITH_TYPE(
1766 "mach-o-rebase",
1767 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1768 << format("SegmentOffset=0x%06X", SegmentOffset)
1769 << ", AdvanceAmount=" << AdvanceAmount
1770 << ", RemainingLoopCount=" << RemainingLoopCount
1771 << "\n");
1772 return;
1773 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1774 RemainingLoopCount = readULEB128() - 1;
1775 AdvanceAmount = readULEB128() + PointerSize;
1776 DEBUG_WITH_TYPE(
1777 "mach-o-rebase",
1778 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1779 << format("SegmentOffset=0x%06X", SegmentOffset)
1780 << ", AdvanceAmount=" << AdvanceAmount
1781 << ", RemainingLoopCount=" << RemainingLoopCount
1782 << "\n");
1783 return;
1784 default:
1785 Malformed = true;
1786 }
1787 }
1788}
1789
1790uint64_t MachORebaseEntry::readULEB128() {
1791 unsigned Count;
1792 uint64_t Result = decodeULEB128(Ptr, &Count);
1793 Ptr += Count;
1794 if (Ptr > Opcodes.end()) {
1795 Ptr = Opcodes.end();
1796 Malformed = true;
1797 }
1798 return Result;
1799}
1800
1801uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1802
1803uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1804
1805StringRef MachORebaseEntry::typeName() const {
1806 switch (RebaseType) {
1807 case MachO::REBASE_TYPE_POINTER:
1808 return "pointer";
1809 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1810 return "text abs32";
1811 case MachO::REBASE_TYPE_TEXT_PCREL32:
1812 return "text rel32";
1813 }
1814 return "unknown";
1815}
1816
1817bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1818 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1819 return (Ptr == Other.Ptr) &&
1820 (RemainingLoopCount == Other.RemainingLoopCount) &&
1821 (Done == Other.Done);
1822}
1823
1824iterator_range<rebase_iterator>
1825MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1826 MachORebaseEntry Start(Opcodes, is64);
1827 Start.moveToFirst();
1828
1829 MachORebaseEntry Finish(Opcodes, is64);
1830 Finish.moveToEnd();
1831
1832 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1833 rebase_iterator(Finish));
1834}
1835
1836iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1837 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1838}
1839
Nick Kledzik56ebef42014-09-16 01:41:51 +00001840
1841MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1842 Kind BK)
1843 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1844 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1845 BindType(0), PointerSize(is64Bit ? 8 : 4),
1846 TableKind(BK), Malformed(false), Done(false) {}
1847
1848void MachOBindEntry::moveToFirst() {
1849 Ptr = Opcodes.begin();
1850 moveNext();
1851}
1852
1853void MachOBindEntry::moveToEnd() {
1854 Ptr = Opcodes.end();
1855 RemainingLoopCount = 0;
1856 Done = true;
1857}
1858
1859void MachOBindEntry::moveNext() {
1860 // If in the middle of some loop, move to next binding in loop.
1861 SegmentOffset += AdvanceAmount;
1862 if (RemainingLoopCount) {
1863 --RemainingLoopCount;
1864 return;
1865 }
1866 if (Ptr == Opcodes.end()) {
1867 Done = true;
1868 return;
1869 }
1870 bool More = true;
1871 while (More && !Malformed) {
1872 // Parse next opcode and set up next loop.
1873 uint8_t Byte = *Ptr++;
1874 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1875 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1876 int8_t SignExtended;
1877 const uint8_t *SymStart;
1878 switch (Opcode) {
1879 case MachO::BIND_OPCODE_DONE:
1880 if (TableKind == Kind::Lazy) {
1881 // Lazying bindings have a DONE opcode between entries. Need to ignore
1882 // it to advance to next entry. But need not if this is last entry.
1883 bool NotLastEntry = false;
1884 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1885 if (*P) {
1886 NotLastEntry = true;
1887 }
1888 }
1889 if (NotLastEntry)
1890 break;
1891 }
1892 More = false;
1893 Done = true;
1894 moveToEnd();
1895 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1896 break;
1897 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1898 Ordinal = ImmValue;
1899 DEBUG_WITH_TYPE(
1900 "mach-o-bind",
1901 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1902 << "Ordinal=" << Ordinal << "\n");
1903 break;
1904 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1905 Ordinal = readULEB128();
1906 DEBUG_WITH_TYPE(
1907 "mach-o-bind",
1908 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1909 << "Ordinal=" << Ordinal << "\n");
1910 break;
1911 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1912 if (ImmValue) {
1913 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1914 Ordinal = SignExtended;
1915 } else
1916 Ordinal = 0;
1917 DEBUG_WITH_TYPE(
1918 "mach-o-bind",
1919 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1920 << "Ordinal=" << Ordinal << "\n");
1921 break;
1922 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1923 Flags = ImmValue;
1924 SymStart = Ptr;
1925 while (*Ptr) {
1926 ++Ptr;
1927 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001928 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1929 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001930 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001931 DEBUG_WITH_TYPE(
1932 "mach-o-bind",
1933 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1934 << "SymbolName=" << SymbolName << "\n");
1935 if (TableKind == Kind::Weak) {
1936 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1937 return;
1938 }
1939 break;
1940 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1941 BindType = ImmValue;
1942 DEBUG_WITH_TYPE(
1943 "mach-o-bind",
1944 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1945 << "BindType=" << (int)BindType << "\n");
1946 break;
1947 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1948 Addend = readSLEB128();
1949 if (TableKind == Kind::Lazy)
1950 Malformed = true;
1951 DEBUG_WITH_TYPE(
1952 "mach-o-bind",
1953 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1954 << "Addend=" << Addend << "\n");
1955 break;
1956 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1957 SegmentIndex = ImmValue;
1958 SegmentOffset = readULEB128();
1959 DEBUG_WITH_TYPE(
1960 "mach-o-bind",
1961 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1962 << "SegmentIndex=" << SegmentIndex << ", "
1963 << format("SegmentOffset=0x%06X", SegmentOffset)
1964 << "\n");
1965 break;
1966 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1967 SegmentOffset += readULEB128();
1968 DEBUG_WITH_TYPE("mach-o-bind",
1969 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1970 << format("SegmentOffset=0x%06X",
1971 SegmentOffset) << "\n");
1972 break;
1973 case MachO::BIND_OPCODE_DO_BIND:
1974 AdvanceAmount = PointerSize;
1975 RemainingLoopCount = 0;
1976 DEBUG_WITH_TYPE("mach-o-bind",
1977 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1978 << format("SegmentOffset=0x%06X",
1979 SegmentOffset) << "\n");
1980 return;
1981 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001982 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001983 RemainingLoopCount = 0;
1984 if (TableKind == Kind::Lazy)
1985 Malformed = true;
1986 DEBUG_WITH_TYPE(
1987 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001988 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001989 << format("SegmentOffset=0x%06X", SegmentOffset)
1990 << ", AdvanceAmount=" << AdvanceAmount
1991 << ", RemainingLoopCount=" << RemainingLoopCount
1992 << "\n");
1993 return;
1994 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001995 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001996 RemainingLoopCount = 0;
1997 if (TableKind == Kind::Lazy)
1998 Malformed = true;
1999 DEBUG_WITH_TYPE("mach-o-bind",
2000 llvm::dbgs()
2001 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2002 << format("SegmentOffset=0x%06X",
2003 SegmentOffset) << "\n");
2004 return;
2005 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2006 RemainingLoopCount = readULEB128() - 1;
2007 AdvanceAmount = readULEB128() + PointerSize;
2008 if (TableKind == Kind::Lazy)
2009 Malformed = true;
2010 DEBUG_WITH_TYPE(
2011 "mach-o-bind",
2012 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2013 << format("SegmentOffset=0x%06X", SegmentOffset)
2014 << ", AdvanceAmount=" << AdvanceAmount
2015 << ", RemainingLoopCount=" << RemainingLoopCount
2016 << "\n");
2017 return;
2018 default:
2019 Malformed = true;
2020 }
2021 }
2022}
2023
2024uint64_t MachOBindEntry::readULEB128() {
2025 unsigned Count;
2026 uint64_t Result = decodeULEB128(Ptr, &Count);
2027 Ptr += Count;
2028 if (Ptr > Opcodes.end()) {
2029 Ptr = Opcodes.end();
2030 Malformed = true;
2031 }
2032 return Result;
2033}
2034
2035int64_t MachOBindEntry::readSLEB128() {
2036 unsigned Count;
2037 int64_t Result = decodeSLEB128(Ptr, &Count);
2038 Ptr += Count;
2039 if (Ptr > Opcodes.end()) {
2040 Ptr = Opcodes.end();
2041 Malformed = true;
2042 }
2043 return Result;
2044}
2045
2046
2047uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2048
2049uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2050
2051StringRef MachOBindEntry::typeName() const {
2052 switch (BindType) {
2053 case MachO::BIND_TYPE_POINTER:
2054 return "pointer";
2055 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2056 return "text abs32";
2057 case MachO::BIND_TYPE_TEXT_PCREL32:
2058 return "text rel32";
2059 }
2060 return "unknown";
2061}
2062
2063StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2064
2065int64_t MachOBindEntry::addend() const { return Addend; }
2066
2067uint32_t MachOBindEntry::flags() const { return Flags; }
2068
2069int MachOBindEntry::ordinal() const { return Ordinal; }
2070
2071bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2072 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2073 return (Ptr == Other.Ptr) &&
2074 (RemainingLoopCount == Other.RemainingLoopCount) &&
2075 (Done == Other.Done);
2076}
2077
2078iterator_range<bind_iterator>
2079MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2080 MachOBindEntry::Kind BKind) {
2081 MachOBindEntry Start(Opcodes, is64, BKind);
2082 Start.moveToFirst();
2083
2084 MachOBindEntry Finish(Opcodes, is64, BKind);
2085 Finish.moveToEnd();
2086
2087 return iterator_range<bind_iterator>(bind_iterator(Start),
2088 bind_iterator(Finish));
2089}
2090
2091iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2092 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2093 MachOBindEntry::Kind::Regular);
2094}
2095
2096iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2097 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2098 MachOBindEntry::Kind::Lazy);
2099}
2100
2101iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2102 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2103 MachOBindEntry::Kind::Weak);
2104}
2105
Rafael Espindola56f976f2013-04-18 18:08:55 +00002106StringRef
2107MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2108 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2109 return parseSegmentOrSectionName(Raw.data());
2110}
2111
2112ArrayRef<char>
2113MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002114 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002115 const section_base *Base =
2116 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002117 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002118}
2119
2120ArrayRef<char>
2121MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00002122 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002123 const section_base *Base =
2124 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002125 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002126}
2127
2128bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002129MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002130 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002131 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002132 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002133 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002134}
2135
Eric Christopher1d62c252013-07-22 22:25:07 +00002136unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002137 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002138 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002139 return RE.r_word1 & 0xffffff;
2140 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002141}
2142
Eric Christopher1d62c252013-07-22 22:25:07 +00002143bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002144 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002145 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002146 return (RE.r_word1 >> 27) & 1;
2147 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002148}
2149
Eric Christopher1d62c252013-07-22 22:25:07 +00002150bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002151 const MachO::any_relocation_info &RE) const {
2152 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002153}
2154
Eric Christopher1d62c252013-07-22 22:25:07 +00002155uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002156 const MachO::any_relocation_info &RE) const {
2157 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002158}
2159
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002160uint32_t MachOObjectFile::getScatteredRelocationType(
2161 const MachO::any_relocation_info &RE) const {
2162 return (RE.r_word0 >> 24) & 0xf;
2163}
2164
Eric Christopher1d62c252013-07-22 22:25:07 +00002165unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002166 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002167 if (isRelocationScattered(RE))
2168 return getScatteredRelocationAddress(RE);
2169 return getPlainRelocationAddress(RE);
2170}
2171
Charles Davis8bdfafd2013-09-01 04:28:48 +00002172unsigned MachOObjectFile::getAnyRelocationPCRel(
2173 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002174 if (isRelocationScattered(RE))
2175 return getScatteredRelocationPCRel(this, RE);
2176 return getPlainRelocationPCRel(this, RE);
2177}
2178
Eric Christopher1d62c252013-07-22 22:25:07 +00002179unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002180 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002181 if (isRelocationScattered(RE))
2182 return getScatteredRelocationLength(RE);
2183 return getPlainRelocationLength(this, RE);
2184}
2185
2186unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002187MachOObjectFile::getAnyRelocationType(
2188 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002189 if (isRelocationScattered(RE))
2190 return getScatteredRelocationType(RE);
2191 return getPlainRelocationType(this, RE);
2192}
2193
Rafael Espindola52501032013-04-30 15:40:54 +00002194SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002195MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002196 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002197 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002198 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002199 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2200 DataRefImpl DRI;
2201 DRI.d.a = SecNum;
2202 return SectionRef(DRI, this);
2203}
2204
Rafael Espindola56f976f2013-04-18 18:08:55 +00002205MachOObjectFile::LoadCommandInfo
2206MachOObjectFile::getFirstLoadCommandInfo() const {
2207 MachOObjectFile::LoadCommandInfo Load;
2208
Charles Davis8bdfafd2013-09-01 04:28:48 +00002209 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2210 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002211 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002212 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002213 if (Load.C.cmdsize < 8)
2214 report_fatal_error("Load command with size < 8 bytes.");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002215 return Load;
2216}
2217
2218MachOObjectFile::LoadCommandInfo
2219MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2220 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002221 Next.Ptr = L.Ptr + L.C.cmdsize;
2222 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002223 if (Next.C.cmdsize < 8)
2224 report_fatal_error("Load command with size < 8 bytes.");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002225 return Next;
2226}
2227
Charles Davis8bdfafd2013-09-01 04:28:48 +00002228MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002229 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002230 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002231}
2232
Charles Davis8bdfafd2013-09-01 04:28:48 +00002233MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002234 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002235 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002236}
2237
Charles Davis8bdfafd2013-09-01 04:28:48 +00002238MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002239 unsigned Index) const {
2240 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002241 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002242}
2243
Charles Davis8bdfafd2013-09-01 04:28:48 +00002244MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2245 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002246 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002247 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002248}
2249
Charles Davis8bdfafd2013-09-01 04:28:48 +00002250MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002251MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002252 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002253 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002254}
2255
Charles Davis8bdfafd2013-09-01 04:28:48 +00002256MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002257MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002258 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002259 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002260}
2261
Charles Davis8bdfafd2013-09-01 04:28:48 +00002262MachO::linkedit_data_command
2263MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2264 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002265}
2266
Charles Davis8bdfafd2013-09-01 04:28:48 +00002267MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002268MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002269 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002270}
2271
Charles Davis8bdfafd2013-09-01 04:28:48 +00002272MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002273MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002274 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002275}
2276
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002277MachO::linker_option_command
2278MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2279 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002280}
2281
Jim Grosbach448334a2014-03-18 22:09:05 +00002282MachO::version_min_command
2283MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2284 return getStruct<MachO::version_min_command>(this, L.Ptr);
2285}
2286
Tim Northover8f9590b2014-06-30 14:40:57 +00002287MachO::dylib_command
2288MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2289 return getStruct<MachO::dylib_command>(this, L.Ptr);
2290}
2291
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002292MachO::dyld_info_command
2293MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2294 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2295}
2296
2297MachO::dylinker_command
2298MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2299 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2300}
2301
2302MachO::uuid_command
2303MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2304 return getStruct<MachO::uuid_command>(this, L.Ptr);
2305}
2306
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002307MachO::rpath_command
2308MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2309 return getStruct<MachO::rpath_command>(this, L.Ptr);
2310}
2311
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002312MachO::source_version_command
2313MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2314 return getStruct<MachO::source_version_command>(this, L.Ptr);
2315}
2316
2317MachO::entry_point_command
2318MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2319 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2320}
2321
Kevin Enderby0804f4672014-12-16 23:25:52 +00002322MachO::encryption_info_command
2323MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2324 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2325}
2326
Kevin Enderby57538292014-12-17 01:01:30 +00002327MachO::encryption_info_command_64
2328MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2329 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2330}
2331
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002332MachO::sub_framework_command
2333MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2334 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2335}
Tim Northover8f9590b2014-06-30 14:40:57 +00002336
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002337MachO::sub_umbrella_command
2338MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2339 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2340}
2341
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002342MachO::sub_library_command
2343MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2344 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2345}
2346
Kevin Enderby186eac32014-12-19 21:06:24 +00002347MachO::sub_client_command
2348MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2349 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2350}
2351
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002352MachO::routines_command
2353MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2354 return getStruct<MachO::routines_command>(this, L.Ptr);
2355}
2356
2357MachO::routines_command_64
2358MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2359 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2360}
2361
Kevin Enderby48ef5342014-12-23 22:56:39 +00002362MachO::thread_command
2363MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2364 return getStruct<MachO::thread_command>(this, L.Ptr);
2365}
2366
Charles Davis8bdfafd2013-09-01 04:28:48 +00002367MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002368MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002369 DataRefImpl Sec;
2370 Sec.d.a = Rel.d.a;
2371 uint32_t Offset;
2372 if (is64Bit()) {
2373 MachO::section_64 Sect = getSection64(Sec);
2374 Offset = Sect.reloff;
2375 } else {
2376 MachO::section Sect = getSection(Sec);
2377 Offset = Sect.reloff;
2378 }
2379
2380 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2381 getPtr(this, Offset)) + Rel.d.b;
2382 return getStruct<MachO::any_relocation_info>(
2383 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002384}
2385
Charles Davis8bdfafd2013-09-01 04:28:48 +00002386MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002387MachOObjectFile::getDice(DataRefImpl Rel) const {
2388 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002389 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002390}
2391
Charles Davis8bdfafd2013-09-01 04:28:48 +00002392MachO::mach_header MachOObjectFile::getHeader() const {
2393 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002394}
2395
Charles Davis8bdfafd2013-09-01 04:28:48 +00002396MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2397 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002398}
2399
Charles Davis8bdfafd2013-09-01 04:28:48 +00002400uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2401 const MachO::dysymtab_command &DLC,
2402 unsigned Index) const {
2403 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2404 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002405}
2406
Charles Davis8bdfafd2013-09-01 04:28:48 +00002407MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002408MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2409 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002410 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2411 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002412}
2413
Charles Davis8bdfafd2013-09-01 04:28:48 +00002414MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002415 if (SymtabLoadCmd)
2416 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2417
2418 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2419 MachO::symtab_command Cmd;
2420 Cmd.cmd = MachO::LC_SYMTAB;
2421 Cmd.cmdsize = sizeof(MachO::symtab_command);
2422 Cmd.symoff = 0;
2423 Cmd.nsyms = 0;
2424 Cmd.stroff = 0;
2425 Cmd.strsize = 0;
2426 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002427}
2428
Charles Davis8bdfafd2013-09-01 04:28:48 +00002429MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002430 if (DysymtabLoadCmd)
2431 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2432
2433 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2434 MachO::dysymtab_command Cmd;
2435 Cmd.cmd = MachO::LC_DYSYMTAB;
2436 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2437 Cmd.ilocalsym = 0;
2438 Cmd.nlocalsym = 0;
2439 Cmd.iextdefsym = 0;
2440 Cmd.nextdefsym = 0;
2441 Cmd.iundefsym = 0;
2442 Cmd.nundefsym = 0;
2443 Cmd.tocoff = 0;
2444 Cmd.ntoc = 0;
2445 Cmd.modtaboff = 0;
2446 Cmd.nmodtab = 0;
2447 Cmd.extrefsymoff = 0;
2448 Cmd.nextrefsyms = 0;
2449 Cmd.indirectsymoff = 0;
2450 Cmd.nindirectsyms = 0;
2451 Cmd.extreloff = 0;
2452 Cmd.nextrel = 0;
2453 Cmd.locreloff = 0;
2454 Cmd.nlocrel = 0;
2455 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002456}
2457
Charles Davis8bdfafd2013-09-01 04:28:48 +00002458MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002459MachOObjectFile::getDataInCodeLoadCommand() const {
2460 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002461 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002462
2463 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002464 MachO::linkedit_data_command Cmd;
2465 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2466 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2467 Cmd.dataoff = 0;
2468 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002469 return Cmd;
2470}
2471
Kevin Enderby9a509442015-01-27 21:28:24 +00002472MachO::linkedit_data_command
2473MachOObjectFile::getLinkOptHintsLoadCommand() const {
2474 if (LinkOptHintsLoadCmd)
2475 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2476
2477 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2478 // fields.
2479 MachO::linkedit_data_command Cmd;
2480 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2481 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2482 Cmd.dataoff = 0;
2483 Cmd.datasize = 0;
2484 return Cmd;
2485}
2486
Nick Kledzikd04bc352014-08-30 00:20:14 +00002487ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2488 if (!DyldInfoLoadCmd)
2489 return ArrayRef<uint8_t>();
2490
2491 MachO::dyld_info_command DyldInfo
2492 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2493 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2494 getPtr(this, DyldInfo.rebase_off));
2495 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2496}
2497
2498ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2499 if (!DyldInfoLoadCmd)
2500 return ArrayRef<uint8_t>();
2501
2502 MachO::dyld_info_command DyldInfo
2503 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2504 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2505 getPtr(this, DyldInfo.bind_off));
2506 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2507}
2508
2509ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2510 if (!DyldInfoLoadCmd)
2511 return ArrayRef<uint8_t>();
2512
2513 MachO::dyld_info_command DyldInfo
2514 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2515 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2516 getPtr(this, DyldInfo.weak_bind_off));
2517 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2518}
2519
2520ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2521 if (!DyldInfoLoadCmd)
2522 return ArrayRef<uint8_t>();
2523
2524 MachO::dyld_info_command DyldInfo
2525 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2526 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2527 getPtr(this, DyldInfo.lazy_bind_off));
2528 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2529}
2530
2531ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2532 if (!DyldInfoLoadCmd)
2533 return ArrayRef<uint8_t>();
2534
2535 MachO::dyld_info_command DyldInfo
2536 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2537 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2538 getPtr(this, DyldInfo.export_off));
2539 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2540}
2541
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002542ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2543 if (!UuidLoadCmd)
2544 return ArrayRef<uint8_t>();
Benjamin Kramer014601d2014-10-24 15:52:05 +00002545 // Returning a pointer is fine as uuid doesn't need endian swapping.
2546 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2547 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002548}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002549
Rafael Espindola6e040c02013-04-26 20:07:33 +00002550StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002551 MachO::symtab_command S = getSymtabLoadCommand();
2552 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002553}
2554
Rafael Espindola56f976f2013-04-18 18:08:55 +00002555bool MachOObjectFile::is64Bit() const {
2556 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002557 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002558}
2559
2560void MachOObjectFile::ReadULEB128s(uint64_t Index,
2561 SmallVectorImpl<uint64_t> &Out) const {
2562 DataExtractor extractor(ObjectFile::getData(), true, 0);
2563
2564 uint32_t offset = Index;
2565 uint64_t data = 0;
2566 while (uint64_t delta = extractor.getULEB128(&offset)) {
2567 data += delta;
2568 Out.push_back(data);
2569 }
2570}
2571
Rafael Espindolac66d7612014-08-17 19:09:37 +00002572bool MachOObjectFile::isRelocatableObject() const {
2573 return getHeader().filetype == MachO::MH_OBJECT;
2574}
2575
Rafael Espindola437b0d52014-07-31 03:12:45 +00002576ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002577ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2578 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002579 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002580 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002581 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002582 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002583 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002584 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002585 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002586 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002587 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002588 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002589 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002590 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002591
Rafael Espindola692410e2014-01-21 23:06:54 +00002592 if (EC)
2593 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002594 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002595}
2596