blob: 36cae16de1c212e1dee0dfc0391d1a1b98088965 [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"
Owen Andersonbc14bd32011-10-26 20:42:54 +000020#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000021#include "llvm/Support/Host.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000022#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000023#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000024#include <cctype>
25#include <cstring>
26#include <limits>
27
28using namespace llvm;
29using namespace object;
30
Artyom Skrobov7d602f72014-07-20 12:08:28 +000031namespace {
32 struct section_base {
33 char sectname[16];
34 char segname[16];
35 };
36}
Rafael Espindola56f976f2013-04-18 18:08:55 +000037
38template<typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000039static T getStruct(const MachOObjectFile *O, const char *P) {
Rafael Espindola3cdeb172013-04-19 13:45:05 +000040 T Cmd;
41 memcpy(&Cmd, P, sizeof(T));
42 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000043 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000044 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000045}
46
Rafael Espindola56f976f2013-04-18 18:08:55 +000047static uint32_t
48getSegmentLoadCommandNumSections(const MachOObjectFile *O,
49 const MachOObjectFile::LoadCommandInfo &L) {
50 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000051 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
52 return S.nsects;
Rafael Espindola421305a2013-04-07 20:01:29 +000053 }
Charles Davis8bdfafd2013-09-01 04:28:48 +000054 MachO::segment_command S = O->getSegmentLoadCommand(L);
55 return S.nsects;
Rafael Espindola5ffc0792013-04-07 16:07:35 +000056}
57
Rafael Espindola6e040c02013-04-26 20:07:33 +000058static const char *
59getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
60 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000061 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
62
63 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000064 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
65 sizeof(MachO::segment_command);
66 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
67 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000068
69 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000070 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000071}
72
Rafael Espindola56f976f2013-04-18 18:08:55 +000073static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
74 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000075}
76
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000077static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000078getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000079 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000080 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000081}
82
Rafael Espindola56f976f2013-04-18 18:08:55 +000083static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000084 if (P[15] == 0)
85 // Null terminated.
86 return P;
87 // Not null terminated, so this is a 16 char string.
88 return StringRef(P, 16);
89}
90
Rafael Espindola56f976f2013-04-18 18:08:55 +000091// Helper to advance a section or symbol iterator multiple increments at a time.
92template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +000093static void advance(T &it, size_t Val) {
94 while (Val--)
95 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +000096}
97
98static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000099 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000100}
101
102static void printRelocationTargetName(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000103 const MachO::any_relocation_info &RE,
Alp Tokere69170a2014-06-26 22:52:05 +0000104 raw_string_ostream &fmt) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000105 bool IsScattered = O->isRelocationScattered(RE);
106
107 // Target of a scattered relocation is an address. In the interest of
108 // generating pretty output, scan through the symbol table looking for a
109 // symbol that aligns with that address. If we find one, print it.
110 // Otherwise, we just print the hex address of the target.
111 if (IsScattered) {
112 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
113
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000114 for (const SymbolRef &Symbol : O->symbols()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000115 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000116 uint64_t Addr;
117 StringRef Name;
118
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000119 if ((ec = Symbol.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000120 report_fatal_error(ec.message());
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000121 if (Addr != Val)
122 continue;
123 if ((ec = Symbol.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000124 report_fatal_error(ec.message());
125 fmt << Name;
126 return;
127 }
128
129 // If we couldn't find a symbol that this relocation refers to, try
130 // to find a section beginning instead.
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000131 for (const SectionRef &Section : O->sections()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000132 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000133 uint64_t Addr;
134 StringRef Name;
135
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000136 if ((ec = Section.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000137 report_fatal_error(ec.message());
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000138 if (Addr != Val)
139 continue;
140 if ((ec = Section.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000141 report_fatal_error(ec.message());
142 fmt << Name;
143 return;
144 }
145
146 fmt << format("0x%x", Val);
147 return;
148 }
149
150 StringRef S;
151 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000152 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000153
154 if (isExtern) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000155 symbol_iterator SI = O->symbol_begin();
Rafael Espindola5e812af2014-01-30 02:49:50 +0000156 advance(SI, Val);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000157 SI->getName(S);
158 } else {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000159 section_iterator SI = O->section_begin();
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000160 // Adjust for the fact that sections are 1-indexed.
Rafael Espindola5e812af2014-01-30 02:49:50 +0000161 advance(SI, Val - 1);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000162 SI->getName(S);
163 }
164
165 fmt << S;
166}
167
Charles Davis8bdfafd2013-09-01 04:28:48 +0000168static uint32_t
169getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
170 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000171}
172
173static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000174getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
175 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000176}
177
178static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000179 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000180 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000181 return (RE.r_word1 >> 24) & 1;
182 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000183}
184
185static bool
186getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000187 const MachO::any_relocation_info &RE) {
188 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000189}
190
191static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000192 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000193 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000194 return (RE.r_word1 >> 25) & 3;
195 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000196}
197
198static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000199getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000201}
202
203static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000204 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000205 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000206 return RE.r_word1 >> 28;
207 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000208}
209
Charles Davis8bdfafd2013-09-01 04:28:48 +0000210static unsigned
211getScatteredRelocationType(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 24) & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000213}
214
215static uint32_t getSectionFlags(const MachOObjectFile *O,
216 DataRefImpl Sec) {
217 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000218 MachO::section_64 Sect = O->getSection64(Sec);
219 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000220 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000221 MachO::section Sect = O->getSection(Sec);
222 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000223}
224
Rafael Espindola2e60ca92014-06-24 13:56:32 +0000225MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,
226 bool IsLittleEndian, bool Is64bits,
227 std::error_code &EC)
228 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)),
Craig Topper2617dcc2014-04-15 06:32:26 +0000229 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
230 DataInCodeLoadCmd(nullptr) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000231 uint32_t LoadCommandCount = this->getHeader().ncmds;
232 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
233 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000234
235 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000236 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000237 if (Load.C.cmd == MachO::LC_SYMTAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000238 assert(!SymtabLoadCmd && "Multiple symbol tables");
239 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000240 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000241 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
242 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000243 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby273ae012013-06-06 17:20:50 +0000244 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
245 DataInCodeLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000246 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000247 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
248 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000249 const char *Sec = getSectionPtr(this, Load, J);
250 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000251 }
Kevin Enderby980b2582014-06-05 21:21:57 +0000252 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
253 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
254 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
255 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
256 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
257 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000258 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000259
260 if (I == LoadCommandCount - 1)
261 break;
262 else
263 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000264 }
265}
266
Rafael Espindola5e812af2014-01-30 02:49:50 +0000267void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000268 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000269 sizeof(MachO::nlist_64) :
270 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000271 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000272}
273
Rafael Espindola3acea392014-06-12 21:46:39 +0000274std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
275 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000276 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000277 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000278 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000279 Res = StringRef(Start);
280 return object_error::success;
281}
282
Kevin Enderby980b2582014-06-05 21:21:57 +0000283// getIndirectName() returns the name of the alias'ed symbol who's string table
284// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000285std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
286 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000287 StringRef StringTable = getStringTableData();
288 uint64_t NValue;
289 if (is64Bit()) {
290 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
291 NValue = Entry.n_value;
292 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
293 return object_error::parse_failed;
294 } else {
295 MachO::nlist Entry = getSymbolTableEntry(Symb);
296 NValue = Entry.n_value;
297 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
298 return object_error::parse_failed;
299 }
300 if (NValue >= StringTable.size())
301 return object_error::parse_failed;
302 const char *Start = &StringTable.data()[NValue];
303 Res = StringRef(Start);
304 return object_error::success;
305}
306
Rafael Espindola3acea392014-06-12 21:46:39 +0000307std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
308 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000309 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000310 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000311 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
312 Entry.n_value == 0)
313 Res = UnknownAddressOrSize;
314 else
315 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000316 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000317 MachO::nlist Entry = getSymbolTableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000318 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
319 Entry.n_value == 0)
320 Res = UnknownAddressOrSize;
321 else
322 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000323 }
324 return object_error::success;
325}
326
Rafael Espindola3acea392014-06-12 21:46:39 +0000327std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
328 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000329 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000330 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000331 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000332 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000333 } else {
334 Result = 0;
335 }
336 return object_error::success;
337}
338
Rafael Espindola3acea392014-06-12 21:46:39 +0000339std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
340 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000341 uint64_t BeginOffset;
342 uint64_t EndOffset = 0;
343 uint8_t SectionIndex;
344
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000345 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000346 uint64_t Value;
347 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000348 if (Value == UnknownAddressOrSize) {
349 Result = UnknownAddressOrSize;
350 return object_error::success;
351 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000352
353 BeginOffset = Value;
354
Charles Davis8bdfafd2013-09-01 04:28:48 +0000355 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000356 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000357 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000358 if (flags & SymbolRef::SF_Common)
359 Result = Value;
360 else
361 Result = UnknownAddressOrSize;
362 return object_error::success;
363 }
364 // Unfortunately symbols are unsorted so we need to touch all
365 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000366 for (const SymbolRef &Symbol : symbols()) {
367 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000368 Entry = getSymbolTableEntryBase(this, DRI);
369 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000370 if (Value == UnknownAddressOrSize)
371 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000372 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000373 if (!EndOffset || Value < EndOffset)
374 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000375 }
376 if (!EndOffset) {
377 uint64_t Size;
378 DataRefImpl Sec;
379 Sec.d.a = SectionIndex-1;
380 getSectionSize(Sec, Size);
381 getSectionAddress(Sec, EndOffset);
382 EndOffset += Size;
383 }
384 Result = EndOffset - BeginOffset;
385 return object_error::success;
386}
387
Rafael Espindola3acea392014-06-12 21:46:39 +0000388std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
389 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000391 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000392
393 Res = SymbolRef::ST_Other;
394
395 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000396 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000397 Res = SymbolRef::ST_Debug;
398 return object_error::success;
399 }
400
Charles Davis74ec8b02013-08-27 05:00:13 +0000401 switch (n_type & MachO::N_TYPE) {
402 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000403 Res = SymbolRef::ST_Unknown;
404 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000405 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000406 Res = SymbolRef::ST_Function;
407 break;
408 }
409 return object_error::success;
410}
411
Rafael Espindola20122a42014-01-31 20:57:12 +0000412uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000414
Charles Davis8bdfafd2013-09-01 04:28:48 +0000415 uint8_t MachOType = Entry.n_type;
416 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000417
Rafael Espindola20122a42014-01-31 20:57:12 +0000418 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000419
Charles Davis74ec8b02013-08-27 05:00:13 +0000420 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000421 Result |= SymbolRef::SF_Undefined;
422
Tim Northovereaef0742014-05-30 13:22:59 +0000423 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
424 Result |= SymbolRef::SF_Indirect;
425
Rafael Espindolaa1356322013-11-02 05:03:24 +0000426 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000427 Result |= SymbolRef::SF_FormatSpecific;
428
Charles Davis74ec8b02013-08-27 05:00:13 +0000429 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000430 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000431 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000432 uint64_t Value;
433 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000434 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000435 Result |= SymbolRef::SF_Common;
436 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437 }
438
Charles Davis74ec8b02013-08-27 05:00:13 +0000439 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000440 Result |= SymbolRef::SF_Weak;
441
Charles Davis74ec8b02013-08-27 05:00:13 +0000442 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000443 Result |= SymbolRef::SF_Absolute;
444
Rafael Espindola20122a42014-01-31 20:57:12 +0000445 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000446}
447
Rafael Espindola3acea392014-06-12 21:46:39 +0000448std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
449 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000450 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000451 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000452
453 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000454 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000455 } else {
456 DataRefImpl DRI;
457 DRI.d.a = index - 1;
458 Res = section_iterator(SectionRef(DRI, this));
459 }
460
461 return object_error::success;
462}
463
Rafael Espindola5e812af2014-01-30 02:49:50 +0000464void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000465 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000466}
467
Rafael Espindola3acea392014-06-12 21:46:39 +0000468std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
469 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000470 ArrayRef<char> Raw = getSectionRawName(Sec);
471 Result = parseSegmentOrSectionName(Raw.data());
472 return object_error::success;
473}
474
Rafael Espindola3acea392014-06-12 21:46:39 +0000475std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
476 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000477 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000478 MachO::section_64 Sect = getSection64(Sec);
479 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000480 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000481 MachO::section Sect = getSection(Sec);
482 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000483 }
484 return object_error::success;
485}
486
Rafael Espindola3acea392014-06-12 21:46:39 +0000487std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
488 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000489 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000490 MachO::section_64 Sect = getSection64(Sec);
491 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000492 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000493 MachO::section Sect = getSection(Sec);
494 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000495 }
496
497 return object_error::success;
498}
499
Rafael Espindola3acea392014-06-12 21:46:39 +0000500std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
501 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000502 uint32_t Offset;
503 uint64_t Size;
504
505 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000506 MachO::section_64 Sect = getSection64(Sec);
507 Offset = Sect.offset;
508 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000509 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000510 MachO::section Sect = getSection(Sec);
511 Offset = Sect.offset;
512 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000513 }
514
515 Res = this->getData().substr(Offset, Size);
516 return object_error::success;
517}
518
Rafael Espindola3acea392014-06-12 21:46:39 +0000519std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
520 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000521 uint32_t Align;
522 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000523 MachO::section_64 Sect = getSection64(Sec);
524 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000525 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000526 MachO::section Sect = getSection(Sec);
527 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000528 }
529
530 Res = uint64_t(1) << Align;
531 return object_error::success;
532}
533
Rafael Espindola3acea392014-06-12 21:46:39 +0000534std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
535 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000536 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000537 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000538 return object_error::success;
539}
540
Rafael Espindola3acea392014-06-12 21:46:39 +0000541std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
542 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000543 uint32_t Flags = getSectionFlags(this, Sec);
544 unsigned SectionType = Flags & MachO::SECTION_TYPE;
545 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
546 !(SectionType == MachO::S_ZEROFILL ||
547 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000548 return object_error::success;
549}
550
Rafael Espindola3acea392014-06-12 21:46:39 +0000551std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
552 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000553 uint32_t Flags = getSectionFlags(this, Sec);
554 unsigned SectionType = Flags & MachO::SECTION_TYPE;
555 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
556 (SectionType == MachO::S_ZEROFILL ||
557 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000558 return object_error::success;
559}
560
Rafael Espindola3acea392014-06-12 21:46:39 +0000561std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000562MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindola137faa02013-04-24 15:14:22 +0000563 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000564 // FIXME: Unimplemented.
565 Result = true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000566 return object_error::success;
567}
568
Rafael Espindola3acea392014-06-12 21:46:39 +0000569std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
570 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000571 // FIXME: Unimplemented.
572 Result = false;
573 return object_error::success;
574}
575
Rafael Espindola3acea392014-06-12 21:46:39 +0000576std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
577 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000578 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis74ec8b02013-08-27 05:00:13 +0000579 unsigned SectionType = Flags & MachO::SECTION_TYPE;
580 Res = SectionType == MachO::S_ZEROFILL ||
581 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000582 return object_error::success;
583}
584
Rafael Espindola3acea392014-06-12 21:46:39 +0000585std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
586 bool &Result) const {
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000587 // Consider using the code from isSectionText to look for __const sections.
588 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
589 // to use section attributes to distinguish code from data.
590
591 // FIXME: Unimplemented.
592 Result = false;
593 return object_error::success;
594}
595
Rafael Espindola3acea392014-06-12 21:46:39 +0000596std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
597 DataRefImpl Symb,
598 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000599 SymbolRef::Type ST;
600 this->getSymbolType(Symb, ST);
601 if (ST == SymbolRef::ST_Unknown) {
602 Result = false;
603 return object_error::success;
604 }
605
606 uint64_t SectBegin, SectEnd;
607 getSectionAddress(Sec, SectBegin);
608 getSectionSize(Sec, SectEnd);
609 SectEnd += SectBegin;
610
611 uint64_t SymAddr;
612 getSymbolAddress(Symb, SymAddr);
613 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
614
615 return object_error::success;
616}
617
Rui Ueyamabc654b12013-09-27 21:47:05 +0000618relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000619 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000620 Ret.d.a = Sec.d.a;
621 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000622 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000623}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000624
Rafael Espindola56f976f2013-04-18 18:08:55 +0000625relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000626MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000627 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000628 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000629 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000630 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000631 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000632 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000633 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000634 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000635
Rafael Espindola56f976f2013-04-18 18:08:55 +0000636 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000637 Ret.d.a = Sec.d.a;
638 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000639 return relocation_iterator(RelocationRef(Ret, this));
640}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000641
Rafael Espindola5e812af2014-01-30 02:49:50 +0000642void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000643 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000644}
Owen Anderson171f4852011-10-24 23:20:07 +0000645
Rafael Espindola3acea392014-06-12 21:46:39 +0000646std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
647 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000648 uint64_t Offset;
649 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000650
651 DataRefImpl Sec;
652 Sec.d.a = Rel.d.a;
653 uint64_t SecAddress;
654 getSectionAddress(Sec, SecAddress);
655 Res = SecAddress + Offset;
656 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000657}
658
Rafael Espindola3acea392014-06-12 21:46:39 +0000659std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
660 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000661 assert(getHeader().filetype == MachO::MH_OBJECT &&
662 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000663 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000664 Res = getAnyRelocationAddress(RE);
665 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000666}
667
Rafael Espindola806f0062013-06-05 01:33:53 +0000668symbol_iterator
669MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000670 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000671 if (isRelocationScattered(RE))
672 return symbol_end();
673
Rafael Espindola56f976f2013-04-18 18:08:55 +0000674 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
675 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000676 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000677 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000678
Charles Davis8bdfafd2013-09-01 04:28:48 +0000679 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000680 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000681 sizeof(MachO::nlist_64) :
682 sizeof(MachO::nlist);
683 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000684 DataRefImpl Sym;
685 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000686 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000687}
688
Rafael Espindola3acea392014-06-12 21:46:39 +0000689std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
690 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000691 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000692 Res = getAnyRelocationType(RE);
693 return object_error::success;
694}
695
Rafael Espindola3acea392014-06-12 21:46:39 +0000696std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000697MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
698 SmallVectorImpl<char> &Result) const {
699 StringRef res;
700 uint64_t RType;
701 getRelocationType(Rel, RType);
702
703 unsigned Arch = this->getArch();
704
705 switch (Arch) {
706 case Triple::x86: {
707 static const char *const Table[] = {
708 "GENERIC_RELOC_VANILLA",
709 "GENERIC_RELOC_PAIR",
710 "GENERIC_RELOC_SECTDIFF",
711 "GENERIC_RELOC_PB_LA_PTR",
712 "GENERIC_RELOC_LOCAL_SECTDIFF",
713 "GENERIC_RELOC_TLV" };
714
Eric Christopher13250cb2013-12-06 02:33:38 +0000715 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000716 res = "Unknown";
717 else
718 res = Table[RType];
719 break;
720 }
721 case Triple::x86_64: {
722 static const char *const Table[] = {
723 "X86_64_RELOC_UNSIGNED",
724 "X86_64_RELOC_SIGNED",
725 "X86_64_RELOC_BRANCH",
726 "X86_64_RELOC_GOT_LOAD",
727 "X86_64_RELOC_GOT",
728 "X86_64_RELOC_SUBTRACTOR",
729 "X86_64_RELOC_SIGNED_1",
730 "X86_64_RELOC_SIGNED_2",
731 "X86_64_RELOC_SIGNED_4",
732 "X86_64_RELOC_TLV" };
733
734 if (RType > 9)
735 res = "Unknown";
736 else
737 res = Table[RType];
738 break;
739 }
740 case Triple::arm: {
741 static const char *const Table[] = {
742 "ARM_RELOC_VANILLA",
743 "ARM_RELOC_PAIR",
744 "ARM_RELOC_SECTDIFF",
745 "ARM_RELOC_LOCAL_SECTDIFF",
746 "ARM_RELOC_PB_LA_PTR",
747 "ARM_RELOC_BR24",
748 "ARM_THUMB_RELOC_BR22",
749 "ARM_THUMB_32BIT_BRANCH",
750 "ARM_RELOC_HALF",
751 "ARM_RELOC_HALF_SECTDIFF" };
752
753 if (RType > 9)
754 res = "Unknown";
755 else
756 res = Table[RType];
757 break;
758 }
Tim Northover00ed9962014-03-29 10:18:08 +0000759 case Triple::aarch64: {
760 static const char *const Table[] = {
761 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
762 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
763 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
764 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
765 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
766 "ARM64_RELOC_ADDEND"
767 };
768
769 if (RType >= array_lengthof(Table))
770 res = "Unknown";
771 else
772 res = Table[RType];
773 break;
774 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000775 case Triple::ppc: {
776 static const char *const Table[] = {
777 "PPC_RELOC_VANILLA",
778 "PPC_RELOC_PAIR",
779 "PPC_RELOC_BR14",
780 "PPC_RELOC_BR24",
781 "PPC_RELOC_HI16",
782 "PPC_RELOC_LO16",
783 "PPC_RELOC_HA16",
784 "PPC_RELOC_LO14",
785 "PPC_RELOC_SECTDIFF",
786 "PPC_RELOC_PB_LA_PTR",
787 "PPC_RELOC_HI16_SECTDIFF",
788 "PPC_RELOC_LO16_SECTDIFF",
789 "PPC_RELOC_HA16_SECTDIFF",
790 "PPC_RELOC_JBSR",
791 "PPC_RELOC_LO14_SECTDIFF",
792 "PPC_RELOC_LOCAL_SECTDIFF" };
793
Eric Christopher13250cb2013-12-06 02:33:38 +0000794 if (RType > 15)
795 res = "Unknown";
796 else
797 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000798 break;
799 }
800 case Triple::UnknownArch:
801 res = "Unknown";
802 break;
803 }
804 Result.append(res.begin(), res.end());
805 return object_error::success;
806}
807
Rafael Espindola3acea392014-06-12 21:46:39 +0000808std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000809MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000810 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000811 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000812
Rafael Espindola56f976f2013-04-18 18:08:55 +0000813 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000814
Alp Tokere69170a2014-06-26 22:52:05 +0000815 std::string fmtbuf;
816 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000817 unsigned Type = this->getAnyRelocationType(RE);
818 bool IsPCRel = this->getAnyRelocationPCRel(RE);
819
820 // Determine any addends that should be displayed with the relocation.
821 // These require decoding the relocation type, which is triple-specific.
822
823 // X86_64 has entirely custom relocation types.
824 if (Arch == Triple::x86_64) {
825 bool isPCRel = getAnyRelocationPCRel(RE);
826
827 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000828 case MachO::X86_64_RELOC_GOT_LOAD:
829 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000830 printRelocationTargetName(this, RE, fmt);
831 fmt << "@GOT";
832 if (isPCRel) fmt << "PCREL";
833 break;
834 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000835 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000836 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000837 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000838 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000839
Charles Davis8bdfafd2013-09-01 04:28:48 +0000840 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000841 // X86_64_RELOC_UNSIGNED.
842 // NOTE: Scattered relocations don't exist on x86_64.
843 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000844 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000845 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
846 "X86_64_RELOC_SUBTRACTOR.");
847
Charles Davis8bdfafd2013-09-01 04:28:48 +0000848 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
849 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000850 printRelocationTargetName(this, RENext, fmt);
851 fmt << "-";
852 printRelocationTargetName(this, RE, fmt);
853 break;
854 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000855 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000856 printRelocationTargetName(this, RE, fmt);
857 fmt << "@TLV";
858 if (isPCRel) fmt << "P";
859 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000860 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000861 printRelocationTargetName(this, RE, fmt);
862 fmt << "-1";
863 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000864 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000865 printRelocationTargetName(this, RE, fmt);
866 fmt << "-2";
867 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000868 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000869 printRelocationTargetName(this, RE, fmt);
870 fmt << "-4";
871 break;
872 default:
873 printRelocationTargetName(this, RE, fmt);
874 break;
875 }
876 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000877 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
878 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000879 // Generic relocation types...
880 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000881 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000882 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000883 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000884 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000885 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000886 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000887
888 // X86 sect diff's must be followed by a relocation of type
889 // GENERIC_RELOC_PAIR.
890 unsigned RType = getAnyRelocationType(RENext);
891
Charles Davis8bdfafd2013-09-01 04:28:48 +0000892 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000893 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
894 "GENERIC_RELOC_SECTDIFF.");
895
896 printRelocationTargetName(this, RE, fmt);
897 fmt << "-";
898 printRelocationTargetName(this, RENext, fmt);
899 break;
900 }
901 }
902
David Fangb88cdf62013-08-08 20:14:40 +0000903 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000904 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000905 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000906 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000907 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000908 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000909
910 // X86 sect diff's must be followed by a relocation of type
911 // GENERIC_RELOC_PAIR.
912 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000913 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000914 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
915 "GENERIC_RELOC_LOCAL_SECTDIFF.");
916
917 printRelocationTargetName(this, RE, fmt);
918 fmt << "-";
919 printRelocationTargetName(this, RENext, fmt);
920 break;
921 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000922 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000923 printRelocationTargetName(this, RE, fmt);
924 fmt << "@TLV";
925 if (IsPCRel) fmt << "P";
926 break;
927 }
928 default:
929 printRelocationTargetName(this, RE, fmt);
930 }
931 } else { // ARM-specific relocations
932 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000933 case MachO::ARM_RELOC_HALF:
934 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000935 // Half relocations steal a bit from the length field to encode
936 // whether this is an upper16 or a lower16 relocation.
937 bool isUpper = getAnyRelocationLength(RE) >> 1;
938
939 if (isUpper)
940 fmt << ":upper16:(";
941 else
942 fmt << ":lower16:(";
943 printRelocationTargetName(this, RE, fmt);
944
945 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000946 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000947 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000948
949 // ARM half relocs must be followed by a relocation of type
950 // ARM_RELOC_PAIR.
951 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000952 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000953 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000954 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000955
956 // NOTE: The half of the target virtual address is stashed in the
957 // address field of the secondary relocation, but we can't reverse
958 // engineer the constant offset from it without decoding the movw/movt
959 // instruction to find the other half in its immediate field.
960
961 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
962 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000963 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000964 fmt << "-";
965 printRelocationTargetName(this, RENext, fmt);
966 }
967
968 fmt << ")";
969 break;
970 }
971 default: {
972 printRelocationTargetName(this, RE, fmt);
973 }
974 }
975 }
976 } else
977 printRelocationTargetName(this, RE, fmt);
978
Alp Tokere69170a2014-06-26 22:52:05 +0000979 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000980 Result.append(fmtbuf.begin(), fmtbuf.end());
981 return object_error::success;
982}
983
Rafael Espindola3acea392014-06-12 21:46:39 +0000984std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
985 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000986 unsigned Arch = getArch();
987 uint64_t Type;
988 getRelocationType(Rel, Type);
989
990 Result = false;
991
992 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
993 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000994 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000995 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000996 } else if (Arch == Triple::x86_64) {
997 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000998 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000999 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001000 DataRefImpl RelPrev = Rel;
1001 RelPrev.d.a--;
1002 uint64_t PrevType;
1003 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001004 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001005 Result = true;
1006 }
1007 }
1008
1009 return object_error::success;
1010}
1011
Rafael Espindola3acea392014-06-12 21:46:39 +00001012std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1013 LibraryRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001014 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1015}
1016
Rafael Espindola3acea392014-06-12 21:46:39 +00001017std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1018 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001019 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1020}
1021
Kevin Enderby980b2582014-06-05 21:21:57 +00001022//
1023// guessLibraryShortName() is passed a name of a dynamic library and returns a
1024// guess on what the short name is. Then name is returned as a substring of the
1025// StringRef Name passed in. The name of the dynamic library is recognized as
1026// a framework if it has one of the two following forms:
1027// Foo.framework/Versions/A/Foo
1028// Foo.framework/Foo
1029// Where A and Foo can be any string. And may contain a trailing suffix
1030// starting with an underbar. If the Name is recognized as a framework then
1031// isFramework is set to true else it is set to false. If the Name has a
1032// suffix then Suffix is set to the substring in Name that contains the suffix
1033// else it is set to a NULL StringRef.
1034//
1035// The Name of the dynamic library is recognized as a library name if it has
1036// one of the two following forms:
1037// libFoo.A.dylib
1038// libFoo.dylib
1039// The library may have a suffix trailing the name Foo of the form:
1040// libFoo_profile.A.dylib
1041// libFoo_profile.dylib
1042//
1043// The Name of the dynamic library is also recognized as a library name if it
1044// has the following form:
1045// Foo.qtx
1046//
1047// If the Name of the dynamic library is none of the forms above then a NULL
1048// StringRef is returned.
1049//
1050StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1051 bool &isFramework,
1052 StringRef &Suffix) {
1053 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1054 size_t a, b, c, d, Idx;
1055
1056 isFramework = false;
1057 Suffix = StringRef();
1058
1059 // Pull off the last component and make Foo point to it
1060 a = Name.rfind('/');
1061 if (a == Name.npos || a == 0)
1062 goto guess_library;
1063 Foo = Name.slice(a+1, Name.npos);
1064
1065 // Look for a suffix starting with a '_'
1066 Idx = Foo.rfind('_');
1067 if (Idx != Foo.npos && Foo.size() >= 2) {
1068 Suffix = Foo.slice(Idx, Foo.npos);
1069 Foo = Foo.slice(0, Idx);
1070 }
1071
1072 // First look for the form Foo.framework/Foo
1073 b = Name.rfind('/', a);
1074 if (b == Name.npos)
1075 Idx = 0;
1076 else
1077 Idx = b+1;
1078 F = Name.slice(Idx, Idx + Foo.size());
1079 DotFramework = Name.slice(Idx + Foo.size(),
1080 Idx + Foo.size() + sizeof(".framework/")-1);
1081 if (F == Foo && DotFramework == ".framework/") {
1082 isFramework = true;
1083 return Foo;
1084 }
1085
1086 // Next look for the form Foo.framework/Versions/A/Foo
1087 if (b == Name.npos)
1088 goto guess_library;
1089 c = Name.rfind('/', b);
1090 if (c == Name.npos || c == 0)
1091 goto guess_library;
1092 V = Name.slice(c+1, Name.npos);
1093 if (!V.startswith("Versions/"))
1094 goto guess_library;
1095 d = Name.rfind('/', c);
1096 if (d == Name.npos)
1097 Idx = 0;
1098 else
1099 Idx = d+1;
1100 F = Name.slice(Idx, Idx + Foo.size());
1101 DotFramework = Name.slice(Idx + Foo.size(),
1102 Idx + Foo.size() + sizeof(".framework/")-1);
1103 if (F == Foo && DotFramework == ".framework/") {
1104 isFramework = true;
1105 return Foo;
1106 }
1107
1108guess_library:
1109 // pull off the suffix after the "." and make a point to it
1110 a = Name.rfind('.');
1111 if (a == Name.npos || a == 0)
1112 return StringRef();
1113 Dylib = Name.slice(a, Name.npos);
1114 if (Dylib != ".dylib")
1115 goto guess_qtx;
1116
1117 // First pull off the version letter for the form Foo.A.dylib if any.
1118 if (a >= 3) {
1119 Dot = Name.slice(a-2, a-1);
1120 if (Dot == ".")
1121 a = a - 2;
1122 }
1123
1124 b = Name.rfind('/', a);
1125 if (b == Name.npos)
1126 b = 0;
1127 else
1128 b = b+1;
1129 // ignore any suffix after an underbar like Foo_profile.A.dylib
1130 Idx = Name.find('_', b);
1131 if (Idx != Name.npos && Idx != b) {
1132 Lib = Name.slice(b, Idx);
1133 Suffix = Name.slice(Idx, a);
1134 }
1135 else
1136 Lib = Name.slice(b, a);
1137 // There are incorrect library names of the form:
1138 // libATS.A_profile.dylib so check for these.
1139 if (Lib.size() >= 3) {
1140 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1141 if (Dot == ".")
1142 Lib = Lib.slice(0, Lib.size()-2);
1143 }
1144 return Lib;
1145
1146guess_qtx:
1147 Qtx = Name.slice(a, Name.npos);
1148 if (Qtx != ".qtx")
1149 return StringRef();
1150 b = Name.rfind('/', a);
1151 if (b == Name.npos)
1152 Lib = Name.slice(0, a);
1153 else
1154 Lib = Name.slice(b+1, a);
1155 // There are library names of the form: QT.A.qtx so check for these.
1156 if (Lib.size() >= 3) {
1157 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1158 if (Dot == ".")
1159 Lib = Lib.slice(0, Lib.size()-2);
1160 }
1161 return Lib;
1162}
1163
1164// getLibraryShortNameByIndex() is used to get the short name of the library
1165// for an undefined symbol in a linked Mach-O binary that was linked with the
1166// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1167// It is passed the index (0 - based) of the library as translated from
1168// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001169std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1170 StringRef &Res) {
Kevin Enderby980b2582014-06-05 21:21:57 +00001171 if (Index >= Libraries.size())
1172 return object_error::parse_failed;
1173
1174 MachO::dylib_command D =
1175 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1176 if (D.dylib.name >= D.cmdsize)
1177 return object_error::parse_failed;
1178
1179 // If the cache of LibrariesShortNames is not built up do that first for
1180 // all the Libraries.
1181 if (LibrariesShortNames.size() == 0) {
1182 for (unsigned i = 0; i < Libraries.size(); i++) {
1183 MachO::dylib_command D =
1184 getStruct<MachO::dylib_command>(this, Libraries[i]);
1185 if (D.dylib.name >= D.cmdsize) {
1186 LibrariesShortNames.push_back(StringRef());
1187 continue;
1188 }
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001189 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001190 StringRef Name = StringRef(P);
1191 StringRef Suffix;
1192 bool isFramework;
1193 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1194 if (shortName == StringRef())
1195 LibrariesShortNames.push_back(Name);
1196 else
1197 LibrariesShortNames.push_back(shortName);
1198 }
1199 }
1200
1201 Res = LibrariesShortNames[Index];
1202 return object_error::success;
1203}
1204
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001205basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001206 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001207}
1208
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001209basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001210 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001211 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001212 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001213
Charles Davis8bdfafd2013-09-01 04:28:48 +00001214 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001215 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001216 sizeof(MachO::nlist_64) :
1217 sizeof(MachO::nlist);
1218 unsigned Offset = Symtab.symoff +
1219 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001220 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001221 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001222}
1223
Lang Hames36072da2014-05-12 21:39:59 +00001224basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1225 DataRefImpl DRI;
1226 if (!SymtabLoadCmd)
1227 return basic_symbol_iterator(SymbolRef(DRI, this));
1228
1229 MachO::symtab_command Symtab = getSymtabLoadCommand();
1230 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1231 unsigned SymbolTableEntrySize =
1232 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1233 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1234 DRI.p += Index * SymbolTableEntrySize;
1235 return basic_symbol_iterator(SymbolRef(DRI, this));
1236}
1237
Rafael Espindolab5155a52014-02-10 20:24:04 +00001238section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001239 DataRefImpl DRI;
1240 return section_iterator(SectionRef(DRI, this));
1241}
1242
Rafael Espindolab5155a52014-02-10 20:24:04 +00001243section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001244 DataRefImpl DRI;
1245 DRI.d.a = Sections.size();
1246 return section_iterator(SectionRef(DRI, this));
1247}
1248
Rafael Espindolab5155a52014-02-10 20:24:04 +00001249library_iterator MachOObjectFile::needed_library_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001250 // TODO: implement
1251 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1252}
1253
Rafael Espindolab5155a52014-02-10 20:24:04 +00001254library_iterator MachOObjectFile::needed_library_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001255 // TODO: implement
1256 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1257}
1258
1259uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001260 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001261}
1262
Rafael Espindola56f976f2013-04-18 18:08:55 +00001263StringRef MachOObjectFile::getFileFormatName() const {
1264 unsigned CPUType = getCPUType(this);
1265 if (!is64Bit()) {
1266 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001267 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001268 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001269 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001270 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001271 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001272 return "Mach-O 32-bit ppc";
1273 default:
Charles Davis74ec8b02013-08-27 05:00:13 +00001274 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindola56f976f2013-04-18 18:08:55 +00001275 "64-bit object file when we're not 64-bit?");
1276 return "Mach-O 32-bit unknown";
1277 }
1278 }
1279
1280 // Make sure the cpu type has the correct mask.
Charles Davis74ec8b02013-08-27 05:00:13 +00001281 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1282 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher1d62c252013-07-22 22:25:07 +00001283 "32-bit object file when we're 64-bit?");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001284
1285 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001286 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001287 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001288 case llvm::MachO::CPU_TYPE_ARM64:
1289 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001290 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001291 return "Mach-O 64-bit ppc64";
1292 default:
1293 return "Mach-O 64-bit unknown";
1294 }
1295}
1296
Alexey Samsonove6388e62013-06-18 15:03:28 +00001297Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1298 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001299 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001300 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001301 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001302 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001303 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001304 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001305 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001306 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001307 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001308 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001309 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001310 return Triple::ppc64;
1311 default:
1312 return Triple::UnknownArch;
1313 }
1314}
1315
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001316Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
1317 switch (CPUType) {
1318 case MachO::CPU_TYPE_I386:
1319 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1320 case MachO::CPU_SUBTYPE_I386_ALL:
1321 return Triple("i386-apple-darwin");
1322 default:
1323 return Triple();
1324 }
1325 case MachO::CPU_TYPE_X86_64:
1326 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1327 case MachO::CPU_SUBTYPE_X86_64_ALL:
1328 return Triple("x86_64-apple-darwin");
1329 case MachO::CPU_SUBTYPE_X86_64_H:
1330 return Triple("x86_64h-apple-darwin");
1331 default:
1332 return Triple();
1333 }
1334 case MachO::CPU_TYPE_ARM:
1335 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1336 case MachO::CPU_SUBTYPE_ARM_V4T:
1337 return Triple("armv4t-apple-darwin");
1338 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1339 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001340 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1341 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001342 case MachO::CPU_SUBTYPE_ARM_V6:
1343 return Triple("armv6-apple-darwin");
1344 case MachO::CPU_SUBTYPE_ARM_V6M:
1345 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001346 case MachO::CPU_SUBTYPE_ARM_V7:
1347 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001348 case MachO::CPU_SUBTYPE_ARM_V7EM:
1349 return Triple("armv7em-apple-darwin");
1350 case MachO::CPU_SUBTYPE_ARM_V7K:
1351 return Triple("armv7k-apple-darwin");
1352 case MachO::CPU_SUBTYPE_ARM_V7M:
1353 return Triple("armv7m-apple-darwin");
1354 case MachO::CPU_SUBTYPE_ARM_V7S:
1355 return Triple("armv7s-apple-darwin");
1356 default:
1357 return Triple();
1358 }
1359 case MachO::CPU_TYPE_ARM64:
1360 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1361 case MachO::CPU_SUBTYPE_ARM64_ALL:
1362 return Triple("arm64-apple-darwin");
1363 default:
1364 return Triple();
1365 }
1366 case MachO::CPU_TYPE_POWERPC:
1367 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1368 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1369 return Triple("ppc-apple-darwin");
1370 default:
1371 return Triple();
1372 }
1373 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001374 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001375 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1376 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001377 default:
1378 return Triple();
1379 }
1380 default:
1381 return Triple();
1382 }
1383}
1384
1385Triple MachOObjectFile::getHostArch() {
1386 return Triple(sys::getDefaultTargetTriple());
1387}
1388
Rafael Espindola72318b42014-08-08 16:30:17 +00001389bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1390 return StringSwitch<bool>(ArchFlag)
1391 .Case("i386", true)
1392 .Case("x86_64", true)
1393 .Case("x86_64h", true)
1394 .Case("armv4t", true)
1395 .Case("arm", true)
1396 .Case("armv5e", true)
1397 .Case("armv6", true)
1398 .Case("armv6m", true)
1399 .Case("armv7em", true)
1400 .Case("armv7k", true)
1401 .Case("armv7m", true)
1402 .Case("armv7s", true)
1403 .Case("arm64", true)
1404 .Case("ppc", true)
1405 .Case("ppc64", true)
1406 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001407}
1408
Alexey Samsonove6388e62013-06-18 15:03:28 +00001409unsigned MachOObjectFile::getArch() const {
1410 return getArch(getCPUType(this));
1411}
1412
Rafael Espindola56f976f2013-04-18 18:08:55 +00001413StringRef MachOObjectFile::getLoadName() const {
1414 // TODO: Implement
Charles Davis1827bd82013-08-27 05:38:30 +00001415 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001416}
1417
Rui Ueyamabc654b12013-09-27 21:47:05 +00001418relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001419 DataRefImpl DRI;
1420 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001421 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001422}
1423
Rui Ueyamabc654b12013-09-27 21:47:05 +00001424relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001425 DataRefImpl DRI;
1426 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001427 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001428}
1429
Kevin Enderby273ae012013-06-06 17:20:50 +00001430dice_iterator MachOObjectFile::begin_dices() const {
1431 DataRefImpl DRI;
1432 if (!DataInCodeLoadCmd)
1433 return dice_iterator(DiceRef(DRI, this));
1434
Charles Davis8bdfafd2013-09-01 04:28:48 +00001435 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1436 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001437 return dice_iterator(DiceRef(DRI, this));
1438}
1439
1440dice_iterator MachOObjectFile::end_dices() const {
1441 DataRefImpl DRI;
1442 if (!DataInCodeLoadCmd)
1443 return dice_iterator(DiceRef(DRI, this));
1444
Charles Davis8bdfafd2013-09-01 04:28:48 +00001445 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1446 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001447 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1448 return dice_iterator(DiceRef(DRI, this));
1449}
1450
Rafael Espindola56f976f2013-04-18 18:08:55 +00001451StringRef
1452MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1453 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1454 return parseSegmentOrSectionName(Raw.data());
1455}
1456
1457ArrayRef<char>
1458MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001459 const section_base *Base =
1460 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1461 return ArrayRef<char>(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001462}
1463
1464ArrayRef<char>
1465MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001466 const section_base *Base =
1467 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1468 return ArrayRef<char>(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001469}
1470
1471bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001472MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001473 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001474 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001475 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001476 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001477}
1478
Eric Christopher1d62c252013-07-22 22:25:07 +00001479unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001480 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001481 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001482 return RE.r_word1 & 0xffffff;
1483 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001484}
1485
Eric Christopher1d62c252013-07-22 22:25:07 +00001486bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001487 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001488 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001489 return (RE.r_word1 >> 27) & 1;
1490 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001491}
1492
Eric Christopher1d62c252013-07-22 22:25:07 +00001493bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001494 const MachO::any_relocation_info &RE) const {
1495 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001496}
1497
Eric Christopher1d62c252013-07-22 22:25:07 +00001498uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001499 const MachO::any_relocation_info &RE) const {
1500 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001501}
1502
Eric Christopher1d62c252013-07-22 22:25:07 +00001503unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001504 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001505 if (isRelocationScattered(RE))
1506 return getScatteredRelocationAddress(RE);
1507 return getPlainRelocationAddress(RE);
1508}
1509
Charles Davis8bdfafd2013-09-01 04:28:48 +00001510unsigned MachOObjectFile::getAnyRelocationPCRel(
1511 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001512 if (isRelocationScattered(RE))
1513 return getScatteredRelocationPCRel(this, RE);
1514 return getPlainRelocationPCRel(this, RE);
1515}
1516
Eric Christopher1d62c252013-07-22 22:25:07 +00001517unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001518 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001519 if (isRelocationScattered(RE))
1520 return getScatteredRelocationLength(RE);
1521 return getPlainRelocationLength(this, RE);
1522}
1523
1524unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00001525MachOObjectFile::getAnyRelocationType(
1526 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001527 if (isRelocationScattered(RE))
1528 return getScatteredRelocationType(RE);
1529 return getPlainRelocationType(this, RE);
1530}
1531
Rafael Espindola52501032013-04-30 15:40:54 +00001532SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00001533MachOObjectFile::getRelocationSection(
1534 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00001535 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00001536 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00001537 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1538 DataRefImpl DRI;
1539 DRI.d.a = SecNum;
1540 return SectionRef(DRI, this);
1541}
1542
Rafael Espindola56f976f2013-04-18 18:08:55 +00001543MachOObjectFile::LoadCommandInfo
1544MachOObjectFile::getFirstLoadCommandInfo() const {
1545 MachOObjectFile::LoadCommandInfo Load;
1546
Charles Davis8bdfafd2013-09-01 04:28:48 +00001547 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1548 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001549 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001550 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001551 return Load;
1552}
1553
1554MachOObjectFile::LoadCommandInfo
1555MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1556 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001557 Next.Ptr = L.Ptr + L.C.cmdsize;
1558 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001559 return Next;
1560}
1561
Charles Davis8bdfafd2013-09-01 04:28:48 +00001562MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1563 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001564}
1565
Charles Davis8bdfafd2013-09-01 04:28:48 +00001566MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1567 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001568}
1569
Charles Davis8bdfafd2013-09-01 04:28:48 +00001570MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00001571 unsigned Index) const {
1572 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001573 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001574}
1575
Charles Davis8bdfafd2013-09-01 04:28:48 +00001576MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1577 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001578 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001579 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001580}
1581
Charles Davis8bdfafd2013-09-01 04:28:48 +00001582MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00001583MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001584 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001585 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001586}
1587
Charles Davis8bdfafd2013-09-01 04:28:48 +00001588MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00001589MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001590 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001591 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001592}
1593
Charles Davis8bdfafd2013-09-01 04:28:48 +00001594MachO::linkedit_data_command
1595MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1596 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001597}
1598
Charles Davis8bdfafd2013-09-01 04:28:48 +00001599MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00001600MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001601 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001602}
1603
Charles Davis8bdfafd2013-09-01 04:28:48 +00001604MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00001605MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001606 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001607}
1608
Charles Davis8bdfafd2013-09-01 04:28:48 +00001609MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00001610MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001611 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001612}
1613
Jim Grosbach448334a2014-03-18 22:09:05 +00001614MachO::version_min_command
1615MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1616 return getStruct<MachO::version_min_command>(this, L.Ptr);
1617}
1618
Tim Northover8f9590b2014-06-30 14:40:57 +00001619MachO::dylib_command
1620MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
1621 return getStruct<MachO::dylib_command>(this, L.Ptr);
1622}
1623
1624
Charles Davis8bdfafd2013-09-01 04:28:48 +00001625MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00001626MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001627 DataRefImpl Sec;
1628 Sec.d.a = Rel.d.a;
1629 uint32_t Offset;
1630 if (is64Bit()) {
1631 MachO::section_64 Sect = getSection64(Sec);
1632 Offset = Sect.reloff;
1633 } else {
1634 MachO::section Sect = getSection(Sec);
1635 Offset = Sect.reloff;
1636 }
1637
1638 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
1639 getPtr(this, Offset)) + Rel.d.b;
1640 return getStruct<MachO::any_relocation_info>(
1641 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001642}
1643
Charles Davis8bdfafd2013-09-01 04:28:48 +00001644MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00001645MachOObjectFile::getDice(DataRefImpl Rel) const {
1646 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001647 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00001648}
1649
Charles Davis8bdfafd2013-09-01 04:28:48 +00001650MachO::mach_header MachOObjectFile::getHeader() const {
1651 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001652}
1653
Charles Davis8bdfafd2013-09-01 04:28:48 +00001654MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1655 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001656}
1657
Charles Davis8bdfafd2013-09-01 04:28:48 +00001658uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1659 const MachO::dysymtab_command &DLC,
1660 unsigned Index) const {
1661 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1662 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001663}
1664
Charles Davis8bdfafd2013-09-01 04:28:48 +00001665MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00001666MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1667 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001668 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1669 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001670}
1671
Charles Davis8bdfafd2013-09-01 04:28:48 +00001672MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1673 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001674}
1675
Charles Davis8bdfafd2013-09-01 04:28:48 +00001676MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1677 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001678}
1679
Charles Davis8bdfafd2013-09-01 04:28:48 +00001680MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00001681MachOObjectFile::getDataInCodeLoadCommand() const {
1682 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00001683 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00001684
1685 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001686 MachO::linkedit_data_command Cmd;
1687 Cmd.cmd = MachO::LC_DATA_IN_CODE;
1688 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1689 Cmd.dataoff = 0;
1690 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00001691 return Cmd;
1692}
1693
Rafael Espindola6e040c02013-04-26 20:07:33 +00001694StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001695 MachO::symtab_command S = getSymtabLoadCommand();
1696 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001697}
1698
Rafael Espindola56f976f2013-04-18 18:08:55 +00001699bool MachOObjectFile::is64Bit() const {
1700 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00001701 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001702}
1703
1704void MachOObjectFile::ReadULEB128s(uint64_t Index,
1705 SmallVectorImpl<uint64_t> &Out) const {
1706 DataExtractor extractor(ObjectFile::getData(), true, 0);
1707
1708 uint32_t offset = Index;
1709 uint64_t data = 0;
1710 while (uint64_t delta = extractor.getULEB128(&offset)) {
1711 data += delta;
1712 Out.push_back(data);
1713 }
1714}
1715
Rafael Espindola437b0d52014-07-31 03:12:45 +00001716ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola6304e942014-06-23 22:00:37 +00001717ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001718 StringRef Magic = Buffer->getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00001719 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00001720 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001721 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola2e60ca92014-06-24 13:56:32 +00001722 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001723 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola2e60ca92014-06-24 13:56:32 +00001724 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001725 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola2e60ca92014-06-24 13:56:32 +00001726 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001727 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola2e60ca92014-06-24 13:56:32 +00001728 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00001729 else
Rafael Espindola692410e2014-01-21 23:06:54 +00001730 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001731
Rafael Espindola692410e2014-01-21 23:06:54 +00001732 if (EC)
1733 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00001734 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001735}
1736