blob: fe5c29d873e10d857c5f87ac19b6524ea844ea56 [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"
Chandler Carruthed0881b2012-12-03 16:50:05 +000017#include "llvm/ADT/Triple.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000018#include "llvm/Support/DataExtractor.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000019#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000020#include "llvm/Support/Host.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000021#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000022#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000023#include <cctype>
24#include <cstring>
25#include <limits>
26
27using namespace llvm;
28using namespace object;
29
Artyom Skrobov7d602f72014-07-20 12:08:28 +000030namespace {
31 struct section_base {
32 char sectname[16];
33 char segname[16];
34 };
35}
Rafael Espindola56f976f2013-04-18 18:08:55 +000036
37template<typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000038static T getStruct(const MachOObjectFile *O, const char *P) {
Rafael Espindola3cdeb172013-04-19 13:45:05 +000039 T Cmd;
40 memcpy(&Cmd, P, sizeof(T));
41 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000042 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000043 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000044}
45
Rafael Espindola56f976f2013-04-18 18:08:55 +000046static uint32_t
47getSegmentLoadCommandNumSections(const MachOObjectFile *O,
48 const MachOObjectFile::LoadCommandInfo &L) {
49 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000050 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
51 return S.nsects;
Rafael Espindola421305a2013-04-07 20:01:29 +000052 }
Charles Davis8bdfafd2013-09-01 04:28:48 +000053 MachO::segment_command S = O->getSegmentLoadCommand(L);
54 return S.nsects;
Rafael Espindola5ffc0792013-04-07 16:07:35 +000055}
56
Rafael Espindola6e040c02013-04-26 20:07:33 +000057static const char *
58getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
59 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000060 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
61
62 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000063 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
64 sizeof(MachO::segment_command);
65 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
66 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000067
68 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000069 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000070}
71
Rafael Espindola56f976f2013-04-18 18:08:55 +000072static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
73 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000074}
75
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000076static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000077getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000078 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000079 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000080}
81
Rafael Espindola56f976f2013-04-18 18:08:55 +000082static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +000083 if (P[15] == 0)
84 // Null terminated.
85 return P;
86 // Not null terminated, so this is a 16 char string.
87 return StringRef(P, 16);
88}
89
Rafael Espindola56f976f2013-04-18 18:08:55 +000090// Helper to advance a section or symbol iterator multiple increments at a time.
91template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +000092static void advance(T &it, size_t Val) {
93 while (Val--)
94 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +000095}
96
97static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000098 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +000099}
100
101static void printRelocationTargetName(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000102 const MachO::any_relocation_info &RE,
Alp Tokere69170a2014-06-26 22:52:05 +0000103 raw_string_ostream &fmt) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000104 bool IsScattered = O->isRelocationScattered(RE);
105
106 // Target of a scattered relocation is an address. In the interest of
107 // generating pretty output, scan through the symbol table looking for a
108 // symbol that aligns with that address. If we find one, print it.
109 // Otherwise, we just print the hex address of the target.
110 if (IsScattered) {
111 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
112
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000113 for (const SymbolRef &Symbol : O->symbols()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000114 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000115 uint64_t Addr;
116 StringRef Name;
117
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000118 if ((ec = Symbol.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000119 report_fatal_error(ec.message());
Alexey Samsonov464d2e42014-03-17 07:28:19 +0000120 if (Addr != Val)
121 continue;
122 if ((ec = Symbol.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000123 report_fatal_error(ec.message());
124 fmt << Name;
125 return;
126 }
127
128 // If we couldn't find a symbol that this relocation refers to, try
129 // to find a section beginning instead.
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000130 for (const SectionRef &Section : O->sections()) {
Rafael Espindola3acea392014-06-12 21:46:39 +0000131 std::error_code ec;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000132 uint64_t Addr;
133 StringRef Name;
134
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000135 if ((ec = Section.getAddress(Addr)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000136 report_fatal_error(ec.message());
Alexey Samsonov063eb3f2014-03-13 13:52:54 +0000137 if (Addr != Val)
138 continue;
139 if ((ec = Section.getName(Name)))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140 report_fatal_error(ec.message());
141 fmt << Name;
142 return;
143 }
144
145 fmt << format("0x%x", Val);
146 return;
147 }
148
149 StringRef S;
150 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000151 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152
153 if (isExtern) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000154 symbol_iterator SI = O->symbol_begin();
Rafael Espindola5e812af2014-01-30 02:49:50 +0000155 advance(SI, Val);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000156 SI->getName(S);
157 } else {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000158 section_iterator SI = O->section_begin();
Ahmed Bougacha9dab0cc2013-05-14 22:41:29 +0000159 // Adjust for the fact that sections are 1-indexed.
Rafael Espindola5e812af2014-01-30 02:49:50 +0000160 advance(SI, Val - 1);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000161 SI->getName(S);
162 }
163
164 fmt << S;
165}
166
Charles Davis8bdfafd2013-09-01 04:28:48 +0000167static uint32_t
168getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
169 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000170}
171
172static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000173getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
174 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000175}
176
177static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000178 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000179 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000180 return (RE.r_word1 >> 24) & 1;
181 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000182}
183
184static bool
185getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000186 const MachO::any_relocation_info &RE) {
187 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000188}
189
190static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000191 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000192 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000193 return (RE.r_word1 >> 25) & 3;
194 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000195}
196
197static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000198getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
199 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000200}
201
202static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000203 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000204 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000205 return RE.r_word1 >> 28;
206 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000207}
208
Charles Davis8bdfafd2013-09-01 04:28:48 +0000209static unsigned
210getScatteredRelocationType(const MachO::any_relocation_info &RE) {
211 return (RE.r_word0 >> 24) & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000212}
213
214static uint32_t getSectionFlags(const MachOObjectFile *O,
215 DataRefImpl Sec) {
216 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000217 MachO::section_64 Sect = O->getSection64(Sec);
218 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000219 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000220 MachO::section Sect = O->getSection(Sec);
221 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000222}
223
Rafael Espindola2e60ca92014-06-24 13:56:32 +0000224MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,
225 bool IsLittleEndian, bool Is64bits,
226 std::error_code &EC)
227 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(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
Charles Davis74ec8b02013-08-27 05:00:13 +0000441 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000442 Result |= SymbolRef::SF_Absolute;
443
Rafael Espindola20122a42014-01-31 20:57:12 +0000444 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000445}
446
Rafael Espindola3acea392014-06-12 21:46:39 +0000447std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
448 section_iterator &Res) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000449 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000450 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000451
452 if (index == 0) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000453 Res = section_end();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000454 } else {
455 DataRefImpl DRI;
456 DRI.d.a = index - 1;
457 Res = section_iterator(SectionRef(DRI, this));
458 }
459
460 return object_error::success;
461}
462
Rafael Espindola5e812af2014-01-30 02:49:50 +0000463void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000464 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000465}
466
Rafael Espindola3acea392014-06-12 21:46:39 +0000467std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
468 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000469 ArrayRef<char> Raw = getSectionRawName(Sec);
470 Result = parseSegmentOrSectionName(Raw.data());
471 return object_error::success;
472}
473
Rafael Espindola3acea392014-06-12 21:46:39 +0000474std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
475 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000476 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000477 MachO::section_64 Sect = getSection64(Sec);
478 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000479 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000480 MachO::section Sect = getSection(Sec);
481 Res = Sect.addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000482 }
483 return object_error::success;
484}
485
Rafael Espindola3acea392014-06-12 21:46:39 +0000486std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
487 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000488 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000489 MachO::section_64 Sect = getSection64(Sec);
490 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000491 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000492 MachO::section Sect = getSection(Sec);
493 Res = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000494 }
495
496 return object_error::success;
497}
498
Rafael Espindola3acea392014-06-12 21:46:39 +0000499std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
500 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000501 uint32_t Offset;
502 uint64_t Size;
503
504 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000505 MachO::section_64 Sect = getSection64(Sec);
506 Offset = Sect.offset;
507 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000508 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000509 MachO::section Sect = getSection(Sec);
510 Offset = Sect.offset;
511 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000512 }
513
514 Res = this->getData().substr(Offset, Size);
515 return object_error::success;
516}
517
Rafael Espindola3acea392014-06-12 21:46:39 +0000518std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
519 uint64_t &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000520 uint32_t Align;
521 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000522 MachO::section_64 Sect = getSection64(Sec);
523 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000524 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000525 MachO::section Sect = getSection(Sec);
526 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000527 }
528
529 Res = uint64_t(1) << Align;
530 return object_error::success;
531}
532
Rafael Espindola3acea392014-06-12 21:46:39 +0000533std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
534 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000535 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000536 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537 return object_error::success;
538}
539
Rafael Espindola3acea392014-06-12 21:46:39 +0000540std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
541 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000542 uint32_t Flags = getSectionFlags(this, Sec);
543 unsigned SectionType = Flags & MachO::SECTION_TYPE;
544 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
545 !(SectionType == MachO::S_ZEROFILL ||
546 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000547 return object_error::success;
548}
549
Rafael Espindola3acea392014-06-12 21:46:39 +0000550std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
551 bool &Result) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000552 uint32_t Flags = getSectionFlags(this, Sec);
553 unsigned SectionType = Flags & MachO::SECTION_TYPE;
554 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
555 (SectionType == MachO::S_ZEROFILL ||
556 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000557 return object_error::success;
558}
559
Rafael Espindola3acea392014-06-12 21:46:39 +0000560std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000561MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindola137faa02013-04-24 15:14:22 +0000562 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000563 // FIXME: Unimplemented.
564 Result = true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000565 return object_error::success;
566}
567
Rafael Espindola3acea392014-06-12 21:46:39 +0000568std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
569 bool &Result) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000570 // FIXME: Unimplemented.
571 Result = false;
572 return object_error::success;
573}
574
Rafael Espindola3acea392014-06-12 21:46:39 +0000575std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
576 bool &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000577 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davis74ec8b02013-08-27 05:00:13 +0000578 unsigned SectionType = Flags & MachO::SECTION_TYPE;
579 Res = SectionType == MachO::S_ZEROFILL ||
580 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000581 return object_error::success;
582}
583
Rafael Espindola3acea392014-06-12 21:46:39 +0000584std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
585 bool &Result) const {
Andrew Kaylor3f31fa02012-10-10 01:41:33 +0000586 // Consider using the code from isSectionText to look for __const sections.
587 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
588 // to use section attributes to distinguish code from data.
589
590 // FIXME: Unimplemented.
591 Result = false;
592 return object_error::success;
593}
594
Rafael Espindola3acea392014-06-12 21:46:39 +0000595std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
596 DataRefImpl Symb,
597 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000598 SymbolRef::Type ST;
599 this->getSymbolType(Symb, ST);
600 if (ST == SymbolRef::ST_Unknown) {
601 Result = false;
602 return object_error::success;
603 }
604
605 uint64_t SectBegin, SectEnd;
606 getSectionAddress(Sec, SectBegin);
607 getSectionSize(Sec, SectEnd);
608 SectEnd += SectBegin;
609
610 uint64_t SymAddr;
611 getSymbolAddress(Symb, SymAddr);
612 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
613
614 return object_error::success;
615}
616
Rui Ueyamabc654b12013-09-27 21:47:05 +0000617relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000618 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000619 Ret.d.a = Sec.d.a;
620 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000621 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000622}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000623
Rafael Espindola56f976f2013-04-18 18:08:55 +0000624relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000625MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000626 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000627 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000628 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000629 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000630 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000631 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000632 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000633 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000634
Rafael Espindola56f976f2013-04-18 18:08:55 +0000635 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000636 Ret.d.a = Sec.d.a;
637 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000638 return relocation_iterator(RelocationRef(Ret, this));
639}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000640
Rafael Espindola5e812af2014-01-30 02:49:50 +0000641void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000642 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000643}
Owen Anderson171f4852011-10-24 23:20:07 +0000644
Rafael Espindola3acea392014-06-12 21:46:39 +0000645std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
646 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000647 uint64_t Offset;
648 getRelocationOffset(Rel, Offset);
Rafael Espindola7e91bc92014-04-03 23:54:35 +0000649
650 DataRefImpl Sec;
651 Sec.d.a = Rel.d.a;
652 uint64_t SecAddress;
653 getSectionAddress(Sec, SecAddress);
654 Res = SecAddress + Offset;
655 return object_error::success;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000656}
657
Rafael Espindola3acea392014-06-12 21:46:39 +0000658std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
659 uint64_t &Res) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000660 assert(getHeader().filetype == MachO::MH_OBJECT &&
661 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000662 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000663 Res = getAnyRelocationAddress(RE);
664 return object_error::success;
David Meyer2fc34c52012-03-01 01:36:50 +0000665}
666
Rafael Espindola806f0062013-06-05 01:33:53 +0000667symbol_iterator
668MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000669 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000670 if (isRelocationScattered(RE))
671 return symbol_end();
672
Rafael Espindola56f976f2013-04-18 18:08:55 +0000673 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
674 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000675 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000676 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000677
Charles Davis8bdfafd2013-09-01 04:28:48 +0000678 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000679 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000680 sizeof(MachO::nlist_64) :
681 sizeof(MachO::nlist);
682 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000683 DataRefImpl Sym;
684 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000685 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000686}
687
Rafael Espindola3acea392014-06-12 21:46:39 +0000688std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
689 uint64_t &Res) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000690 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000691 Res = getAnyRelocationType(RE);
692 return object_error::success;
693}
694
Rafael Espindola3acea392014-06-12 21:46:39 +0000695std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000696MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
697 SmallVectorImpl<char> &Result) const {
698 StringRef res;
699 uint64_t RType;
700 getRelocationType(Rel, RType);
701
702 unsigned Arch = this->getArch();
703
704 switch (Arch) {
705 case Triple::x86: {
706 static const char *const Table[] = {
707 "GENERIC_RELOC_VANILLA",
708 "GENERIC_RELOC_PAIR",
709 "GENERIC_RELOC_SECTDIFF",
710 "GENERIC_RELOC_PB_LA_PTR",
711 "GENERIC_RELOC_LOCAL_SECTDIFF",
712 "GENERIC_RELOC_TLV" };
713
Eric Christopher13250cb2013-12-06 02:33:38 +0000714 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000715 res = "Unknown";
716 else
717 res = Table[RType];
718 break;
719 }
720 case Triple::x86_64: {
721 static const char *const Table[] = {
722 "X86_64_RELOC_UNSIGNED",
723 "X86_64_RELOC_SIGNED",
724 "X86_64_RELOC_BRANCH",
725 "X86_64_RELOC_GOT_LOAD",
726 "X86_64_RELOC_GOT",
727 "X86_64_RELOC_SUBTRACTOR",
728 "X86_64_RELOC_SIGNED_1",
729 "X86_64_RELOC_SIGNED_2",
730 "X86_64_RELOC_SIGNED_4",
731 "X86_64_RELOC_TLV" };
732
733 if (RType > 9)
734 res = "Unknown";
735 else
736 res = Table[RType];
737 break;
738 }
739 case Triple::arm: {
740 static const char *const Table[] = {
741 "ARM_RELOC_VANILLA",
742 "ARM_RELOC_PAIR",
743 "ARM_RELOC_SECTDIFF",
744 "ARM_RELOC_LOCAL_SECTDIFF",
745 "ARM_RELOC_PB_LA_PTR",
746 "ARM_RELOC_BR24",
747 "ARM_THUMB_RELOC_BR22",
748 "ARM_THUMB_32BIT_BRANCH",
749 "ARM_RELOC_HALF",
750 "ARM_RELOC_HALF_SECTDIFF" };
751
752 if (RType > 9)
753 res = "Unknown";
754 else
755 res = Table[RType];
756 break;
757 }
Tim Northover00ed9962014-03-29 10:18:08 +0000758 case Triple::aarch64: {
759 static const char *const Table[] = {
760 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
761 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
762 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
763 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
764 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
765 "ARM64_RELOC_ADDEND"
766 };
767
768 if (RType >= array_lengthof(Table))
769 res = "Unknown";
770 else
771 res = Table[RType];
772 break;
773 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000774 case Triple::ppc: {
775 static const char *const Table[] = {
776 "PPC_RELOC_VANILLA",
777 "PPC_RELOC_PAIR",
778 "PPC_RELOC_BR14",
779 "PPC_RELOC_BR24",
780 "PPC_RELOC_HI16",
781 "PPC_RELOC_LO16",
782 "PPC_RELOC_HA16",
783 "PPC_RELOC_LO14",
784 "PPC_RELOC_SECTDIFF",
785 "PPC_RELOC_PB_LA_PTR",
786 "PPC_RELOC_HI16_SECTDIFF",
787 "PPC_RELOC_LO16_SECTDIFF",
788 "PPC_RELOC_HA16_SECTDIFF",
789 "PPC_RELOC_JBSR",
790 "PPC_RELOC_LO14_SECTDIFF",
791 "PPC_RELOC_LOCAL_SECTDIFF" };
792
Eric Christopher13250cb2013-12-06 02:33:38 +0000793 if (RType > 15)
794 res = "Unknown";
795 else
796 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000797 break;
798 }
799 case Triple::UnknownArch:
800 res = "Unknown";
801 break;
802 }
803 Result.append(res.begin(), res.end());
804 return object_error::success;
805}
806
Rafael Espindola3acea392014-06-12 21:46:39 +0000807std::error_code
Rafael Espindola56f976f2013-04-18 18:08:55 +0000808MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindola137faa02013-04-24 15:14:22 +0000809 SmallVectorImpl<char> &Result) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000810 MachO::any_relocation_info RE = getRelocation(Rel);
David Meyer2fc34c52012-03-01 01:36:50 +0000811
Rafael Espindola56f976f2013-04-18 18:08:55 +0000812 unsigned Arch = this->getArch();
Eric Christopher7b015c72011-04-22 03:19:48 +0000813
Alp Tokere69170a2014-06-26 22:52:05 +0000814 std::string fmtbuf;
815 raw_string_ostream fmt(fmtbuf);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000816 unsigned Type = this->getAnyRelocationType(RE);
817 bool IsPCRel = this->getAnyRelocationPCRel(RE);
818
819 // Determine any addends that should be displayed with the relocation.
820 // These require decoding the relocation type, which is triple-specific.
821
822 // X86_64 has entirely custom relocation types.
823 if (Arch == Triple::x86_64) {
824 bool isPCRel = getAnyRelocationPCRel(RE);
825
826 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000827 case MachO::X86_64_RELOC_GOT_LOAD:
828 case MachO::X86_64_RELOC_GOT: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000829 printRelocationTargetName(this, RE, fmt);
830 fmt << "@GOT";
831 if (isPCRel) fmt << "PCREL";
832 break;
833 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000834 case MachO::X86_64_RELOC_SUBTRACTOR: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000835 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000836 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000837 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000838
Charles Davis8bdfafd2013-09-01 04:28:48 +0000839 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
Rafael Espindola56f976f2013-04-18 18:08:55 +0000840 // X86_64_RELOC_UNSIGNED.
841 // NOTE: Scattered relocations don't exist on x86_64.
842 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000843 if (RType != MachO::X86_64_RELOC_UNSIGNED)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000844 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
845 "X86_64_RELOC_SUBTRACTOR.");
846
Charles Davis8bdfafd2013-09-01 04:28:48 +0000847 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
848 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
Rafael Espindola56f976f2013-04-18 18:08:55 +0000849 printRelocationTargetName(this, RENext, fmt);
850 fmt << "-";
851 printRelocationTargetName(this, RE, fmt);
852 break;
853 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000854 case MachO::X86_64_RELOC_TLV:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000855 printRelocationTargetName(this, RE, fmt);
856 fmt << "@TLV";
857 if (isPCRel) fmt << "P";
858 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000859 case MachO::X86_64_RELOC_SIGNED_1:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000860 printRelocationTargetName(this, RE, fmt);
861 fmt << "-1";
862 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000863 case MachO::X86_64_RELOC_SIGNED_2:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000864 printRelocationTargetName(this, RE, fmt);
865 fmt << "-2";
866 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000867 case MachO::X86_64_RELOC_SIGNED_4:
Rafael Espindola56f976f2013-04-18 18:08:55 +0000868 printRelocationTargetName(this, RE, fmt);
869 fmt << "-4";
870 break;
871 default:
872 printRelocationTargetName(this, RE, fmt);
873 break;
874 }
875 // X86 and ARM share some relocation types in common.
David Fangb88cdf62013-08-08 20:14:40 +0000876 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
877 Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000878 // Generic relocation types...
879 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000880 case MachO::GENERIC_RELOC_PAIR: // prints no info
Rafael Espindola56f976f2013-04-18 18:08:55 +0000881 return object_error::success;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000882 case MachO::GENERIC_RELOC_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000883 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000884 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000885 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000886
887 // X86 sect diff's must be followed by a relocation of type
888 // GENERIC_RELOC_PAIR.
889 unsigned RType = getAnyRelocationType(RENext);
890
Charles Davis8bdfafd2013-09-01 04:28:48 +0000891 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000892 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
893 "GENERIC_RELOC_SECTDIFF.");
894
895 printRelocationTargetName(this, RE, fmt);
896 fmt << "-";
897 printRelocationTargetName(this, RENext, fmt);
898 break;
899 }
900 }
901
David Fangb88cdf62013-08-08 20:14:40 +0000902 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000903 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000904 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000905 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000906 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000907 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000908
909 // X86 sect diff's must be followed by a relocation of type
910 // GENERIC_RELOC_PAIR.
911 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000912 if (RType != MachO::GENERIC_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000913 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
914 "GENERIC_RELOC_LOCAL_SECTDIFF.");
915
916 printRelocationTargetName(this, RE, fmt);
917 fmt << "-";
918 printRelocationTargetName(this, RENext, fmt);
919 break;
920 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000921 case MachO::GENERIC_RELOC_TLV: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000922 printRelocationTargetName(this, RE, fmt);
923 fmt << "@TLV";
924 if (IsPCRel) fmt << "P";
925 break;
926 }
927 default:
928 printRelocationTargetName(this, RE, fmt);
929 }
930 } else { // ARM-specific relocations
931 switch (Type) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000932 case MachO::ARM_RELOC_HALF:
933 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000934 // Half relocations steal a bit from the length field to encode
935 // whether this is an upper16 or a lower16 relocation.
936 bool isUpper = getAnyRelocationLength(RE) >> 1;
937
938 if (isUpper)
939 fmt << ":upper16:(";
940 else
941 fmt << ":lower16:(";
942 printRelocationTargetName(this, RE, fmt);
943
944 DataRefImpl RelNext = Rel;
Rafael Espindola0cc9ba12014-04-03 23:20:02 +0000945 moveRelocationNext(RelNext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000946 MachO::any_relocation_info RENext = getRelocation(RelNext);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000947
948 // ARM half relocs must be followed by a relocation of type
949 // ARM_RELOC_PAIR.
950 unsigned RType = getAnyRelocationType(RENext);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000951 if (RType != MachO::ARM_RELOC_PAIR)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000952 report_fatal_error("Expected ARM_RELOC_PAIR after "
Charles Davis8bdfafd2013-09-01 04:28:48 +0000953 "ARM_RELOC_HALF");
Rafael Espindola56f976f2013-04-18 18:08:55 +0000954
955 // NOTE: The half of the target virtual address is stashed in the
956 // address field of the secondary relocation, but we can't reverse
957 // engineer the constant offset from it without decoding the movw/movt
958 // instruction to find the other half in its immediate field.
959
960 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
961 // symbol/section pointer of the follow-on relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000962 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000963 fmt << "-";
964 printRelocationTargetName(this, RENext, fmt);
965 }
966
967 fmt << ")";
968 break;
969 }
970 default: {
971 printRelocationTargetName(this, RE, fmt);
972 }
973 }
974 }
975 } else
976 printRelocationTargetName(this, RE, fmt);
977
Alp Tokere69170a2014-06-26 22:52:05 +0000978 fmt.flush();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000979 Result.append(fmtbuf.begin(), fmtbuf.end());
980 return object_error::success;
981}
982
Rafael Espindola3acea392014-06-12 21:46:39 +0000983std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
984 bool &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000985 unsigned Arch = getArch();
986 uint64_t Type;
987 getRelocationType(Rel, Type);
988
989 Result = false;
990
991 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
992 // is always hidden.
David Fangb88cdf62013-08-08 20:14:40 +0000993 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000994 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000995 } else if (Arch == Triple::x86_64) {
996 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopher1ff26ab62013-07-22 22:25:09 +0000997 // an X86_64_RELOC_SUBTRACTOR.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000998 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000999 DataRefImpl RelPrev = Rel;
1000 RelPrev.d.a--;
1001 uint64_t PrevType;
1002 getRelocationType(RelPrev, PrevType);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001003 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001004 Result = true;
1005 }
1006 }
1007
1008 return object_error::success;
1009}
1010
Rafael Espindola3acea392014-06-12 21:46:39 +00001011std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1012 LibraryRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001013 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1014}
1015
Rafael Espindola3acea392014-06-12 21:46:39 +00001016std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1017 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001018 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1019}
1020
Kevin Enderby980b2582014-06-05 21:21:57 +00001021//
1022// guessLibraryShortName() is passed a name of a dynamic library and returns a
1023// guess on what the short name is. Then name is returned as a substring of the
1024// StringRef Name passed in. The name of the dynamic library is recognized as
1025// a framework if it has one of the two following forms:
1026// Foo.framework/Versions/A/Foo
1027// Foo.framework/Foo
1028// Where A and Foo can be any string. And may contain a trailing suffix
1029// starting with an underbar. If the Name is recognized as a framework then
1030// isFramework is set to true else it is set to false. If the Name has a
1031// suffix then Suffix is set to the substring in Name that contains the suffix
1032// else it is set to a NULL StringRef.
1033//
1034// The Name of the dynamic library is recognized as a library name if it has
1035// one of the two following forms:
1036// libFoo.A.dylib
1037// libFoo.dylib
1038// The library may have a suffix trailing the name Foo of the form:
1039// libFoo_profile.A.dylib
1040// libFoo_profile.dylib
1041//
1042// The Name of the dynamic library is also recognized as a library name if it
1043// has the following form:
1044// Foo.qtx
1045//
1046// If the Name of the dynamic library is none of the forms above then a NULL
1047// StringRef is returned.
1048//
1049StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1050 bool &isFramework,
1051 StringRef &Suffix) {
1052 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1053 size_t a, b, c, d, Idx;
1054
1055 isFramework = false;
1056 Suffix = StringRef();
1057
1058 // Pull off the last component and make Foo point to it
1059 a = Name.rfind('/');
1060 if (a == Name.npos || a == 0)
1061 goto guess_library;
1062 Foo = Name.slice(a+1, Name.npos);
1063
1064 // Look for a suffix starting with a '_'
1065 Idx = Foo.rfind('_');
1066 if (Idx != Foo.npos && Foo.size() >= 2) {
1067 Suffix = Foo.slice(Idx, Foo.npos);
1068 Foo = Foo.slice(0, Idx);
1069 }
1070
1071 // First look for the form Foo.framework/Foo
1072 b = Name.rfind('/', a);
1073 if (b == Name.npos)
1074 Idx = 0;
1075 else
1076 Idx = b+1;
1077 F = Name.slice(Idx, Idx + Foo.size());
1078 DotFramework = Name.slice(Idx + Foo.size(),
1079 Idx + Foo.size() + sizeof(".framework/")-1);
1080 if (F == Foo && DotFramework == ".framework/") {
1081 isFramework = true;
1082 return Foo;
1083 }
1084
1085 // Next look for the form Foo.framework/Versions/A/Foo
1086 if (b == Name.npos)
1087 goto guess_library;
1088 c = Name.rfind('/', b);
1089 if (c == Name.npos || c == 0)
1090 goto guess_library;
1091 V = Name.slice(c+1, Name.npos);
1092 if (!V.startswith("Versions/"))
1093 goto guess_library;
1094 d = Name.rfind('/', c);
1095 if (d == Name.npos)
1096 Idx = 0;
1097 else
1098 Idx = d+1;
1099 F = Name.slice(Idx, Idx + Foo.size());
1100 DotFramework = Name.slice(Idx + Foo.size(),
1101 Idx + Foo.size() + sizeof(".framework/")-1);
1102 if (F == Foo && DotFramework == ".framework/") {
1103 isFramework = true;
1104 return Foo;
1105 }
1106
1107guess_library:
1108 // pull off the suffix after the "." and make a point to it
1109 a = Name.rfind('.');
1110 if (a == Name.npos || a == 0)
1111 return StringRef();
1112 Dylib = Name.slice(a, Name.npos);
1113 if (Dylib != ".dylib")
1114 goto guess_qtx;
1115
1116 // First pull off the version letter for the form Foo.A.dylib if any.
1117 if (a >= 3) {
1118 Dot = Name.slice(a-2, a-1);
1119 if (Dot == ".")
1120 a = a - 2;
1121 }
1122
1123 b = Name.rfind('/', a);
1124 if (b == Name.npos)
1125 b = 0;
1126 else
1127 b = b+1;
1128 // ignore any suffix after an underbar like Foo_profile.A.dylib
1129 Idx = Name.find('_', b);
1130 if (Idx != Name.npos && Idx != b) {
1131 Lib = Name.slice(b, Idx);
1132 Suffix = Name.slice(Idx, a);
1133 }
1134 else
1135 Lib = Name.slice(b, a);
1136 // There are incorrect library names of the form:
1137 // libATS.A_profile.dylib so check for these.
1138 if (Lib.size() >= 3) {
1139 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1140 if (Dot == ".")
1141 Lib = Lib.slice(0, Lib.size()-2);
1142 }
1143 return Lib;
1144
1145guess_qtx:
1146 Qtx = Name.slice(a, Name.npos);
1147 if (Qtx != ".qtx")
1148 return StringRef();
1149 b = Name.rfind('/', a);
1150 if (b == Name.npos)
1151 Lib = Name.slice(0, a);
1152 else
1153 Lib = Name.slice(b+1, a);
1154 // There are library names of the form: QT.A.qtx so check for these.
1155 if (Lib.size() >= 3) {
1156 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1157 if (Dot == ".")
1158 Lib = Lib.slice(0, Lib.size()-2);
1159 }
1160 return Lib;
1161}
1162
1163// getLibraryShortNameByIndex() is used to get the short name of the library
1164// for an undefined symbol in a linked Mach-O binary that was linked with the
1165// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1166// It is passed the index (0 - based) of the library as translated from
1167// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001168std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1169 StringRef &Res) {
Kevin Enderby980b2582014-06-05 21:21:57 +00001170 if (Index >= Libraries.size())
1171 return object_error::parse_failed;
1172
1173 MachO::dylib_command D =
1174 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1175 if (D.dylib.name >= D.cmdsize)
1176 return object_error::parse_failed;
1177
1178 // If the cache of LibrariesShortNames is not built up do that first for
1179 // all the Libraries.
1180 if (LibrariesShortNames.size() == 0) {
1181 for (unsigned i = 0; i < Libraries.size(); i++) {
1182 MachO::dylib_command D =
1183 getStruct<MachO::dylib_command>(this, Libraries[i]);
1184 if (D.dylib.name >= D.cmdsize) {
1185 LibrariesShortNames.push_back(StringRef());
1186 continue;
1187 }
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001188 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001189 StringRef Name = StringRef(P);
1190 StringRef Suffix;
1191 bool isFramework;
1192 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1193 if (shortName == StringRef())
1194 LibrariesShortNames.push_back(Name);
1195 else
1196 LibrariesShortNames.push_back(shortName);
1197 }
1198 }
1199
1200 Res = LibrariesShortNames[Index];
1201 return object_error::success;
1202}
1203
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001204basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Lang Hames36072da2014-05-12 21:39:59 +00001205 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001206}
1207
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001208basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001209 DataRefImpl DRI;
Rafael Espindola75c30362013-04-24 19:47:55 +00001210 if (!SymtabLoadCmd)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001211 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001212
Charles Davis8bdfafd2013-09-01 04:28:48 +00001213 MachO::symtab_command Symtab = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001214 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001215 sizeof(MachO::nlist_64) :
1216 sizeof(MachO::nlist);
1217 unsigned Offset = Symtab.symoff +
1218 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001219 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001220 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001221}
1222
Lang Hames36072da2014-05-12 21:39:59 +00001223basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1224 DataRefImpl DRI;
1225 if (!SymtabLoadCmd)
1226 return basic_symbol_iterator(SymbolRef(DRI, this));
1227
1228 MachO::symtab_command Symtab = getSymtabLoadCommand();
1229 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1230 unsigned SymbolTableEntrySize =
1231 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1232 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1233 DRI.p += Index * SymbolTableEntrySize;
1234 return basic_symbol_iterator(SymbolRef(DRI, this));
1235}
1236
Rafael Espindolab5155a52014-02-10 20:24:04 +00001237section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001238 DataRefImpl DRI;
1239 return section_iterator(SectionRef(DRI, this));
1240}
1241
Rafael Espindolab5155a52014-02-10 20:24:04 +00001242section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001243 DataRefImpl DRI;
1244 DRI.d.a = Sections.size();
1245 return section_iterator(SectionRef(DRI, this));
1246}
1247
Rafael Espindolab5155a52014-02-10 20:24:04 +00001248library_iterator MachOObjectFile::needed_library_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001249 // TODO: implement
1250 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1251}
1252
Rafael Espindolab5155a52014-02-10 20:24:04 +00001253library_iterator MachOObjectFile::needed_library_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001254 // TODO: implement
1255 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1256}
1257
1258uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001259 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001260}
1261
Rafael Espindola56f976f2013-04-18 18:08:55 +00001262StringRef MachOObjectFile::getFileFormatName() const {
1263 unsigned CPUType = getCPUType(this);
1264 if (!is64Bit()) {
1265 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001266 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001267 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001268 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001269 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001270 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001271 return "Mach-O 32-bit ppc";
1272 default:
Charles Davis74ec8b02013-08-27 05:00:13 +00001273 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindola56f976f2013-04-18 18:08:55 +00001274 "64-bit object file when we're not 64-bit?");
1275 return "Mach-O 32-bit unknown";
1276 }
1277 }
1278
1279 // Make sure the cpu type has the correct mask.
Charles Davis74ec8b02013-08-27 05:00:13 +00001280 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1281 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher1d62c252013-07-22 22:25:07 +00001282 "32-bit object file when we're 64-bit?");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001283
1284 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001285 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001286 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001287 case llvm::MachO::CPU_TYPE_ARM64:
1288 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001289 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001290 return "Mach-O 64-bit ppc64";
1291 default:
1292 return "Mach-O 64-bit unknown";
1293 }
1294}
1295
Alexey Samsonove6388e62013-06-18 15:03:28 +00001296Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1297 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001298 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001299 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001300 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001301 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001302 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001303 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001304 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001305 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001306 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001307 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001308 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001309 return Triple::ppc64;
1310 default:
1311 return Triple::UnknownArch;
1312 }
1313}
1314
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001315Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
1316 switch (CPUType) {
1317 case MachO::CPU_TYPE_I386:
1318 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1319 case MachO::CPU_SUBTYPE_I386_ALL:
1320 return Triple("i386-apple-darwin");
1321 default:
1322 return Triple();
1323 }
1324 case MachO::CPU_TYPE_X86_64:
1325 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1326 case MachO::CPU_SUBTYPE_X86_64_ALL:
1327 return Triple("x86_64-apple-darwin");
1328 case MachO::CPU_SUBTYPE_X86_64_H:
1329 return Triple("x86_64h-apple-darwin");
1330 default:
1331 return Triple();
1332 }
1333 case MachO::CPU_TYPE_ARM:
1334 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1335 case MachO::CPU_SUBTYPE_ARM_V4T:
1336 return Triple("armv4t-apple-darwin");
1337 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1338 return Triple("armv5e-apple-darwin");
1339 case MachO::CPU_SUBTYPE_ARM_V6:
1340 return Triple("armv6-apple-darwin");
1341 case MachO::CPU_SUBTYPE_ARM_V6M:
1342 return Triple("armv6m-apple-darwin");
1343 case MachO::CPU_SUBTYPE_ARM_V7EM:
1344 return Triple("armv7em-apple-darwin");
1345 case MachO::CPU_SUBTYPE_ARM_V7K:
1346 return Triple("armv7k-apple-darwin");
1347 case MachO::CPU_SUBTYPE_ARM_V7M:
1348 return Triple("armv7m-apple-darwin");
1349 case MachO::CPU_SUBTYPE_ARM_V7S:
1350 return Triple("armv7s-apple-darwin");
1351 default:
1352 return Triple();
1353 }
1354 case MachO::CPU_TYPE_ARM64:
1355 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1356 case MachO::CPU_SUBTYPE_ARM64_ALL:
1357 return Triple("arm64-apple-darwin");
1358 default:
1359 return Triple();
1360 }
1361 case MachO::CPU_TYPE_POWERPC:
1362 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1363 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1364 return Triple("ppc-apple-darwin");
1365 default:
1366 return Triple();
1367 }
1368 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001369 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001370 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1371 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001372 default:
1373 return Triple();
1374 }
1375 default:
1376 return Triple();
1377 }
1378}
1379
1380Triple MachOObjectFile::getHostArch() {
1381 return Triple(sys::getDefaultTargetTriple());
1382}
1383
1384Triple MachOObjectFile::getArch(StringRef ArchFlag) {
1385 if (ArchFlag == "i386")
1386 return Triple("i386-apple-darwin");
1387 else if (ArchFlag == "x86_64")
1388 return Triple("x86_64-apple-darwin");
1389 else if (ArchFlag == "x86_64h")
1390 return Triple("x86_64h-apple-darwin");
1391 else if (ArchFlag == "armv4t" || ArchFlag == "arm")
1392 return Triple("armv4t-apple-darwin");
1393 else if (ArchFlag == "armv5e")
1394 return Triple("armv5e-apple-darwin");
1395 else if (ArchFlag == "armv6")
1396 return Triple("armv6-apple-darwin");
1397 else if (ArchFlag == "armv6m")
1398 return Triple("armv6m-apple-darwin");
1399 else if (ArchFlag == "armv7em")
1400 return Triple("armv7em-apple-darwin");
1401 else if (ArchFlag == "armv7k")
1402 return Triple("armv7k-apple-darwin");
1403 else if (ArchFlag == "armv7k")
1404 return Triple("armv7m-apple-darwin");
1405 else if (ArchFlag == "armv7s")
1406 return Triple("armv7s-apple-darwin");
1407 else if (ArchFlag == "arm64")
1408 return Triple("arm64-apple-darwin");
1409 else if (ArchFlag == "ppc")
1410 return Triple("ppc-apple-darwin");
1411 else if (ArchFlag == "ppc64")
1412 return Triple("ppc64-apple-darwin");
1413 else
1414 return Triple();
1415}
1416
Alexey Samsonove6388e62013-06-18 15:03:28 +00001417unsigned MachOObjectFile::getArch() const {
1418 return getArch(getCPUType(this));
1419}
1420
Rafael Espindola56f976f2013-04-18 18:08:55 +00001421StringRef MachOObjectFile::getLoadName() const {
1422 // TODO: Implement
Charles Davis1827bd82013-08-27 05:38:30 +00001423 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
Rafael Espindola56f976f2013-04-18 18:08:55 +00001424}
1425
Rui Ueyamabc654b12013-09-27 21:47:05 +00001426relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001427 DataRefImpl DRI;
1428 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001429 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001430}
1431
Rui Ueyamabc654b12013-09-27 21:47:05 +00001432relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001433 DataRefImpl DRI;
1434 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001435 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001436}
1437
Kevin Enderby273ae012013-06-06 17:20:50 +00001438dice_iterator MachOObjectFile::begin_dices() const {
1439 DataRefImpl DRI;
1440 if (!DataInCodeLoadCmd)
1441 return dice_iterator(DiceRef(DRI, this));
1442
Charles Davis8bdfafd2013-09-01 04:28:48 +00001443 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1444 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001445 return dice_iterator(DiceRef(DRI, this));
1446}
1447
1448dice_iterator MachOObjectFile::end_dices() const {
1449 DataRefImpl DRI;
1450 if (!DataInCodeLoadCmd)
1451 return dice_iterator(DiceRef(DRI, this));
1452
Charles Davis8bdfafd2013-09-01 04:28:48 +00001453 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1454 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001455 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1456 return dice_iterator(DiceRef(DRI, this));
1457}
1458
Rafael Espindola56f976f2013-04-18 18:08:55 +00001459StringRef
1460MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1461 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1462 return parseSegmentOrSectionName(Raw.data());
1463}
1464
1465ArrayRef<char>
1466MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001467 const section_base *Base =
1468 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1469 return ArrayRef<char>(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001470}
1471
1472ArrayRef<char>
1473MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001474 const section_base *Base =
1475 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1476 return ArrayRef<char>(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001477}
1478
1479bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001480MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001481 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001482 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001483 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001484 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001485}
1486
Eric Christopher1d62c252013-07-22 22:25:07 +00001487unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001488 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001489 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001490 return RE.r_word1 & 0xffffff;
1491 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001492}
1493
Eric Christopher1d62c252013-07-22 22:25:07 +00001494bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001495 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001496 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001497 return (RE.r_word1 >> 27) & 1;
1498 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001499}
1500
Eric Christopher1d62c252013-07-22 22:25:07 +00001501bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001502 const MachO::any_relocation_info &RE) const {
1503 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001504}
1505
Eric Christopher1d62c252013-07-22 22:25:07 +00001506uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001507 const MachO::any_relocation_info &RE) const {
1508 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001509}
1510
Eric Christopher1d62c252013-07-22 22:25:07 +00001511unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001512 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001513 if (isRelocationScattered(RE))
1514 return getScatteredRelocationAddress(RE);
1515 return getPlainRelocationAddress(RE);
1516}
1517
Charles Davis8bdfafd2013-09-01 04:28:48 +00001518unsigned MachOObjectFile::getAnyRelocationPCRel(
1519 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001520 if (isRelocationScattered(RE))
1521 return getScatteredRelocationPCRel(this, RE);
1522 return getPlainRelocationPCRel(this, RE);
1523}
1524
Eric Christopher1d62c252013-07-22 22:25:07 +00001525unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001526 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001527 if (isRelocationScattered(RE))
1528 return getScatteredRelocationLength(RE);
1529 return getPlainRelocationLength(this, RE);
1530}
1531
1532unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00001533MachOObjectFile::getAnyRelocationType(
1534 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001535 if (isRelocationScattered(RE))
1536 return getScatteredRelocationType(RE);
1537 return getPlainRelocationType(this, RE);
1538}
1539
Rafael Espindola52501032013-04-30 15:40:54 +00001540SectionRef
Charles Davis8bdfafd2013-09-01 04:28:48 +00001541MachOObjectFile::getRelocationSection(
1542 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00001543 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00001544 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00001545 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1546 DataRefImpl DRI;
1547 DRI.d.a = SecNum;
1548 return SectionRef(DRI, this);
1549}
1550
Rafael Espindola56f976f2013-04-18 18:08:55 +00001551MachOObjectFile::LoadCommandInfo
1552MachOObjectFile::getFirstLoadCommandInfo() const {
1553 MachOObjectFile::LoadCommandInfo Load;
1554
Charles Davis8bdfafd2013-09-01 04:28:48 +00001555 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1556 sizeof(MachO::mach_header);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001557 Load.Ptr = getPtr(this, HeaderSize);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001558 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001559 return Load;
1560}
1561
1562MachOObjectFile::LoadCommandInfo
1563MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1564 MachOObjectFile::LoadCommandInfo Next;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001565 Next.Ptr = L.Ptr + L.C.cmdsize;
1566 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001567 return Next;
1568}
1569
Charles Davis8bdfafd2013-09-01 04:28:48 +00001570MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1571 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001572}
1573
Charles Davis8bdfafd2013-09-01 04:28:48 +00001574MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1575 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001576}
1577
Charles Davis8bdfafd2013-09-01 04:28:48 +00001578MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00001579 unsigned Index) const {
1580 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001581 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001582}
1583
Charles Davis8bdfafd2013-09-01 04:28:48 +00001584MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1585 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001586 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001587 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001588}
1589
Charles Davis8bdfafd2013-09-01 04:28:48 +00001590MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00001591MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001592 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001593 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001594}
1595
Charles Davis8bdfafd2013-09-01 04:28:48 +00001596MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00001597MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001598 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001599 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001600}
1601
Charles Davis8bdfafd2013-09-01 04:28:48 +00001602MachO::linkedit_data_command
1603MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1604 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001605}
1606
Charles Davis8bdfafd2013-09-01 04:28:48 +00001607MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00001608MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001609 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001610}
1611
Charles Davis8bdfafd2013-09-01 04:28:48 +00001612MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00001613MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001614 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001615}
1616
Charles Davis8bdfafd2013-09-01 04:28:48 +00001617MachO::linker_options_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00001618MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001619 return getStruct<MachO::linker_options_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001620}
1621
Jim Grosbach448334a2014-03-18 22:09:05 +00001622MachO::version_min_command
1623MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1624 return getStruct<MachO::version_min_command>(this, L.Ptr);
1625}
1626
Tim Northover8f9590b2014-06-30 14:40:57 +00001627MachO::dylib_command
1628MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
1629 return getStruct<MachO::dylib_command>(this, L.Ptr);
1630}
1631
1632
Charles Davis8bdfafd2013-09-01 04:28:48 +00001633MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00001634MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001635 DataRefImpl Sec;
1636 Sec.d.a = Rel.d.a;
1637 uint32_t Offset;
1638 if (is64Bit()) {
1639 MachO::section_64 Sect = getSection64(Sec);
1640 Offset = Sect.reloff;
1641 } else {
1642 MachO::section Sect = getSection(Sec);
1643 Offset = Sect.reloff;
1644 }
1645
1646 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
1647 getPtr(this, Offset)) + Rel.d.b;
1648 return getStruct<MachO::any_relocation_info>(
1649 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001650}
1651
Charles Davis8bdfafd2013-09-01 04:28:48 +00001652MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00001653MachOObjectFile::getDice(DataRefImpl Rel) const {
1654 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001655 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00001656}
1657
Charles Davis8bdfafd2013-09-01 04:28:48 +00001658MachO::mach_header MachOObjectFile::getHeader() const {
1659 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001660}
1661
Charles Davis8bdfafd2013-09-01 04:28:48 +00001662MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1663 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001664}
1665
Charles Davis8bdfafd2013-09-01 04:28:48 +00001666uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1667 const MachO::dysymtab_command &DLC,
1668 unsigned Index) const {
1669 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1670 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001671}
1672
Charles Davis8bdfafd2013-09-01 04:28:48 +00001673MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00001674MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1675 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001676 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1677 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00001678}
1679
Charles Davis8bdfafd2013-09-01 04:28:48 +00001680MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1681 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001682}
1683
Charles Davis8bdfafd2013-09-01 04:28:48 +00001684MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1685 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001686}
1687
Charles Davis8bdfafd2013-09-01 04:28:48 +00001688MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00001689MachOObjectFile::getDataInCodeLoadCommand() const {
1690 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00001691 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00001692
1693 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00001694 MachO::linkedit_data_command Cmd;
1695 Cmd.cmd = MachO::LC_DATA_IN_CODE;
1696 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1697 Cmd.dataoff = 0;
1698 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00001699 return Cmd;
1700}
1701
Rafael Espindola6e040c02013-04-26 20:07:33 +00001702StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001703 MachO::symtab_command S = getSymtabLoadCommand();
1704 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001705}
1706
Rafael Espindola56f976f2013-04-18 18:08:55 +00001707bool MachOObjectFile::is64Bit() const {
1708 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00001709 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001710}
1711
1712void MachOObjectFile::ReadULEB128s(uint64_t Index,
1713 SmallVectorImpl<uint64_t> &Out) const {
1714 DataExtractor extractor(ObjectFile::getData(), true, 0);
1715
1716 uint32_t offset = Index;
1717 uint64_t data = 0;
1718 while (uint64_t delta = extractor.getULEB128(&offset)) {
1719 data += delta;
1720 Out.push_back(data);
1721 }
1722}
1723
Rafael Espindola6304e942014-06-23 22:00:37 +00001724ErrorOr<ObjectFile *>
1725ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001726 StringRef Magic = Buffer->getBuffer().slice(0, 4);
Rafael Espindola3acea392014-06-12 21:46:39 +00001727 std::error_code EC;
Ahmed Charles56440fd2014-03-06 05:51:42 +00001728 std::unique_ptr<MachOObjectFile> Ret;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001729 if (Magic == "\xFE\xED\xFA\xCE")
Rafael Espindola2e60ca92014-06-24 13:56:32 +00001730 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001731 else if (Magic == "\xCE\xFA\xED\xFE")
Rafael Espindola2e60ca92014-06-24 13:56:32 +00001732 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001733 else if (Magic == "\xFE\xED\xFA\xCF")
Rafael Espindola2e60ca92014-06-24 13:56:32 +00001734 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001735 else if (Magic == "\xCF\xFA\xED\xFE")
Rafael Espindola2e60ca92014-06-24 13:56:32 +00001736 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
Rafael Espindola6304e942014-06-23 22:00:37 +00001737 else
Rafael Espindola692410e2014-01-21 23:06:54 +00001738 return object_error::parse_failed;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001739
Rafael Espindola692410e2014-01-21 23:06:54 +00001740 if (EC)
1741 return EC;
Ahmed Charles96c9d952014-03-05 10:19:29 +00001742 return Ret.release();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001743}
1744