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