blob: cc11244d9ebcb408401ae7f2b70acdf9ed3317fd [file] [log] [blame]
Eric Christopher7b015c72011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Anderson27c579d2011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Tim Northover00ed9962014-03-29 10:18:08 +000016#include "llvm/ADT/STLExtras.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000017#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "llvm/ADT/Triple.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000019#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000020#include "llvm/Support/Debug.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000021#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000022#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000023#include "llvm/Support/LEB128.h"
24#include "llvm/Support/MachO.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000025#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000026#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000027#include <cctype>
28#include <cstring>
29#include <limits>
30
31using namespace llvm;
32using namespace object;
33
Artyom Skrobov7d602f72014-07-20 12:08:28 +000034namespace {
35 struct section_base {
36 char sectname[16];
37 char segname[16];
38 };
39}
Rafael Espindola56f976f2013-04-18 18:08:55 +000040
41template<typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000042static T getStruct(const MachOObjectFile *O, const char *P) {
Rafael Espindola3cdeb172013-04-19 13:45:05 +000043 T Cmd;
44 memcpy(&Cmd, P, sizeof(T));
45 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000046 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000047 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000048}
49
Rafael Espindola56f976f2013-04-18 18:08:55 +000050static uint32_t
51getSegmentLoadCommandNumSections(const MachOObjectFile *O,
52 const MachOObjectFile::LoadCommandInfo &L) {
53 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000054 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
55 return S.nsects;
Rafael Espindola421305a2013-04-07 20:01:29 +000056 }
Charles Davis8bdfafd2013-09-01 04:28:48 +000057 MachO::segment_command S = O->getSegmentLoadCommand(L);
58 return S.nsects;
Rafael Espindola5ffc0792013-04-07 16:07:35 +000059}
60
Nick Kledzik56ebef42014-09-16 01:41:51 +000061static bool isPageZeroSegment(const MachOObjectFile *O,
62 const MachOObjectFile::LoadCommandInfo &L) {
63 if (O->is64Bit()) {
64 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
65 return StringRef("__PAGEZERO").equals(S.segname);
66 }
67 MachO::segment_command S = O->getSegmentLoadCommand(L);
68 return StringRef("__PAGEZERO").equals(S.segname);
69}
70
71
Rafael Espindola6e040c02013-04-26 20:07:33 +000072static const char *
73getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
74 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000075 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
76
77 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000078 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
79 sizeof(MachO::segment_command);
80 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
81 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000082
83 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000084 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000085}
86
Rafael Espindola56f976f2013-04-18 18:08:55 +000087static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
88 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000089}
90
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000091static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000092getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000093 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000094 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000095}
96
Rafael Espindola56f976f2013-04-18 18:08:55 +000097static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000098 if (P[15] == 0)
99 // Null terminated.
100 return P;
101 // Not null terminated, so this is a 16 char string.
102 return StringRef(P, 16);
103}
104
Rafael Espindola56f976f2013-04-18 18:08:55 +0000105// Helper to advance a section or symbol iterator multiple increments at a time.
106template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000107static void advance(T &it, size_t Val) {
108 while (Val--)
109 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000110}
111
112static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000113 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000114}
115
116static void printRelocationTargetName(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000117 const MachO::any_relocation_info &RE,
Alp Tokere69170a2014-06-26 22:52:05 +0000118 raw_string_ostream &fmt) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000119 bool IsScattered = O->isRelocationScattered(RE);
120
121 // Target of a scattered relocation is an address. In the interest of
122 // generating pretty output, scan through the symbol table looking for a
123 // symbol that aligns with that address. If we find one, print it.
124 // Otherwise, we just print the hex address of the target.
125 if (IsScattered) {
126 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
127
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000128 for (const SymbolRef &Symbol : O->symbols()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000129 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000130 uint64_t Addr;
131 StringRef Name;
132
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000133 if ((ec = Symbol.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134 report_fatal_error(ec.message());
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000135 if (Addr != Val)
136 continue;
137 if ((ec = Symbol.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000138 report_fatal_error(ec.message());
139 fmt << Name;
140 return;
141 }
142
143 // If we couldn't find a symbol that this relocation refers to, try
144 // to find a section beginning instead.
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000145 for (const SectionRef &Section : O->sections()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000146 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000147 uint64_t Addr;
148 StringRef Name;
149
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000150 if ((ec = Section.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000151 report_fatal_error(ec.message());
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000152 if (Addr != Val)
153 continue;
154 if ((ec = Section.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000155 report_fatal_error(ec.message());
156 fmt << Name;
157 return;
158 }
159
160 fmt << format("0x%x", Val);
161 return;
162 }
163
164 StringRef S;
165 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000166 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000167
168 if (isExtern) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000169 symbol_iterator SI = O->symbol_begin();
Rafael Espindola5e812af2014-01-30 02:49:50 +0000170 advance(SI, Val);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000171 SI->getName(S);
172 } else {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000173 section_iterator SI = O->section_begin();
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000174 // Adjust for the fact that sections are 1-indexed.
Rafael Espindola5e812af2014-01-30 02:49:50 +0000175 advance(SI, Val - 1);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000176 SI->getName(S);
177 }
178
179 fmt << S;
180}
181
Charles Davis8bdfafd2013-09-01 04:28:48 +0000182static uint32_t
183getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
184 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000185}
186
187static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000188getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
189 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000190}
191
192static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000193 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000194 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000195 return (RE.r_word1 >> 24) & 1;
196 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000197}
198
199static bool
200getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000201 const MachO::any_relocation_info &RE) {
202 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000203}
204
205static unsigned getPlainRelocationLength(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 >> 25) & 3;
209 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000210}
211
212static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000213getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
214 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000215}
216
217static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000218 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000219 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000220 return RE.r_word1 >> 28;
221 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000222}
223
Charles Davis8bdfafd2013-09-01 04:28:48 +0000224static unsigned
225getScatteredRelocationType(const MachO::any_relocation_info &RE) {
226 return (RE.r_word0 >> 24) & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000227}
228
229static uint32_t getSectionFlags(const MachOObjectFile *O,
230 DataRefImpl Sec) {
231 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000232 MachO::section_64 Sect = O->getSection64(Sec);
233 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000234 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000235 MachO::section Sect = O->getSection(Sec);
236 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000237}
238
Rafael Espindola48af1c22014-08-19 18:44:46 +0000239MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
240 bool Is64bits, std::error_code &EC)
241 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000242 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Nick Kledzik56ebef42014-09-16 01:41:51 +0000243 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
244 HasPageZeroSegment(false) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000245 uint32_t LoadCommandCount = this->getHeader().ncmds;
246 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
247 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000248
249 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000250 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000251 if (Load.C.cmd == MachO::LC_SYMTAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000252 assert(!SymtabLoadCmd && "Multiple symbol tables");
253 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000254 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000255 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
256 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000257 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby273ae012013-06-06 17:20:50 +0000258 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
259 DataInCodeLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000260 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
261 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
262 assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");
263 DyldInfoLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000264 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000265 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
266 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000267 const char *Sec = getSectionPtr(this, Load, J);
268 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000269 }
Nick Kledzik56ebef42014-09-16 01:41:51 +0000270 if (isPageZeroSegment(this, Load))
271 HasPageZeroSegment = true;
Kevin Enderby980b2582014-06-05 21:21:57 +0000272 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
273 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
274 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
275 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
276 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
277 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000278 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000279
280 if (I == LoadCommandCount - 1)
281 break;
282 else
283 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000284 }
285}
286
Rafael Espindola5e812af2014-01-30 02:49:50 +0000287void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000288 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000289 sizeof(MachO::nlist_64) :
290 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000291 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000292}
293
Rafael Espindola3acea392014-06-12 21:46:39 +0000294std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
295 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000296 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000297 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000298 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000299 Res = StringRef(Start);
300 return object_error::success;
301}
302
Kevin Enderby980b2582014-06-05 21:21:57 +0000303// getIndirectName() returns the name of the alias'ed symbol who's string table
304// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000305std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
306 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000307 StringRef StringTable = getStringTableData();
308 uint64_t NValue;
309 if (is64Bit()) {
310 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
311 NValue = Entry.n_value;
312 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
313 return object_error::parse_failed;
314 } else {
315 MachO::nlist Entry = getSymbolTableEntry(Symb);
316 NValue = Entry.n_value;
317 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
318 return object_error::parse_failed;
319 }
320 if (NValue >= StringTable.size())
321 return object_error::parse_failed;
322 const char *Start = &StringTable.data()[NValue];
323 Res = StringRef(Start);
324 return object_error::success;
325}
326
Rafael Espindola3acea392014-06-12 21:46:39 +0000327std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
328 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000329 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000330 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000331 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
332 Entry.n_value == 0)
333 Res = UnknownAddressOrSize;
334 else
335 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000336 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000337 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000338 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
339 Entry.n_value == 0)
340 Res = UnknownAddressOrSize;
341 else
342 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000343 }
344 return object_error::success;
345}
346
Rafael Espindola3acea392014-06-12 21:46:39 +0000347std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
348 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000349 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000350 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000351 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000352 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000353 } else {
354 Result = 0;
355 }
356 return object_error::success;
357}
358
Rafael Espindola3acea392014-06-12 21:46:39 +0000359std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
360 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000361 uint64_t BeginOffset;
362 uint64_t EndOffset = 0;
363 uint8_t SectionIndex;
364
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000365 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000366 uint64_t Value;
367 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000368 if (Value == UnknownAddressOrSize) {
369 Result = UnknownAddressOrSize;
370 return object_error::success;
371 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000372
373 BeginOffset = Value;
374
Charles Davis8bdfafd2013-09-01 04:28:48 +0000375 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000376 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000377 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000378 if (flags & SymbolRef::SF_Common)
379 Result = Value;
380 else
381 Result = UnknownAddressOrSize;
382 return object_error::success;
383 }
384 // Unfortunately symbols are unsorted so we need to touch all
385 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000386 for (const SymbolRef &Symbol : symbols()) {
387 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000388 Entry = getSymbolTableEntryBase(this, DRI);
389 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000390 if (Value == UnknownAddressOrSize)
391 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000392 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000393 if (!EndOffset || Value < EndOffset)
394 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000395 }
396 if (!EndOffset) {
397 uint64_t Size;
398 DataRefImpl Sec;
399 Sec.d.a = SectionIndex-1;
400 getSectionSize(Sec, Size);
401 getSectionAddress(Sec, EndOffset);
402 EndOffset += Size;
403 }
404 Result = EndOffset - BeginOffset;
405 return object_error::success;
406}
407
Rafael Espindola3acea392014-06-12 21:46:39 +0000408std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
409 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000411 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000412
413 Res = SymbolRef::ST_Other;
414
415 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000416 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000417 Res = SymbolRef::ST_Debug;
418 return object_error::success;
419 }
420
Charles Davis74ec8b02013-08-27 05:00:13 +0000421 switch (n_type & MachO::N_TYPE) {
422 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000423 Res = SymbolRef::ST_Unknown;
424 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000425 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000426 Res = SymbolRef::ST_Function;
427 break;
428 }
429 return object_error::success;
430}
431
Rafael Espindola20122a42014-01-31 20:57:12 +0000432uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000433 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000434
Charles Davis8bdfafd2013-09-01 04:28:48 +0000435 uint8_t MachOType = Entry.n_type;
436 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437
Rafael Espindola20122a42014-01-31 20:57:12 +0000438 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000439
Charles Davis74ec8b02013-08-27 05:00:13 +0000440 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000441 Result |= SymbolRef::SF_Undefined;
442
Tim Northovereaef0742014-05-30 13:22:59 +0000443 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
444 Result |= SymbolRef::SF_Indirect;
445
Rafael Espindolaa1356322013-11-02 05:03:24 +0000446 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000447 Result |= SymbolRef::SF_FormatSpecific;
448
Charles Davis74ec8b02013-08-27 05:00:13 +0000449 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000450 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000451 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000452 uint64_t Value;
453 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000454 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000455 Result |= SymbolRef::SF_Common;
456 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000457 }
458
Charles Davis74ec8b02013-08-27 05:00:13 +0000459 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000460 Result |= SymbolRef::SF_Weak;
461
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000462 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
463 Result |= SymbolRef::SF_Thumb;
464
Charles Davis74ec8b02013-08-27 05:00:13 +0000465 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000466 Result |= SymbolRef::SF_Absolute;
467
Rafael Espindola20122a42014-01-31 20:57:12 +0000468 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000469}
470
Rafael Espindola3acea392014-06-12 21:46:39 +0000471std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
472 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000473 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000474 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000475
476 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000477 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000478 } else {
479 DataRefImpl DRI;
480 DRI.d.a = index - 1;
481 Res = section_iterator(SectionRef(DRI, this));
482 }
483
484 return object_error::success;
485}
486
Rafael Espindola5e812af2014-01-30 02:49:50 +0000487void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000488 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000489}
490
Rafael Espindola3acea392014-06-12 21:46:39 +0000491std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
492 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000493 ArrayRef<char> Raw = getSectionRawName(Sec);
494 Result = parseSegmentOrSectionName(Raw.data());
495 return object_error::success;
496}
497
Rafael Espindola3acea392014-06-12 21:46:39 +0000498std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
499 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000500 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000501 MachO::section_64 Sect = getSection64(Sec);
502 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000503 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000504 MachO::section Sect = getSection(Sec);
505 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000506 }
507 return object_error::success;
508}
509
Rafael Espindola3acea392014-06-12 21:46:39 +0000510std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
511 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000512 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000513 MachO::section_64 Sect = getSection64(Sec);
514 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000515 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000516 MachO::section Sect = getSection(Sec);
517 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000518 }
519
520 return object_error::success;
521}
522
Rafael Espindola3acea392014-06-12 21:46:39 +0000523std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
524 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000525 uint32_t Offset;
526 uint64_t Size;
527
528 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000529 MachO::section_64 Sect = getSection64(Sec);
530 Offset = Sect.offset;
531 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000532 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000533 MachO::section Sect = getSection(Sec);
534 Offset = Sect.offset;
535 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000536 }
537
538 Res = this->getData().substr(Offset, Size);
539 return object_error::success;
540}
541
Rafael Espindola3acea392014-06-12 21:46:39 +0000542std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
543 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000544 uint32_t Align;
545 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000546 MachO::section_64 Sect = getSection64(Sec);
547 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000548 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000549 MachO::section Sect = getSection(Sec);
550 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000551 }
552
553 Res = uint64_t(1) << Align;
554 return object_error::success;
555}
556
Rafael Espindola3acea392014-06-12 21:46:39 +0000557std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
558 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000559 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000560 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000561 return object_error::success;
562}
563
Rafael Espindola3acea392014-06-12 21:46:39 +0000564std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
565 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000566 uint32_t Flags = getSectionFlags(this, Sec);
567 unsigned SectionType = Flags & MachO::SECTION_TYPE;
568 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
569 !(SectionType == MachO::S_ZEROFILL ||
570 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000571 return object_error::success;
572}
573
Rafael Espindola3acea392014-06-12 21:46:39 +0000574std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
575 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000576 uint32_t Flags = getSectionFlags(this, Sec);
577 unsigned SectionType = Flags & MachO::SECTION_TYPE;
578 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
579 (SectionType == MachO::S_ZEROFILL ||
580 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000581 return object_error::success;
582}
583
Rafael Espindola3acea392014-06-12 21:46:39 +0000584std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000585MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindola137faa02013-04-24 15:14:22 +0000586 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000587 // FIXME: Unimplemented.
588 Result = true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000589 return object_error::success;
590}
591
Rafael Espindola3acea392014-06-12 21:46:39 +0000592std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
593 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000594 // FIXME: Unimplemented.
595 Result = false;
596 return object_error::success;
597}
598
Rafael Espindola3acea392014-06-12 21:46:39 +0000599std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
600 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000601 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis74ec8b02013-08-27 05:00:13 +0000602 unsigned SectionType = Flags & MachO::SECTION_TYPE;
603 Res = SectionType == MachO::S_ZEROFILL ||
604 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000605 return object_error::success;
606}
607
Rafael Espindola3acea392014-06-12 21:46:39 +0000608std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
609 bool &Result) const {
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000610 // Consider using the code from isSectionText to look for __const sections.
611 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
612 // to use section attributes to distinguish code from data.
613
614 // FIXME: Unimplemented.
615 Result = false;
616 return object_error::success;
617}
618
Rafael Espindola3acea392014-06-12 21:46:39 +0000619std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
620 DataRefImpl Symb,
621 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000622 SymbolRef::Type ST;
623 this->getSymbolType(Symb, ST);
624 if (ST == SymbolRef::ST_Unknown) {
625 Result = false;
626 return object_error::success;
627 }
628
629 uint64_t SectBegin, SectEnd;
630 getSectionAddress(Sec, SectBegin);
631 getSectionSize(Sec, SectEnd);
632 SectEnd += SectBegin;
633
634 uint64_t SymAddr;
635 getSymbolAddress(Symb, SymAddr);
636 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
637
638 return object_error::success;
639}
640
Rui Ueyamabc654b12013-09-27 21:47:05 +0000641relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000642 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000643 Ret.d.a = Sec.d.a;
644 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000645 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000646}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000647
Rafael Espindola56f976f2013-04-18 18:08:55 +0000648relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000649MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000650 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000651 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000652 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000653 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000654 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000655 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000656 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000657 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000658
Rafael Espindola56f976f2013-04-18 18:08:55 +0000659 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000660 Ret.d.a = Sec.d.a;
661 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000662 return relocation_iterator(RelocationRef(Ret, this));
663}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000664
Rafael Espindola5e812af2014-01-30 02:49:50 +0000665void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000666 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000667}
Owen Anderson171f4852011-10-24 23:20:07 +0000668
Rafael Espindola3acea392014-06-12 21:46:39 +0000669std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
670 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000671 uint64_t Offset;
672 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000673
674 DataRefImpl Sec;
675 Sec.d.a = Rel.d.a;
676 uint64_t SecAddress;
677 getSectionAddress(Sec, SecAddress);
678 Res = SecAddress + Offset;
679 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000680}
681
Rafael Espindola3acea392014-06-12 21:46:39 +0000682std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
683 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000684 assert(getHeader().filetype == MachO::MH_OBJECT &&
685 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000686 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000687 Res = getAnyRelocationAddress(RE);
688 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000689}
690
Rafael Espindola806f0062013-06-05 01:33:53 +0000691symbol_iterator
692MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000693 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000694 if (isRelocationScattered(RE))
695 return symbol_end();
696
Rafael Espindola56f976f2013-04-18 18:08:55 +0000697 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
698 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000699 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000700 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000701
Charles Davis8bdfafd2013-09-01 04:28:48 +0000702 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000703 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000704 sizeof(MachO::nlist_64) :
705 sizeof(MachO::nlist);
706 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000707 DataRefImpl Sym;
708 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000709 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000710}
711
Rafael Espindola3acea392014-06-12 21:46:39 +0000712std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
713 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000714 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000715 Res = getAnyRelocationType(RE);
716 return object_error::success;
717}
718
Rafael Espindola3acea392014-06-12 21:46:39 +0000719std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000720MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
721 SmallVectorImpl<char> &Result) const {
722 StringRef res;
723 uint64_t RType;
724 getRelocationType(Rel, RType);
725
726 unsigned Arch = this->getArch();
727
728 switch (Arch) {
729 case Triple::x86: {
730 static const char *const Table[] = {
731 "GENERIC_RELOC_VANILLA",
732 "GENERIC_RELOC_PAIR",
733 "GENERIC_RELOC_SECTDIFF",
734 "GENERIC_RELOC_PB_LA_PTR",
735 "GENERIC_RELOC_LOCAL_SECTDIFF",
736 "GENERIC_RELOC_TLV" };
737
Eric Christopher13250cb2013-12-06 02:33:38 +0000738 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000739 res = "Unknown";
740 else
741 res = Table[RType];
742 break;
743 }
744 case Triple::x86_64: {
745 static const char *const Table[] = {
746 "X86_64_RELOC_UNSIGNED",
747 "X86_64_RELOC_SIGNED",
748 "X86_64_RELOC_BRANCH",
749 "X86_64_RELOC_GOT_LOAD",
750 "X86_64_RELOC_GOT",
751 "X86_64_RELOC_SUBTRACTOR",
752 "X86_64_RELOC_SIGNED_1",
753 "X86_64_RELOC_SIGNED_2",
754 "X86_64_RELOC_SIGNED_4",
755 "X86_64_RELOC_TLV" };
756
757 if (RType > 9)
758 res = "Unknown";
759 else
760 res = Table[RType];
761 break;
762 }
763 case Triple::arm: {
764 static const char *const Table[] = {
765 "ARM_RELOC_VANILLA",
766 "ARM_RELOC_PAIR",
767 "ARM_RELOC_SECTDIFF",
768 "ARM_RELOC_LOCAL_SECTDIFF",
769 "ARM_RELOC_PB_LA_PTR",
770 "ARM_RELOC_BR24",
771 "ARM_THUMB_RELOC_BR22",
772 "ARM_THUMB_32BIT_BRANCH",
773 "ARM_RELOC_HALF",
774 "ARM_RELOC_HALF_SECTDIFF" };
775
776 if (RType > 9)
777 res = "Unknown";
778 else
779 res = Table[RType];
780 break;
781 }
Tim Northover00ed9962014-03-29 10:18:08 +0000782 case Triple::aarch64: {
783 static const char *const Table[] = {
784 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
785 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
786 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
787 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
788 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
789 "ARM64_RELOC_ADDEND"
790 };
791
792 if (RType >= array_lengthof(Table))
793 res = "Unknown";
794 else
795 res = Table[RType];
796 break;
797 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000798 case Triple::ppc: {
799 static const char *const Table[] = {
800 "PPC_RELOC_VANILLA",
801 "PPC_RELOC_PAIR",
802 "PPC_RELOC_BR14",
803 "PPC_RELOC_BR24",
804 "PPC_RELOC_HI16",
805 "PPC_RELOC_LO16",
806 "PPC_RELOC_HA16",
807 "PPC_RELOC_LO14",
808 "PPC_RELOC_SECTDIFF",
809 "PPC_RELOC_PB_LA_PTR",
810 "PPC_RELOC_HI16_SECTDIFF",
811 "PPC_RELOC_LO16_SECTDIFF",
812 "PPC_RELOC_HA16_SECTDIFF",
813 "PPC_RELOC_JBSR",
814 "PPC_RELOC_LO14_SECTDIFF",
815 "PPC_RELOC_LOCAL_SECTDIFF" };
816
Eric Christopher13250cb2013-12-06 02:33:38 +0000817 if (RType > 15)
818 res = "Unknown";
819 else
820 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000821 break;
822 }
823 case Triple::UnknownArch:
824 res = "Unknown";
825 break;
826 }
827 Result.append(res.begin(), res.end());
828 return object_error::success;
829}
830
Rafael Espindola3acea392014-06-12 21:46:39 +0000831std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000832MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000833 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000834 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000835
Rafael Espindola56f976f2013-04-18 18:08:55 +0000836 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000837
Alp Tokere69170a2014-06-26 22:52:05 +0000838 std::string fmtbuf;
839 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000840 unsigned Type = this->getAnyRelocationType(RE);
841 bool IsPCRel = this->getAnyRelocationPCRel(RE);
842
843 // Determine any addends that should be displayed with the relocation.
844 // These require decoding the relocation type, which is triple-specific.
845
846 // X86_64 has entirely custom relocation types.
847 if (Arch == Triple::x86_64) {
848 bool isPCRel = getAnyRelocationPCRel(RE);
849
850 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000851 case MachO::X86_64_RELOC_GOT_LOAD:
852 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000853 printRelocationTargetName(this, RE, fmt);
854 fmt << "@GOT";
855 if (isPCRel) fmt << "PCREL";
856 break;
857 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000858 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000859 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000860 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000861 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000862
Charles Davis8bdfafd2013-09-01 04:28:48 +0000863 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000864 // X86_64_RELOC_UNSIGNED.
865 // NOTE: Scattered relocations don't exist on x86_64.
866 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000867 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000868 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
869 "X86_64_RELOC_SUBTRACTOR.");
870
Charles Davis8bdfafd2013-09-01 04:28:48 +0000871 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
872 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000873 printRelocationTargetName(this, RENext, fmt);
874 fmt << "-";
875 printRelocationTargetName(this, RE, fmt);
876 break;
877 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000878 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000879 printRelocationTargetName(this, RE, fmt);
880 fmt << "@TLV";
881 if (isPCRel) fmt << "P";
882 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000883 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000884 printRelocationTargetName(this, RE, fmt);
885 fmt << "-1";
886 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000887 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000888 printRelocationTargetName(this, RE, fmt);
889 fmt << "-2";
890 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000891 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000892 printRelocationTargetName(this, RE, fmt);
893 fmt << "-4";
894 break;
895 default:
896 printRelocationTargetName(this, RE, fmt);
897 break;
898 }
899 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000900 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
901 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000902 // Generic relocation types...
903 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000904 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000905 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000906 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000907 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000908 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000909 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000910
911 // X86 sect diff's must be followed by a relocation of type
912 // GENERIC_RELOC_PAIR.
913 unsigned RType = getAnyRelocationType(RENext);
914
Charles Davis8bdfafd2013-09-01 04:28:48 +0000915 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000916 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
917 "GENERIC_RELOC_SECTDIFF.");
918
919 printRelocationTargetName(this, RE, fmt);
920 fmt << "-";
921 printRelocationTargetName(this, RENext, fmt);
922 break;
923 }
924 }
925
David Fangb88cdf62013-08-08 20:14:40 +0000926 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000927 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000928 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000929 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000930 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000931 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000932
933 // X86 sect diff's must be followed by a relocation of type
934 // GENERIC_RELOC_PAIR.
935 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000936 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000937 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
938 "GENERIC_RELOC_LOCAL_SECTDIFF.");
939
940 printRelocationTargetName(this, RE, fmt);
941 fmt << "-";
942 printRelocationTargetName(this, RENext, fmt);
943 break;
944 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000945 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000946 printRelocationTargetName(this, RE, fmt);
947 fmt << "@TLV";
948 if (IsPCRel) fmt << "P";
949 break;
950 }
951 default:
952 printRelocationTargetName(this, RE, fmt);
953 }
954 } else { // ARM-specific relocations
955 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000956 case MachO::ARM_RELOC_HALF:
957 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000958 // Half relocations steal a bit from the length field to encode
959 // whether this is an upper16 or a lower16 relocation.
960 bool isUpper = getAnyRelocationLength(RE) >> 1;
961
962 if (isUpper)
963 fmt << ":upper16:(";
964 else
965 fmt << ":lower16:(";
966 printRelocationTargetName(this, RE, fmt);
967
968 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000969 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000970 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000971
972 // ARM half relocs must be followed by a relocation of type
973 // ARM_RELOC_PAIR.
974 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000975 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000976 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000977 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000978
979 // NOTE: The half of the target virtual address is stashed in the
980 // address field of the secondary relocation, but we can't reverse
981 // engineer the constant offset from it without decoding the movw/movt
982 // instruction to find the other half in its immediate field.
983
984 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
985 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000986 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000987 fmt << "-";
988 printRelocationTargetName(this, RENext, fmt);
989 }
990
991 fmt << ")";
992 break;
993 }
994 default: {
995 printRelocationTargetName(this, RE, fmt);
996 }
997 }
998 }
999 } else
1000 printRelocationTargetName(this, RE, fmt);
1001
Alp Tokere69170a2014-06-26 22:52:05 +00001002 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001003 Result.append(fmtbuf.begin(), fmtbuf.end());
1004 return object_error::success;
1005}
1006
Rafael Espindola3acea392014-06-12 21:46:39 +00001007std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1008 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001009 unsigned Arch = getArch();
1010 uint64_t Type;
1011 getRelocationType(Rel, Type);
1012
1013 Result = false;
1014
1015 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1016 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +00001017 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001018 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001019 } else if (Arch == Triple::x86_64) {
1020 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +00001021 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001022 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001023 DataRefImpl RelPrev = Rel;
1024 RelPrev.d.a--;
1025 uint64_t PrevType;
1026 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001027 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001028 Result = true;
1029 }
1030 }
1031
1032 return object_error::success;
1033}
1034
Kevin Enderby980b2582014-06-05 21:21:57 +00001035//
1036// guessLibraryShortName() is passed a name of a dynamic library and returns a
1037// guess on what the short name is. Then name is returned as a substring of the
1038// StringRef Name passed in. The name of the dynamic library is recognized as
1039// a framework if it has one of the two following forms:
1040// Foo.framework/Versions/A/Foo
1041// Foo.framework/Foo
1042// Where A and Foo can be any string. And may contain a trailing suffix
1043// starting with an underbar. If the Name is recognized as a framework then
1044// isFramework is set to true else it is set to false. If the Name has a
1045// suffix then Suffix is set to the substring in Name that contains the suffix
1046// else it is set to a NULL StringRef.
1047//
1048// The Name of the dynamic library is recognized as a library name if it has
1049// one of the two following forms:
1050// libFoo.A.dylib
1051// libFoo.dylib
1052// The library may have a suffix trailing the name Foo of the form:
1053// libFoo_profile.A.dylib
1054// libFoo_profile.dylib
1055//
1056// The Name of the dynamic library is also recognized as a library name if it
1057// has the following form:
1058// Foo.qtx
1059//
1060// If the Name of the dynamic library is none of the forms above then a NULL
1061// StringRef is returned.
1062//
1063StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1064 bool &isFramework,
1065 StringRef &Suffix) {
1066 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1067 size_t a, b, c, d, Idx;
1068
1069 isFramework = false;
1070 Suffix = StringRef();
1071
1072 // Pull off the last component and make Foo point to it
1073 a = Name.rfind('/');
1074 if (a == Name.npos || a == 0)
1075 goto guess_library;
1076 Foo = Name.slice(a+1, Name.npos);
1077
1078 // Look for a suffix starting with a '_'
1079 Idx = Foo.rfind('_');
1080 if (Idx != Foo.npos && Foo.size() >= 2) {
1081 Suffix = Foo.slice(Idx, Foo.npos);
1082 Foo = Foo.slice(0, Idx);
1083 }
1084
1085 // First look for the form Foo.framework/Foo
1086 b = Name.rfind('/', a);
1087 if (b == Name.npos)
1088 Idx = 0;
1089 else
1090 Idx = b+1;
1091 F = Name.slice(Idx, Idx + Foo.size());
1092 DotFramework = Name.slice(Idx + Foo.size(),
1093 Idx + Foo.size() + sizeof(".framework/")-1);
1094 if (F == Foo && DotFramework == ".framework/") {
1095 isFramework = true;
1096 return Foo;
1097 }
1098
1099 // Next look for the form Foo.framework/Versions/A/Foo
1100 if (b == Name.npos)
1101 goto guess_library;
1102 c = Name.rfind('/', b);
1103 if (c == Name.npos || c == 0)
1104 goto guess_library;
1105 V = Name.slice(c+1, Name.npos);
1106 if (!V.startswith("Versions/"))
1107 goto guess_library;
1108 d = Name.rfind('/', c);
1109 if (d == Name.npos)
1110 Idx = 0;
1111 else
1112 Idx = d+1;
1113 F = Name.slice(Idx, Idx + Foo.size());
1114 DotFramework = Name.slice(Idx + Foo.size(),
1115 Idx + Foo.size() + sizeof(".framework/")-1);
1116 if (F == Foo && DotFramework == ".framework/") {
1117 isFramework = true;
1118 return Foo;
1119 }
1120
1121guess_library:
1122 // pull off the suffix after the "." and make a point to it
1123 a = Name.rfind('.');
1124 if (a == Name.npos || a == 0)
1125 return StringRef();
1126 Dylib = Name.slice(a, Name.npos);
1127 if (Dylib != ".dylib")
1128 goto guess_qtx;
1129
1130 // First pull off the version letter for the form Foo.A.dylib if any.
1131 if (a >= 3) {
1132 Dot = Name.slice(a-2, a-1);
1133 if (Dot == ".")
1134 a = a - 2;
1135 }
1136
1137 b = Name.rfind('/', a);
1138 if (b == Name.npos)
1139 b = 0;
1140 else
1141 b = b+1;
1142 // ignore any suffix after an underbar like Foo_profile.A.dylib
1143 Idx = Name.find('_', b);
1144 if (Idx != Name.npos && Idx != b) {
1145 Lib = Name.slice(b, Idx);
1146 Suffix = Name.slice(Idx, a);
1147 }
1148 else
1149 Lib = Name.slice(b, a);
1150 // There are incorrect library names of the form:
1151 // libATS.A_profile.dylib so check for these.
1152 if (Lib.size() >= 3) {
1153 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1154 if (Dot == ".")
1155 Lib = Lib.slice(0, Lib.size()-2);
1156 }
1157 return Lib;
1158
1159guess_qtx:
1160 Qtx = Name.slice(a, Name.npos);
1161 if (Qtx != ".qtx")
1162 return StringRef();
1163 b = Name.rfind('/', a);
1164 if (b == Name.npos)
1165 Lib = Name.slice(0, a);
1166 else
1167 Lib = Name.slice(b+1, a);
1168 // There are library names of the form: QT.A.qtx so check for these.
1169 if (Lib.size() >= 3) {
1170 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1171 if (Dot == ".")
1172 Lib = Lib.slice(0, Lib.size()-2);
1173 }
1174 return Lib;
1175}
1176
1177// getLibraryShortNameByIndex() is used to get the short name of the library
1178// for an undefined symbol in a linked Mach-O binary that was linked with the
1179// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1180// It is passed the index (0 - based) of the library as translated from
1181// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001182std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001183 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001184 if (Index >= Libraries.size())
1185 return object_error::parse_failed;
1186
Kevin Enderby980b2582014-06-05 21:21:57 +00001187 // If the cache of LibrariesShortNames is not built up do that first for
1188 // all the Libraries.
1189 if (LibrariesShortNames.size() == 0) {
1190 for (unsigned i = 0; i < Libraries.size(); i++) {
1191 MachO::dylib_command D =
1192 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001193 if (D.dylib.name >= D.cmdsize)
1194 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001195 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001196 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001197 if (D.dylib.name+Name.size() >= D.cmdsize)
1198 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001199 StringRef Suffix;
1200 bool isFramework;
1201 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001202 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001203 LibrariesShortNames.push_back(Name);
1204 else
1205 LibrariesShortNames.push_back(shortName);
1206 }
1207 }
1208
1209 Res = LibrariesShortNames[Index];
1210 return object_error::success;
1211}
1212
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001213basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001214 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001215}
1216
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001217basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001218 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001219 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001220 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001221
Charles Davis8bdfafd2013-09-01 04:28:48 +00001222 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001223 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001224 sizeof(MachO::nlist_64) :
1225 sizeof(MachO::nlist);
1226 unsigned Offset = Symtab.symoff +
1227 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001228 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001229 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001230}
1231
Lang Hames36072da2014-05-12 21:39:59 +00001232basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1233 DataRefImpl DRI;
1234 if (!SymtabLoadCmd)
1235 return basic_symbol_iterator(SymbolRef(DRI, this));
1236
1237 MachO::symtab_command Symtab = getSymtabLoadCommand();
1238 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1239 unsigned SymbolTableEntrySize =
1240 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1241 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1242 DRI.p += Index * SymbolTableEntrySize;
1243 return basic_symbol_iterator(SymbolRef(DRI, this));
1244}
1245
Rafael Espindolab5155a52014-02-10 20:24:04 +00001246section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001247 DataRefImpl DRI;
1248 return section_iterator(SectionRef(DRI, this));
1249}
1250
Rafael Espindolab5155a52014-02-10 20:24:04 +00001251section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001252 DataRefImpl DRI;
1253 DRI.d.a = Sections.size();
1254 return section_iterator(SectionRef(DRI, this));
1255}
1256
Rafael Espindola56f976f2013-04-18 18:08:55 +00001257uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001258 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001259}
1260
Rafael Espindola56f976f2013-04-18 18:08:55 +00001261StringRef MachOObjectFile::getFileFormatName() const {
1262 unsigned CPUType = getCPUType(this);
1263 if (!is64Bit()) {
1264 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001265 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001266 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001267 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001268 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001269 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001270 return "Mach-O 32-bit ppc";
1271 default:
Charles Davis74ec8b02013-08-27 05:00:13 +00001272 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindola56f976f2013-04-18 18:08:55 +00001273 "64-bit object file when we're not 64-bit?");
1274 return "Mach-O 32-bit unknown";
1275 }
1276 }
1277
1278 // Make sure the cpu type has the correct mask.
Charles Davis74ec8b02013-08-27 05:00:13 +00001279 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1280 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher1d62c252013-07-22 22:25:07 +00001281 "32-bit object file when we're 64-bit?");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001282
1283 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001284 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001285 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001286 case llvm::MachO::CPU_TYPE_ARM64:
1287 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001288 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001289 return "Mach-O 64-bit ppc64";
1290 default:
1291 return "Mach-O 64-bit unknown";
1292 }
1293}
1294
Alexey Samsonove6388e62013-06-18 15:03:28 +00001295Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1296 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001297 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001298 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001299 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001300 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001301 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001302 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001303 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001304 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001305 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001306 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001307 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001308 return Triple::ppc64;
1309 default:
1310 return Triple::UnknownArch;
1311 }
1312}
1313
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001314Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1315 const char **McpuDefault) {
1316 if (McpuDefault)
1317 *McpuDefault = nullptr;
1318
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001319 switch (CPUType) {
1320 case MachO::CPU_TYPE_I386:
1321 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1322 case MachO::CPU_SUBTYPE_I386_ALL:
1323 return Triple("i386-apple-darwin");
1324 default:
1325 return Triple();
1326 }
1327 case MachO::CPU_TYPE_X86_64:
1328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1329 case MachO::CPU_SUBTYPE_X86_64_ALL:
1330 return Triple("x86_64-apple-darwin");
1331 case MachO::CPU_SUBTYPE_X86_64_H:
1332 return Triple("x86_64h-apple-darwin");
1333 default:
1334 return Triple();
1335 }
1336 case MachO::CPU_TYPE_ARM:
1337 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1338 case MachO::CPU_SUBTYPE_ARM_V4T:
1339 return Triple("armv4t-apple-darwin");
1340 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1341 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001342 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1343 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001344 case MachO::CPU_SUBTYPE_ARM_V6:
1345 return Triple("armv6-apple-darwin");
1346 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001347 if (McpuDefault)
1348 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001349 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001350 case MachO::CPU_SUBTYPE_ARM_V7:
1351 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001352 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001353 if (McpuDefault)
1354 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001355 return Triple("armv7em-apple-darwin");
1356 case MachO::CPU_SUBTYPE_ARM_V7K:
1357 return Triple("armv7k-apple-darwin");
1358 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001359 if (McpuDefault)
1360 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001361 return Triple("armv7m-apple-darwin");
1362 case MachO::CPU_SUBTYPE_ARM_V7S:
1363 return Triple("armv7s-apple-darwin");
1364 default:
1365 return Triple();
1366 }
1367 case MachO::CPU_TYPE_ARM64:
1368 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1369 case MachO::CPU_SUBTYPE_ARM64_ALL:
1370 return Triple("arm64-apple-darwin");
1371 default:
1372 return Triple();
1373 }
1374 case MachO::CPU_TYPE_POWERPC:
1375 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1376 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1377 return Triple("ppc-apple-darwin");
1378 default:
1379 return Triple();
1380 }
1381 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001382 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001383 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1384 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001385 default:
1386 return Triple();
1387 }
1388 default:
1389 return Triple();
1390 }
1391}
1392
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001393Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1394 const char **McpuDefault) {
1395 if (McpuDefault)
1396 *McpuDefault = nullptr;
1397
1398 switch (CPUType) {
1399 case MachO::CPU_TYPE_ARM:
1400 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1401 case MachO::CPU_SUBTYPE_ARM_V4T:
1402 return Triple("thumbv4t-apple-darwin");
1403 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1404 return Triple("thumbv5e-apple-darwin");
1405 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1406 return Triple("xscale-apple-darwin");
1407 case MachO::CPU_SUBTYPE_ARM_V6:
1408 return Triple("thumbv6-apple-darwin");
1409 case MachO::CPU_SUBTYPE_ARM_V6M:
1410 if (McpuDefault)
1411 *McpuDefault = "cortex-m0";
1412 return Triple("thumbv6m-apple-darwin");
1413 case MachO::CPU_SUBTYPE_ARM_V7:
1414 return Triple("thumbv7-apple-darwin");
1415 case MachO::CPU_SUBTYPE_ARM_V7EM:
1416 if (McpuDefault)
1417 *McpuDefault = "cortex-m4";
1418 return Triple("thumbv7em-apple-darwin");
1419 case MachO::CPU_SUBTYPE_ARM_V7K:
1420 return Triple("thumbv7k-apple-darwin");
1421 case MachO::CPU_SUBTYPE_ARM_V7M:
1422 if (McpuDefault)
1423 *McpuDefault = "cortex-m3";
1424 return Triple("thumbv7m-apple-darwin");
1425 case MachO::CPU_SUBTYPE_ARM_V7S:
1426 return Triple("thumbv7s-apple-darwin");
1427 default:
1428 return Triple();
1429 }
1430 default:
1431 return Triple();
1432 }
1433}
1434
1435Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1436 const char **McpuDefault,
1437 Triple *ThumbTriple) {
1438 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1439 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1440 McpuDefault);
1441 return T;
1442}
1443
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001444Triple MachOObjectFile::getHostArch() {
1445 return Triple(sys::getDefaultTargetTriple());
1446}
1447
Rafael Espindola72318b42014-08-08 16:30:17 +00001448bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1449 return StringSwitch<bool>(ArchFlag)
1450 .Case("i386", true)
1451 .Case("x86_64", true)
1452 .Case("x86_64h", true)
1453 .Case("armv4t", true)
1454 .Case("arm", true)
1455 .Case("armv5e", true)
1456 .Case("armv6", true)
1457 .Case("armv6m", true)
1458 .Case("armv7em", true)
1459 .Case("armv7k", true)
1460 .Case("armv7m", true)
1461 .Case("armv7s", true)
1462 .Case("arm64", true)
1463 .Case("ppc", true)
1464 .Case("ppc64", true)
1465 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001466}
1467
Alexey Samsonove6388e62013-06-18 15:03:28 +00001468unsigned MachOObjectFile::getArch() const {
1469 return getArch(getCPUType(this));
1470}
1471
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001472Triple MachOObjectFile::getArch(const char **McpuDefault,
1473 Triple *ThumbTriple) const {
1474 Triple T;
1475 if (is64Bit()) {
1476 MachO::mach_header_64 H_64;
1477 H_64 = getHeader64();
1478 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1479 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1480 McpuDefault);
1481 } else {
1482 MachO::mach_header H;
1483 H = getHeader();
1484 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1485 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1486 McpuDefault);
1487 }
1488 return T;
1489}
1490
Rui Ueyamabc654b12013-09-27 21:47:05 +00001491relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001492 DataRefImpl DRI;
1493 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001494 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001495}
1496
Rui Ueyamabc654b12013-09-27 21:47:05 +00001497relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001498 DataRefImpl DRI;
1499 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001500 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001501}
1502
Kevin Enderby273ae012013-06-06 17:20:50 +00001503dice_iterator MachOObjectFile::begin_dices() const {
1504 DataRefImpl DRI;
1505 if (!DataInCodeLoadCmd)
1506 return dice_iterator(DiceRef(DRI, this));
1507
Charles Davis8bdfafd2013-09-01 04:28:48 +00001508 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1509 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001510 return dice_iterator(DiceRef(DRI, this));
1511}
1512
1513dice_iterator MachOObjectFile::end_dices() const {
1514 DataRefImpl DRI;
1515 if (!DataInCodeLoadCmd)
1516 return dice_iterator(DiceRef(DRI, this));
1517
Charles Davis8bdfafd2013-09-01 04:28:48 +00001518 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1519 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001520 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1521 return dice_iterator(DiceRef(DRI, this));
1522}
1523
Nick Kledzikd04bc352014-08-30 00:20:14 +00001524ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1525 : Trie(T), Malformed(false), Done(false) { }
1526
1527void ExportEntry::moveToFirst() {
1528 pushNode(0);
1529 pushDownUntilBottom();
1530}
1531
1532void ExportEntry::moveToEnd() {
1533 Stack.clear();
1534 Done = true;
1535}
1536
1537bool ExportEntry::operator==(const ExportEntry &Other) const {
1538 // Common case, one at end, other iterating from begin.
1539 if (Done || Other.Done)
1540 return (Done == Other.Done);
1541 // Not equal if different stack sizes.
1542 if (Stack.size() != Other.Stack.size())
1543 return false;
1544 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001545 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001546 return false;
1547 // Equal if all nodes in both stacks match.
1548 for (unsigned i=0; i < Stack.size(); ++i) {
1549 if (Stack[i].Start != Other.Stack[i].Start)
1550 return false;
1551 }
1552 return true;
1553}
1554
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001555uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1556 unsigned Count;
1557 uint64_t Result = decodeULEB128(Ptr, &Count);
1558 Ptr += Count;
1559 if (Ptr > Trie.end()) {
1560 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001561 Malformed = true;
1562 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001563 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001564}
1565
1566StringRef ExportEntry::name() const {
1567 return CumulativeString.str();
1568}
1569
1570uint64_t ExportEntry::flags() const {
1571 return Stack.back().Flags;
1572}
1573
1574uint64_t ExportEntry::address() const {
1575 return Stack.back().Address;
1576}
1577
1578uint64_t ExportEntry::other() const {
1579 return Stack.back().Other;
1580}
1581
1582StringRef ExportEntry::otherName() const {
1583 const char* ImportName = Stack.back().ImportName;
1584 if (ImportName)
1585 return StringRef(ImportName);
1586 return StringRef();
1587}
1588
1589uint32_t ExportEntry::nodeOffset() const {
1590 return Stack.back().Start - Trie.begin();
1591}
1592
1593ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1594 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1595 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1596 ParentStringLength(0), IsExportNode(false) {
1597}
1598
1599void ExportEntry::pushNode(uint64_t offset) {
1600 const uint8_t *Ptr = Trie.begin() + offset;
1601 NodeState State(Ptr);
1602 uint64_t ExportInfoSize = readULEB128(State.Current);
1603 State.IsExportNode = (ExportInfoSize != 0);
1604 const uint8_t* Children = State.Current + ExportInfoSize;
1605 if (State.IsExportNode) {
1606 State.Flags = readULEB128(State.Current);
1607 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1608 State.Address = 0;
1609 State.Other = readULEB128(State.Current); // dylib ordinal
1610 State.ImportName = reinterpret_cast<const char*>(State.Current);
1611 } else {
1612 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001613 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1614 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001615 }
1616 }
1617 State.ChildCount = *Children;
1618 State.Current = Children + 1;
1619 State.NextChildIndex = 0;
1620 State.ParentStringLength = CumulativeString.size();
1621 Stack.push_back(State);
1622}
1623
1624void ExportEntry::pushDownUntilBottom() {
1625 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1626 NodeState &Top = Stack.back();
1627 CumulativeString.resize(Top.ParentStringLength);
1628 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001629 char C = *Top.Current;
1630 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001631 }
1632 Top.Current += 1;
1633 uint64_t childNodeIndex = readULEB128(Top.Current);
1634 Top.NextChildIndex += 1;
1635 pushNode(childNodeIndex);
1636 }
1637 if (!Stack.back().IsExportNode) {
1638 Malformed = true;
1639 moveToEnd();
1640 }
1641}
1642
1643// We have a trie data structure and need a way to walk it that is compatible
1644// with the C++ iterator model. The solution is a non-recursive depth first
1645// traversal where the iterator contains a stack of parent nodes along with a
1646// string that is the accumulation of all edge strings along the parent chain
1647// to this point.
1648//
1649// There is one “export” node for each exported symbol. But because some
1650// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1651// node may have child nodes too.
1652//
1653// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1654// child until hitting a node with no children (which is an export node or
1655// else the trie is malformed). On the way down, each node is pushed on the
1656// stack ivar. If there is no more ways down, it pops up one and tries to go
1657// down a sibling path until a childless node is reached.
1658void ExportEntry::moveNext() {
1659 if (Stack.empty() || !Stack.back().IsExportNode) {
1660 Malformed = true;
1661 moveToEnd();
1662 return;
1663 }
1664
1665 Stack.pop_back();
1666 while (!Stack.empty()) {
1667 NodeState &Top = Stack.back();
1668 if (Top.NextChildIndex < Top.ChildCount) {
1669 pushDownUntilBottom();
1670 // Now at the next export node.
1671 return;
1672 } else {
1673 if (Top.IsExportNode) {
1674 // This node has no children but is itself an export node.
1675 CumulativeString.resize(Top.ParentStringLength);
1676 return;
1677 }
1678 Stack.pop_back();
1679 }
1680 }
1681 Done = true;
1682}
1683
1684iterator_range<export_iterator>
1685MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1686 ExportEntry Start(Trie);
1687 Start.moveToFirst();
1688
1689 ExportEntry Finish(Trie);
1690 Finish.moveToEnd();
1691
1692 return iterator_range<export_iterator>(export_iterator(Start),
1693 export_iterator(Finish));
1694}
1695
1696iterator_range<export_iterator> MachOObjectFile::exports() const {
1697 return exports(getDyldInfoExportsTrie());
1698}
1699
1700
Nick Kledzikac431442014-09-12 21:34:15 +00001701MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1702 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1703 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1704 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1705
1706void MachORebaseEntry::moveToFirst() {
1707 Ptr = Opcodes.begin();
1708 moveNext();
1709}
1710
1711void MachORebaseEntry::moveToEnd() {
1712 Ptr = Opcodes.end();
1713 RemainingLoopCount = 0;
1714 Done = true;
1715}
1716
1717void MachORebaseEntry::moveNext() {
1718 // If in the middle of some loop, move to next rebasing in loop.
1719 SegmentOffset += AdvanceAmount;
1720 if (RemainingLoopCount) {
1721 --RemainingLoopCount;
1722 return;
1723 }
1724 if (Ptr == Opcodes.end()) {
1725 Done = true;
1726 return;
1727 }
1728 bool More = true;
1729 while (More && !Malformed) {
1730 // Parse next opcode and set up next loop.
1731 uint8_t Byte = *Ptr++;
1732 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1733 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1734 switch (Opcode) {
1735 case MachO::REBASE_OPCODE_DONE:
1736 More = false;
1737 Done = true;
1738 moveToEnd();
1739 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1740 break;
1741 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1742 RebaseType = ImmValue;
1743 DEBUG_WITH_TYPE(
1744 "mach-o-rebase",
1745 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1746 << "RebaseType=" << (int) RebaseType << "\n");
1747 break;
1748 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1749 SegmentIndex = ImmValue;
1750 SegmentOffset = readULEB128();
1751 DEBUG_WITH_TYPE(
1752 "mach-o-rebase",
1753 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1754 << "SegmentIndex=" << SegmentIndex << ", "
1755 << format("SegmentOffset=0x%06X", SegmentOffset)
1756 << "\n");
1757 break;
1758 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1759 SegmentOffset += readULEB128();
1760 DEBUG_WITH_TYPE("mach-o-rebase",
1761 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1762 << format("SegmentOffset=0x%06X",
1763 SegmentOffset) << "\n");
1764 break;
1765 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1766 SegmentOffset += ImmValue * PointerSize;
1767 DEBUG_WITH_TYPE("mach-o-rebase",
1768 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1769 << format("SegmentOffset=0x%06X",
1770 SegmentOffset) << "\n");
1771 break;
1772 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1773 AdvanceAmount = PointerSize;
1774 RemainingLoopCount = ImmValue - 1;
1775 DEBUG_WITH_TYPE(
1776 "mach-o-rebase",
1777 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1778 << format("SegmentOffset=0x%06X", SegmentOffset)
1779 << ", AdvanceAmount=" << AdvanceAmount
1780 << ", RemainingLoopCount=" << RemainingLoopCount
1781 << "\n");
1782 return;
1783 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1784 AdvanceAmount = PointerSize;
1785 RemainingLoopCount = readULEB128() - 1;
1786 DEBUG_WITH_TYPE(
1787 "mach-o-rebase",
1788 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1789 << format("SegmentOffset=0x%06X", SegmentOffset)
1790 << ", AdvanceAmount=" << AdvanceAmount
1791 << ", RemainingLoopCount=" << RemainingLoopCount
1792 << "\n");
1793 return;
1794 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1795 AdvanceAmount = readULEB128() + PointerSize;
1796 RemainingLoopCount = 0;
1797 DEBUG_WITH_TYPE(
1798 "mach-o-rebase",
1799 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1800 << format("SegmentOffset=0x%06X", SegmentOffset)
1801 << ", AdvanceAmount=" << AdvanceAmount
1802 << ", RemainingLoopCount=" << RemainingLoopCount
1803 << "\n");
1804 return;
1805 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1806 RemainingLoopCount = readULEB128() - 1;
1807 AdvanceAmount = readULEB128() + PointerSize;
1808 DEBUG_WITH_TYPE(
1809 "mach-o-rebase",
1810 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1811 << format("SegmentOffset=0x%06X", SegmentOffset)
1812 << ", AdvanceAmount=" << AdvanceAmount
1813 << ", RemainingLoopCount=" << RemainingLoopCount
1814 << "\n");
1815 return;
1816 default:
1817 Malformed = true;
1818 }
1819 }
1820}
1821
1822uint64_t MachORebaseEntry::readULEB128() {
1823 unsigned Count;
1824 uint64_t Result = decodeULEB128(Ptr, &Count);
1825 Ptr += Count;
1826 if (Ptr > Opcodes.end()) {
1827 Ptr = Opcodes.end();
1828 Malformed = true;
1829 }
1830 return Result;
1831}
1832
1833uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1834
1835uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1836
1837StringRef MachORebaseEntry::typeName() const {
1838 switch (RebaseType) {
1839 case MachO::REBASE_TYPE_POINTER:
1840 return "pointer";
1841 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1842 return "text abs32";
1843 case MachO::REBASE_TYPE_TEXT_PCREL32:
1844 return "text rel32";
1845 }
1846 return "unknown";
1847}
1848
1849bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1850 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1851 return (Ptr == Other.Ptr) &&
1852 (RemainingLoopCount == Other.RemainingLoopCount) &&
1853 (Done == Other.Done);
1854}
1855
1856iterator_range<rebase_iterator>
1857MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1858 MachORebaseEntry Start(Opcodes, is64);
1859 Start.moveToFirst();
1860
1861 MachORebaseEntry Finish(Opcodes, is64);
1862 Finish.moveToEnd();
1863
1864 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1865 rebase_iterator(Finish));
1866}
1867
1868iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1869 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1870}
1871
Nick Kledzik56ebef42014-09-16 01:41:51 +00001872
1873MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1874 Kind BK)
1875 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1876 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1877 BindType(0), PointerSize(is64Bit ? 8 : 4),
1878 TableKind(BK), Malformed(false), Done(false) {}
1879
1880void MachOBindEntry::moveToFirst() {
1881 Ptr = Opcodes.begin();
1882 moveNext();
1883}
1884
1885void MachOBindEntry::moveToEnd() {
1886 Ptr = Opcodes.end();
1887 RemainingLoopCount = 0;
1888 Done = true;
1889}
1890
1891void MachOBindEntry::moveNext() {
1892 // If in the middle of some loop, move to next binding in loop.
1893 SegmentOffset += AdvanceAmount;
1894 if (RemainingLoopCount) {
1895 --RemainingLoopCount;
1896 return;
1897 }
1898 if (Ptr == Opcodes.end()) {
1899 Done = true;
1900 return;
1901 }
1902 bool More = true;
1903 while (More && !Malformed) {
1904 // Parse next opcode and set up next loop.
1905 uint8_t Byte = *Ptr++;
1906 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1907 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1908 int8_t SignExtended;
1909 const uint8_t *SymStart;
1910 switch (Opcode) {
1911 case MachO::BIND_OPCODE_DONE:
1912 if (TableKind == Kind::Lazy) {
1913 // Lazying bindings have a DONE opcode between entries. Need to ignore
1914 // it to advance to next entry. But need not if this is last entry.
1915 bool NotLastEntry = false;
1916 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1917 if (*P) {
1918 NotLastEntry = true;
1919 }
1920 }
1921 if (NotLastEntry)
1922 break;
1923 }
1924 More = false;
1925 Done = true;
1926 moveToEnd();
1927 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1928 break;
1929 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1930 Ordinal = ImmValue;
1931 DEBUG_WITH_TYPE(
1932 "mach-o-bind",
1933 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1934 << "Ordinal=" << Ordinal << "\n");
1935 break;
1936 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1937 Ordinal = readULEB128();
1938 DEBUG_WITH_TYPE(
1939 "mach-o-bind",
1940 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1941 << "Ordinal=" << Ordinal << "\n");
1942 break;
1943 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1944 if (ImmValue) {
1945 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1946 Ordinal = SignExtended;
1947 } else
1948 Ordinal = 0;
1949 DEBUG_WITH_TYPE(
1950 "mach-o-bind",
1951 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1952 << "Ordinal=" << Ordinal << "\n");
1953 break;
1954 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1955 Flags = ImmValue;
1956 SymStart = Ptr;
1957 while (*Ptr) {
1958 ++Ptr;
1959 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001960 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1961 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001962 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001963 DEBUG_WITH_TYPE(
1964 "mach-o-bind",
1965 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1966 << "SymbolName=" << SymbolName << "\n");
1967 if (TableKind == Kind::Weak) {
1968 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1969 return;
1970 }
1971 break;
1972 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1973 BindType = ImmValue;
1974 DEBUG_WITH_TYPE(
1975 "mach-o-bind",
1976 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1977 << "BindType=" << (int)BindType << "\n");
1978 break;
1979 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1980 Addend = readSLEB128();
1981 if (TableKind == Kind::Lazy)
1982 Malformed = true;
1983 DEBUG_WITH_TYPE(
1984 "mach-o-bind",
1985 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1986 << "Addend=" << Addend << "\n");
1987 break;
1988 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1989 SegmentIndex = ImmValue;
1990 SegmentOffset = readULEB128();
1991 DEBUG_WITH_TYPE(
1992 "mach-o-bind",
1993 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1994 << "SegmentIndex=" << SegmentIndex << ", "
1995 << format("SegmentOffset=0x%06X", SegmentOffset)
1996 << "\n");
1997 break;
1998 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1999 SegmentOffset += readULEB128();
2000 DEBUG_WITH_TYPE("mach-o-bind",
2001 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2002 << format("SegmentOffset=0x%06X",
2003 SegmentOffset) << "\n");
2004 break;
2005 case MachO::BIND_OPCODE_DO_BIND:
2006 AdvanceAmount = PointerSize;
2007 RemainingLoopCount = 0;
2008 DEBUG_WITH_TYPE("mach-o-bind",
2009 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2010 << format("SegmentOffset=0x%06X",
2011 SegmentOffset) << "\n");
2012 return;
2013 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2014 AdvanceAmount = readULEB128();
2015 RemainingLoopCount = 0;
2016 if (TableKind == Kind::Lazy)
2017 Malformed = true;
2018 DEBUG_WITH_TYPE(
2019 "mach-o-bind",
2020 llvm::dbgs() << "BIND_OPCODE_DO_BIND_IMM_TIMES: "
2021 << format("SegmentOffset=0x%06X", SegmentOffset)
2022 << ", AdvanceAmount=" << AdvanceAmount
2023 << ", RemainingLoopCount=" << RemainingLoopCount
2024 << "\n");
2025 return;
2026 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2027 AdvanceAmount = ImmValue * PointerSize;
2028 RemainingLoopCount = 0;
2029 if (TableKind == Kind::Lazy)
2030 Malformed = true;
2031 DEBUG_WITH_TYPE("mach-o-bind",
2032 llvm::dbgs()
2033 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2034 << format("SegmentOffset=0x%06X",
2035 SegmentOffset) << "\n");
2036 return;
2037 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2038 RemainingLoopCount = readULEB128() - 1;
2039 AdvanceAmount = readULEB128() + PointerSize;
2040 if (TableKind == Kind::Lazy)
2041 Malformed = true;
2042 DEBUG_WITH_TYPE(
2043 "mach-o-bind",
2044 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2045 << format("SegmentOffset=0x%06X", SegmentOffset)
2046 << ", AdvanceAmount=" << AdvanceAmount
2047 << ", RemainingLoopCount=" << RemainingLoopCount
2048 << "\n");
2049 return;
2050 default:
2051 Malformed = true;
2052 }
2053 }
2054}
2055
2056uint64_t MachOBindEntry::readULEB128() {
2057 unsigned Count;
2058 uint64_t Result = decodeULEB128(Ptr, &Count);
2059 Ptr += Count;
2060 if (Ptr > Opcodes.end()) {
2061 Ptr = Opcodes.end();
2062 Malformed = true;
2063 }
2064 return Result;
2065}
2066
2067int64_t MachOBindEntry::readSLEB128() {
2068 unsigned Count;
2069 int64_t Result = decodeSLEB128(Ptr, &Count);
2070 Ptr += Count;
2071 if (Ptr > Opcodes.end()) {
2072 Ptr = Opcodes.end();
2073 Malformed = true;
2074 }
2075 return Result;
2076}
2077
2078
2079uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2080
2081uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2082
2083StringRef MachOBindEntry::typeName() const {
2084 switch (BindType) {
2085 case MachO::BIND_TYPE_POINTER:
2086 return "pointer";
2087 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2088 return "text abs32";
2089 case MachO::BIND_TYPE_TEXT_PCREL32:
2090 return "text rel32";
2091 }
2092 return "unknown";
2093}
2094
2095StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2096
2097int64_t MachOBindEntry::addend() const { return Addend; }
2098
2099uint32_t MachOBindEntry::flags() const { return Flags; }
2100
2101int MachOBindEntry::ordinal() const { return Ordinal; }
2102
2103bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2104 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2105 return (Ptr == Other.Ptr) &&
2106 (RemainingLoopCount == Other.RemainingLoopCount) &&
2107 (Done == Other.Done);
2108}
2109
2110iterator_range<bind_iterator>
2111MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2112 MachOBindEntry::Kind BKind) {
2113 MachOBindEntry Start(Opcodes, is64, BKind);
2114 Start.moveToFirst();
2115
2116 MachOBindEntry Finish(Opcodes, is64, BKind);
2117 Finish.moveToEnd();
2118
2119 return iterator_range<bind_iterator>(bind_iterator(Start),
2120 bind_iterator(Finish));
2121}
2122
2123iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2124 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2125 MachOBindEntry::Kind::Regular);
2126}
2127
2128iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2129 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2130 MachOBindEntry::Kind::Lazy);
2131}
2132
2133iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2134 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2135 MachOBindEntry::Kind::Weak);
2136}
2137
Rafael Espindola56f976f2013-04-18 18:08:55 +00002138StringRef
2139MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2140 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2141 return parseSegmentOrSectionName(Raw.data());
2142}
2143
2144ArrayRef<char>
2145MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002146 const section_base *Base =
2147 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002148 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002149}
2150
2151ArrayRef<char>
2152MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002153 const section_base *Base =
2154 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002155 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002156}
2157
2158bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002159MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002160 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002161 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002162 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002163 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002164}
2165
Eric Christopher1d62c252013-07-22 22:25:07 +00002166unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002167 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002168 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002169 return RE.r_word1 & 0xffffff;
2170 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002171}
2172
Eric Christopher1d62c252013-07-22 22:25:07 +00002173bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002174 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002175 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002176 return (RE.r_word1 >> 27) & 1;
2177 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002178}
2179
Eric Christopher1d62c252013-07-22 22:25:07 +00002180bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002181 const MachO::any_relocation_info &RE) const {
2182 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002183}
2184
Eric Christopher1d62c252013-07-22 22:25:07 +00002185uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002186 const MachO::any_relocation_info &RE) const {
2187 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002188}
2189
Eric Christopher1d62c252013-07-22 22:25:07 +00002190unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002191 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002192 if (isRelocationScattered(RE))
2193 return getScatteredRelocationAddress(RE);
2194 return getPlainRelocationAddress(RE);
2195}
2196
Charles Davis8bdfafd2013-09-01 04:28:48 +00002197unsigned MachOObjectFile::getAnyRelocationPCRel(
2198 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002199 if (isRelocationScattered(RE))
2200 return getScatteredRelocationPCRel(this, RE);
2201 return getPlainRelocationPCRel(this, RE);
2202}
2203
Eric Christopher1d62c252013-07-22 22:25:07 +00002204unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002205 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002206 if (isRelocationScattered(RE))
2207 return getScatteredRelocationLength(RE);
2208 return getPlainRelocationLength(this, RE);
2209}
2210
2211unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002212MachOObjectFile::getAnyRelocationType(
2213 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002214 if (isRelocationScattered(RE))
2215 return getScatteredRelocationType(RE);
2216 return getPlainRelocationType(this, RE);
2217}
2218
Rafael Espindola52501032013-04-30 15:40:54 +00002219SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00002220MachOObjectFile::getRelocationSection(
2221 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002222 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002223 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002224 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2225 DataRefImpl DRI;
2226 DRI.d.a = SecNum;
2227 return SectionRef(DRI, this);
2228}
2229
Rafael Espindola56f976f2013-04-18 18:08:55 +00002230MachOObjectFile::LoadCommandInfo
2231MachOObjectFile::getFirstLoadCommandInfo() const {
2232 MachOObjectFile::LoadCommandInfo Load;
2233
Charles Davis8bdfafd2013-09-01 04:28:48 +00002234 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2235 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002236 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002237 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002238 return Load;
2239}
2240
2241MachOObjectFile::LoadCommandInfo
2242MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2243 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002244 Next.Ptr = L.Ptr + L.C.cmdsize;
2245 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002246 return Next;
2247}
2248
Charles Davis8bdfafd2013-09-01 04:28:48 +00002249MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2250 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002251}
2252
Charles Davis8bdfafd2013-09-01 04:28:48 +00002253MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2254 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002255}
2256
Charles Davis8bdfafd2013-09-01 04:28:48 +00002257MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002258 unsigned Index) const {
2259 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002260 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002261}
2262
Charles Davis8bdfafd2013-09-01 04:28:48 +00002263MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2264 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002265 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002266 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002267}
2268
Charles Davis8bdfafd2013-09-01 04:28:48 +00002269MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002270MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002271 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002272 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002273}
2274
Charles Davis8bdfafd2013-09-01 04:28:48 +00002275MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002276MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002277 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002278 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002279}
2280
Charles Davis8bdfafd2013-09-01 04:28:48 +00002281MachO::linkedit_data_command
2282MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2283 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002284}
2285
Charles Davis8bdfafd2013-09-01 04:28:48 +00002286MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002287MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002288 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002289}
2290
Charles Davis8bdfafd2013-09-01 04:28:48 +00002291MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002292MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002293 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002294}
2295
Charles Davis8bdfafd2013-09-01 04:28:48 +00002296MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002297MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002298 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002299}
2300
Jim Grosbach448334a2014-03-18 22:09:05 +00002301MachO::version_min_command
2302MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2303 return getStruct<MachO::version_min_command>(this, L.Ptr);
2304}
2305
Tim Northover8f9590b2014-06-30 14:40:57 +00002306MachO::dylib_command
2307MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2308 return getStruct<MachO::dylib_command>(this, L.Ptr);
2309}
2310
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002311MachO::dyld_info_command
2312MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2313 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2314}
2315
2316MachO::dylinker_command
2317MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2318 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2319}
2320
2321MachO::uuid_command
2322MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2323 return getStruct<MachO::uuid_command>(this, L.Ptr);
2324}
2325
2326MachO::source_version_command
2327MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2328 return getStruct<MachO::source_version_command>(this, L.Ptr);
2329}
2330
2331MachO::entry_point_command
2332MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2333 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2334}
2335
Tim Northover8f9590b2014-06-30 14:40:57 +00002336
Charles Davis8bdfafd2013-09-01 04:28:48 +00002337MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002338MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002339 DataRefImpl Sec;
2340 Sec.d.a = Rel.d.a;
2341 uint32_t Offset;
2342 if (is64Bit()) {
2343 MachO::section_64 Sect = getSection64(Sec);
2344 Offset = Sect.reloff;
2345 } else {
2346 MachO::section Sect = getSection(Sec);
2347 Offset = Sect.reloff;
2348 }
2349
2350 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2351 getPtr(this, Offset)) + Rel.d.b;
2352 return getStruct<MachO::any_relocation_info>(
2353 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002354}
2355
Charles Davis8bdfafd2013-09-01 04:28:48 +00002356MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002357MachOObjectFile::getDice(DataRefImpl Rel) const {
2358 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002359 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002360}
2361
Charles Davis8bdfafd2013-09-01 04:28:48 +00002362MachO::mach_header MachOObjectFile::getHeader() const {
2363 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002364}
2365
Charles Davis8bdfafd2013-09-01 04:28:48 +00002366MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2367 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002368}
2369
Charles Davis8bdfafd2013-09-01 04:28:48 +00002370uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2371 const MachO::dysymtab_command &DLC,
2372 unsigned Index) const {
2373 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2374 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002375}
2376
Charles Davis8bdfafd2013-09-01 04:28:48 +00002377MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002378MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2379 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002380 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2381 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002382}
2383
Charles Davis8bdfafd2013-09-01 04:28:48 +00002384MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2385 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002386}
2387
Charles Davis8bdfafd2013-09-01 04:28:48 +00002388MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2389 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002390}
2391
Charles Davis8bdfafd2013-09-01 04:28:48 +00002392MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002393MachOObjectFile::getDataInCodeLoadCommand() const {
2394 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002395 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002396
2397 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002398 MachO::linkedit_data_command Cmd;
2399 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2400 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2401 Cmd.dataoff = 0;
2402 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002403 return Cmd;
2404}
2405
Nick Kledzikd04bc352014-08-30 00:20:14 +00002406ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2407 if (!DyldInfoLoadCmd)
2408 return ArrayRef<uint8_t>();
2409
2410 MachO::dyld_info_command DyldInfo
2411 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2412 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2413 getPtr(this, DyldInfo.rebase_off));
2414 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2415}
2416
2417ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2418 if (!DyldInfoLoadCmd)
2419 return ArrayRef<uint8_t>();
2420
2421 MachO::dyld_info_command DyldInfo
2422 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2423 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2424 getPtr(this, DyldInfo.bind_off));
2425 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2426}
2427
2428ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2429 if (!DyldInfoLoadCmd)
2430 return ArrayRef<uint8_t>();
2431
2432 MachO::dyld_info_command DyldInfo
2433 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2434 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2435 getPtr(this, DyldInfo.weak_bind_off));
2436 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2437}
2438
2439ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2440 if (!DyldInfoLoadCmd)
2441 return ArrayRef<uint8_t>();
2442
2443 MachO::dyld_info_command DyldInfo
2444 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2445 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2446 getPtr(this, DyldInfo.lazy_bind_off));
2447 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2448}
2449
2450ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2451 if (!DyldInfoLoadCmd)
2452 return ArrayRef<uint8_t>();
2453
2454 MachO::dyld_info_command DyldInfo
2455 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2456 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2457 getPtr(this, DyldInfo.export_off));
2458 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2459}
2460
2461
Rafael Espindola6e040c02013-04-26 20:07:33 +00002462StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002463 MachO::symtab_command S = getSymtabLoadCommand();
2464 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002465}
2466
Rafael Espindola56f976f2013-04-18 18:08:55 +00002467bool MachOObjectFile::is64Bit() const {
2468 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002469 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002470}
2471
2472void MachOObjectFile::ReadULEB128s(uint64_t Index,
2473 SmallVectorImpl<uint64_t> &Out) const {
2474 DataExtractor extractor(ObjectFile::getData(), true, 0);
2475
2476 uint32_t offset = Index;
2477 uint64_t data = 0;
2478 while (uint64_t delta = extractor.getULEB128(&offset)) {
2479 data += delta;
2480 Out.push_back(data);
2481 }
2482}
2483
Rafael Espindolac66d7612014-08-17 19:09:37 +00002484bool MachOObjectFile::isRelocatableObject() const {
2485 return getHeader().filetype == MachO::MH_OBJECT;
2486}
2487
Rafael Espindola437b0d52014-07-31 03:12:45 +00002488ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002489ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2490 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002491 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002492 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002493 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002494 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002495 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002496 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002497 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002498 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002499 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002500 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002501 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002502 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002503
Rafael Espindola692410e2014-01-21 23:06:54 +00002504 if (EC)
2505 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002506 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002507}
2508