blob: 746fd7391bc023ea14737b87dadafe85c11d3023 [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 Espindola48af1c22014-08-19 18:44:46 +0000225MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
226 bool Is64bits, std::error_code &EC)
227 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000228 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
229 DataInCodeLoadCmd(nullptr) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000230 uint32_t LoadCommandCount = this->getHeader().ncmds;
231 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
232 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000233
234 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000235 for (unsigned I = 0; ; ++I) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000236 if (Load.C.cmd == MachO::LC_SYMTAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000237 assert(!SymtabLoadCmd && "Multiple symbol tables");
238 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000239 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000240 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
241 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000242 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Kevin Enderby273ae012013-06-06 17:20:50 +0000243 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
244 DataInCodeLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000245 } else if (Load.C.cmd == SegmentLoadType) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000246 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
247 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000248 const char *Sec = getSectionPtr(this, Load, J);
249 Sections.push_back(Sec);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000250 }
Kevin Enderby980b2582014-06-05 21:21:57 +0000251 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
252 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
253 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
254 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
255 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
256 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000257 }
Rafael Espindolafeef8c22013-04-19 11:36:47 +0000258
259 if (I == LoadCommandCount - 1)
260 break;
261 else
262 Load = getNextLoadCommandInfo(Load);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000263 }
264}
265
Rafael Espindola5e812af2014-01-30 02:49:50 +0000266void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000267 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000268 sizeof(MachO::nlist_64) :
269 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000270 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000271}
272
Rafael Espindola3acea392014-06-12 21:46:39 +0000273std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
274 StringRef &Res) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000275 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000276 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000277 const char *Start = &StringTable.data()[Entry.n_strx];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000278 Res = StringRef(Start);
279 return object_error::success;
280}
281
Kevin Enderby980b2582014-06-05 21:21:57 +0000282// getIndirectName() returns the name of the alias'ed symbol who's string table
283// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000284std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
285 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000286 StringRef StringTable = getStringTableData();
287 uint64_t NValue;
288 if (is64Bit()) {
289 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
290 NValue = Entry.n_value;
291 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
292 return object_error::parse_failed;
293 } else {
294 MachO::nlist Entry = getSymbolTableEntry(Symb);
295 NValue = Entry.n_value;
296 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
297 return object_error::parse_failed;
298 }
299 if (NValue >= StringTable.size())
300 return object_error::parse_failed;
301 const char *Start = &StringTable.data()[NValue];
302 Res = StringRef(Start);
303 return object_error::success;
304}
305
Rafael Espindola3acea392014-06-12 21:46:39 +0000306std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
307 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000308 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000309 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000310 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
311 Entry.n_value == 0)
312 Res = UnknownAddressOrSize;
313 else
314 Res = Entry.n_value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000315 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000316 MachO::nlist Entry = getSymbolTableEntry(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 }
323 return object_error::success;
324}
325
Rafael Espindola3acea392014-06-12 21:46:39 +0000326std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
327 uint32_t &Result) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000328 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000329 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000330 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000331 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000332 } else {
333 Result = 0;
334 }
335 return object_error::success;
336}
337
Rafael Espindola3acea392014-06-12 21:46:39 +0000338std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
339 uint64_t &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000340 uint64_t BeginOffset;
341 uint64_t EndOffset = 0;
342 uint8_t SectionIndex;
343
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000344 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000345 uint64_t Value;
346 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000347 if (Value == UnknownAddressOrSize) {
348 Result = UnknownAddressOrSize;
349 return object_error::success;
350 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000351
352 BeginOffset = Value;
353
Charles Davis8bdfafd2013-09-01 04:28:48 +0000354 SectionIndex = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000355 if (!SectionIndex) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000356 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000357 if (flags & SymbolRef::SF_Common)
358 Result = Value;
359 else
360 Result = UnknownAddressOrSize;
361 return object_error::success;
362 }
363 // Unfortunately symbols are unsorted so we need to touch all
364 // symbols from load command
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000365 for (const SymbolRef &Symbol : symbols()) {
366 DataRefImpl DRI = Symbol.getRawDataRefImpl();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000367 Entry = getSymbolTableEntryBase(this, DRI);
368 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000369 if (Value == UnknownAddressOrSize)
370 continue;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000371 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000372 if (!EndOffset || Value < EndOffset)
373 EndOffset = Value;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000374 }
375 if (!EndOffset) {
376 uint64_t Size;
377 DataRefImpl Sec;
378 Sec.d.a = SectionIndex-1;
379 getSectionSize(Sec, Size);
380 getSectionAddress(Sec, EndOffset);
381 EndOffset += Size;
382 }
383 Result = EndOffset - BeginOffset;
384 return object_error::success;
385}
386
Rafael Espindola3acea392014-06-12 21:46:39 +0000387std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
388 SymbolRef::Type &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000389 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000390 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000391
392 Res = SymbolRef::ST_Other;
393
394 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davis74ec8b02013-08-27 05:00:13 +0000395 if (n_type & MachO::N_STAB) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000396 Res = SymbolRef::ST_Debug;
397 return object_error::success;
398 }
399
Charles Davis74ec8b02013-08-27 05:00:13 +0000400 switch (n_type & MachO::N_TYPE) {
401 case MachO::N_UNDF :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000402 Res = SymbolRef::ST_Unknown;
403 break;
Charles Davis74ec8b02013-08-27 05:00:13 +0000404 case MachO::N_SECT :
Rafael Espindola56f976f2013-04-18 18:08:55 +0000405 Res = SymbolRef::ST_Function;
406 break;
407 }
408 return object_error::success;
409}
410
Rafael Espindola20122a42014-01-31 20:57:12 +0000411uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000412 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000413
Charles Davis8bdfafd2013-09-01 04:28:48 +0000414 uint8_t MachOType = Entry.n_type;
415 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000416
Rafael Espindola20122a42014-01-31 20:57:12 +0000417 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000418
Charles Davis74ec8b02013-08-27 05:00:13 +0000419 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000420 Result |= SymbolRef::SF_Undefined;
421
Tim Northovereaef0742014-05-30 13:22:59 +0000422 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
423 Result |= SymbolRef::SF_Indirect;
424
Rafael Espindolaa1356322013-11-02 05:03:24 +0000425 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000426 Result |= SymbolRef::SF_FormatSpecific;
427
Charles Davis74ec8b02013-08-27 05:00:13 +0000428 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000429 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000430 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000431 uint64_t Value;
432 getSymbolAddress(DRI, Value);
Kevin Enderby1b985af2014-05-20 23:04:47 +0000433 if (Value && Value != UnknownAddressOrSize)
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000434 Result |= SymbolRef::SF_Common;
435 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000436 }
437
Charles Davis74ec8b02013-08-27 05:00:13 +0000438 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000439 Result |= SymbolRef::SF_Weak;
440
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000441 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
442 Result |= SymbolRef::SF_Thumb;
443
Charles Davis74ec8b02013-08-27 05:00:13 +0000444 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000445 Result |= SymbolRef::SF_Absolute;
446
Rafael Espindola20122a42014-01-31 20:57:12 +0000447 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000448}
449
Rafael Espindola3acea392014-06-12 21:46:39 +0000450std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
451 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000452 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000453 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000454
455 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000456 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000457 } else {
458 DataRefImpl DRI;
459 DRI.d.a = index - 1;
460 Res = section_iterator(SectionRef(DRI, this));
461 }
462
463 return object_error::success;
464}
465
Rafael Espindola5e812af2014-01-30 02:49:50 +0000466void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000467 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000468}
469
Rafael Espindola3acea392014-06-12 21:46:39 +0000470std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
471 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000472 ArrayRef<char> Raw = getSectionRawName(Sec);
473 Result = parseSegmentOrSectionName(Raw.data());
474 return object_error::success;
475}
476
Rafael Espindola3acea392014-06-12 21:46:39 +0000477std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
478 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000479 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000480 MachO::section_64 Sect = getSection64(Sec);
481 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000482 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000483 MachO::section Sect = getSection(Sec);
484 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000485 }
486 return object_error::success;
487}
488
Rafael Espindola3acea392014-06-12 21:46:39 +0000489std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
490 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000491 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000492 MachO::section_64 Sect = getSection64(Sec);
493 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000494 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000495 MachO::section Sect = getSection(Sec);
496 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000497 }
498
499 return object_error::success;
500}
501
Rafael Espindola3acea392014-06-12 21:46:39 +0000502std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
503 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000504 uint32_t Offset;
505 uint64_t Size;
506
507 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000508 MachO::section_64 Sect = getSection64(Sec);
509 Offset = Sect.offset;
510 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000511 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000512 MachO::section Sect = getSection(Sec);
513 Offset = Sect.offset;
514 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000515 }
516
517 Res = this->getData().substr(Offset, Size);
518 return object_error::success;
519}
520
Rafael Espindola3acea392014-06-12 21:46:39 +0000521std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
522 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000523 uint32_t Align;
524 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000525 MachO::section_64 Sect = getSection64(Sec);
526 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000527 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000528 MachO::section Sect = getSection(Sec);
529 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000530 }
531
532 Res = uint64_t(1) << Align;
533 return object_error::success;
534}
535
Rafael Espindola3acea392014-06-12 21:46:39 +0000536std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
537 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000538 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000539 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000540 return object_error::success;
541}
542
Rafael Espindola3acea392014-06-12 21:46:39 +0000543std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
544 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000545 uint32_t Flags = getSectionFlags(this, Sec);
546 unsigned SectionType = Flags & MachO::SECTION_TYPE;
547 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
548 !(SectionType == MachO::S_ZEROFILL ||
549 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000550 return object_error::success;
551}
552
Rafael Espindola3acea392014-06-12 21:46:39 +0000553std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
554 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000555 uint32_t Flags = getSectionFlags(this, Sec);
556 unsigned SectionType = Flags & MachO::SECTION_TYPE;
557 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
558 (SectionType == MachO::S_ZEROFILL ||
559 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000560 return object_error::success;
561}
562
Rafael Espindola3acea392014-06-12 21:46:39 +0000563std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000564MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindola137faa02013-04-24 15:14:22 +0000565 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000566 // FIXME: Unimplemented.
567 Result = true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000568 return object_error::success;
569}
570
Rafael Espindola3acea392014-06-12 21:46:39 +0000571std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
572 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000573 // FIXME: Unimplemented.
574 Result = false;
575 return object_error::success;
576}
577
Rafael Espindola3acea392014-06-12 21:46:39 +0000578std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
579 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000580 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis74ec8b02013-08-27 05:00:13 +0000581 unsigned SectionType = Flags & MachO::SECTION_TYPE;
582 Res = SectionType == MachO::S_ZEROFILL ||
583 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000584 return object_error::success;
585}
586
Rafael Espindola3acea392014-06-12 21:46:39 +0000587std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
588 bool &Result) const {
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000589 // Consider using the code from isSectionText to look for __const sections.
590 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
591 // to use section attributes to distinguish code from data.
592
593 // FIXME: Unimplemented.
594 Result = false;
595 return object_error::success;
596}
597
Rafael Espindola3acea392014-06-12 21:46:39 +0000598std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
599 DataRefImpl Symb,
600 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000601 SymbolRef::Type ST;
602 this->getSymbolType(Symb, ST);
603 if (ST == SymbolRef::ST_Unknown) {
604 Result = false;
605 return object_error::success;
606 }
607
608 uint64_t SectBegin, SectEnd;
609 getSectionAddress(Sec, SectBegin);
610 getSectionSize(Sec, SectEnd);
611 SectEnd += SectBegin;
612
613 uint64_t SymAddr;
614 getSymbolAddress(Symb, SymAddr);
615 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
616
617 return object_error::success;
618}
619
Rui Ueyamabc654b12013-09-27 21:47:05 +0000620relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000621 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000622 Ret.d.a = Sec.d.a;
623 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000624 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000625}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000626
Rafael Espindola56f976f2013-04-18 18:08:55 +0000627relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000628MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000629 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000630 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000631 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000632 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000633 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000634 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000635 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000636 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000637
Rafael Espindola56f976f2013-04-18 18:08:55 +0000638 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000639 Ret.d.a = Sec.d.a;
640 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000641 return relocation_iterator(RelocationRef(Ret, this));
642}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000643
Rafael Espindola5e812af2014-01-30 02:49:50 +0000644void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000645 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000646}
Owen Anderson171f4852011-10-24 23:20:07 +0000647
Rafael Espindola3acea392014-06-12 21:46:39 +0000648std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
649 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000650 uint64_t Offset;
651 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000652
653 DataRefImpl Sec;
654 Sec.d.a = Rel.d.a;
655 uint64_t SecAddress;
656 getSectionAddress(Sec, SecAddress);
657 Res = SecAddress + Offset;
658 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000659}
660
Rafael Espindola3acea392014-06-12 21:46:39 +0000661std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
662 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000663 assert(getHeader().filetype == MachO::MH_OBJECT &&
664 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000665 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000666 Res = getAnyRelocationAddress(RE);
667 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000668}
669
Rafael Espindola806f0062013-06-05 01:33:53 +0000670symbol_iterator
671MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000672 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000673 if (isRelocationScattered(RE))
674 return symbol_end();
675
Rafael Espindola56f976f2013-04-18 18:08:55 +0000676 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
677 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000678 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000679 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000680
Charles Davis8bdfafd2013-09-01 04:28:48 +0000681 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000682 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000683 sizeof(MachO::nlist_64) :
684 sizeof(MachO::nlist);
685 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000686 DataRefImpl Sym;
687 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000688 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000689}
690
Rafael Espindola3acea392014-06-12 21:46:39 +0000691std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
692 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000693 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000694 Res = getAnyRelocationType(RE);
695 return object_error::success;
696}
697
Rafael Espindola3acea392014-06-12 21:46:39 +0000698std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000699MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
700 SmallVectorImpl<char> &Result) const {
701 StringRef res;
702 uint64_t RType;
703 getRelocationType(Rel, RType);
704
705 unsigned Arch = this->getArch();
706
707 switch (Arch) {
708 case Triple::x86: {
709 static const char *const Table[] = {
710 "GENERIC_RELOC_VANILLA",
711 "GENERIC_RELOC_PAIR",
712 "GENERIC_RELOC_SECTDIFF",
713 "GENERIC_RELOC_PB_LA_PTR",
714 "GENERIC_RELOC_LOCAL_SECTDIFF",
715 "GENERIC_RELOC_TLV" };
716
Eric Christopher13250cb2013-12-06 02:33:38 +0000717 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000718 res = "Unknown";
719 else
720 res = Table[RType];
721 break;
722 }
723 case Triple::x86_64: {
724 static const char *const Table[] = {
725 "X86_64_RELOC_UNSIGNED",
726 "X86_64_RELOC_SIGNED",
727 "X86_64_RELOC_BRANCH",
728 "X86_64_RELOC_GOT_LOAD",
729 "X86_64_RELOC_GOT",
730 "X86_64_RELOC_SUBTRACTOR",
731 "X86_64_RELOC_SIGNED_1",
732 "X86_64_RELOC_SIGNED_2",
733 "X86_64_RELOC_SIGNED_4",
734 "X86_64_RELOC_TLV" };
735
736 if (RType > 9)
737 res = "Unknown";
738 else
739 res = Table[RType];
740 break;
741 }
742 case Triple::arm: {
743 static const char *const Table[] = {
744 "ARM_RELOC_VANILLA",
745 "ARM_RELOC_PAIR",
746 "ARM_RELOC_SECTDIFF",
747 "ARM_RELOC_LOCAL_SECTDIFF",
748 "ARM_RELOC_PB_LA_PTR",
749 "ARM_RELOC_BR24",
750 "ARM_THUMB_RELOC_BR22",
751 "ARM_THUMB_32BIT_BRANCH",
752 "ARM_RELOC_HALF",
753 "ARM_RELOC_HALF_SECTDIFF" };
754
755 if (RType > 9)
756 res = "Unknown";
757 else
758 res = Table[RType];
759 break;
760 }
Tim Northover00ed9962014-03-29 10:18:08 +0000761 case Triple::aarch64: {
762 static const char *const Table[] = {
763 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
764 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
765 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
766 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
767 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
768 "ARM64_RELOC_ADDEND"
769 };
770
771 if (RType >= array_lengthof(Table))
772 res = "Unknown";
773 else
774 res = Table[RType];
775 break;
776 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000777 case Triple::ppc: {
778 static const char *const Table[] = {
779 "PPC_RELOC_VANILLA",
780 "PPC_RELOC_PAIR",
781 "PPC_RELOC_BR14",
782 "PPC_RELOC_BR24",
783 "PPC_RELOC_HI16",
784 "PPC_RELOC_LO16",
785 "PPC_RELOC_HA16",
786 "PPC_RELOC_LO14",
787 "PPC_RELOC_SECTDIFF",
788 "PPC_RELOC_PB_LA_PTR",
789 "PPC_RELOC_HI16_SECTDIFF",
790 "PPC_RELOC_LO16_SECTDIFF",
791 "PPC_RELOC_HA16_SECTDIFF",
792 "PPC_RELOC_JBSR",
793 "PPC_RELOC_LO14_SECTDIFF",
794 "PPC_RELOC_LOCAL_SECTDIFF" };
795
Eric Christopher13250cb2013-12-06 02:33:38 +0000796 if (RType > 15)
797 res = "Unknown";
798 else
799 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000800 break;
801 }
802 case Triple::UnknownArch:
803 res = "Unknown";
804 break;
805 }
806 Result.append(res.begin(), res.end());
807 return object_error::success;
808}
809
Rafael Espindola3acea392014-06-12 21:46:39 +0000810std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000811MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000812 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000813 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000814
Rafael Espindola56f976f2013-04-18 18:08:55 +0000815 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000816
Alp Tokere69170a2014-06-26 22:52:05 +0000817 std::string fmtbuf;
818 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000819 unsigned Type = this->getAnyRelocationType(RE);
820 bool IsPCRel = this->getAnyRelocationPCRel(RE);
821
822 // Determine any addends that should be displayed with the relocation.
823 // These require decoding the relocation type, which is triple-specific.
824
825 // X86_64 has entirely custom relocation types.
826 if (Arch == Triple::x86_64) {
827 bool isPCRel = getAnyRelocationPCRel(RE);
828
829 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000830 case MachO::X86_64_RELOC_GOT_LOAD:
831 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000832 printRelocationTargetName(this, RE, fmt);
833 fmt << "@GOT";
834 if (isPCRel) fmt << "PCREL";
835 break;
836 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000837 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000838 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000839 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000840 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000841
Charles Davis8bdfafd2013-09-01 04:28:48 +0000842 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000843 // X86_64_RELOC_UNSIGNED.
844 // NOTE: Scattered relocations don't exist on x86_64.
845 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000846 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000847 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
848 "X86_64_RELOC_SUBTRACTOR.");
849
Charles Davis8bdfafd2013-09-01 04:28:48 +0000850 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
851 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000852 printRelocationTargetName(this, RENext, fmt);
853 fmt << "-";
854 printRelocationTargetName(this, RE, fmt);
855 break;
856 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000857 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000858 printRelocationTargetName(this, RE, fmt);
859 fmt << "@TLV";
860 if (isPCRel) fmt << "P";
861 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000862 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000863 printRelocationTargetName(this, RE, fmt);
864 fmt << "-1";
865 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000866 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000867 printRelocationTargetName(this, RE, fmt);
868 fmt << "-2";
869 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000870 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000871 printRelocationTargetName(this, RE, fmt);
872 fmt << "-4";
873 break;
874 default:
875 printRelocationTargetName(this, RE, fmt);
876 break;
877 }
878 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000879 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
880 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000881 // Generic relocation types...
882 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000883 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000884 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000885 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000886 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000887 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000888 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000889
890 // X86 sect diff's must be followed by a relocation of type
891 // GENERIC_RELOC_PAIR.
892 unsigned RType = getAnyRelocationType(RENext);
893
Charles Davis8bdfafd2013-09-01 04:28:48 +0000894 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000895 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
896 "GENERIC_RELOC_SECTDIFF.");
897
898 printRelocationTargetName(this, RE, fmt);
899 fmt << "-";
900 printRelocationTargetName(this, RENext, fmt);
901 break;
902 }
903 }
904
David Fangb88cdf62013-08-08 20:14:40 +0000905 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000906 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000907 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000908 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000909 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000910 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000911
912 // X86 sect diff's must be followed by a relocation of type
913 // GENERIC_RELOC_PAIR.
914 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000915 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000916 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
917 "GENERIC_RELOC_LOCAL_SECTDIFF.");
918
919 printRelocationTargetName(this, RE, fmt);
920 fmt << "-";
921 printRelocationTargetName(this, RENext, fmt);
922 break;
923 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000924 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000925 printRelocationTargetName(this, RE, fmt);
926 fmt << "@TLV";
927 if (IsPCRel) fmt << "P";
928 break;
929 }
930 default:
931 printRelocationTargetName(this, RE, fmt);
932 }
933 } else { // ARM-specific relocations
934 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000935 case MachO::ARM_RELOC_HALF:
936 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000937 // Half relocations steal a bit from the length field to encode
938 // whether this is an upper16 or a lower16 relocation.
939 bool isUpper = getAnyRelocationLength(RE) >> 1;
940
941 if (isUpper)
942 fmt << ":upper16:(";
943 else
944 fmt << ":lower16:(";
945 printRelocationTargetName(this, RE, fmt);
946
947 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000948 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000949 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000950
951 // ARM half relocs must be followed by a relocation of type
952 // ARM_RELOC_PAIR.
953 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000954 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000955 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000956 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000957
958 // NOTE: The half of the target virtual address is stashed in the
959 // address field of the secondary relocation, but we can't reverse
960 // engineer the constant offset from it without decoding the movw/movt
961 // instruction to find the other half in its immediate field.
962
963 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
964 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000965 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000966 fmt << "-";
967 printRelocationTargetName(this, RENext, fmt);
968 }
969
970 fmt << ")";
971 break;
972 }
973 default: {
974 printRelocationTargetName(this, RE, fmt);
975 }
976 }
977 }
978 } else
979 printRelocationTargetName(this, RE, fmt);
980
Alp Tokere69170a2014-06-26 22:52:05 +0000981 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000982 Result.append(fmtbuf.begin(), fmtbuf.end());
983 return object_error::success;
984}
985
Rafael Espindola3acea392014-06-12 21:46:39 +0000986std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
987 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000988 unsigned Arch = getArch();
989 uint64_t Type;
990 getRelocationType(Rel, Type);
991
992 Result = false;
993
994 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
995 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000996 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000997 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000998 } else if (Arch == Triple::x86_64) {
999 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +00001000 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001001 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001002 DataRefImpl RelPrev = Rel;
1003 RelPrev.d.a--;
1004 uint64_t PrevType;
1005 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001006 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001007 Result = true;
1008 }
1009 }
1010
1011 return object_error::success;
1012}
1013
Kevin Enderby980b2582014-06-05 21:21:57 +00001014//
1015// guessLibraryShortName() is passed a name of a dynamic library and returns a
1016// guess on what the short name is. Then name is returned as a substring of the
1017// StringRef Name passed in. The name of the dynamic library is recognized as
1018// a framework if it has one of the two following forms:
1019// Foo.framework/Versions/A/Foo
1020// Foo.framework/Foo
1021// Where A and Foo can be any string. And may contain a trailing suffix
1022// starting with an underbar. If the Name is recognized as a framework then
1023// isFramework is set to true else it is set to false. If the Name has a
1024// suffix then Suffix is set to the substring in Name that contains the suffix
1025// else it is set to a NULL StringRef.
1026//
1027// The Name of the dynamic library is recognized as a library name if it has
1028// one of the two following forms:
1029// libFoo.A.dylib
1030// libFoo.dylib
1031// The library may have a suffix trailing the name Foo of the form:
1032// libFoo_profile.A.dylib
1033// libFoo_profile.dylib
1034//
1035// The Name of the dynamic library is also recognized as a library name if it
1036// has the following form:
1037// Foo.qtx
1038//
1039// If the Name of the dynamic library is none of the forms above then a NULL
1040// StringRef is returned.
1041//
1042StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1043 bool &isFramework,
1044 StringRef &Suffix) {
1045 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1046 size_t a, b, c, d, Idx;
1047
1048 isFramework = false;
1049 Suffix = StringRef();
1050
1051 // Pull off the last component and make Foo point to it
1052 a = Name.rfind('/');
1053 if (a == Name.npos || a == 0)
1054 goto guess_library;
1055 Foo = Name.slice(a+1, Name.npos);
1056
1057 // Look for a suffix starting with a '_'
1058 Idx = Foo.rfind('_');
1059 if (Idx != Foo.npos && Foo.size() >= 2) {
1060 Suffix = Foo.slice(Idx, Foo.npos);
1061 Foo = Foo.slice(0, Idx);
1062 }
1063
1064 // First look for the form Foo.framework/Foo
1065 b = Name.rfind('/', a);
1066 if (b == Name.npos)
1067 Idx = 0;
1068 else
1069 Idx = b+1;
1070 F = Name.slice(Idx, Idx + Foo.size());
1071 DotFramework = Name.slice(Idx + Foo.size(),
1072 Idx + Foo.size() + sizeof(".framework/")-1);
1073 if (F == Foo && DotFramework == ".framework/") {
1074 isFramework = true;
1075 return Foo;
1076 }
1077
1078 // Next look for the form Foo.framework/Versions/A/Foo
1079 if (b == Name.npos)
1080 goto guess_library;
1081 c = Name.rfind('/', b);
1082 if (c == Name.npos || c == 0)
1083 goto guess_library;
1084 V = Name.slice(c+1, Name.npos);
1085 if (!V.startswith("Versions/"))
1086 goto guess_library;
1087 d = Name.rfind('/', c);
1088 if (d == Name.npos)
1089 Idx = 0;
1090 else
1091 Idx = d+1;
1092 F = Name.slice(Idx, Idx + Foo.size());
1093 DotFramework = Name.slice(Idx + Foo.size(),
1094 Idx + Foo.size() + sizeof(".framework/")-1);
1095 if (F == Foo && DotFramework == ".framework/") {
1096 isFramework = true;
1097 return Foo;
1098 }
1099
1100guess_library:
1101 // pull off the suffix after the "." and make a point to it
1102 a = Name.rfind('.');
1103 if (a == Name.npos || a == 0)
1104 return StringRef();
1105 Dylib = Name.slice(a, Name.npos);
1106 if (Dylib != ".dylib")
1107 goto guess_qtx;
1108
1109 // First pull off the version letter for the form Foo.A.dylib if any.
1110 if (a >= 3) {
1111 Dot = Name.slice(a-2, a-1);
1112 if (Dot == ".")
1113 a = a - 2;
1114 }
1115
1116 b = Name.rfind('/', a);
1117 if (b == Name.npos)
1118 b = 0;
1119 else
1120 b = b+1;
1121 // ignore any suffix after an underbar like Foo_profile.A.dylib
1122 Idx = Name.find('_', b);
1123 if (Idx != Name.npos && Idx != b) {
1124 Lib = Name.slice(b, Idx);
1125 Suffix = Name.slice(Idx, a);
1126 }
1127 else
1128 Lib = Name.slice(b, a);
1129 // There are incorrect library names of the form:
1130 // libATS.A_profile.dylib so check for these.
1131 if (Lib.size() >= 3) {
1132 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1133 if (Dot == ".")
1134 Lib = Lib.slice(0, Lib.size()-2);
1135 }
1136 return Lib;
1137
1138guess_qtx:
1139 Qtx = Name.slice(a, Name.npos);
1140 if (Qtx != ".qtx")
1141 return StringRef();
1142 b = Name.rfind('/', a);
1143 if (b == Name.npos)
1144 Lib = Name.slice(0, a);
1145 else
1146 Lib = Name.slice(b+1, a);
1147 // There are library names of the form: QT.A.qtx so check for these.
1148 if (Lib.size() >= 3) {
1149 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1150 if (Dot == ".")
1151 Lib = Lib.slice(0, Lib.size()-2);
1152 }
1153 return Lib;
1154}
1155
1156// getLibraryShortNameByIndex() is used to get the short name of the library
1157// for an undefined symbol in a linked Mach-O binary that was linked with the
1158// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1159// It is passed the index (0 - based) of the library as translated from
1160// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001161std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1162 StringRef &Res) {
Kevin Enderby980b2582014-06-05 21:21:57 +00001163 if (Index >= Libraries.size())
1164 return object_error::parse_failed;
1165
1166 MachO::dylib_command D =
1167 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1168 if (D.dylib.name >= D.cmdsize)
1169 return object_error::parse_failed;
1170
1171 // If the cache of LibrariesShortNames is not built up do that first for
1172 // all the Libraries.
1173 if (LibrariesShortNames.size() == 0) {
1174 for (unsigned i = 0; i < Libraries.size(); i++) {
1175 MachO::dylib_command D =
1176 getStruct<MachO::dylib_command>(this, Libraries[i]);
1177 if (D.dylib.name >= D.cmdsize) {
1178 LibrariesShortNames.push_back(StringRef());
1179 continue;
1180 }
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001181 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001182 StringRef Name = StringRef(P);
1183 StringRef Suffix;
1184 bool isFramework;
1185 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1186 if (shortName == StringRef())
1187 LibrariesShortNames.push_back(Name);
1188 else
1189 LibrariesShortNames.push_back(shortName);
1190 }
1191 }
1192
1193 Res = LibrariesShortNames[Index];
1194 return object_error::success;
1195}
1196
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001197basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001198 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001199}
1200
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001201basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001202 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001203 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001204 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001205
Charles Davis8bdfafd2013-09-01 04:28:48 +00001206 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001207 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001208 sizeof(MachO::nlist_64) :
1209 sizeof(MachO::nlist);
1210 unsigned Offset = Symtab.symoff +
1211 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001212 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001213 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001214}
1215
Lang Hames36072da2014-05-12 21:39:59 +00001216basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1217 DataRefImpl DRI;
1218 if (!SymtabLoadCmd)
1219 return basic_symbol_iterator(SymbolRef(DRI, this));
1220
1221 MachO::symtab_command Symtab = getSymtabLoadCommand();
1222 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1223 unsigned SymbolTableEntrySize =
1224 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1225 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1226 DRI.p += Index * SymbolTableEntrySize;
1227 return basic_symbol_iterator(SymbolRef(DRI, this));
1228}
1229
Rafael Espindolab5155a52014-02-10 20:24:04 +00001230section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001231 DataRefImpl DRI;
1232 return section_iterator(SectionRef(DRI, this));
1233}
1234
Rafael Espindolab5155a52014-02-10 20:24:04 +00001235section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001236 DataRefImpl DRI;
1237 DRI.d.a = Sections.size();
1238 return section_iterator(SectionRef(DRI, this));
1239}
1240
Rafael Espindola56f976f2013-04-18 18:08:55 +00001241uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001242 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001243}
1244
Rafael Espindola56f976f2013-04-18 18:08:55 +00001245StringRef MachOObjectFile::getFileFormatName() const {
1246 unsigned CPUType = getCPUType(this);
1247 if (!is64Bit()) {
1248 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001249 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001250 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001251 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001252 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001253 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001254 return "Mach-O 32-bit ppc";
1255 default:
Charles Davis74ec8b02013-08-27 05:00:13 +00001256 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindola56f976f2013-04-18 18:08:55 +00001257 "64-bit object file when we're not 64-bit?");
1258 return "Mach-O 32-bit unknown";
1259 }
1260 }
1261
1262 // Make sure the cpu type has the correct mask.
Charles Davis74ec8b02013-08-27 05:00:13 +00001263 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1264 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher1d62c252013-07-22 22:25:07 +00001265 "32-bit object file when we're 64-bit?");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001266
1267 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001268 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001269 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001270 case llvm::MachO::CPU_TYPE_ARM64:
1271 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001272 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001273 return "Mach-O 64-bit ppc64";
1274 default:
1275 return "Mach-O 64-bit unknown";
1276 }
1277}
1278
Alexey Samsonove6388e62013-06-18 15:03:28 +00001279Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1280 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001281 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001282 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001283 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001284 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001285 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001286 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001287 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001288 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001289 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001290 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001291 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001292 return Triple::ppc64;
1293 default:
1294 return Triple::UnknownArch;
1295 }
1296}
1297
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001298Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1299 const char **McpuDefault) {
1300 if (McpuDefault)
1301 *McpuDefault = nullptr;
1302
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001303 switch (CPUType) {
1304 case MachO::CPU_TYPE_I386:
1305 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1306 case MachO::CPU_SUBTYPE_I386_ALL:
1307 return Triple("i386-apple-darwin");
1308 default:
1309 return Triple();
1310 }
1311 case MachO::CPU_TYPE_X86_64:
1312 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1313 case MachO::CPU_SUBTYPE_X86_64_ALL:
1314 return Triple("x86_64-apple-darwin");
1315 case MachO::CPU_SUBTYPE_X86_64_H:
1316 return Triple("x86_64h-apple-darwin");
1317 default:
1318 return Triple();
1319 }
1320 case MachO::CPU_TYPE_ARM:
1321 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1322 case MachO::CPU_SUBTYPE_ARM_V4T:
1323 return Triple("armv4t-apple-darwin");
1324 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1325 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001326 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1327 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001328 case MachO::CPU_SUBTYPE_ARM_V6:
1329 return Triple("armv6-apple-darwin");
1330 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001331 if (McpuDefault)
1332 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001333 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001334 case MachO::CPU_SUBTYPE_ARM_V7:
1335 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001336 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001337 if (McpuDefault)
1338 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001339 return Triple("armv7em-apple-darwin");
1340 case MachO::CPU_SUBTYPE_ARM_V7K:
1341 return Triple("armv7k-apple-darwin");
1342 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001343 if (McpuDefault)
1344 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001345 return Triple("armv7m-apple-darwin");
1346 case MachO::CPU_SUBTYPE_ARM_V7S:
1347 return Triple("armv7s-apple-darwin");
1348 default:
1349 return Triple();
1350 }
1351 case MachO::CPU_TYPE_ARM64:
1352 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1353 case MachO::CPU_SUBTYPE_ARM64_ALL:
1354 return Triple("arm64-apple-darwin");
1355 default:
1356 return Triple();
1357 }
1358 case MachO::CPU_TYPE_POWERPC:
1359 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1360 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1361 return Triple("ppc-apple-darwin");
1362 default:
1363 return Triple();
1364 }
1365 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001366 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001367 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1368 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001369 default:
1370 return Triple();
1371 }
1372 default:
1373 return Triple();
1374 }
1375}
1376
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001377Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1378 const char **McpuDefault) {
1379 if (McpuDefault)
1380 *McpuDefault = nullptr;
1381
1382 switch (CPUType) {
1383 case MachO::CPU_TYPE_ARM:
1384 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1385 case MachO::CPU_SUBTYPE_ARM_V4T:
1386 return Triple("thumbv4t-apple-darwin");
1387 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1388 return Triple("thumbv5e-apple-darwin");
1389 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1390 return Triple("xscale-apple-darwin");
1391 case MachO::CPU_SUBTYPE_ARM_V6:
1392 return Triple("thumbv6-apple-darwin");
1393 case MachO::CPU_SUBTYPE_ARM_V6M:
1394 if (McpuDefault)
1395 *McpuDefault = "cortex-m0";
1396 return Triple("thumbv6m-apple-darwin");
1397 case MachO::CPU_SUBTYPE_ARM_V7:
1398 return Triple("thumbv7-apple-darwin");
1399 case MachO::CPU_SUBTYPE_ARM_V7EM:
1400 if (McpuDefault)
1401 *McpuDefault = "cortex-m4";
1402 return Triple("thumbv7em-apple-darwin");
1403 case MachO::CPU_SUBTYPE_ARM_V7K:
1404 return Triple("thumbv7k-apple-darwin");
1405 case MachO::CPU_SUBTYPE_ARM_V7M:
1406 if (McpuDefault)
1407 *McpuDefault = "cortex-m3";
1408 return Triple("thumbv7m-apple-darwin");
1409 case MachO::CPU_SUBTYPE_ARM_V7S:
1410 return Triple("thumbv7s-apple-darwin");
1411 default:
1412 return Triple();
1413 }
1414 default:
1415 return Triple();
1416 }
1417}
1418
1419Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1420 const char **McpuDefault,
1421 Triple *ThumbTriple) {
1422 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1423 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1424 McpuDefault);
1425 return T;
1426}
1427
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001428Triple MachOObjectFile::getHostArch() {
1429 return Triple(sys::getDefaultTargetTriple());
1430}
1431
Rafael Espindola72318b42014-08-08 16:30:17 +00001432bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1433 return StringSwitch<bool>(ArchFlag)
1434 .Case("i386", true)
1435 .Case("x86_64", true)
1436 .Case("x86_64h", true)
1437 .Case("armv4t", true)
1438 .Case("arm", true)
1439 .Case("armv5e", true)
1440 .Case("armv6", true)
1441 .Case("armv6m", true)
1442 .Case("armv7em", true)
1443 .Case("armv7k", true)
1444 .Case("armv7m", true)
1445 .Case("armv7s", true)
1446 .Case("arm64", true)
1447 .Case("ppc", true)
1448 .Case("ppc64", true)
1449 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001450}
1451
Alexey Samsonove6388e62013-06-18 15:03:28 +00001452unsigned MachOObjectFile::getArch() const {
1453 return getArch(getCPUType(this));
1454}
1455
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001456Triple MachOObjectFile::getArch(const char **McpuDefault,
1457 Triple *ThumbTriple) const {
1458 Triple T;
1459 if (is64Bit()) {
1460 MachO::mach_header_64 H_64;
1461 H_64 = getHeader64();
1462 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1463 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1464 McpuDefault);
1465 } else {
1466 MachO::mach_header H;
1467 H = getHeader();
1468 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1469 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1470 McpuDefault);
1471 }
1472 return T;
1473}
1474
Rui Ueyamabc654b12013-09-27 21:47:05 +00001475relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001476 DataRefImpl DRI;
1477 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001478 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001479}
1480
Rui Ueyamabc654b12013-09-27 21:47:05 +00001481relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001482 DataRefImpl DRI;
1483 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001484 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001485}
1486
Kevin Enderby273ae012013-06-06 17:20:50 +00001487dice_iterator MachOObjectFile::begin_dices() const {
1488 DataRefImpl DRI;
1489 if (!DataInCodeLoadCmd)
1490 return dice_iterator(DiceRef(DRI, this));
1491
Charles Davis8bdfafd2013-09-01 04:28:48 +00001492 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1493 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001494 return dice_iterator(DiceRef(DRI, this));
1495}
1496
1497dice_iterator MachOObjectFile::end_dices() const {
1498 DataRefImpl DRI;
1499 if (!DataInCodeLoadCmd)
1500 return dice_iterator(DiceRef(DRI, this));
1501
Charles Davis8bdfafd2013-09-01 04:28:48 +00001502 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1503 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001504 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1505 return dice_iterator(DiceRef(DRI, this));
1506}
1507
Rafael Espindola56f976f2013-04-18 18:08:55 +00001508StringRef
1509MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1510 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1511 return parseSegmentOrSectionName(Raw.data());
1512}
1513
1514ArrayRef<char>
1515MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001516 const section_base *Base =
1517 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1518 return ArrayRef<char>(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001519}
1520
1521ArrayRef<char>
1522MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001523 const section_base *Base =
1524 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1525 return ArrayRef<char>(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001526}
1527
1528bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001529MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001530 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001531 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001532 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001533 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001534}
1535
Eric Christopher1d62c252013-07-22 22:25:07 +00001536unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001537 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001538 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001539 return RE.r_word1 & 0xffffff;
1540 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001541}
1542
Eric Christopher1d62c252013-07-22 22:25:07 +00001543bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001544 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001545 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001546 return (RE.r_word1 >> 27) & 1;
1547 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001548}
1549
Eric Christopher1d62c252013-07-22 22:25:07 +00001550bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001551 const MachO::any_relocation_info &RE) const {
1552 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001553}
1554
Eric Christopher1d62c252013-07-22 22:25:07 +00001555uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001556 const MachO::any_relocation_info &RE) const {
1557 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001558}
1559
Eric Christopher1d62c252013-07-22 22:25:07 +00001560unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001561 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001562 if (isRelocationScattered(RE))
1563 return getScatteredRelocationAddress(RE);
1564 return getPlainRelocationAddress(RE);
1565}
1566
Charles Davis8bdfafd2013-09-01 04:28:48 +00001567unsigned MachOObjectFile::getAnyRelocationPCRel(
1568 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001569 if (isRelocationScattered(RE))
1570 return getScatteredRelocationPCRel(this, RE);
1571 return getPlainRelocationPCRel(this, RE);
1572}
1573
Eric Christopher1d62c252013-07-22 22:25:07 +00001574unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001575 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001576 if (isRelocationScattered(RE))
1577 return getScatteredRelocationLength(RE);
1578 return getPlainRelocationLength(this, RE);
1579}
1580
1581unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00001582MachOObjectFile::getAnyRelocationType(
1583 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001584 if (isRelocationScattered(RE))
1585 return getScatteredRelocationType(RE);
1586 return getPlainRelocationType(this, RE);
1587}
1588
Rafael Espindola52501032013-04-30 15:40:54 +00001589SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00001590MachOObjectFile::getRelocationSection(
1591 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00001592 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00001593 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00001594 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1595 DataRefImpl DRI;
1596 DRI.d.a = SecNum;
1597 return SectionRef(DRI, this);
1598}
1599
Rafael Espindola56f976f2013-04-18 18:08:55 +00001600MachOObjectFile::LoadCommandInfo
1601MachOObjectFile::getFirstLoadCommandInfo() const {
1602 MachOObjectFile::LoadCommandInfo Load;
1603
Charles Davis8bdfafd2013-09-01 04:28:48 +00001604 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1605 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001606 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001607 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001608 return Load;
1609}
1610
1611MachOObjectFile::LoadCommandInfo
1612MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1613 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001614 Next.Ptr = L.Ptr + L.C.cmdsize;
1615 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001616 return Next;
1617}
1618
Charles Davis8bdfafd2013-09-01 04:28:48 +00001619MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1620 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001621}
1622
Charles Davis8bdfafd2013-09-01 04:28:48 +00001623MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1624 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001625}
1626
Charles Davis8bdfafd2013-09-01 04:28:48 +00001627MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00001628 unsigned Index) const {
1629 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001630 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001631}
1632
Charles Davis8bdfafd2013-09-01 04:28:48 +00001633MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1634 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001635 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001636 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001637}
1638
Charles Davis8bdfafd2013-09-01 04:28:48 +00001639MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00001640MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001641 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001642 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001643}
1644
Charles Davis8bdfafd2013-09-01 04:28:48 +00001645MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00001646MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001647 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001648 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001649}
1650
Charles Davis8bdfafd2013-09-01 04:28:48 +00001651MachO::linkedit_data_command
1652MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1653 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001654}
1655
Charles Davis8bdfafd2013-09-01 04:28:48 +00001656MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00001657MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001658 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001659}
1660
Charles Davis8bdfafd2013-09-01 04:28:48 +00001661MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00001662MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001663 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001664}
1665
Charles Davis8bdfafd2013-09-01 04:28:48 +00001666MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00001667MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001668 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001669}
1670
Jim Grosbach448334a2014-03-18 22:09:05 +00001671MachO::version_min_command
1672MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1673 return getStruct<MachO::version_min_command>(this, L.Ptr);
1674}
1675
Tim Northover8f9590b2014-06-30 14:40:57 +00001676MachO::dylib_command
1677MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
1678 return getStruct<MachO::dylib_command>(this, L.Ptr);
1679}
1680
1681
Charles Davis8bdfafd2013-09-01 04:28:48 +00001682MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00001683MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001684 DataRefImpl Sec;
1685 Sec.d.a = Rel.d.a;
1686 uint32_t Offset;
1687 if (is64Bit()) {
1688 MachO::section_64 Sect = getSection64(Sec);
1689 Offset = Sect.reloff;
1690 } else {
1691 MachO::section Sect = getSection(Sec);
1692 Offset = Sect.reloff;
1693 }
1694
1695 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
1696 getPtr(this, Offset)) + Rel.d.b;
1697 return getStruct<MachO::any_relocation_info>(
1698 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001699}
1700
Charles Davis8bdfafd2013-09-01 04:28:48 +00001701MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00001702MachOObjectFile::getDice(DataRefImpl Rel) const {
1703 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001704 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00001705}
1706
Charles Davis8bdfafd2013-09-01 04:28:48 +00001707MachO::mach_header MachOObjectFile::getHeader() const {
1708 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001709}
1710
Charles Davis8bdfafd2013-09-01 04:28:48 +00001711MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1712 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001713}
1714
Charles Davis8bdfafd2013-09-01 04:28:48 +00001715uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1716 const MachO::dysymtab_command &DLC,
1717 unsigned Index) const {
1718 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1719 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001720}
1721
Charles Davis8bdfafd2013-09-01 04:28:48 +00001722MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00001723MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1724 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001725 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1726 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001727}
1728
Charles Davis8bdfafd2013-09-01 04:28:48 +00001729MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1730 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001731}
1732
Charles Davis8bdfafd2013-09-01 04:28:48 +00001733MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1734 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001735}
1736
Charles Davis8bdfafd2013-09-01 04:28:48 +00001737MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00001738MachOObjectFile::getDataInCodeLoadCommand() const {
1739 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00001740 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00001741
1742 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001743 MachO::linkedit_data_command Cmd;
1744 Cmd.cmd = MachO::LC_DATA_IN_CODE;
1745 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1746 Cmd.dataoff = 0;
1747 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00001748 return Cmd;
1749}
1750
Rafael Espindola6e040c02013-04-26 20:07:33 +00001751StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001752 MachO::symtab_command S = getSymtabLoadCommand();
1753 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001754}
1755
Rafael Espindola56f976f2013-04-18 18:08:55 +00001756bool MachOObjectFile::is64Bit() const {
1757 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00001758 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001759}
1760
1761void MachOObjectFile::ReadULEB128s(uint64_t Index,
1762 SmallVectorImpl<uint64_t> &Out) const {
1763 DataExtractor extractor(ObjectFile::getData(), true, 0);
1764
1765 uint32_t offset = Index;
1766 uint64_t data = 0;
1767 while (uint64_t delta = extractor.getULEB128(&offset)) {
1768 data += delta;
1769 Out.push_back(data);
1770 }
1771}
1772
Rafael Espindolac66d7612014-08-17 19:09:37 +00001773bool MachOObjectFile::isRelocatableObject() const {
1774 return getHeader().filetype == MachO::MH_OBJECT;
1775}
1776
Rafael Espindola437b0d52014-07-31 03:12:45 +00001777ErrorOr<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00001778ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
1779 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00001780 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00001781 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001782 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00001783 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001784 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00001785 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001786 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola48af1c22014-08-19 18:44:46 +00001787 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001788 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola48af1c22014-08-19 18:44:46 +00001789 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00001790 else
Rafael Espindola692410e2014-01-21 23:06:54 +00001791 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001792
Rafael Espindola692410e2014-01-21 23:06:54 +00001793 if (EC)
1794 return EC;
Rafael Espindola437b0d52014-07-31 03:12:45 +00001795 return std::move(Ret);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001796}
1797