blob: 7e7e8c493154e4f46139ca515942da8bb7b24bb5 [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
Rafael Espindola6e040c02013-04-26 20:07:33 +000061static const char *
62getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
63 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000064 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
65
66 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000067 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
68 sizeof(MachO::segment_command);
69 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
70 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000071
72 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000073 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000074}
75
Rafael Espindola56f976f2013-04-18 18:08:55 +000076static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
77 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000078}
79
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000080static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000081getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000082 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000083 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000084}
85
Rafael Espindola56f976f2013-04-18 18:08:55 +000086static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000087 if (P[15] == 0)
88 // Null terminated.
89 return P;
90 // Not null terminated, so this is a 16 char string.
91 return StringRef(P, 16);
92}
93
Rafael Espindola56f976f2013-04-18 18:08:55 +000094// Helper to advance a section or symbol iterator multiple increments at a time.
95template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +000096static void advance(T &it, size_t Val) {
97 while (Val--)
98 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +000099}
100
101static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000102 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000103}
104
105static void printRelocationTargetName(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000106 const MachO::any_relocation_info &RE,
Alp Tokere69170a2014-06-26 22:52:05 +0000107 raw_string_ostream &fmt) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000108 bool IsScattered = O->isRelocationScattered(RE);
109
110 // Target of a scattered relocation is an address. In the interest of
111 // generating pretty output, scan through the symbol table looking for a
112 // symbol that aligns with that address. If we find one, print it.
113 // Otherwise, we just print the hex address of the target.
114 if (IsScattered) {
115 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
116
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000117 for (const SymbolRef &Symbol : O->symbols()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000118 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000119 uint64_t Addr;
120 StringRef Name;
121
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000122 if ((ec = Symbol.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000123 report_fatal_error(ec.message());
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000124 if (Addr != Val)
125 continue;
126 if ((ec = Symbol.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000127 report_fatal_error(ec.message());
128 fmt << Name;
129 return;
130 }
131
132 // If we couldn't find a symbol that this relocation refers to, try
133 // to find a section beginning instead.
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000134 for (const SectionRef &Section : O->sections()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000135 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000136 uint64_t Addr;
137 StringRef Name;
138
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000139 if ((ec = Section.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140 report_fatal_error(ec.message());
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000141 if (Addr != Val)
142 continue;
143 if ((ec = Section.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000144 report_fatal_error(ec.message());
145 fmt << Name;
146 return;
147 }
148
149 fmt << format("0x%x", Val);
150 return;
151 }
152
153 StringRef S;
154 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000155 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000156
157 if (isExtern) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000158 symbol_iterator SI = O->symbol_begin();
Rafael Espindola5e812af2014-01-30 02:49:50 +0000159 advance(SI, Val);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000160 SI->getName(S);
161 } else {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000162 section_iterator SI = O->section_begin();
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000163 // Adjust for the fact that sections are 1-indexed.
Rafael Espindola5e812af2014-01-30 02:49:50 +0000164 advance(SI, Val - 1);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000165 SI->getName(S);
166 }
167
168 fmt << S;
169}
170
Charles Davis8bdfafd2013-09-01 04:28:48 +0000171static uint32_t
172getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
173 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000174}
175
176static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000177getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
178 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000179}
180
181static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000182 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000183 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000184 return (RE.r_word1 >> 24) & 1;
185 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000186}
187
188static bool
189getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000190 const MachO::any_relocation_info &RE) {
191 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000192}
193
194static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000195 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000196 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000197 return (RE.r_word1 >> 25) & 3;
198 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000199}
200
201static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000202getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
203 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000204}
205
206static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000207 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000208 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000209 return RE.r_word1 >> 28;
210 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000211}
212
Charles Davis8bdfafd2013-09-01 04:28:48 +0000213static unsigned
214getScatteredRelocationType(const MachO::any_relocation_info &RE) {
215 return (RE.r_word0 >> 24) & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000216}
217
218static uint32_t getSectionFlags(const MachOObjectFile *O,
219 DataRefImpl Sec) {
220 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000221 MachO::section_64 Sect = O->getSection64(Sec);
222 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000223 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000224 MachO::section Sect = O->getSection(Sec);
225 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000226}
227
Rafael Espindola48af1c22014-08-19 18:44:46 +0000228MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
229 bool Is64bits, std::error_code &EC)
230 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000231 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Nick Kledzikd04bc352014-08-30 00:20:14 +0000232 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000233 uint32_t LoadCommandCount = this->getHeader().ncmds;
234 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
235 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000236
237 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000238 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000239 if (Load.C.cmd == MachO::LC_SYMTAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000240 assert(!SymtabLoadCmd && "Multiple symbol tables");
241 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000242 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000243 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
244 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000245 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby273ae012013-06-06 17:20:50 +0000246 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
247 DataInCodeLoadCmd = Load.Ptr;
Nick Kledzikd04bc352014-08-30 00:20:14 +0000248 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
249 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
250 assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");
251 DyldInfoLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000252 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000253 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
254 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000255 const char *Sec = getSectionPtr(this, Load, J);
256 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000257 }
Kevin Enderby980b2582014-06-05 21:21:57 +0000258 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
259 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
260 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
261 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
262 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
263 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000264 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000265
266 if (I == LoadCommandCount - 1)
267 break;
268 else
269 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000270 }
271}
272
Rafael Espindola5e812af2014-01-30 02:49:50 +0000273void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000274 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000275 sizeof(MachO::nlist_64) :
276 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000277 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000278}
279
Rafael Espindola3acea392014-06-12 21:46:39 +0000280std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
281 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000282 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000283 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000284 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000285 Res = StringRef(Start);
286 return object_error::success;
287}
288
Kevin Enderby980b2582014-06-05 21:21:57 +0000289// getIndirectName() returns the name of the alias'ed symbol who's string table
290// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000291std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
292 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000293 StringRef StringTable = getStringTableData();
294 uint64_t NValue;
295 if (is64Bit()) {
296 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
297 NValue = Entry.n_value;
298 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
299 return object_error::parse_failed;
300 } else {
301 MachO::nlist Entry = getSymbolTableEntry(Symb);
302 NValue = Entry.n_value;
303 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
304 return object_error::parse_failed;
305 }
306 if (NValue >= StringTable.size())
307 return object_error::parse_failed;
308 const char *Start = &StringTable.data()[NValue];
309 Res = StringRef(Start);
310 return object_error::success;
311}
312
Rafael Espindola3acea392014-06-12 21:46:39 +0000313std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
314 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000315 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000316 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000317 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
318 Entry.n_value == 0)
319 Res = UnknownAddressOrSize;
320 else
321 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000322 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000323 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000324 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
325 Entry.n_value == 0)
326 Res = UnknownAddressOrSize;
327 else
328 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000329 }
330 return object_error::success;
331}
332
Rafael Espindola3acea392014-06-12 21:46:39 +0000333std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
334 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000335 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000336 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000337 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000338 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000339 } else {
340 Result = 0;
341 }
342 return object_error::success;
343}
344
Rafael Espindola3acea392014-06-12 21:46:39 +0000345std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
346 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000347 uint64_t BeginOffset;
348 uint64_t EndOffset = 0;
349 uint8_t SectionIndex;
350
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000351 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000352 uint64_t Value;
353 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000354 if (Value == UnknownAddressOrSize) {
355 Result = UnknownAddressOrSize;
356 return object_error::success;
357 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000358
359 BeginOffset = Value;
360
Charles Davis8bdfafd2013-09-01 04:28:48 +0000361 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000362 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000363 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000364 if (flags & SymbolRef::SF_Common)
365 Result = Value;
366 else
367 Result = UnknownAddressOrSize;
368 return object_error::success;
369 }
370 // Unfortunately symbols are unsorted so we need to touch all
371 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000372 for (const SymbolRef &Symbol : symbols()) {
373 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000374 Entry = getSymbolTableEntryBase(this, DRI);
375 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000376 if (Value == UnknownAddressOrSize)
377 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000378 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000379 if (!EndOffset || Value < EndOffset)
380 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000381 }
382 if (!EndOffset) {
383 uint64_t Size;
384 DataRefImpl Sec;
385 Sec.d.a = SectionIndex-1;
386 getSectionSize(Sec, Size);
387 getSectionAddress(Sec, EndOffset);
388 EndOffset += Size;
389 }
390 Result = EndOffset - BeginOffset;
391 return object_error::success;
392}
393
Rafael Espindola3acea392014-06-12 21:46:39 +0000394std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
395 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000396 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000397 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000398
399 Res = SymbolRef::ST_Other;
400
401 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000402 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000403 Res = SymbolRef::ST_Debug;
404 return object_error::success;
405 }
406
Charles Davis74ec8b02013-08-27 05:00:13 +0000407 switch (n_type & MachO::N_TYPE) {
408 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000409 Res = SymbolRef::ST_Unknown;
410 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000411 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000412 Res = SymbolRef::ST_Function;
413 break;
414 }
415 return object_error::success;
416}
417
Rafael Espindola20122a42014-01-31 20:57:12 +0000418uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000419 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000420
Charles Davis8bdfafd2013-09-01 04:28:48 +0000421 uint8_t MachOType = Entry.n_type;
422 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000423
Rafael Espindola20122a42014-01-31 20:57:12 +0000424 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000425
Charles Davis74ec8b02013-08-27 05:00:13 +0000426 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000427 Result |= SymbolRef::SF_Undefined;
428
Tim Northovereaef0742014-05-30 13:22:59 +0000429 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
430 Result |= SymbolRef::SF_Indirect;
431
Rafael Espindolaa1356322013-11-02 05:03:24 +0000432 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000433 Result |= SymbolRef::SF_FormatSpecific;
434
Charles Davis74ec8b02013-08-27 05:00:13 +0000435 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000436 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000437 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000438 uint64_t Value;
439 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000440 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000441 Result |= SymbolRef::SF_Common;
442 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000443 }
444
Charles Davis74ec8b02013-08-27 05:00:13 +0000445 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000446 Result |= SymbolRef::SF_Weak;
447
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000448 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
449 Result |= SymbolRef::SF_Thumb;
450
Charles Davis74ec8b02013-08-27 05:00:13 +0000451 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000452 Result |= SymbolRef::SF_Absolute;
453
Rafael Espindola20122a42014-01-31 20:57:12 +0000454 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000455}
456
Rafael Espindola3acea392014-06-12 21:46:39 +0000457std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
458 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000459 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000460 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000461
462 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000463 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000464 } else {
465 DataRefImpl DRI;
466 DRI.d.a = index - 1;
467 Res = section_iterator(SectionRef(DRI, this));
468 }
469
470 return object_error::success;
471}
472
Rafael Espindola5e812af2014-01-30 02:49:50 +0000473void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000474 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000475}
476
Rafael Espindola3acea392014-06-12 21:46:39 +0000477std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
478 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000479 ArrayRef<char> Raw = getSectionRawName(Sec);
480 Result = parseSegmentOrSectionName(Raw.data());
481 return object_error::success;
482}
483
Rafael Espindola3acea392014-06-12 21:46:39 +0000484std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
485 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000486 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000487 MachO::section_64 Sect = getSection64(Sec);
488 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000489 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000490 MachO::section Sect = getSection(Sec);
491 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000492 }
493 return object_error::success;
494}
495
Rafael Espindola3acea392014-06-12 21:46:39 +0000496std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
497 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000498 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000499 MachO::section_64 Sect = getSection64(Sec);
500 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000501 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000502 MachO::section Sect = getSection(Sec);
503 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000504 }
505
506 return object_error::success;
507}
508
Rafael Espindola3acea392014-06-12 21:46:39 +0000509std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
510 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000511 uint32_t Offset;
512 uint64_t Size;
513
514 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000515 MachO::section_64 Sect = getSection64(Sec);
516 Offset = Sect.offset;
517 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000518 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000519 MachO::section Sect = getSection(Sec);
520 Offset = Sect.offset;
521 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000522 }
523
524 Res = this->getData().substr(Offset, Size);
525 return object_error::success;
526}
527
Rafael Espindola3acea392014-06-12 21:46:39 +0000528std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
529 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000530 uint32_t Align;
531 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000532 MachO::section_64 Sect = getSection64(Sec);
533 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000534 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000535 MachO::section Sect = getSection(Sec);
536 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537 }
538
539 Res = uint64_t(1) << Align;
540 return object_error::success;
541}
542
Rafael Espindola3acea392014-06-12 21:46:39 +0000543std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
544 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000545 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000546 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000547 return object_error::success;
548}
549
Rafael Espindola3acea392014-06-12 21:46:39 +0000550std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
551 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000552 uint32_t Flags = getSectionFlags(this, Sec);
553 unsigned SectionType = Flags & MachO::SECTION_TYPE;
554 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
555 !(SectionType == MachO::S_ZEROFILL ||
556 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000557 return object_error::success;
558}
559
Rafael Espindola3acea392014-06-12 21:46:39 +0000560std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
561 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000562 uint32_t Flags = getSectionFlags(this, Sec);
563 unsigned SectionType = Flags & MachO::SECTION_TYPE;
564 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
565 (SectionType == MachO::S_ZEROFILL ||
566 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000567 return object_error::success;
568}
569
Rafael Espindola3acea392014-06-12 21:46:39 +0000570std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000571MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindola137faa02013-04-24 15:14:22 +0000572 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000573 // FIXME: Unimplemented.
574 Result = true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000575 return object_error::success;
576}
577
Rafael Espindola3acea392014-06-12 21:46:39 +0000578std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
579 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000580 // FIXME: Unimplemented.
581 Result = false;
582 return object_error::success;
583}
584
Rafael Espindola3acea392014-06-12 21:46:39 +0000585std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
586 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000587 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis74ec8b02013-08-27 05:00:13 +0000588 unsigned SectionType = Flags & MachO::SECTION_TYPE;
589 Res = SectionType == MachO::S_ZEROFILL ||
590 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000591 return object_error::success;
592}
593
Rafael Espindola3acea392014-06-12 21:46:39 +0000594std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
595 bool &Result) const {
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000596 // Consider using the code from isSectionText to look for __const sections.
597 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
598 // to use section attributes to distinguish code from data.
599
600 // FIXME: Unimplemented.
601 Result = false;
602 return object_error::success;
603}
604
Rafael Espindola3acea392014-06-12 21:46:39 +0000605std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
606 DataRefImpl Symb,
607 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000608 SymbolRef::Type ST;
609 this->getSymbolType(Symb, ST);
610 if (ST == SymbolRef::ST_Unknown) {
611 Result = false;
612 return object_error::success;
613 }
614
615 uint64_t SectBegin, SectEnd;
616 getSectionAddress(Sec, SectBegin);
617 getSectionSize(Sec, SectEnd);
618 SectEnd += SectBegin;
619
620 uint64_t SymAddr;
621 getSymbolAddress(Symb, SymAddr);
622 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
623
624 return object_error::success;
625}
626
Rui Ueyamabc654b12013-09-27 21:47:05 +0000627relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000628 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000629 Ret.d.a = Sec.d.a;
630 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000631 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000632}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000633
Rafael Espindola56f976f2013-04-18 18:08:55 +0000634relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000635MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000636 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000637 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000638 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000639 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000640 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000641 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000642 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000643 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000644
Rafael Espindola56f976f2013-04-18 18:08:55 +0000645 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000646 Ret.d.a = Sec.d.a;
647 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000648 return relocation_iterator(RelocationRef(Ret, this));
649}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000650
Rafael Espindola5e812af2014-01-30 02:49:50 +0000651void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000652 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000653}
Owen Anderson171f4852011-10-24 23:20:07 +0000654
Rafael Espindola3acea392014-06-12 21:46:39 +0000655std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
656 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000657 uint64_t Offset;
658 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000659
660 DataRefImpl Sec;
661 Sec.d.a = Rel.d.a;
662 uint64_t SecAddress;
663 getSectionAddress(Sec, SecAddress);
664 Res = SecAddress + Offset;
665 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000666}
667
Rafael Espindola3acea392014-06-12 21:46:39 +0000668std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
669 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000670 assert(getHeader().filetype == MachO::MH_OBJECT &&
671 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000672 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000673 Res = getAnyRelocationAddress(RE);
674 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000675}
676
Rafael Espindola806f0062013-06-05 01:33:53 +0000677symbol_iterator
678MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000679 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000680 if (isRelocationScattered(RE))
681 return symbol_end();
682
Rafael Espindola56f976f2013-04-18 18:08:55 +0000683 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
684 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000685 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000686 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000687
Charles Davis8bdfafd2013-09-01 04:28:48 +0000688 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000689 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000690 sizeof(MachO::nlist_64) :
691 sizeof(MachO::nlist);
692 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000693 DataRefImpl Sym;
694 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000695 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000696}
697
Rafael Espindola3acea392014-06-12 21:46:39 +0000698std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
699 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000700 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000701 Res = getAnyRelocationType(RE);
702 return object_error::success;
703}
704
Rafael Espindola3acea392014-06-12 21:46:39 +0000705std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000706MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
707 SmallVectorImpl<char> &Result) const {
708 StringRef res;
709 uint64_t RType;
710 getRelocationType(Rel, RType);
711
712 unsigned Arch = this->getArch();
713
714 switch (Arch) {
715 case Triple::x86: {
716 static const char *const Table[] = {
717 "GENERIC_RELOC_VANILLA",
718 "GENERIC_RELOC_PAIR",
719 "GENERIC_RELOC_SECTDIFF",
720 "GENERIC_RELOC_PB_LA_PTR",
721 "GENERIC_RELOC_LOCAL_SECTDIFF",
722 "GENERIC_RELOC_TLV" };
723
Eric Christopher13250cb2013-12-06 02:33:38 +0000724 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000725 res = "Unknown";
726 else
727 res = Table[RType];
728 break;
729 }
730 case Triple::x86_64: {
731 static const char *const Table[] = {
732 "X86_64_RELOC_UNSIGNED",
733 "X86_64_RELOC_SIGNED",
734 "X86_64_RELOC_BRANCH",
735 "X86_64_RELOC_GOT_LOAD",
736 "X86_64_RELOC_GOT",
737 "X86_64_RELOC_SUBTRACTOR",
738 "X86_64_RELOC_SIGNED_1",
739 "X86_64_RELOC_SIGNED_2",
740 "X86_64_RELOC_SIGNED_4",
741 "X86_64_RELOC_TLV" };
742
743 if (RType > 9)
744 res = "Unknown";
745 else
746 res = Table[RType];
747 break;
748 }
749 case Triple::arm: {
750 static const char *const Table[] = {
751 "ARM_RELOC_VANILLA",
752 "ARM_RELOC_PAIR",
753 "ARM_RELOC_SECTDIFF",
754 "ARM_RELOC_LOCAL_SECTDIFF",
755 "ARM_RELOC_PB_LA_PTR",
756 "ARM_RELOC_BR24",
757 "ARM_THUMB_RELOC_BR22",
758 "ARM_THUMB_32BIT_BRANCH",
759 "ARM_RELOC_HALF",
760 "ARM_RELOC_HALF_SECTDIFF" };
761
762 if (RType > 9)
763 res = "Unknown";
764 else
765 res = Table[RType];
766 break;
767 }
Tim Northover00ed9962014-03-29 10:18:08 +0000768 case Triple::aarch64: {
769 static const char *const Table[] = {
770 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
771 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
772 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
773 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
774 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
775 "ARM64_RELOC_ADDEND"
776 };
777
778 if (RType >= array_lengthof(Table))
779 res = "Unknown";
780 else
781 res = Table[RType];
782 break;
783 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000784 case Triple::ppc: {
785 static const char *const Table[] = {
786 "PPC_RELOC_VANILLA",
787 "PPC_RELOC_PAIR",
788 "PPC_RELOC_BR14",
789 "PPC_RELOC_BR24",
790 "PPC_RELOC_HI16",
791 "PPC_RELOC_LO16",
792 "PPC_RELOC_HA16",
793 "PPC_RELOC_LO14",
794 "PPC_RELOC_SECTDIFF",
795 "PPC_RELOC_PB_LA_PTR",
796 "PPC_RELOC_HI16_SECTDIFF",
797 "PPC_RELOC_LO16_SECTDIFF",
798 "PPC_RELOC_HA16_SECTDIFF",
799 "PPC_RELOC_JBSR",
800 "PPC_RELOC_LO14_SECTDIFF",
801 "PPC_RELOC_LOCAL_SECTDIFF" };
802
Eric Christopher13250cb2013-12-06 02:33:38 +0000803 if (RType > 15)
804 res = "Unknown";
805 else
806 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000807 break;
808 }
809 case Triple::UnknownArch:
810 res = "Unknown";
811 break;
812 }
813 Result.append(res.begin(), res.end());
814 return object_error::success;
815}
816
Rafael Espindola3acea392014-06-12 21:46:39 +0000817std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000818MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000819 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000820 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000821
Rafael Espindola56f976f2013-04-18 18:08:55 +0000822 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000823
Alp Tokere69170a2014-06-26 22:52:05 +0000824 std::string fmtbuf;
825 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000826 unsigned Type = this->getAnyRelocationType(RE);
827 bool IsPCRel = this->getAnyRelocationPCRel(RE);
828
829 // Determine any addends that should be displayed with the relocation.
830 // These require decoding the relocation type, which is triple-specific.
831
832 // X86_64 has entirely custom relocation types.
833 if (Arch == Triple::x86_64) {
834 bool isPCRel = getAnyRelocationPCRel(RE);
835
836 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000837 case MachO::X86_64_RELOC_GOT_LOAD:
838 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000839 printRelocationTargetName(this, RE, fmt);
840 fmt << "@GOT";
841 if (isPCRel) fmt << "PCREL";
842 break;
843 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000844 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000845 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000846 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000847 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000848
Charles Davis8bdfafd2013-09-01 04:28:48 +0000849 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000850 // X86_64_RELOC_UNSIGNED.
851 // NOTE: Scattered relocations don't exist on x86_64.
852 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000853 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000854 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
855 "X86_64_RELOC_SUBTRACTOR.");
856
Charles Davis8bdfafd2013-09-01 04:28:48 +0000857 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
858 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000859 printRelocationTargetName(this, RENext, fmt);
860 fmt << "-";
861 printRelocationTargetName(this, RE, fmt);
862 break;
863 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000864 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000865 printRelocationTargetName(this, RE, fmt);
866 fmt << "@TLV";
867 if (isPCRel) fmt << "P";
868 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000869 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000870 printRelocationTargetName(this, RE, fmt);
871 fmt << "-1";
872 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000873 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000874 printRelocationTargetName(this, RE, fmt);
875 fmt << "-2";
876 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000877 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000878 printRelocationTargetName(this, RE, fmt);
879 fmt << "-4";
880 break;
881 default:
882 printRelocationTargetName(this, RE, fmt);
883 break;
884 }
885 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000886 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
887 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000888 // Generic relocation types...
889 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000890 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000891 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000892 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000893 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000894 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000895 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000896
897 // X86 sect diff's must be followed by a relocation of type
898 // GENERIC_RELOC_PAIR.
899 unsigned RType = getAnyRelocationType(RENext);
900
Charles Davis8bdfafd2013-09-01 04:28:48 +0000901 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000902 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
903 "GENERIC_RELOC_SECTDIFF.");
904
905 printRelocationTargetName(this, RE, fmt);
906 fmt << "-";
907 printRelocationTargetName(this, RENext, fmt);
908 break;
909 }
910 }
911
David Fangb88cdf62013-08-08 20:14:40 +0000912 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000913 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000914 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000915 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000916 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000917 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000918
919 // X86 sect diff's must be followed by a relocation of type
920 // GENERIC_RELOC_PAIR.
921 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000922 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000923 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
924 "GENERIC_RELOC_LOCAL_SECTDIFF.");
925
926 printRelocationTargetName(this, RE, fmt);
927 fmt << "-";
928 printRelocationTargetName(this, RENext, fmt);
929 break;
930 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000931 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000932 printRelocationTargetName(this, RE, fmt);
933 fmt << "@TLV";
934 if (IsPCRel) fmt << "P";
935 break;
936 }
937 default:
938 printRelocationTargetName(this, RE, fmt);
939 }
940 } else { // ARM-specific relocations
941 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000942 case MachO::ARM_RELOC_HALF:
943 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000944 // Half relocations steal a bit from the length field to encode
945 // whether this is an upper16 or a lower16 relocation.
946 bool isUpper = getAnyRelocationLength(RE) >> 1;
947
948 if (isUpper)
949 fmt << ":upper16:(";
950 else
951 fmt << ":lower16:(";
952 printRelocationTargetName(this, RE, fmt);
953
954 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000955 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000956 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000957
958 // ARM half relocs must be followed by a relocation of type
959 // ARM_RELOC_PAIR.
960 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000961 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000962 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000963 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000964
965 // NOTE: The half of the target virtual address is stashed in the
966 // address field of the secondary relocation, but we can't reverse
967 // engineer the constant offset from it without decoding the movw/movt
968 // instruction to find the other half in its immediate field.
969
970 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
971 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000972 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000973 fmt << "-";
974 printRelocationTargetName(this, RENext, fmt);
975 }
976
977 fmt << ")";
978 break;
979 }
980 default: {
981 printRelocationTargetName(this, RE, fmt);
982 }
983 }
984 }
985 } else
986 printRelocationTargetName(this, RE, fmt);
987
Alp Tokere69170a2014-06-26 22:52:05 +0000988 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000989 Result.append(fmtbuf.begin(), fmtbuf.end());
990 return object_error::success;
991}
992
Rafael Espindola3acea392014-06-12 21:46:39 +0000993std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
994 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000995 unsigned Arch = getArch();
996 uint64_t Type;
997 getRelocationType(Rel, Type);
998
999 Result = false;
1000
1001 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1002 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +00001003 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001004 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001005 } else if (Arch == Triple::x86_64) {
1006 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +00001007 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001008 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001009 DataRefImpl RelPrev = Rel;
1010 RelPrev.d.a--;
1011 uint64_t PrevType;
1012 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001013 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001014 Result = true;
1015 }
1016 }
1017
1018 return object_error::success;
1019}
1020
Kevin Enderby980b2582014-06-05 21:21:57 +00001021//
1022// guessLibraryShortName() is passed a name of a dynamic library and returns a
1023// guess on what the short name is. Then name is returned as a substring of the
1024// StringRef Name passed in. The name of the dynamic library is recognized as
1025// a framework if it has one of the two following forms:
1026// Foo.framework/Versions/A/Foo
1027// Foo.framework/Foo
1028// Where A and Foo can be any string. And may contain a trailing suffix
1029// starting with an underbar. If the Name is recognized as a framework then
1030// isFramework is set to true else it is set to false. If the Name has a
1031// suffix then Suffix is set to the substring in Name that contains the suffix
1032// else it is set to a NULL StringRef.
1033//
1034// The Name of the dynamic library is recognized as a library name if it has
1035// one of the two following forms:
1036// libFoo.A.dylib
1037// libFoo.dylib
1038// The library may have a suffix trailing the name Foo of the form:
1039// libFoo_profile.A.dylib
1040// libFoo_profile.dylib
1041//
1042// The Name of the dynamic library is also recognized as a library name if it
1043// has the following form:
1044// Foo.qtx
1045//
1046// If the Name of the dynamic library is none of the forms above then a NULL
1047// StringRef is returned.
1048//
1049StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1050 bool &isFramework,
1051 StringRef &Suffix) {
1052 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1053 size_t a, b, c, d, Idx;
1054
1055 isFramework = false;
1056 Suffix = StringRef();
1057
1058 // Pull off the last component and make Foo point to it
1059 a = Name.rfind('/');
1060 if (a == Name.npos || a == 0)
1061 goto guess_library;
1062 Foo = Name.slice(a+1, Name.npos);
1063
1064 // Look for a suffix starting with a '_'
1065 Idx = Foo.rfind('_');
1066 if (Idx != Foo.npos && Foo.size() >= 2) {
1067 Suffix = Foo.slice(Idx, Foo.npos);
1068 Foo = Foo.slice(0, Idx);
1069 }
1070
1071 // First look for the form Foo.framework/Foo
1072 b = Name.rfind('/', a);
1073 if (b == Name.npos)
1074 Idx = 0;
1075 else
1076 Idx = b+1;
1077 F = Name.slice(Idx, Idx + Foo.size());
1078 DotFramework = Name.slice(Idx + Foo.size(),
1079 Idx + Foo.size() + sizeof(".framework/")-1);
1080 if (F == Foo && DotFramework == ".framework/") {
1081 isFramework = true;
1082 return Foo;
1083 }
1084
1085 // Next look for the form Foo.framework/Versions/A/Foo
1086 if (b == Name.npos)
1087 goto guess_library;
1088 c = Name.rfind('/', b);
1089 if (c == Name.npos || c == 0)
1090 goto guess_library;
1091 V = Name.slice(c+1, Name.npos);
1092 if (!V.startswith("Versions/"))
1093 goto guess_library;
1094 d = Name.rfind('/', c);
1095 if (d == Name.npos)
1096 Idx = 0;
1097 else
1098 Idx = d+1;
1099 F = Name.slice(Idx, Idx + Foo.size());
1100 DotFramework = Name.slice(Idx + Foo.size(),
1101 Idx + Foo.size() + sizeof(".framework/")-1);
1102 if (F == Foo && DotFramework == ".framework/") {
1103 isFramework = true;
1104 return Foo;
1105 }
1106
1107guess_library:
1108 // pull off the suffix after the "." and make a point to it
1109 a = Name.rfind('.');
1110 if (a == Name.npos || a == 0)
1111 return StringRef();
1112 Dylib = Name.slice(a, Name.npos);
1113 if (Dylib != ".dylib")
1114 goto guess_qtx;
1115
1116 // First pull off the version letter for the form Foo.A.dylib if any.
1117 if (a >= 3) {
1118 Dot = Name.slice(a-2, a-1);
1119 if (Dot == ".")
1120 a = a - 2;
1121 }
1122
1123 b = Name.rfind('/', a);
1124 if (b == Name.npos)
1125 b = 0;
1126 else
1127 b = b+1;
1128 // ignore any suffix after an underbar like Foo_profile.A.dylib
1129 Idx = Name.find('_', b);
1130 if (Idx != Name.npos && Idx != b) {
1131 Lib = Name.slice(b, Idx);
1132 Suffix = Name.slice(Idx, a);
1133 }
1134 else
1135 Lib = Name.slice(b, a);
1136 // There are incorrect library names of the form:
1137 // libATS.A_profile.dylib so check for these.
1138 if (Lib.size() >= 3) {
1139 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1140 if (Dot == ".")
1141 Lib = Lib.slice(0, Lib.size()-2);
1142 }
1143 return Lib;
1144
1145guess_qtx:
1146 Qtx = Name.slice(a, Name.npos);
1147 if (Qtx != ".qtx")
1148 return StringRef();
1149 b = Name.rfind('/', a);
1150 if (b == Name.npos)
1151 Lib = Name.slice(0, a);
1152 else
1153 Lib = Name.slice(b+1, a);
1154 // There are library names of the form: QT.A.qtx so check for these.
1155 if (Lib.size() >= 3) {
1156 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1157 if (Dot == ".")
1158 Lib = Lib.slice(0, Lib.size()-2);
1159 }
1160 return Lib;
1161}
1162
1163// getLibraryShortNameByIndex() is used to get the short name of the library
1164// for an undefined symbol in a linked Mach-O binary that was linked with the
1165// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1166// It is passed the index (0 - based) of the library as translated from
1167// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001168std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001169 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001170 if (Index >= Libraries.size())
1171 return object_error::parse_failed;
1172
1173 MachO::dylib_command D =
1174 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1175 if (D.dylib.name >= D.cmdsize)
1176 return object_error::parse_failed;
1177
1178 // If the cache of LibrariesShortNames is not built up do that first for
1179 // all the Libraries.
1180 if (LibrariesShortNames.size() == 0) {
1181 for (unsigned i = 0; i < Libraries.size(); i++) {
1182 MachO::dylib_command D =
1183 getStruct<MachO::dylib_command>(this, Libraries[i]);
1184 if (D.dylib.name >= D.cmdsize) {
1185 LibrariesShortNames.push_back(StringRef());
1186 continue;
1187 }
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001188 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001189 StringRef Name = StringRef(P);
1190 StringRef Suffix;
1191 bool isFramework;
1192 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1193 if (shortName == StringRef())
1194 LibrariesShortNames.push_back(Name);
1195 else
1196 LibrariesShortNames.push_back(shortName);
1197 }
1198 }
1199
1200 Res = LibrariesShortNames[Index];
1201 return object_error::success;
1202}
1203
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001204basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001205 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001206}
1207
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001208basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001209 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001210 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001211 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001212
Charles Davis8bdfafd2013-09-01 04:28:48 +00001213 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001214 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001215 sizeof(MachO::nlist_64) :
1216 sizeof(MachO::nlist);
1217 unsigned Offset = Symtab.symoff +
1218 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001219 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001220 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001221}
1222
Lang Hames36072da2014-05-12 21:39:59 +00001223basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1224 DataRefImpl DRI;
1225 if (!SymtabLoadCmd)
1226 return basic_symbol_iterator(SymbolRef(DRI, this));
1227
1228 MachO::symtab_command Symtab = getSymtabLoadCommand();
1229 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1230 unsigned SymbolTableEntrySize =
1231 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1232 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1233 DRI.p += Index * SymbolTableEntrySize;
1234 return basic_symbol_iterator(SymbolRef(DRI, this));
1235}
1236
Rafael Espindolab5155a52014-02-10 20:24:04 +00001237section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001238 DataRefImpl DRI;
1239 return section_iterator(SectionRef(DRI, this));
1240}
1241
Rafael Espindolab5155a52014-02-10 20:24:04 +00001242section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001243 DataRefImpl DRI;
1244 DRI.d.a = Sections.size();
1245 return section_iterator(SectionRef(DRI, this));
1246}
1247
Rafael Espindola56f976f2013-04-18 18:08:55 +00001248uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001249 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001250}
1251
Rafael Espindola56f976f2013-04-18 18:08:55 +00001252StringRef MachOObjectFile::getFileFormatName() const {
1253 unsigned CPUType = getCPUType(this);
1254 if (!is64Bit()) {
1255 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001256 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001257 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001258 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001259 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001260 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001261 return "Mach-O 32-bit ppc";
1262 default:
Charles Davis74ec8b02013-08-27 05:00:13 +00001263 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindola56f976f2013-04-18 18:08:55 +00001264 "64-bit object file when we're not 64-bit?");
1265 return "Mach-O 32-bit unknown";
1266 }
1267 }
1268
1269 // Make sure the cpu type has the correct mask.
Charles Davis74ec8b02013-08-27 05:00:13 +00001270 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1271 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher1d62c252013-07-22 22:25:07 +00001272 "32-bit object file when we're 64-bit?");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001273
1274 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001275 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001276 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001277 case llvm::MachO::CPU_TYPE_ARM64:
1278 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001279 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001280 return "Mach-O 64-bit ppc64";
1281 default:
1282 return "Mach-O 64-bit unknown";
1283 }
1284}
1285
Alexey Samsonove6388e62013-06-18 15:03:28 +00001286Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1287 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001288 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001289 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001290 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001291 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001292 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001293 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001294 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001295 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001296 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001297 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001298 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001299 return Triple::ppc64;
1300 default:
1301 return Triple::UnknownArch;
1302 }
1303}
1304
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001305Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1306 const char **McpuDefault) {
1307 if (McpuDefault)
1308 *McpuDefault = nullptr;
1309
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001310 switch (CPUType) {
1311 case MachO::CPU_TYPE_I386:
1312 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1313 case MachO::CPU_SUBTYPE_I386_ALL:
1314 return Triple("i386-apple-darwin");
1315 default:
1316 return Triple();
1317 }
1318 case MachO::CPU_TYPE_X86_64:
1319 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1320 case MachO::CPU_SUBTYPE_X86_64_ALL:
1321 return Triple("x86_64-apple-darwin");
1322 case MachO::CPU_SUBTYPE_X86_64_H:
1323 return Triple("x86_64h-apple-darwin");
1324 default:
1325 return Triple();
1326 }
1327 case MachO::CPU_TYPE_ARM:
1328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1329 case MachO::CPU_SUBTYPE_ARM_V4T:
1330 return Triple("armv4t-apple-darwin");
1331 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1332 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001333 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1334 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001335 case MachO::CPU_SUBTYPE_ARM_V6:
1336 return Triple("armv6-apple-darwin");
1337 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001338 if (McpuDefault)
1339 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001340 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001341 case MachO::CPU_SUBTYPE_ARM_V7:
1342 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001343 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001344 if (McpuDefault)
1345 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001346 return Triple("armv7em-apple-darwin");
1347 case MachO::CPU_SUBTYPE_ARM_V7K:
1348 return Triple("armv7k-apple-darwin");
1349 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001350 if (McpuDefault)
1351 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001352 return Triple("armv7m-apple-darwin");
1353 case MachO::CPU_SUBTYPE_ARM_V7S:
1354 return Triple("armv7s-apple-darwin");
1355 default:
1356 return Triple();
1357 }
1358 case MachO::CPU_TYPE_ARM64:
1359 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1360 case MachO::CPU_SUBTYPE_ARM64_ALL:
1361 return Triple("arm64-apple-darwin");
1362 default:
1363 return Triple();
1364 }
1365 case MachO::CPU_TYPE_POWERPC:
1366 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1367 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1368 return Triple("ppc-apple-darwin");
1369 default:
1370 return Triple();
1371 }
1372 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001373 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001374 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1375 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001376 default:
1377 return Triple();
1378 }
1379 default:
1380 return Triple();
1381 }
1382}
1383
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001384Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1385 const char **McpuDefault) {
1386 if (McpuDefault)
1387 *McpuDefault = nullptr;
1388
1389 switch (CPUType) {
1390 case MachO::CPU_TYPE_ARM:
1391 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1392 case MachO::CPU_SUBTYPE_ARM_V4T:
1393 return Triple("thumbv4t-apple-darwin");
1394 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1395 return Triple("thumbv5e-apple-darwin");
1396 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1397 return Triple("xscale-apple-darwin");
1398 case MachO::CPU_SUBTYPE_ARM_V6:
1399 return Triple("thumbv6-apple-darwin");
1400 case MachO::CPU_SUBTYPE_ARM_V6M:
1401 if (McpuDefault)
1402 *McpuDefault = "cortex-m0";
1403 return Triple("thumbv6m-apple-darwin");
1404 case MachO::CPU_SUBTYPE_ARM_V7:
1405 return Triple("thumbv7-apple-darwin");
1406 case MachO::CPU_SUBTYPE_ARM_V7EM:
1407 if (McpuDefault)
1408 *McpuDefault = "cortex-m4";
1409 return Triple("thumbv7em-apple-darwin");
1410 case MachO::CPU_SUBTYPE_ARM_V7K:
1411 return Triple("thumbv7k-apple-darwin");
1412 case MachO::CPU_SUBTYPE_ARM_V7M:
1413 if (McpuDefault)
1414 *McpuDefault = "cortex-m3";
1415 return Triple("thumbv7m-apple-darwin");
1416 case MachO::CPU_SUBTYPE_ARM_V7S:
1417 return Triple("thumbv7s-apple-darwin");
1418 default:
1419 return Triple();
1420 }
1421 default:
1422 return Triple();
1423 }
1424}
1425
1426Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1427 const char **McpuDefault,
1428 Triple *ThumbTriple) {
1429 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1430 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1431 McpuDefault);
1432 return T;
1433}
1434
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001435Triple MachOObjectFile::getHostArch() {
1436 return Triple(sys::getDefaultTargetTriple());
1437}
1438
Rafael Espindola72318b42014-08-08 16:30:17 +00001439bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1440 return StringSwitch<bool>(ArchFlag)
1441 .Case("i386", true)
1442 .Case("x86_64", true)
1443 .Case("x86_64h", true)
1444 .Case("armv4t", true)
1445 .Case("arm", true)
1446 .Case("armv5e", true)
1447 .Case("armv6", true)
1448 .Case("armv6m", true)
1449 .Case("armv7em", true)
1450 .Case("armv7k", true)
1451 .Case("armv7m", true)
1452 .Case("armv7s", true)
1453 .Case("arm64", true)
1454 .Case("ppc", true)
1455 .Case("ppc64", true)
1456 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001457}
1458
Alexey Samsonove6388e62013-06-18 15:03:28 +00001459unsigned MachOObjectFile::getArch() const {
1460 return getArch(getCPUType(this));
1461}
1462
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001463Triple MachOObjectFile::getArch(const char **McpuDefault,
1464 Triple *ThumbTriple) const {
1465 Triple T;
1466 if (is64Bit()) {
1467 MachO::mach_header_64 H_64;
1468 H_64 = getHeader64();
1469 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1470 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1471 McpuDefault);
1472 } else {
1473 MachO::mach_header H;
1474 H = getHeader();
1475 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1476 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1477 McpuDefault);
1478 }
1479 return T;
1480}
1481
Rui Ueyamabc654b12013-09-27 21:47:05 +00001482relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001483 DataRefImpl DRI;
1484 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001485 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001486}
1487
Rui Ueyamabc654b12013-09-27 21:47:05 +00001488relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001489 DataRefImpl DRI;
1490 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001491 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001492}
1493
Kevin Enderby273ae012013-06-06 17:20:50 +00001494dice_iterator MachOObjectFile::begin_dices() const {
1495 DataRefImpl DRI;
1496 if (!DataInCodeLoadCmd)
1497 return dice_iterator(DiceRef(DRI, this));
1498
Charles Davis8bdfafd2013-09-01 04:28:48 +00001499 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1500 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001501 return dice_iterator(DiceRef(DRI, this));
1502}
1503
1504dice_iterator MachOObjectFile::end_dices() const {
1505 DataRefImpl DRI;
1506 if (!DataInCodeLoadCmd)
1507 return dice_iterator(DiceRef(DRI, this));
1508
Charles Davis8bdfafd2013-09-01 04:28:48 +00001509 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1510 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001511 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1512 return dice_iterator(DiceRef(DRI, this));
1513}
1514
Nick Kledzikd04bc352014-08-30 00:20:14 +00001515ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1516 : Trie(T), Malformed(false), Done(false) { }
1517
1518void ExportEntry::moveToFirst() {
1519 pushNode(0);
1520 pushDownUntilBottom();
1521}
1522
1523void ExportEntry::moveToEnd() {
1524 Stack.clear();
1525 Done = true;
1526}
1527
1528bool ExportEntry::operator==(const ExportEntry &Other) const {
1529 // Common case, one at end, other iterating from begin.
1530 if (Done || Other.Done)
1531 return (Done == Other.Done);
1532 // Not equal if different stack sizes.
1533 if (Stack.size() != Other.Stack.size())
1534 return false;
1535 // Not equal if different cumulative strings.
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001536 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001537 return false;
1538 // Equal if all nodes in both stacks match.
1539 for (unsigned i=0; i < Stack.size(); ++i) {
1540 if (Stack[i].Start != Other.Stack[i].Start)
1541 return false;
1542 }
1543 return true;
1544}
1545
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001546uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1547 unsigned Count;
1548 uint64_t Result = decodeULEB128(Ptr, &Count);
1549 Ptr += Count;
1550 if (Ptr > Trie.end()) {
1551 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001552 Malformed = true;
1553 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001554 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001555}
1556
1557StringRef ExportEntry::name() const {
1558 return CumulativeString.str();
1559}
1560
1561uint64_t ExportEntry::flags() const {
1562 return Stack.back().Flags;
1563}
1564
1565uint64_t ExportEntry::address() const {
1566 return Stack.back().Address;
1567}
1568
1569uint64_t ExportEntry::other() const {
1570 return Stack.back().Other;
1571}
1572
1573StringRef ExportEntry::otherName() const {
1574 const char* ImportName = Stack.back().ImportName;
1575 if (ImportName)
1576 return StringRef(ImportName);
1577 return StringRef();
1578}
1579
1580uint32_t ExportEntry::nodeOffset() const {
1581 return Stack.back().Start - Trie.begin();
1582}
1583
1584ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1585 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1586 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1587 ParentStringLength(0), IsExportNode(false) {
1588}
1589
1590void ExportEntry::pushNode(uint64_t offset) {
1591 const uint8_t *Ptr = Trie.begin() + offset;
1592 NodeState State(Ptr);
1593 uint64_t ExportInfoSize = readULEB128(State.Current);
1594 State.IsExportNode = (ExportInfoSize != 0);
1595 const uint8_t* Children = State.Current + ExportInfoSize;
1596 if (State.IsExportNode) {
1597 State.Flags = readULEB128(State.Current);
1598 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1599 State.Address = 0;
1600 State.Other = readULEB128(State.Current); // dylib ordinal
1601 State.ImportName = reinterpret_cast<const char*>(State.Current);
1602 } else {
1603 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001604 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1605 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001606 }
1607 }
1608 State.ChildCount = *Children;
1609 State.Current = Children + 1;
1610 State.NextChildIndex = 0;
1611 State.ParentStringLength = CumulativeString.size();
1612 Stack.push_back(State);
1613}
1614
1615void ExportEntry::pushDownUntilBottom() {
1616 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1617 NodeState &Top = Stack.back();
1618 CumulativeString.resize(Top.ParentStringLength);
1619 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001620 char C = *Top.Current;
1621 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001622 }
1623 Top.Current += 1;
1624 uint64_t childNodeIndex = readULEB128(Top.Current);
1625 Top.NextChildIndex += 1;
1626 pushNode(childNodeIndex);
1627 }
1628 if (!Stack.back().IsExportNode) {
1629 Malformed = true;
1630 moveToEnd();
1631 }
1632}
1633
1634// We have a trie data structure and need a way to walk it that is compatible
1635// with the C++ iterator model. The solution is a non-recursive depth first
1636// traversal where the iterator contains a stack of parent nodes along with a
1637// string that is the accumulation of all edge strings along the parent chain
1638// to this point.
1639//
1640// There is one “export” node for each exported symbol. But because some
1641// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1642// node may have child nodes too.
1643//
1644// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1645// child until hitting a node with no children (which is an export node or
1646// else the trie is malformed). On the way down, each node is pushed on the
1647// stack ivar. If there is no more ways down, it pops up one and tries to go
1648// down a sibling path until a childless node is reached.
1649void ExportEntry::moveNext() {
1650 if (Stack.empty() || !Stack.back().IsExportNode) {
1651 Malformed = true;
1652 moveToEnd();
1653 return;
1654 }
1655
1656 Stack.pop_back();
1657 while (!Stack.empty()) {
1658 NodeState &Top = Stack.back();
1659 if (Top.NextChildIndex < Top.ChildCount) {
1660 pushDownUntilBottom();
1661 // Now at the next export node.
1662 return;
1663 } else {
1664 if (Top.IsExportNode) {
1665 // This node has no children but is itself an export node.
1666 CumulativeString.resize(Top.ParentStringLength);
1667 return;
1668 }
1669 Stack.pop_back();
1670 }
1671 }
1672 Done = true;
1673}
1674
1675iterator_range<export_iterator>
1676MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1677 ExportEntry Start(Trie);
1678 Start.moveToFirst();
1679
1680 ExportEntry Finish(Trie);
1681 Finish.moveToEnd();
1682
1683 return iterator_range<export_iterator>(export_iterator(Start),
1684 export_iterator(Finish));
1685}
1686
1687iterator_range<export_iterator> MachOObjectFile::exports() const {
1688 return exports(getDyldInfoExportsTrie());
1689}
1690
1691
Nick Kledzikac431442014-09-12 21:34:15 +00001692MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1693 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1694 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1695 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1696
1697void MachORebaseEntry::moveToFirst() {
1698 Ptr = Opcodes.begin();
1699 moveNext();
1700}
1701
1702void MachORebaseEntry::moveToEnd() {
1703 Ptr = Opcodes.end();
1704 RemainingLoopCount = 0;
1705 Done = true;
1706}
1707
1708void MachORebaseEntry::moveNext() {
1709 // If in the middle of some loop, move to next rebasing in loop.
1710 SegmentOffset += AdvanceAmount;
1711 if (RemainingLoopCount) {
1712 --RemainingLoopCount;
1713 return;
1714 }
1715 if (Ptr == Opcodes.end()) {
1716 Done = true;
1717 return;
1718 }
1719 bool More = true;
1720 while (More && !Malformed) {
1721 // Parse next opcode and set up next loop.
1722 uint8_t Byte = *Ptr++;
1723 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1724 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1725 switch (Opcode) {
1726 case MachO::REBASE_OPCODE_DONE:
1727 More = false;
1728 Done = true;
1729 moveToEnd();
1730 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1731 break;
1732 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1733 RebaseType = ImmValue;
1734 DEBUG_WITH_TYPE(
1735 "mach-o-rebase",
1736 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1737 << "RebaseType=" << (int) RebaseType << "\n");
1738 break;
1739 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1740 SegmentIndex = ImmValue;
1741 SegmentOffset = readULEB128();
1742 DEBUG_WITH_TYPE(
1743 "mach-o-rebase",
1744 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1745 << "SegmentIndex=" << SegmentIndex << ", "
1746 << format("SegmentOffset=0x%06X", SegmentOffset)
1747 << "\n");
1748 break;
1749 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1750 SegmentOffset += readULEB128();
1751 DEBUG_WITH_TYPE("mach-o-rebase",
1752 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1753 << format("SegmentOffset=0x%06X",
1754 SegmentOffset) << "\n");
1755 break;
1756 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1757 SegmentOffset += ImmValue * PointerSize;
1758 DEBUG_WITH_TYPE("mach-o-rebase",
1759 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1760 << format("SegmentOffset=0x%06X",
1761 SegmentOffset) << "\n");
1762 break;
1763 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1764 AdvanceAmount = PointerSize;
1765 RemainingLoopCount = ImmValue - 1;
1766 DEBUG_WITH_TYPE(
1767 "mach-o-rebase",
1768 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1769 << format("SegmentOffset=0x%06X", SegmentOffset)
1770 << ", AdvanceAmount=" << AdvanceAmount
1771 << ", RemainingLoopCount=" << RemainingLoopCount
1772 << "\n");
1773 return;
1774 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1775 AdvanceAmount = PointerSize;
1776 RemainingLoopCount = readULEB128() - 1;
1777 DEBUG_WITH_TYPE(
1778 "mach-o-rebase",
1779 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1780 << format("SegmentOffset=0x%06X", SegmentOffset)
1781 << ", AdvanceAmount=" << AdvanceAmount
1782 << ", RemainingLoopCount=" << RemainingLoopCount
1783 << "\n");
1784 return;
1785 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1786 AdvanceAmount = readULEB128() + PointerSize;
1787 RemainingLoopCount = 0;
1788 DEBUG_WITH_TYPE(
1789 "mach-o-rebase",
1790 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1791 << format("SegmentOffset=0x%06X", SegmentOffset)
1792 << ", AdvanceAmount=" << AdvanceAmount
1793 << ", RemainingLoopCount=" << RemainingLoopCount
1794 << "\n");
1795 return;
1796 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1797 RemainingLoopCount = readULEB128() - 1;
1798 AdvanceAmount = readULEB128() + PointerSize;
1799 DEBUG_WITH_TYPE(
1800 "mach-o-rebase",
1801 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1802 << format("SegmentOffset=0x%06X", SegmentOffset)
1803 << ", AdvanceAmount=" << AdvanceAmount
1804 << ", RemainingLoopCount=" << RemainingLoopCount
1805 << "\n");
1806 return;
1807 default:
1808 Malformed = true;
1809 }
1810 }
1811}
1812
1813uint64_t MachORebaseEntry::readULEB128() {
1814 unsigned Count;
1815 uint64_t Result = decodeULEB128(Ptr, &Count);
1816 Ptr += Count;
1817 if (Ptr > Opcodes.end()) {
1818 Ptr = Opcodes.end();
1819 Malformed = true;
1820 }
1821 return Result;
1822}
1823
1824uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1825
1826uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1827
1828StringRef MachORebaseEntry::typeName() const {
1829 switch (RebaseType) {
1830 case MachO::REBASE_TYPE_POINTER:
1831 return "pointer";
1832 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1833 return "text abs32";
1834 case MachO::REBASE_TYPE_TEXT_PCREL32:
1835 return "text rel32";
1836 }
1837 return "unknown";
1838}
1839
1840bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1841 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1842 return (Ptr == Other.Ptr) &&
1843 (RemainingLoopCount == Other.RemainingLoopCount) &&
1844 (Done == Other.Done);
1845}
1846
1847iterator_range<rebase_iterator>
1848MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1849 MachORebaseEntry Start(Opcodes, is64);
1850 Start.moveToFirst();
1851
1852 MachORebaseEntry Finish(Opcodes, is64);
1853 Finish.moveToEnd();
1854
1855 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1856 rebase_iterator(Finish));
1857}
1858
1859iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1860 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1861}
1862
Rafael Espindola56f976f2013-04-18 18:08:55 +00001863StringRef
1864MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1865 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1866 return parseSegmentOrSectionName(Raw.data());
1867}
1868
1869ArrayRef<char>
1870MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001871 const section_base *Base =
1872 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001873 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001874}
1875
1876ArrayRef<char>
1877MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001878 const section_base *Base =
1879 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001880 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001881}
1882
1883bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001884MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001885 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001886 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001887 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001888 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001889}
1890
Eric Christopher1d62c252013-07-22 22:25:07 +00001891unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001892 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001893 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001894 return RE.r_word1 & 0xffffff;
1895 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001896}
1897
Eric Christopher1d62c252013-07-22 22:25:07 +00001898bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001899 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001900 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001901 return (RE.r_word1 >> 27) & 1;
1902 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001903}
1904
Eric Christopher1d62c252013-07-22 22:25:07 +00001905bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001906 const MachO::any_relocation_info &RE) const {
1907 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001908}
1909
Eric Christopher1d62c252013-07-22 22:25:07 +00001910uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001911 const MachO::any_relocation_info &RE) const {
1912 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001913}
1914
Eric Christopher1d62c252013-07-22 22:25:07 +00001915unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001916 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001917 if (isRelocationScattered(RE))
1918 return getScatteredRelocationAddress(RE);
1919 return getPlainRelocationAddress(RE);
1920}
1921
Charles Davis8bdfafd2013-09-01 04:28:48 +00001922unsigned MachOObjectFile::getAnyRelocationPCRel(
1923 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001924 if (isRelocationScattered(RE))
1925 return getScatteredRelocationPCRel(this, RE);
1926 return getPlainRelocationPCRel(this, RE);
1927}
1928
Eric Christopher1d62c252013-07-22 22:25:07 +00001929unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001930 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001931 if (isRelocationScattered(RE))
1932 return getScatteredRelocationLength(RE);
1933 return getPlainRelocationLength(this, RE);
1934}
1935
1936unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00001937MachOObjectFile::getAnyRelocationType(
1938 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001939 if (isRelocationScattered(RE))
1940 return getScatteredRelocationType(RE);
1941 return getPlainRelocationType(this, RE);
1942}
1943
Rafael Espindola52501032013-04-30 15:40:54 +00001944SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00001945MachOObjectFile::getRelocationSection(
1946 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00001947 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00001948 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00001949 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1950 DataRefImpl DRI;
1951 DRI.d.a = SecNum;
1952 return SectionRef(DRI, this);
1953}
1954
Rafael Espindola56f976f2013-04-18 18:08:55 +00001955MachOObjectFile::LoadCommandInfo
1956MachOObjectFile::getFirstLoadCommandInfo() const {
1957 MachOObjectFile::LoadCommandInfo Load;
1958
Charles Davis8bdfafd2013-09-01 04:28:48 +00001959 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1960 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001961 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001962 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001963 return Load;
1964}
1965
1966MachOObjectFile::LoadCommandInfo
1967MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1968 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001969 Next.Ptr = L.Ptr + L.C.cmdsize;
1970 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001971 return Next;
1972}
1973
Charles Davis8bdfafd2013-09-01 04:28:48 +00001974MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1975 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001976}
1977
Charles Davis8bdfafd2013-09-01 04:28:48 +00001978MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1979 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001980}
1981
Charles Davis8bdfafd2013-09-01 04:28:48 +00001982MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00001983 unsigned Index) const {
1984 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001985 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001986}
1987
Charles Davis8bdfafd2013-09-01 04:28:48 +00001988MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1989 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001990 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001991 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001992}
1993
Charles Davis8bdfafd2013-09-01 04:28:48 +00001994MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00001995MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001996 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001997 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001998}
1999
Charles Davis8bdfafd2013-09-01 04:28:48 +00002000MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002001MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002002 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002003 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002004}
2005
Charles Davis8bdfafd2013-09-01 04:28:48 +00002006MachO::linkedit_data_command
2007MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2008 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002009}
2010
Charles Davis8bdfafd2013-09-01 04:28:48 +00002011MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002012MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002013 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002014}
2015
Charles Davis8bdfafd2013-09-01 04:28:48 +00002016MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002017MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002018 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002019}
2020
Charles Davis8bdfafd2013-09-01 04:28:48 +00002021MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002022MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002023 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002024}
2025
Jim Grosbach448334a2014-03-18 22:09:05 +00002026MachO::version_min_command
2027MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2028 return getStruct<MachO::version_min_command>(this, L.Ptr);
2029}
2030
Tim Northover8f9590b2014-06-30 14:40:57 +00002031MachO::dylib_command
2032MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2033 return getStruct<MachO::dylib_command>(this, L.Ptr);
2034}
2035
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002036MachO::dyld_info_command
2037MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2038 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2039}
2040
2041MachO::dylinker_command
2042MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2043 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2044}
2045
2046MachO::uuid_command
2047MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2048 return getStruct<MachO::uuid_command>(this, L.Ptr);
2049}
2050
2051MachO::source_version_command
2052MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2053 return getStruct<MachO::source_version_command>(this, L.Ptr);
2054}
2055
2056MachO::entry_point_command
2057MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2058 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2059}
2060
Tim Northover8f9590b2014-06-30 14:40:57 +00002061
Charles Davis8bdfafd2013-09-01 04:28:48 +00002062MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002063MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002064 DataRefImpl Sec;
2065 Sec.d.a = Rel.d.a;
2066 uint32_t Offset;
2067 if (is64Bit()) {
2068 MachO::section_64 Sect = getSection64(Sec);
2069 Offset = Sect.reloff;
2070 } else {
2071 MachO::section Sect = getSection(Sec);
2072 Offset = Sect.reloff;
2073 }
2074
2075 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2076 getPtr(this, Offset)) + Rel.d.b;
2077 return getStruct<MachO::any_relocation_info>(
2078 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002079}
2080
Charles Davis8bdfafd2013-09-01 04:28:48 +00002081MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002082MachOObjectFile::getDice(DataRefImpl Rel) const {
2083 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002084 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002085}
2086
Charles Davis8bdfafd2013-09-01 04:28:48 +00002087MachO::mach_header MachOObjectFile::getHeader() const {
2088 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002089}
2090
Charles Davis8bdfafd2013-09-01 04:28:48 +00002091MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2092 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002093}
2094
Charles Davis8bdfafd2013-09-01 04:28:48 +00002095uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2096 const MachO::dysymtab_command &DLC,
2097 unsigned Index) const {
2098 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2099 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002100}
2101
Charles Davis8bdfafd2013-09-01 04:28:48 +00002102MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002103MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2104 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002105 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2106 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002107}
2108
Charles Davis8bdfafd2013-09-01 04:28:48 +00002109MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2110 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002111}
2112
Charles Davis8bdfafd2013-09-01 04:28:48 +00002113MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2114 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002115}
2116
Charles Davis8bdfafd2013-09-01 04:28:48 +00002117MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002118MachOObjectFile::getDataInCodeLoadCommand() const {
2119 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002120 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002121
2122 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002123 MachO::linkedit_data_command Cmd;
2124 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2125 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2126 Cmd.dataoff = 0;
2127 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002128 return Cmd;
2129}
2130
Nick Kledzikd04bc352014-08-30 00:20:14 +00002131ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2132 if (!DyldInfoLoadCmd)
2133 return ArrayRef<uint8_t>();
2134
2135 MachO::dyld_info_command DyldInfo
2136 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2137 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2138 getPtr(this, DyldInfo.rebase_off));
2139 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2140}
2141
2142ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2143 if (!DyldInfoLoadCmd)
2144 return ArrayRef<uint8_t>();
2145
2146 MachO::dyld_info_command DyldInfo
2147 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2148 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2149 getPtr(this, DyldInfo.bind_off));
2150 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2151}
2152
2153ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2154 if (!DyldInfoLoadCmd)
2155 return ArrayRef<uint8_t>();
2156
2157 MachO::dyld_info_command DyldInfo
2158 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2159 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2160 getPtr(this, DyldInfo.weak_bind_off));
2161 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2162}
2163
2164ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2165 if (!DyldInfoLoadCmd)
2166 return ArrayRef<uint8_t>();
2167
2168 MachO::dyld_info_command DyldInfo
2169 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2170 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2171 getPtr(this, DyldInfo.lazy_bind_off));
2172 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2173}
2174
2175ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2176 if (!DyldInfoLoadCmd)
2177 return ArrayRef<uint8_t>();
2178
2179 MachO::dyld_info_command DyldInfo
2180 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2181 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2182 getPtr(this, DyldInfo.export_off));
2183 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2184}
2185
2186
Rafael Espindola6e040c02013-04-26 20:07:33 +00002187StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002188 MachO::symtab_command S = getSymtabLoadCommand();
2189 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002190}
2191
Rafael Espindola56f976f2013-04-18 18:08:55 +00002192bool MachOObjectFile::is64Bit() const {
2193 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002194 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002195}
2196
2197void MachOObjectFile::ReadULEB128s(uint64_t Index,
2198 SmallVectorImpl<uint64_t> &Out) const {
2199 DataExtractor extractor(ObjectFile::getData(), true, 0);
2200
2201 uint32_t offset = Index;
2202 uint64_t data = 0;
2203 while (uint64_t delta = extractor.getULEB128(&offset)) {
2204 data += delta;
2205 Out.push_back(data);
2206 }
2207}
2208
Rafael Espindolac66d7612014-08-17 19:09:37 +00002209bool MachOObjectFile::isRelocatableObject() const {
2210 return getHeader().filetype == MachO::MH_OBJECT;
2211}
2212
Rafael Espindola437b0d52014-07-31 03:12:45 +00002213ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002214ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2215 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00002216 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00002217 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002218 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002219 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002220 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002221 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002222 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002223 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002224 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00002225 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00002226 else
Rafael Espindola692410e2014-01-21 23:06:54 +00002227 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002228
Rafael Espindola692410e2014-01-21 23:06:54 +00002229 if (EC)
2230 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00002231 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002232}
2233