blob: bb973b41db2d80ed57ec6eb42e2d273483a1a744 [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
1187 MachO::dylib_command D =
1188 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1189 if (D.dylib.name >= D.cmdsize)
1190 return object_error::parse_failed;
1191
1192 // If the cache of LibrariesShortNames is not built up do that first for
1193 // all the Libraries.
1194 if (LibrariesShortNames.size() == 0) {
1195 for (unsigned i = 0; i < Libraries.size(); i++) {
1196 MachO::dylib_command D =
1197 getStruct<MachO::dylib_command>(this, Libraries[i]);
1198 if (D.dylib.name >= D.cmdsize) {
1199 LibrariesShortNames.push_back(StringRef());
1200 continue;
1201 }
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001202 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001203 StringRef Name = StringRef(P);
1204 StringRef Suffix;
1205 bool isFramework;
1206 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1207 if (shortName == StringRef())
1208 LibrariesShortNames.push_back(Name);
1209 else
1210 LibrariesShortNames.push_back(shortName);
1211 }
1212 }
1213
1214 Res = LibrariesShortNames[Index];
1215 return object_error::success;
1216}
1217
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001218basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001219 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001220}
1221
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001222basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001223 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001224 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001225 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001226
Charles Davis8bdfafd2013-09-01 04:28:48 +00001227 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001228 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001229 sizeof(MachO::nlist_64) :
1230 sizeof(MachO::nlist);
1231 unsigned Offset = Symtab.symoff +
1232 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001233 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001234 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001235}
1236
Lang Hames36072da2014-05-12 21:39:59 +00001237basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1238 DataRefImpl DRI;
1239 if (!SymtabLoadCmd)
1240 return basic_symbol_iterator(SymbolRef(DRI, this));
1241
1242 MachO::symtab_command Symtab = getSymtabLoadCommand();
1243 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1244 unsigned SymbolTableEntrySize =
1245 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1246 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1247 DRI.p += Index * SymbolTableEntrySize;
1248 return basic_symbol_iterator(SymbolRef(DRI, this));
1249}
1250
Rafael Espindolab5155a52014-02-10 20:24:04 +00001251section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001252 DataRefImpl DRI;
1253 return section_iterator(SectionRef(DRI, this));
1254}
1255
Rafael Espindolab5155a52014-02-10 20:24:04 +00001256section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001257 DataRefImpl DRI;
1258 DRI.d.a = Sections.size();
1259 return section_iterator(SectionRef(DRI, this));
1260}
1261
Rafael Espindola56f976f2013-04-18 18:08:55 +00001262uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001263 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001264}
1265
Rafael Espindola56f976f2013-04-18 18:08:55 +00001266StringRef MachOObjectFile::getFileFormatName() const {
1267 unsigned CPUType = getCPUType(this);
1268 if (!is64Bit()) {
1269 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001270 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001271 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001272 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001273 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001274 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001275 return "Mach-O 32-bit ppc";
1276 default:
Charles Davis74ec8b02013-08-27 05:00:13 +00001277 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindola56f976f2013-04-18 18:08:55 +00001278 "64-bit object file when we're not 64-bit?");
1279 return "Mach-O 32-bit unknown";
1280 }
1281 }
1282
1283 // Make sure the cpu type has the correct mask.
Charles Davis74ec8b02013-08-27 05:00:13 +00001284 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1285 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher1d62c252013-07-22 22:25:07 +00001286 "32-bit object file when we're 64-bit?");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001287
1288 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001289 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001290 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001291 case llvm::MachO::CPU_TYPE_ARM64:
1292 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001293 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001294 return "Mach-O 64-bit ppc64";
1295 default:
1296 return "Mach-O 64-bit unknown";
1297 }
1298}
1299
Alexey Samsonove6388e62013-06-18 15:03:28 +00001300Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1301 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001302 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001303 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001304 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001305 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001306 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001307 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001308 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001309 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001310 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001311 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001312 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001313 return Triple::ppc64;
1314 default:
1315 return Triple::UnknownArch;
1316 }
1317}
1318
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001319Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1320 const char **McpuDefault) {
1321 if (McpuDefault)
1322 *McpuDefault = nullptr;
1323
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001324 switch (CPUType) {
1325 case MachO::CPU_TYPE_I386:
1326 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1327 case MachO::CPU_SUBTYPE_I386_ALL:
1328 return Triple("i386-apple-darwin");
1329 default:
1330 return Triple();
1331 }
1332 case MachO::CPU_TYPE_X86_64:
1333 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1334 case MachO::CPU_SUBTYPE_X86_64_ALL:
1335 return Triple("x86_64-apple-darwin");
1336 case MachO::CPU_SUBTYPE_X86_64_H:
1337 return Triple("x86_64h-apple-darwin");
1338 default:
1339 return Triple();
1340 }
1341 case MachO::CPU_TYPE_ARM:
1342 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1343 case MachO::CPU_SUBTYPE_ARM_V4T:
1344 return Triple("armv4t-apple-darwin");
1345 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1346 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001347 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1348 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001349 case MachO::CPU_SUBTYPE_ARM_V6:
1350 return Triple("armv6-apple-darwin");
1351 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001352 if (McpuDefault)
1353 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001354 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001355 case MachO::CPU_SUBTYPE_ARM_V7:
1356 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001357 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001358 if (McpuDefault)
1359 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001360 return Triple("armv7em-apple-darwin");
1361 case MachO::CPU_SUBTYPE_ARM_V7K:
1362 return Triple("armv7k-apple-darwin");
1363 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001364 if (McpuDefault)
1365 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001366 return Triple("armv7m-apple-darwin");
1367 case MachO::CPU_SUBTYPE_ARM_V7S:
1368 return Triple("armv7s-apple-darwin");
1369 default:
1370 return Triple();
1371 }
1372 case MachO::CPU_TYPE_ARM64:
1373 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1374 case MachO::CPU_SUBTYPE_ARM64_ALL:
1375 return Triple("arm64-apple-darwin");
1376 default:
1377 return Triple();
1378 }
1379 case MachO::CPU_TYPE_POWERPC:
1380 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1381 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1382 return Triple("ppc-apple-darwin");
1383 default:
1384 return Triple();
1385 }
1386 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001387 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001388 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1389 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001390 default:
1391 return Triple();
1392 }
1393 default:
1394 return Triple();
1395 }
1396}
1397
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001398Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1399 const char **McpuDefault) {
1400 if (McpuDefault)
1401 *McpuDefault = nullptr;
1402
1403 switch (CPUType) {
1404 case MachO::CPU_TYPE_ARM:
1405 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1406 case MachO::CPU_SUBTYPE_ARM_V4T:
1407 return Triple("thumbv4t-apple-darwin");
1408 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1409 return Triple("thumbv5e-apple-darwin");
1410 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1411 return Triple("xscale-apple-darwin");
1412 case MachO::CPU_SUBTYPE_ARM_V6:
1413 return Triple("thumbv6-apple-darwin");
1414 case MachO::CPU_SUBTYPE_ARM_V6M:
1415 if (McpuDefault)
1416 *McpuDefault = "cortex-m0";
1417 return Triple("thumbv6m-apple-darwin");
1418 case MachO::CPU_SUBTYPE_ARM_V7:
1419 return Triple("thumbv7-apple-darwin");
1420 case MachO::CPU_SUBTYPE_ARM_V7EM:
1421 if (McpuDefault)
1422 *McpuDefault = "cortex-m4";
1423 return Triple("thumbv7em-apple-darwin");
1424 case MachO::CPU_SUBTYPE_ARM_V7K:
1425 return Triple("thumbv7k-apple-darwin");
1426 case MachO::CPU_SUBTYPE_ARM_V7M:
1427 if (McpuDefault)
1428 *McpuDefault = "cortex-m3";
1429 return Triple("thumbv7m-apple-darwin");
1430 case MachO::CPU_SUBTYPE_ARM_V7S:
1431 return Triple("thumbv7s-apple-darwin");
1432 default:
1433 return Triple();
1434 }
1435 default:
1436 return Triple();
1437 }
1438}
1439
1440Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1441 const char **McpuDefault,
1442 Triple *ThumbTriple) {
1443 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1444 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1445 McpuDefault);
1446 return T;
1447}
1448
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001449Triple MachOObjectFile::getHostArch() {
1450 return Triple(sys::getDefaultTargetTriple());
1451}
1452
Rafael Espindola72318b42014-08-08 16:30:17 +00001453bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1454 return StringSwitch<bool>(ArchFlag)
1455 .Case("i386", true)
1456 .Case("x86_64", true)
1457 .Case("x86_64h", true)
1458 .Case("armv4t", true)
1459 .Case("arm", true)
1460 .Case("armv5e", true)
1461 .Case("armv6", true)
1462 .Case("armv6m", true)
1463 .Case("armv7em", true)
1464 .Case("armv7k", true)
1465 .Case("armv7m", true)
1466 .Case("armv7s", true)
1467 .Case("arm64", true)
1468 .Case("ppc", true)
1469 .Case("ppc64", true)
1470 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001471}
1472
Alexey Samsonove6388e62013-06-18 15:03:28 +00001473unsigned MachOObjectFile::getArch() const {
1474 return getArch(getCPUType(this));
1475}
1476
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001477Triple MachOObjectFile::getArch(const char **McpuDefault,
1478 Triple *ThumbTriple) const {
1479 Triple T;
1480 if (is64Bit()) {
1481 MachO::mach_header_64 H_64;
1482 H_64 = getHeader64();
1483 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1484 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1485 McpuDefault);
1486 } else {
1487 MachO::mach_header H;
1488 H = getHeader();
1489 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1490 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1491 McpuDefault);
1492 }
1493 return T;
1494}
1495
Rui Ueyamabc654b12013-09-27 21:47:05 +00001496relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001497 DataRefImpl DRI;
1498 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001499 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001500}
1501
Rui Ueyamabc654b12013-09-27 21:47:05 +00001502relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001503 DataRefImpl DRI;
1504 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001505 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001506}
1507
Kevin Enderby273ae012013-06-06 17:20:50 +00001508dice_iterator MachOObjectFile::begin_dices() const {
1509 DataRefImpl DRI;
1510 if (!DataInCodeLoadCmd)
1511 return dice_iterator(DiceRef(DRI, this));
1512
Charles Davis8bdfafd2013-09-01 04:28:48 +00001513 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1514 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001515 return dice_iterator(DiceRef(DRI, this));
1516}
1517
1518dice_iterator MachOObjectFile::end_dices() const {
1519 DataRefImpl DRI;
1520 if (!DataInCodeLoadCmd)
1521 return dice_iterator(DiceRef(DRI, this));
1522
Charles Davis8bdfafd2013-09-01 04:28:48 +00001523 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1524 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001525 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1526 return dice_iterator(DiceRef(DRI, this));
1527}
1528
Nick Kledzikd04bc352014-08-30 00:20:14 +00001529ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1530 : Trie(T), Malformed(false), Done(false) { }
1531
1532void ExportEntry::moveToFirst() {
1533 pushNode(0);
1534 pushDownUntilBottom();
1535}
1536
1537void ExportEntry::moveToEnd() {
1538 Stack.clear();
1539 Done = true;
1540}
1541
1542bool ExportEntry::operator==(const ExportEntry &Other) const {
1543 // Common case, one at end, other iterating from begin.
1544 if (Done || Other.Done)
1545 return (Done == Other.Done);
1546 // Not equal if different stack sizes.
1547 if (Stack.size() != Other.Stack.size())
1548 return false;
1549 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001550 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001551 return false;
1552 // Equal if all nodes in both stacks match.
1553 for (unsigned i=0; i < Stack.size(); ++i) {
1554 if (Stack[i].Start != Other.Stack[i].Start)
1555 return false;
1556 }
1557 return true;
1558}
1559
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001560uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1561 unsigned Count;
1562 uint64_t Result = decodeULEB128(Ptr, &Count);
1563 Ptr += Count;
1564 if (Ptr > Trie.end()) {
1565 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001566 Malformed = true;
1567 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001568 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001569}
1570
1571StringRef ExportEntry::name() const {
1572 return CumulativeString.str();
1573}
1574
1575uint64_t ExportEntry::flags() const {
1576 return Stack.back().Flags;
1577}
1578
1579uint64_t ExportEntry::address() const {
1580 return Stack.back().Address;
1581}
1582
1583uint64_t ExportEntry::other() const {
1584 return Stack.back().Other;
1585}
1586
1587StringRef ExportEntry::otherName() const {
1588 const char* ImportName = Stack.back().ImportName;
1589 if (ImportName)
1590 return StringRef(ImportName);
1591 return StringRef();
1592}
1593
1594uint32_t ExportEntry::nodeOffset() const {
1595 return Stack.back().Start - Trie.begin();
1596}
1597
1598ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1599 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1600 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1601 ParentStringLength(0), IsExportNode(false) {
1602}
1603
1604void ExportEntry::pushNode(uint64_t offset) {
1605 const uint8_t *Ptr = Trie.begin() + offset;
1606 NodeState State(Ptr);
1607 uint64_t ExportInfoSize = readULEB128(State.Current);
1608 State.IsExportNode = (ExportInfoSize != 0);
1609 const uint8_t* Children = State.Current + ExportInfoSize;
1610 if (State.IsExportNode) {
1611 State.Flags = readULEB128(State.Current);
1612 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1613 State.Address = 0;
1614 State.Other = readULEB128(State.Current); // dylib ordinal
1615 State.ImportName = reinterpret_cast<const char*>(State.Current);
1616 } else {
1617 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001618 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1619 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001620 }
1621 }
1622 State.ChildCount = *Children;
1623 State.Current = Children + 1;
1624 State.NextChildIndex = 0;
1625 State.ParentStringLength = CumulativeString.size();
1626 Stack.push_back(State);
1627}
1628
1629void ExportEntry::pushDownUntilBottom() {
1630 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1631 NodeState &Top = Stack.back();
1632 CumulativeString.resize(Top.ParentStringLength);
1633 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001634 char C = *Top.Current;
1635 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001636 }
1637 Top.Current += 1;
1638 uint64_t childNodeIndex = readULEB128(Top.Current);
1639 Top.NextChildIndex += 1;
1640 pushNode(childNodeIndex);
1641 }
1642 if (!Stack.back().IsExportNode) {
1643 Malformed = true;
1644 moveToEnd();
1645 }
1646}
1647
1648// We have a trie data structure and need a way to walk it that is compatible
1649// with the C++ iterator model. The solution is a non-recursive depth first
1650// traversal where the iterator contains a stack of parent nodes along with a
1651// string that is the accumulation of all edge strings along the parent chain
1652// to this point.
1653//
1654// There is one “export” node for each exported symbol. But because some
1655// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1656// node may have child nodes too.
1657//
1658// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1659// child until hitting a node with no children (which is an export node or
1660// else the trie is malformed). On the way down, each node is pushed on the
1661// stack ivar. If there is no more ways down, it pops up one and tries to go
1662// down a sibling path until a childless node is reached.
1663void ExportEntry::moveNext() {
1664 if (Stack.empty() || !Stack.back().IsExportNode) {
1665 Malformed = true;
1666 moveToEnd();
1667 return;
1668 }
1669
1670 Stack.pop_back();
1671 while (!Stack.empty()) {
1672 NodeState &Top = Stack.back();
1673 if (Top.NextChildIndex < Top.ChildCount) {
1674 pushDownUntilBottom();
1675 // Now at the next export node.
1676 return;
1677 } else {
1678 if (Top.IsExportNode) {
1679 // This node has no children but is itself an export node.
1680 CumulativeString.resize(Top.ParentStringLength);
1681 return;
1682 }
1683 Stack.pop_back();
1684 }
1685 }
1686 Done = true;
1687}
1688
1689iterator_range<export_iterator>
1690MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1691 ExportEntry Start(Trie);
1692 Start.moveToFirst();
1693
1694 ExportEntry Finish(Trie);
1695 Finish.moveToEnd();
1696
1697 return iterator_range<export_iterator>(export_iterator(Start),
1698 export_iterator(Finish));
1699}
1700
1701iterator_range<export_iterator> MachOObjectFile::exports() const {
1702 return exports(getDyldInfoExportsTrie());
1703}
1704
1705
Nick Kledzikac431442014-09-12 21:34:15 +00001706MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1707 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1708 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1709 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1710
1711void MachORebaseEntry::moveToFirst() {
1712 Ptr = Opcodes.begin();
1713 moveNext();
1714}
1715
1716void MachORebaseEntry::moveToEnd() {
1717 Ptr = Opcodes.end();
1718 RemainingLoopCount = 0;
1719 Done = true;
1720}
1721
1722void MachORebaseEntry::moveNext() {
1723 // If in the middle of some loop, move to next rebasing in loop.
1724 SegmentOffset += AdvanceAmount;
1725 if (RemainingLoopCount) {
1726 --RemainingLoopCount;
1727 return;
1728 }
1729 if (Ptr == Opcodes.end()) {
1730 Done = true;
1731 return;
1732 }
1733 bool More = true;
1734 while (More && !Malformed) {
1735 // Parse next opcode and set up next loop.
1736 uint8_t Byte = *Ptr++;
1737 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1738 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1739 switch (Opcode) {
1740 case MachO::REBASE_OPCODE_DONE:
1741 More = false;
1742 Done = true;
1743 moveToEnd();
1744 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1745 break;
1746 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1747 RebaseType = ImmValue;
1748 DEBUG_WITH_TYPE(
1749 "mach-o-rebase",
1750 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1751 << "RebaseType=" << (int) RebaseType << "\n");
1752 break;
1753 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1754 SegmentIndex = ImmValue;
1755 SegmentOffset = readULEB128();
1756 DEBUG_WITH_TYPE(
1757 "mach-o-rebase",
1758 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1759 << "SegmentIndex=" << SegmentIndex << ", "
1760 << format("SegmentOffset=0x%06X", SegmentOffset)
1761 << "\n");
1762 break;
1763 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1764 SegmentOffset += readULEB128();
1765 DEBUG_WITH_TYPE("mach-o-rebase",
1766 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1767 << format("SegmentOffset=0x%06X",
1768 SegmentOffset) << "\n");
1769 break;
1770 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1771 SegmentOffset += ImmValue * PointerSize;
1772 DEBUG_WITH_TYPE("mach-o-rebase",
1773 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1774 << format("SegmentOffset=0x%06X",
1775 SegmentOffset) << "\n");
1776 break;
1777 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1778 AdvanceAmount = PointerSize;
1779 RemainingLoopCount = ImmValue - 1;
1780 DEBUG_WITH_TYPE(
1781 "mach-o-rebase",
1782 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1783 << format("SegmentOffset=0x%06X", SegmentOffset)
1784 << ", AdvanceAmount=" << AdvanceAmount
1785 << ", RemainingLoopCount=" << RemainingLoopCount
1786 << "\n");
1787 return;
1788 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1789 AdvanceAmount = PointerSize;
1790 RemainingLoopCount = readULEB128() - 1;
1791 DEBUG_WITH_TYPE(
1792 "mach-o-rebase",
1793 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1794 << format("SegmentOffset=0x%06X", SegmentOffset)
1795 << ", AdvanceAmount=" << AdvanceAmount
1796 << ", RemainingLoopCount=" << RemainingLoopCount
1797 << "\n");
1798 return;
1799 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1800 AdvanceAmount = readULEB128() + PointerSize;
1801 RemainingLoopCount = 0;
1802 DEBUG_WITH_TYPE(
1803 "mach-o-rebase",
1804 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1805 << format("SegmentOffset=0x%06X", SegmentOffset)
1806 << ", AdvanceAmount=" << AdvanceAmount
1807 << ", RemainingLoopCount=" << RemainingLoopCount
1808 << "\n");
1809 return;
1810 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1811 RemainingLoopCount = readULEB128() - 1;
1812 AdvanceAmount = readULEB128() + PointerSize;
1813 DEBUG_WITH_TYPE(
1814 "mach-o-rebase",
1815 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1816 << format("SegmentOffset=0x%06X", SegmentOffset)
1817 << ", AdvanceAmount=" << AdvanceAmount
1818 << ", RemainingLoopCount=" << RemainingLoopCount
1819 << "\n");
1820 return;
1821 default:
1822 Malformed = true;
1823 }
1824 }
1825}
1826
1827uint64_t MachORebaseEntry::readULEB128() {
1828 unsigned Count;
1829 uint64_t Result = decodeULEB128(Ptr, &Count);
1830 Ptr += Count;
1831 if (Ptr > Opcodes.end()) {
1832 Ptr = Opcodes.end();
1833 Malformed = true;
1834 }
1835 return Result;
1836}
1837
1838uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1839
1840uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1841
1842StringRef MachORebaseEntry::typeName() const {
1843 switch (RebaseType) {
1844 case MachO::REBASE_TYPE_POINTER:
1845 return "pointer";
1846 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1847 return "text abs32";
1848 case MachO::REBASE_TYPE_TEXT_PCREL32:
1849 return "text rel32";
1850 }
1851 return "unknown";
1852}
1853
1854bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1855 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1856 return (Ptr == Other.Ptr) &&
1857 (RemainingLoopCount == Other.RemainingLoopCount) &&
1858 (Done == Other.Done);
1859}
1860
1861iterator_range<rebase_iterator>
1862MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1863 MachORebaseEntry Start(Opcodes, is64);
1864 Start.moveToFirst();
1865
1866 MachORebaseEntry Finish(Opcodes, is64);
1867 Finish.moveToEnd();
1868
1869 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1870 rebase_iterator(Finish));
1871}
1872
1873iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1874 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1875}
1876
Nick Kledzik56ebef42014-09-16 01:41:51 +00001877
1878MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1879 Kind BK)
1880 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1881 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1882 BindType(0), PointerSize(is64Bit ? 8 : 4),
1883 TableKind(BK), Malformed(false), Done(false) {}
1884
1885void MachOBindEntry::moveToFirst() {
1886 Ptr = Opcodes.begin();
1887 moveNext();
1888}
1889
1890void MachOBindEntry::moveToEnd() {
1891 Ptr = Opcodes.end();
1892 RemainingLoopCount = 0;
1893 Done = true;
1894}
1895
1896void MachOBindEntry::moveNext() {
1897 // If in the middle of some loop, move to next binding in loop.
1898 SegmentOffset += AdvanceAmount;
1899 if (RemainingLoopCount) {
1900 --RemainingLoopCount;
1901 return;
1902 }
1903 if (Ptr == Opcodes.end()) {
1904 Done = true;
1905 return;
1906 }
1907 bool More = true;
1908 while (More && !Malformed) {
1909 // Parse next opcode and set up next loop.
1910 uint8_t Byte = *Ptr++;
1911 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1912 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1913 int8_t SignExtended;
1914 const uint8_t *SymStart;
1915 switch (Opcode) {
1916 case MachO::BIND_OPCODE_DONE:
1917 if (TableKind == Kind::Lazy) {
1918 // Lazying bindings have a DONE opcode between entries. Need to ignore
1919 // it to advance to next entry. But need not if this is last entry.
1920 bool NotLastEntry = false;
1921 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1922 if (*P) {
1923 NotLastEntry = true;
1924 }
1925 }
1926 if (NotLastEntry)
1927 break;
1928 }
1929 More = false;
1930 Done = true;
1931 moveToEnd();
1932 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1933 break;
1934 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1935 Ordinal = ImmValue;
1936 DEBUG_WITH_TYPE(
1937 "mach-o-bind",
1938 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1939 << "Ordinal=" << Ordinal << "\n");
1940 break;
1941 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1942 Ordinal = readULEB128();
1943 DEBUG_WITH_TYPE(
1944 "mach-o-bind",
1945 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1946 << "Ordinal=" << Ordinal << "\n");
1947 break;
1948 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1949 if (ImmValue) {
1950 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1951 Ordinal = SignExtended;
1952 } else
1953 Ordinal = 0;
1954 DEBUG_WITH_TYPE(
1955 "mach-o-bind",
1956 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1957 << "Ordinal=" << Ordinal << "\n");
1958 break;
1959 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1960 Flags = ImmValue;
1961 SymStart = Ptr;
1962 while (*Ptr) {
1963 ++Ptr;
1964 }
1965 ++Ptr;
1966 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1967 Ptr-SymStart);
1968 DEBUG_WITH_TYPE(
1969 "mach-o-bind",
1970 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1971 << "SymbolName=" << SymbolName << "\n");
1972 if (TableKind == Kind::Weak) {
1973 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1974 return;
1975 }
1976 break;
1977 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1978 BindType = ImmValue;
1979 DEBUG_WITH_TYPE(
1980 "mach-o-bind",
1981 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1982 << "BindType=" << (int)BindType << "\n");
1983 break;
1984 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1985 Addend = readSLEB128();
1986 if (TableKind == Kind::Lazy)
1987 Malformed = true;
1988 DEBUG_WITH_TYPE(
1989 "mach-o-bind",
1990 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1991 << "Addend=" << Addend << "\n");
1992 break;
1993 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1994 SegmentIndex = ImmValue;
1995 SegmentOffset = readULEB128();
1996 DEBUG_WITH_TYPE(
1997 "mach-o-bind",
1998 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1999 << "SegmentIndex=" << SegmentIndex << ", "
2000 << format("SegmentOffset=0x%06X", SegmentOffset)
2001 << "\n");
2002 break;
2003 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2004 SegmentOffset += readULEB128();
2005 DEBUG_WITH_TYPE("mach-o-bind",
2006 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2007 << format("SegmentOffset=0x%06X",
2008 SegmentOffset) << "\n");
2009 break;
2010 case MachO::BIND_OPCODE_DO_BIND:
2011 AdvanceAmount = PointerSize;
2012 RemainingLoopCount = 0;
2013 DEBUG_WITH_TYPE("mach-o-bind",
2014 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2015 << format("SegmentOffset=0x%06X",
2016 SegmentOffset) << "\n");
2017 return;
2018 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2019 AdvanceAmount = readULEB128();
2020 RemainingLoopCount = 0;
2021 if (TableKind == Kind::Lazy)
2022 Malformed = true;
2023 DEBUG_WITH_TYPE(
2024 "mach-o-bind",
2025 llvm::dbgs() << "BIND_OPCODE_DO_BIND_IMM_TIMES: "
2026 << format("SegmentOffset=0x%06X", SegmentOffset)
2027 << ", AdvanceAmount=" << AdvanceAmount
2028 << ", RemainingLoopCount=" << RemainingLoopCount
2029 << "\n");
2030 return;
2031 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2032 AdvanceAmount = ImmValue * PointerSize;
2033 RemainingLoopCount = 0;
2034 if (TableKind == Kind::Lazy)
2035 Malformed = true;
2036 DEBUG_WITH_TYPE("mach-o-bind",
2037 llvm::dbgs()
2038 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2039 << format("SegmentOffset=0x%06X",
2040 SegmentOffset) << "\n");
2041 return;
2042 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2043 RemainingLoopCount = readULEB128() - 1;
2044 AdvanceAmount = readULEB128() + PointerSize;
2045 if (TableKind == Kind::Lazy)
2046 Malformed = true;
2047 DEBUG_WITH_TYPE(
2048 "mach-o-bind",
2049 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2050 << format("SegmentOffset=0x%06X", SegmentOffset)
2051 << ", AdvanceAmount=" << AdvanceAmount
2052 << ", RemainingLoopCount=" << RemainingLoopCount
2053 << "\n");
2054 return;
2055 default:
2056 Malformed = true;
2057 }
2058 }
2059}
2060
2061uint64_t MachOBindEntry::readULEB128() {
2062 unsigned Count;
2063 uint64_t Result = decodeULEB128(Ptr, &Count);
2064 Ptr += Count;
2065 if (Ptr > Opcodes.end()) {
2066 Ptr = Opcodes.end();
2067 Malformed = true;
2068 }
2069 return Result;
2070}
2071
2072int64_t MachOBindEntry::readSLEB128() {
2073 unsigned Count;
2074 int64_t Result = decodeSLEB128(Ptr, &Count);
2075 Ptr += Count;
2076 if (Ptr > Opcodes.end()) {
2077 Ptr = Opcodes.end();
2078 Malformed = true;
2079 }
2080 return Result;
2081}
2082
2083
2084uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2085
2086uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2087
2088StringRef MachOBindEntry::typeName() const {
2089 switch (BindType) {
2090 case MachO::BIND_TYPE_POINTER:
2091 return "pointer";
2092 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2093 return "text abs32";
2094 case MachO::BIND_TYPE_TEXT_PCREL32:
2095 return "text rel32";
2096 }
2097 return "unknown";
2098}
2099
2100StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2101
2102int64_t MachOBindEntry::addend() const { return Addend; }
2103
2104uint32_t MachOBindEntry::flags() const { return Flags; }
2105
2106int MachOBindEntry::ordinal() const { return Ordinal; }
2107
2108bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2109 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2110 return (Ptr == Other.Ptr) &&
2111 (RemainingLoopCount == Other.RemainingLoopCount) &&
2112 (Done == Other.Done);
2113}
2114
2115iterator_range<bind_iterator>
2116MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2117 MachOBindEntry::Kind BKind) {
2118 MachOBindEntry Start(Opcodes, is64, BKind);
2119 Start.moveToFirst();
2120
2121 MachOBindEntry Finish(Opcodes, is64, BKind);
2122 Finish.moveToEnd();
2123
2124 return iterator_range<bind_iterator>(bind_iterator(Start),
2125 bind_iterator(Finish));
2126}
2127
2128iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2129 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2130 MachOBindEntry::Kind::Regular);
2131}
2132
2133iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2134 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2135 MachOBindEntry::Kind::Lazy);
2136}
2137
2138iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2139 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2140 MachOBindEntry::Kind::Weak);
2141}
2142
Rafael Espindola56f976f2013-04-18 18:08:55 +00002143StringRef
2144MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2145 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2146 return parseSegmentOrSectionName(Raw.data());
2147}
2148
2149ArrayRef<char>
2150MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002151 const section_base *Base =
2152 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002153 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002154}
2155
2156ArrayRef<char>
2157MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002158 const section_base *Base =
2159 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00002160 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002161}
2162
2163bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002164MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002165 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002166 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002167 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002168 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002169}
2170
Eric Christopher1d62c252013-07-22 22:25:07 +00002171unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002172 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002173 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002174 return RE.r_word1 & 0xffffff;
2175 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002176}
2177
Eric Christopher1d62c252013-07-22 22:25:07 +00002178bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002179 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002180 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002181 return (RE.r_word1 >> 27) & 1;
2182 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002183}
2184
Eric Christopher1d62c252013-07-22 22:25:07 +00002185bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002186 const MachO::any_relocation_info &RE) const {
2187 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002188}
2189
Eric Christopher1d62c252013-07-22 22:25:07 +00002190uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002191 const MachO::any_relocation_info &RE) const {
2192 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002193}
2194
Eric Christopher1d62c252013-07-22 22:25:07 +00002195unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002196 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002197 if (isRelocationScattered(RE))
2198 return getScatteredRelocationAddress(RE);
2199 return getPlainRelocationAddress(RE);
2200}
2201
Charles Davis8bdfafd2013-09-01 04:28:48 +00002202unsigned MachOObjectFile::getAnyRelocationPCRel(
2203 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002204 if (isRelocationScattered(RE))
2205 return getScatteredRelocationPCRel(this, RE);
2206 return getPlainRelocationPCRel(this, RE);
2207}
2208
Eric Christopher1d62c252013-07-22 22:25:07 +00002209unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002210 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002211 if (isRelocationScattered(RE))
2212 return getScatteredRelocationLength(RE);
2213 return getPlainRelocationLength(this, RE);
2214}
2215
2216unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002217MachOObjectFile::getAnyRelocationType(
2218 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002219 if (isRelocationScattered(RE))
2220 return getScatteredRelocationType(RE);
2221 return getPlainRelocationType(this, RE);
2222}
2223
Rafael Espindola52501032013-04-30 15:40:54 +00002224SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00002225MachOObjectFile::getRelocationSection(
2226 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002227 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002228 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002229 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2230 DataRefImpl DRI;
2231 DRI.d.a = SecNum;
2232 return SectionRef(DRI, this);
2233}
2234
Rafael Espindola56f976f2013-04-18 18:08:55 +00002235MachOObjectFile::LoadCommandInfo
2236MachOObjectFile::getFirstLoadCommandInfo() const {
2237 MachOObjectFile::LoadCommandInfo Load;
2238
Charles Davis8bdfafd2013-09-01 04:28:48 +00002239 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2240 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002241 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002242 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002243 return Load;
2244}
2245
2246MachOObjectFile::LoadCommandInfo
2247MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2248 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002249 Next.Ptr = L.Ptr + L.C.cmdsize;
2250 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002251 return Next;
2252}
2253
Charles Davis8bdfafd2013-09-01 04:28:48 +00002254MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2255 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002256}
2257
Charles Davis8bdfafd2013-09-01 04:28:48 +00002258MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2259 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002260}
2261
Charles Davis8bdfafd2013-09-01 04:28:48 +00002262MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002263 unsigned Index) const {
2264 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002265 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002266}
2267
Charles Davis8bdfafd2013-09-01 04:28:48 +00002268MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2269 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002270 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002271 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002272}
2273
Charles Davis8bdfafd2013-09-01 04:28:48 +00002274MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002275MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002276 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002277 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002278}
2279
Charles Davis8bdfafd2013-09-01 04:28:48 +00002280MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002281MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002282 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002283 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002284}
2285
Charles Davis8bdfafd2013-09-01 04:28:48 +00002286MachO::linkedit_data_command
2287MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2288 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002289}
2290
Charles Davis8bdfafd2013-09-01 04:28:48 +00002291MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002292MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002293 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002294}
2295
Charles Davis8bdfafd2013-09-01 04:28:48 +00002296MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002297MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002298 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002299}
2300
Charles Davis8bdfafd2013-09-01 04:28:48 +00002301MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002302MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002303 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002304}
2305
Jim Grosbach448334a2014-03-18 22:09:05 +00002306MachO::version_min_command
2307MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2308 return getStruct<MachO::version_min_command>(this, L.Ptr);
2309}
2310
Tim Northover8f9590b2014-06-30 14:40:57 +00002311MachO::dylib_command
2312MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2313 return getStruct<MachO::dylib_command>(this, L.Ptr);
2314}
2315
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002316MachO::dyld_info_command
2317MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2318 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2319}
2320
2321MachO::dylinker_command
2322MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2323 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2324}
2325
2326MachO::uuid_command
2327MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2328 return getStruct<MachO::uuid_command>(this, L.Ptr);
2329}
2330
2331MachO::source_version_command
2332MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2333 return getStruct<MachO::source_version_command>(this, L.Ptr);
2334}
2335
2336MachO::entry_point_command
2337MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2338 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2339}
2340
Tim Northover8f9590b2014-06-30 14:40:57 +00002341
Charles Davis8bdfafd2013-09-01 04:28:48 +00002342MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002343MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002344 DataRefImpl Sec;
2345 Sec.d.a = Rel.d.a;
2346 uint32_t Offset;
2347 if (is64Bit()) {
2348 MachO::section_64 Sect = getSection64(Sec);
2349 Offset = Sect.reloff;
2350 } else {
2351 MachO::section Sect = getSection(Sec);
2352 Offset = Sect.reloff;
2353 }
2354
2355 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2356 getPtr(this, Offset)) + Rel.d.b;
2357 return getStruct<MachO::any_relocation_info>(
2358 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002359}
2360
Charles Davis8bdfafd2013-09-01 04:28:48 +00002361MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002362MachOObjectFile::getDice(DataRefImpl Rel) const {
2363 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002364 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002365}
2366
Charles Davis8bdfafd2013-09-01 04:28:48 +00002367MachO::mach_header MachOObjectFile::getHeader() const {
2368 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002369}
2370
Charles Davis8bdfafd2013-09-01 04:28:48 +00002371MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2372 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002373}
2374
Charles Davis8bdfafd2013-09-01 04:28:48 +00002375uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2376 const MachO::dysymtab_command &DLC,
2377 unsigned Index) const {
2378 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2379 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002380}
2381
Charles Davis8bdfafd2013-09-01 04:28:48 +00002382MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002383MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2384 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002385 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2386 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002387}
2388
Charles Davis8bdfafd2013-09-01 04:28:48 +00002389MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2390 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002391}
2392
Charles Davis8bdfafd2013-09-01 04:28:48 +00002393MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2394 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002395}
2396
Charles Davis8bdfafd2013-09-01 04:28:48 +00002397MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002398MachOObjectFile::getDataInCodeLoadCommand() const {
2399 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002400 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002401
2402 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002403 MachO::linkedit_data_command Cmd;
2404 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2405 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2406 Cmd.dataoff = 0;
2407 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002408 return Cmd;
2409}
2410
Nick Kledzikd04bc352014-08-30 00:20:14 +00002411ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2412 if (!DyldInfoLoadCmd)
2413 return ArrayRef<uint8_t>();
2414
2415 MachO::dyld_info_command DyldInfo
2416 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2417 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2418 getPtr(this, DyldInfo.rebase_off));
2419 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2420}
2421
2422ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2423 if (!DyldInfoLoadCmd)
2424 return ArrayRef<uint8_t>();
2425
2426 MachO::dyld_info_command DyldInfo
2427 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2428 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2429 getPtr(this, DyldInfo.bind_off));
2430 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2431}
2432
2433ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2434 if (!DyldInfoLoadCmd)
2435 return ArrayRef<uint8_t>();
2436
2437 MachO::dyld_info_command DyldInfo
2438 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2439 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2440 getPtr(this, DyldInfo.weak_bind_off));
2441 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2442}
2443
2444ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2445 if (!DyldInfoLoadCmd)
2446 return ArrayRef<uint8_t>();
2447
2448 MachO::dyld_info_command DyldInfo
2449 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2450 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2451 getPtr(this, DyldInfo.lazy_bind_off));
2452 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2453}
2454
2455ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2456 if (!DyldInfoLoadCmd)
2457 return ArrayRef<uint8_t>();
2458
2459 MachO::dyld_info_command DyldInfo
2460 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2461 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2462 getPtr(this, DyldInfo.export_off));
2463 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2464}
2465
2466
Rafael Espindola6e040c02013-04-26 20:07:33 +00002467StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002468 MachO::symtab_command S = getSymtabLoadCommand();
2469 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002470}
2471
Rafael Espindola56f976f2013-04-18 18:08:55 +00002472bool MachOObjectFile::is64Bit() const {
2473 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002474 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002475}
2476
2477void MachOObjectFile::ReadULEB128s(uint64_t Index,
2478 SmallVectorImpl<uint64_t> &Out) const {
2479 DataExtractor extractor(ObjectFile::getData(), true, 0);
2480
2481 uint32_t offset = Index;
2482 uint64_t data = 0;
2483 while (uint64_t delta = extractor.getULEB128(&offset)) {
2484 data += delta;
2485 Out.push_back(data);
2486 }
2487}
2488
Rafael Espindolac66d7612014-08-17 19:09:37 +00002489bool MachOObjectFile::isRelocatableObject() const {
2490 return getHeader().filetype == MachO::MH_OBJECT;
2491}
2492
Rafael Espindola437b0d52014-07-31 03:12:45 +00002493ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002494ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2495 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002496 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002497 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002498 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002499 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002500 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002501 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002502 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002503 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002504 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002505 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002506 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002507 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002508
Rafael Espindola692410e2014-01-21 23:06:54 +00002509 if (EC)
2510 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002511 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002512}
2513