blob: ae30105a93c3b8fcefb3719673b228bb5b8c5658 [file] [log] [blame]
Eric Christopher6256b032011-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 Andersonf7c93a32011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000016#include "llvm/ADT/Triple.h"
Eric Christopher6256b032011-04-22 03:19:48 +000017#include "llvm/Object/MachOFormat.h"
Rafael Espindola8764c892013-04-07 20:01:29 +000018#include "llvm/Support/DataExtractor.h"
Owen Anderson1832f4d2011-10-26 20:42:54 +000019#include "llvm/Support/Format.h"
Eric Christopher6256b032011-04-22 03:19:48 +000020#include "llvm/Support/MemoryBuffer.h"
Eric Christopher6256b032011-04-22 03:19:48 +000021#include <cctype>
22#include <cstring>
23#include <limits>
24
25using namespace llvm;
26using namespace object;
27
28namespace llvm {
Owen Andersonf7c93a32011-10-11 17:32:27 +000029namespace object {
Eric Christopher6256b032011-04-22 03:19:48 +000030
Rafael Espindola9d55c092013-04-08 13:25:33 +000031MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool Is64bits,
32 error_code &ec)
33 : ObjectFile(getMachOType(true, Is64bits), Object) {
Benjamin Kramer0fcab072011-09-08 20:52:17 +000034 DataRefImpl DRI;
Benjamin Kramer0fcab072011-09-08 20:52:17 +000035 moveToNextSection(DRI);
Rafael Espindola433611b2013-04-07 19:26:57 +000036 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Benjamin Kramer0fcab072011-09-08 20:52:17 +000037 while (DRI.d.a < LoadCommandCount) {
38 Sections.push_back(DRI);
Benjamin Kramer0fcab072011-09-08 20:52:17 +000039 DRI.d.b++;
40 moveToNextSection(DRI);
41 }
42}
43
Rafael Espindola0be4eaf2013-04-07 15:46:05 +000044bool MachOObjectFile::is64Bit() const {
Rafael Espindola9d55c092013-04-08 13:25:33 +000045 unsigned int Type = getType();
46 return Type == ID_MachO64L || Type == ID_MachO64B;
Rafael Espindola0be4eaf2013-04-07 15:46:05 +000047}
Benjamin Kramer0fcab072011-09-08 20:52:17 +000048
Rafael Espindola6ab85a82013-04-07 18:42:06 +000049const MachOFormat::LoadCommand *
Rafael Espindola3eff3182013-04-07 16:07:35 +000050MachOObjectFile::getLoadCommandInfo(unsigned Index) const {
Rafael Espindola77638d92013-04-07 18:08:12 +000051 uint64_t Offset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000052 uint64_t NewOffset = getHeaderSize();
Rafael Espindola77638d92013-04-07 18:08:12 +000053 const MachOFormat::LoadCommand *Load;
54 unsigned I = 0;
55 do {
56 Offset = NewOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000057 StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand));
Rafael Espindola77638d92013-04-07 18:08:12 +000058 Load = reinterpret_cast<const MachOFormat::LoadCommand*>(Data.data());
59 NewOffset = Offset + Load->Size;
60 ++I;
61 } while (I != Index + 1);
62
Rafael Espindola6ab85a82013-04-07 18:42:06 +000063 return Load;
Rafael Espindola3eff3182013-04-07 16:07:35 +000064}
65
66void MachOObjectFile::ReadULEB128s(uint64_t Index,
67 SmallVectorImpl<uint64_t> &Out) const {
Rafael Espindola8764c892013-04-07 20:01:29 +000068 DataExtractor extractor(ObjectFile::getData(), true, 0);
69
70 uint32_t offset = Index;
71 uint64_t data = 0;
72 while (uint64_t delta = extractor.getULEB128(&offset)) {
73 data += delta;
74 Out.push_back(data);
75 }
Rafael Espindola3eff3182013-04-07 16:07:35 +000076}
77
Rafael Espindola433611b2013-04-07 19:26:57 +000078const MachOFormat::Header *MachOObjectFile::getHeader() const {
79 StringRef Data = getData(0, sizeof(MachOFormat::Header));
80 return reinterpret_cast<const MachOFormat::Header*>(Data.data());
Rafael Espindola3eff3182013-04-07 16:07:35 +000081}
82
Rafael Espindola0f08eb12013-04-07 19:05:30 +000083unsigned MachOObjectFile::getHeaderSize() const {
Rafael Espindolac90cc182013-04-07 19:31:49 +000084 return is64Bit() ? macho::Header64Size : macho::Header32Size;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000085}
86
87StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const {
Rafael Espindolaf1cc8002013-04-07 19:42:15 +000088 return ObjectFile::getData().substr(Offset, Size);
Rafael Espindola0f08eb12013-04-07 19:05:30 +000089}
90
Eric Christopher6256b032011-04-22 03:19:48 +000091ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Rafael Espindola9d55c092013-04-08 13:25:33 +000092 StringRef Magic = Buffer->getBuffer().slice(0, 4);
Michael J. Spencer001c9202011-06-25 17:54:50 +000093 error_code ec;
Rafael Espindola9d55c092013-04-08 13:25:33 +000094 bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
95 ObjectFile *Ret = new MachOObjectFile(Buffer, Is64Bits, ec);
Rafael Espindola6f1f3392013-04-07 16:58:48 +000096 if (ec)
Eric Christopher6256b032011-04-22 03:19:48 +000097 return NULL;
Rafael Espindola6f1f3392013-04-07 16:58:48 +000098 return Ret;
Eric Christopher6256b032011-04-22 03:19:48 +000099}
100
101/*===-- Symbols -----------------------------------------------------------===*/
102
103void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000104 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000105 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000106 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
107 if (Command->Type == macho::LCT_Symtab) {
Rafael Espindola82a21072013-04-06 03:31:08 +0000108 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000109 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000110 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
111 return;
112 }
113
114 DRI.d.a++;
115 DRI.d.b = 0;
116 }
117}
118
Rafael Espindola7df9c572013-04-09 00:22:58 +0000119const MachOFormat::SymbolTableEntryBase *
120MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000121 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000122 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000123 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Rafael Espindola7df9c572013-04-09 00:22:58 +0000124 return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
Rafael Espindola82a21072013-04-06 03:31:08 +0000125}
Eric Christopher6256b032011-04-22 03:19:48 +0000126
Rafael Espindola335f1d42013-04-08 20:45:01 +0000127const MachOFormat::SymbolTableEntry<false> *
Rafael Espindola7df9c572013-04-09 00:22:58 +0000128MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
129 const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
130 return reinterpret_cast<const MachOFormat::SymbolTableEntry<false>*>(Base);
131}
132
133const MachOFormat::SymbolTableEntryBase *
134MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI,
Rafael Espindola82a21072013-04-06 03:31:08 +0000135 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola00555c12013-04-06 01:59:05 +0000136 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
137 unsigned Index = DRI.d.b;
Rafael Espindola7df9c572013-04-09 00:22:58 +0000138
139 unsigned SymbolTableEntrySize = is64Bit() ?
140 sizeof(MachOFormat::SymbolTableEntry<true>) :
141 sizeof(MachOFormat::SymbolTableEntry<false>);
142
143 uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
144 StringRef Data = getData(Offset, SymbolTableEntrySize);
Rafael Espindola335f1d42013-04-08 20:45:01 +0000145 return
Rafael Espindola7df9c572013-04-09 00:22:58 +0000146 reinterpret_cast<const MachOFormat::SymbolTableEntryBase*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000147}
148
Rafael Espindola335f1d42013-04-08 20:45:01 +0000149const MachOFormat::SymbolTableEntry<true>*
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000150MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola7df9c572013-04-09 00:22:58 +0000151 const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
152 return reinterpret_cast<const MachOFormat::SymbolTableEntry<true>*>(Base);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000153}
154
Michael J. Spencer25b15772011-06-25 17:55:23 +0000155error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
156 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000157 DRI.d.b++;
158 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000159 Result = SymbolRef(DRI, this);
160 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000161}
162
Michael J. Spencer25b15772011-06-25 17:55:23 +0000163error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
164 StringRef &Result) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000165 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000166 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000167 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Rafael Espindola82a21072013-04-06 03:31:08 +0000168
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000169 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
170 SymtabLoadCmd->StringTableSize);
Rafael Espindola82a21072013-04-06 03:31:08 +0000171
Rafael Espindola7df9c572013-04-09 00:22:58 +0000172 const MachOFormat::SymbolTableEntryBase *Entry =
173 getSymbolTableEntryBase(DRI, SymtabLoadCmd);
174 uint32_t StringIndex = Entry->StringIndex;
Rafael Espindola82a21072013-04-06 03:31:08 +0000175
176 const char *Start = &StringTable.data()[StringIndex];
177 Result = StringRef(Start);
178
Michael J. Spencer25b15772011-06-25 17:55:23 +0000179 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000180}
181
Danil Malyshevb0436a72011-11-29 17:40:10 +0000182error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
183 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000184 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000185 const MachOFormat::SymbolTableEntry<true> *Entry =
186 getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000187 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000188 if (Entry->SectionIndex) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000189 const MachOFormat::Section<true> *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000190 getSection64(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000191 Result += Section->Offset - Section->Address;
192 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000193 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000194 const MachOFormat::SymbolTableEntry<false> *Entry =
195 getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000196 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000197 if (Entry->SectionIndex) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000198 const MachOFormat::Section<false> *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000199 getSection(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000200 Result += Section->Offset - Section->Address;
201 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000202 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000203
Michael J. Spencer25b15772011-06-25 17:55:23 +0000204 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000205}
206
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000207error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
208 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000209 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000210 const MachOFormat::SymbolTableEntry<true> *Entry =
211 getSymbol64TableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000212 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000213 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000214 const MachOFormat::SymbolTableEntry<false> *Entry =
215 getSymbolTableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000216 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000217 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000218 return object_error::success;
219}
220
Michael J. Spencer25b15772011-06-25 17:55:23 +0000221error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
222 uint64_t &Result) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000223 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000224 uint64_t BeginOffset;
225 uint64_t EndOffset = 0;
226 uint8_t SectionIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000227 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000228 const MachOFormat::SymbolTableEntry<true> *Entry =
229 getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000230 BeginOffset = Entry->Value;
231 SectionIndex = Entry->SectionIndex;
232 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000233 uint32_t flags = SymbolRef::SF_None;
234 getSymbolFlags(DRI, flags);
235 if (flags & SymbolRef::SF_Common)
236 Result = Entry->Value;
237 else
238 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000239 return object_error::success;
240 }
241 // Unfortunately symbols are unsorted so we need to touch all
242 // symbols from load command
243 DRI.d.b = 0;
244 uint32_t Command = DRI.d.a;
245 while (Command == DRI.d.a) {
246 moveToNextSymbol(DRI);
247 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000248 Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000249 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
250 if (!EndOffset || Entry->Value < EndOffset)
251 EndOffset = Entry->Value;
252 }
253 DRI.d.b++;
254 }
255 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000256 const MachOFormat::SymbolTableEntry<false> *Entry =
257 getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000258 BeginOffset = Entry->Value;
259 SectionIndex = Entry->SectionIndex;
260 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000261 uint32_t flags = SymbolRef::SF_None;
262 getSymbolFlags(DRI, flags);
263 if (flags & SymbolRef::SF_Common)
264 Result = Entry->Value;
265 else
266 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000267 return object_error::success;
268 }
269 // Unfortunately symbols are unsorted so we need to touch all
270 // symbols from load command
271 DRI.d.b = 0;
272 uint32_t Command = DRI.d.a;
273 while (Command == DRI.d.a) {
274 moveToNextSymbol(DRI);
275 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola00555c12013-04-06 01:59:05 +0000276 Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000277 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
278 if (!EndOffset || Entry->Value < EndOffset)
279 EndOffset = Entry->Value;
280 }
281 DRI.d.b++;
282 }
283 }
284 if (!EndOffset) {
285 uint64_t Size;
286 getSectionSize(Sections[SectionIndex-1], Size);
287 getSectionAddress(Sections[SectionIndex-1], EndOffset);
288 EndOffset += Size;
289 }
290 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000291 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000292}
293
Michael J. Spencer25b15772011-06-25 17:55:23 +0000294error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
295 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000296 uint8_t Type, Flags;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000297 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000298 const MachOFormat::SymbolTableEntry<true> *Entry =
299 getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000300 Type = Entry->Type;
301 Flags = Entry->Flags;
302 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000303 const MachOFormat::SymbolTableEntry<false> *Entry =
304 getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000305 Type = Entry->Type;
306 Flags = Entry->Flags;
307 }
Eric Christopher6256b032011-04-22 03:19:48 +0000308
309 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000310 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000311 case macho::STT_Undefined:
312 Char = 'u';
313 break;
314 case macho::STT_Absolute:
315 case macho::STT_Section:
316 Char = 's';
317 break;
318 default:
319 Char = '?';
320 break;
321 }
322
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000323 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000324 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000325 Result = Char;
326 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000327}
328
David Meyerc46255a2012-02-28 23:47:53 +0000329error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
330 uint32_t &Result) const {
331 uint16_t MachOFlags;
332 uint8_t MachOType;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000333 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000334 const MachOFormat::SymbolTableEntry<true> *Entry =
335 getSymbol64TableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000336 MachOFlags = Entry->Flags;
337 MachOType = Entry->Type;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000338 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000339 const MachOFormat::SymbolTableEntry<false> *Entry =
340 getSymbolTableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000341 MachOFlags = Entry->Flags;
342 MachOType = Entry->Type;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000343 }
344
Preston Gurdc68dda82012-04-12 20:13:57 +0000345 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000346 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000347
348 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
349 Result |= SymbolRef::SF_Undefined;
350
David Meyerc46255a2012-02-28 23:47:53 +0000351 if (MachOFlags & macho::STF_StabsEntryMask)
352 Result |= SymbolRef::SF_FormatSpecific;
353
Preston Gurdc68dda82012-04-12 20:13:57 +0000354 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000355 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000356 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
357 Result |= SymbolRef::SF_Common;
358 }
David Meyerc46255a2012-02-28 23:47:53 +0000359
360 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
361 Result |= SymbolRef::SF_Weak;
362
363 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
364 Result |= SymbolRef::SF_Absolute;
365
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000366 return object_error::success;
367}
368
369error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
370 section_iterator &Res) const {
371 uint8_t index;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000372 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000373 const MachOFormat::SymbolTableEntry<true> *Entry =
374 getSymbol64TableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000375 index = Entry->SectionIndex;
376 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000377 const MachOFormat::SymbolTableEntry<false> *Entry =
378 getSymbolTableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000379 index = Entry->SectionIndex;
380 }
381
382 if (index == 0)
383 Res = end_sections();
384 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000385 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000386
387 return object_error::success;
388}
389
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000390error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000391 SymbolRef::Type &Res) const {
Rafael Espindola7df9c572013-04-09 00:22:58 +0000392 const MachOFormat::SymbolTableEntryBase *Entry =
393 getSymbolTableEntryBase(Symb);
394 uint8_t n_type = Entry->Type;
395
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000396 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000397
398 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000399 if (n_type & MachO::NlistMaskStab) {
400 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000401 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000402 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000403
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000404 switch (n_type & MachO::NlistMaskType) {
405 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000406 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000407 break;
408 case MachO::NListTypeSection :
409 Res = SymbolRef::ST_Function;
410 break;
411 }
412 return object_error::success;
413}
414
Tim Northovera41dce32012-10-29 10:47:00 +0000415error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
416 uint64_t &Val) const {
417 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
418}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000419
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000420symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000421 // DRI.d.a = segment number; DRI.d.b = symbol index.
422 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000423 moveToNextSymbol(DRI);
424 return symbol_iterator(SymbolRef(DRI, this));
425}
426
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000427symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000428 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000429 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000430 return symbol_iterator(SymbolRef(DRI, this));
431}
432
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000433symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
434 // TODO: implement
435 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
436}
437
438symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
439 // TODO: implement
440 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
441}
Eric Christopher6256b032011-04-22 03:19:48 +0000442
David Meyer5c2b4ea2012-03-01 01:36:50 +0000443library_iterator MachOObjectFile::begin_libraries_needed() const {
444 // TODO: implement
445 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
446}
447
448library_iterator MachOObjectFile::end_libraries_needed() const {
449 // TODO: implement
450 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
451}
452
David Meyer97f77872012-03-01 22:19:54 +0000453StringRef MachOObjectFile::getLoadName() const {
454 // TODO: Implement
455 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
456}
457
Eric Christopher6256b032011-04-22 03:19:48 +0000458/*===-- Sections ----------------------------------------------------------===*/
459
460void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000461 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000462 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000463 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
464 if (Command->Type == macho::LCT_Segment) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000465 const MachOFormat::SegmentLoadCommand<false> *SegmentLoadCmd =
466 reinterpret_cast<const MachOFormat::SegmentLoadCommand<false>*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000467 if (DRI.d.b < SegmentLoadCmd->NumSections)
468 return;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000469 } else if (Command->Type == macho::LCT_Segment64) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000470 const MachOFormat::SegmentLoadCommand<true> *SegmentLoadCmd =
471 reinterpret_cast<const MachOFormat::SegmentLoadCommand<true>*>(Command);
472 if (DRI.d.b < SegmentLoadCmd->NumSections)
Eric Christopher6256b032011-04-22 03:19:48 +0000473 return;
474 }
475
476 DRI.d.a++;
477 DRI.d.b = 0;
478 }
479}
480
Michael J. Spencer25b15772011-06-25 17:55:23 +0000481error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
482 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000483 DRI.d.b++;
484 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000485 Result = SectionRef(DRI, this);
486 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000487}
488
Rafael Espindola335f1d42013-04-08 20:45:01 +0000489const MachOFormat::Section<false> *
490MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000491 assert(!is64Bit());
Rafael Espindola33885892013-04-08 23:57:13 +0000492 const MachOFormat::SectionBase *Addr = getSectionBase(DRI);
493 return reinterpret_cast<const MachOFormat::Section<false>*>(Addr);
Eric Christopher6256b032011-04-22 03:19:48 +0000494}
495
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000496std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
497 SectionList::const_iterator loc =
498 std::find(Sections.begin(), Sections.end(), Sec);
499 assert(loc != Sections.end() && "Sec is not a valid section!");
500 return std::distance(Sections.begin(), loc);
501}
502
Rafael Espindola33885892013-04-08 23:57:13 +0000503const MachOFormat::SectionBase*
504MachOObjectFile::getSectionBase(DataRefImpl DRI) const {
505 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
506 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
507
508 bool Is64 = is64Bit();
509 unsigned SegmentLoadSize =
510 Is64 ? sizeof(MachOFormat::SegmentLoadCommand<true>) :
511 sizeof(MachOFormat::SegmentLoadCommand<false>);
512 unsigned SectionSize = Is64 ? sizeof(MachOFormat::Section<true>) :
513 sizeof(MachOFormat::Section<false>);
514
515 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
516 return reinterpret_cast<const MachOFormat::SectionBase*>(SectionAddr);
517}
518
Rafael Espindola335f1d42013-04-08 20:45:01 +0000519const MachOFormat::Section<true> *
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000520MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000521 assert(is64Bit());
Rafael Espindola33885892013-04-08 23:57:13 +0000522 const MachOFormat::SectionBase *Addr = getSectionBase(DRI);
523 return reinterpret_cast<const MachOFormat::Section<true>*>(Addr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000524}
525
Rafael Espindolacef81b32012-12-21 03:47:03 +0000526static StringRef parseSegmentOrSectionName(const char *P) {
527 if (P[15] == 0)
528 // Null terminated.
529 return P;
530 // Not null terminated, so this is a 16 char string.
531 return StringRef(P, 16);
532}
533
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000534ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
Rafael Espindola33885892013-04-08 23:57:13 +0000535 const MachOFormat::SectionBase *Base = getSectionBase(DRI);
536 return ArrayRef<char>(Base->Name);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000537}
538
539error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
540 StringRef &Result) const {
541 ArrayRef<char> Raw = getSectionRawName(DRI);
542 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000543 return object_error::success;
544}
545
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000546ArrayRef<char>
547MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola33885892013-04-08 23:57:13 +0000548 const MachOFormat::SectionBase *Base = getSectionBase(Sec);
549 return ArrayRef<char>(Base->SegmentName);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000550}
551
552StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
553 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
554 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000555}
556
Michael J. Spencer25b15772011-06-25 17:55:23 +0000557error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
558 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000559 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000560 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000561 Result = Sect->Address;
562 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000563 const MachOFormat::Section<false> *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000564 Result = Sect->Address;
565 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000566 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000567}
568
Michael J. Spencer25b15772011-06-25 17:55:23 +0000569error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
570 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000571 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000572 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000573 Result = Sect->Size;
574 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000575 const MachOFormat::Section<false> *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000576 Result = Sect->Size;
577 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000578 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000579}
580
Michael J. Spencer25b15772011-06-25 17:55:23 +0000581error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
582 StringRef &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000583 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000584 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000585 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000586 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000587 const MachOFormat::Section<false> *Sect = getSection(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000588 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000589 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000590 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000591}
592
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000593error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
594 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000595 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000596 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000597 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000598 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000599 const MachOFormat::Section<false> *Sect = getSection(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000600 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000601 }
602 return object_error::success;
603}
604
Michael J. Spencer25b15772011-06-25 17:55:23 +0000605error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
606 bool &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000607 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000608 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000609 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000610 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000611 const MachOFormat::Section<false> *Sect = getSection(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000612 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000613 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000614 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000615}
616
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000617error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
618 bool &Result) const {
619 // FIXME: Unimplemented.
620 Result = false;
621 return object_error::success;
622}
623
624error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
625 bool &Result) const {
626 // FIXME: Unimplemented.
627 Result = false;
628 return object_error::success;
629}
630
Preston Gurdc68dda82012-04-12 20:13:57 +0000631error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
632 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000633 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000634 Result = true;
635 return object_error::success;
636}
637
638error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000639 bool &Result) const {
640 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000641 Result = false;
642 return object_error::success;
643}
644
645error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
646 bool &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000647 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000648 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000649 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
650 Result = (SectionType == MachO::SectionTypeZeroFill ||
651 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000652 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000653 const MachOFormat::Section<false> *Sect = getSection(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000654 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
655 Result = (SectionType == MachO::SectionTypeZeroFill ||
656 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000657 }
658
659 return object_error::success;
660}
661
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000662error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
663 bool &Result) const {
664 // Consider using the code from isSectionText to look for __const sections.
665 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
666 // to use section attributes to distinguish code from data.
667
668 // FIXME: Unimplemented.
669 Result = false;
670 return object_error::success;
671}
672
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000673error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
674 DataRefImpl Symb,
675 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000676 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000677 getSymbolType(Symb, ST);
David Meyer2c677272012-02-29 02:11:55 +0000678 if (ST == SymbolRef::ST_Unknown) {
Owen Andersoncd749882011-10-12 22:21:32 +0000679 Result = false;
680 return object_error::success;
681 }
682
683 uint64_t SectBegin, SectEnd;
684 getSectionAddress(Sec, SectBegin);
685 getSectionSize(Sec, SectEnd);
686 SectEnd += SectBegin;
687
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000688 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000689 const MachOFormat::SymbolTableEntry<true> *Entry =
690 getSymbol64TableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000691 uint64_t SymAddr= Entry->Value;
692 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000693 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000694 const MachOFormat::SymbolTableEntry<false> *Entry =
695 getSymbolTableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000696 uint64_t SymAddr= Entry->Value;
697 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000698 }
Owen Andersoncd749882011-10-12 22:21:32 +0000699
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000700 return object_error::success;
701}
702
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000703relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
704 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000705 ret.d.b = getSectionIndex(Sec);
706 return relocation_iterator(RelocationRef(ret, this));
707}
Rafael Espindola335f1d42013-04-08 20:45:01 +0000708
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000709relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
710 uint32_t last_reloc;
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000711 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000712 const MachOFormat::Section<true> *Sect = getSection64(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000713 last_reloc = Sect->NumRelocationTableEntries;
714 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000715 const MachOFormat::Section<false> *Sect = getSection(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000716 last_reloc = Sect->NumRelocationTableEntries;
717 }
718 DataRefImpl ret;
719 ret.d.a = last_reloc;
720 ret.d.b = getSectionIndex(Sec);
721 return relocation_iterator(RelocationRef(ret, this));
722}
723
724section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000725 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000726 moveToNextSection(DRI);
727 return section_iterator(SectionRef(DRI, this));
728}
729
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000730section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000731 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000732 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000733 return section_iterator(SectionRef(DRI, this));
734}
735
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000736/*===-- Relocations -------------------------------------------------------===*/
737
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000738const MachOFormat::RelocationEntry *
739MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000740 uint32_t relOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000741 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000742 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000743 relOffset = Sect->RelocationTableOffset;
744 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000745 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000746 relOffset = Sect->RelocationTableOffset;
747 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000748 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000749 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000750 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000751}
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000752
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000753error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
754 RelocationRef &Res) const {
755 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000756 Res = RelocationRef(Rel, this);
757 return object_error::success;
758}
759error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
760 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000761 const uint8_t* sectAddress = 0;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000762 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000763 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000764 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000765 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000766 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000767 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000768 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000769 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000770
771 unsigned Arch = getArch();
772 bool isScattered = (Arch != Triple::x86_64) &&
773 (RE->Word0 & macho::RF_Scattered);
774 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000775 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000776 RelAddr = RE->Word0 & 0xFFFFFF;
777 else
778 RelAddr = RE->Word0;
779
780 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000781 return object_error::success;
782}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000783error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
784 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000785 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000786
787 unsigned Arch = getArch();
788 bool isScattered = (Arch != Triple::x86_64) &&
789 (RE->Word0 & macho::RF_Scattered);
790 if (isScattered)
791 Res = RE->Word0 & 0xFFFFFF;
792 else
793 Res = RE->Word0;
794 return object_error::success;
795}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000796error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
797 SymbolRef &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000798 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000799 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
800 bool isExtern = (RE->Word1 >> 27) & 1;
801
802 DataRefImpl Sym;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000803 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000804 if (isExtern) {
805 for (unsigned i = 0; i < SymbolIdx; i++) {
806 Sym.d.b++;
807 moveToNextSymbol(Sym);
Rafael Espindola433611b2013-04-07 19:26:57 +0000808 assert(Sym.d.a < getHeader()->NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000809 "Relocation symbol index out of range!");
810 }
811 }
812 Res = SymbolRef(Sym, this);
813 return object_error::success;
814}
815error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000816 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000817 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Andersonf8261e72011-10-26 17:10:22 +0000818 Res = RE->Word0;
819 Res <<= 32;
820 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000821 return object_error::success;
822}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000823error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
824 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000825 // TODO: Support scattered relocations.
826 StringRef res;
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000827 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +0000828
829 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000830 bool isScattered = (Arch != Triple::x86_64) &&
831 (RE->Word0 & macho::RF_Scattered);
832
833 unsigned r_type;
834 if (isScattered)
835 r_type = (RE->Word0 >> 24) & 0xF;
836 else
837 r_type = (RE->Word1 >> 28) & 0xF;
838
Owen Anderson0135fe12011-10-24 21:44:00 +0000839 switch (Arch) {
840 case Triple::x86: {
Craig Toppere3298102012-05-24 06:35:32 +0000841 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000842 "GENERIC_RELOC_VANILLA",
843 "GENERIC_RELOC_PAIR",
844 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000845 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000846 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000847 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000848
Owen Andersoneb6bd332011-10-27 20:46:09 +0000849 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000850 res = "Unknown";
851 else
852 res = Table[r_type];
853 break;
854 }
855 case Triple::x86_64: {
Craig Toppere3298102012-05-24 06:35:32 +0000856 static const char *const Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000857 "X86_64_RELOC_UNSIGNED",
858 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000859 "X86_64_RELOC_BRANCH",
860 "X86_64_RELOC_GOT_LOAD",
861 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000862 "X86_64_RELOC_SUBTRACTOR",
863 "X86_64_RELOC_SIGNED_1",
864 "X86_64_RELOC_SIGNED_2",
865 "X86_64_RELOC_SIGNED_4",
866 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000867
Owen Andersond8fa76d2011-10-24 23:20:07 +0000868 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000869 res = "Unknown";
870 else
871 res = Table[r_type];
872 break;
873 }
874 case Triple::arm: {
Craig Toppere3298102012-05-24 06:35:32 +0000875 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000876 "ARM_RELOC_VANILLA",
877 "ARM_RELOC_PAIR",
878 "ARM_RELOC_SECTDIFF",
879 "ARM_RELOC_LOCAL_SECTDIFF",
880 "ARM_RELOC_PB_LA_PTR",
881 "ARM_RELOC_BR24",
882 "ARM_THUMB_RELOC_BR22",
883 "ARM_THUMB_32BIT_BRANCH",
884 "ARM_RELOC_HALF",
885 "ARM_RELOC_HALF_SECTDIFF" };
886
887 if (r_type > 9)
888 res = "Unknown";
889 else
890 res = Table[r_type];
891 break;
892 }
893 case Triple::ppc: {
Craig Toppere3298102012-05-24 06:35:32 +0000894 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000895 "PPC_RELOC_VANILLA",
896 "PPC_RELOC_PAIR",
897 "PPC_RELOC_BR14",
898 "PPC_RELOC_BR24",
899 "PPC_RELOC_HI16",
900 "PPC_RELOC_LO16",
901 "PPC_RELOC_HA16",
902 "PPC_RELOC_LO14",
903 "PPC_RELOC_SECTDIFF",
904 "PPC_RELOC_PB_LA_PTR",
905 "PPC_RELOC_HI16_SECTDIFF",
906 "PPC_RELOC_LO16_SECTDIFF",
907 "PPC_RELOC_HA16_SECTDIFF",
908 "PPC_RELOC_JBSR",
909 "PPC_RELOC_LO14_SECTDIFF",
910 "PPC_RELOC_LOCAL_SECTDIFF" };
911
912 res = Table[r_type];
913 break;
914 }
915 case Triple::UnknownArch:
916 res = "Unknown";
917 break;
918 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000919 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000920 return object_error::success;
921}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000922error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
923 int64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000924 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000925 bool isExtern = (RE->Word1 >> 27) & 1;
926 Res = 0;
927 if (!isExtern) {
928 const uint8_t* sectAddress = base();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000929 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000930 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000931 sectAddress += Sect->Offset;
932 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000933 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000934 sectAddress += Sect->Offset;
935 }
936 Res = reinterpret_cast<uintptr_t>(sectAddress);
937 }
938 return object_error::success;
939}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000940
941// Helper to advance a section or symbol iterator multiple increments at a time.
942template<class T>
943error_code advance(T &it, size_t Val) {
944 error_code ec;
945 while (Val--) {
946 it.increment(ec);
947 }
948 return ec;
949}
950
951template<class T>
952void advanceTo(T &it, size_t Val) {
953 if (error_code ec = advance(it, Val))
954 report_fatal_error(ec.message());
955}
956
Owen Anderson1832f4d2011-10-26 20:42:54 +0000957void MachOObjectFile::printRelocationTargetName(
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000958 const MachOFormat::RelocationEntry *RE,
Owen Anderson1832f4d2011-10-26 20:42:54 +0000959 raw_string_ostream &fmt) const {
960 unsigned Arch = getArch();
961 bool isScattered = (Arch != Triple::x86_64) &&
962 (RE->Word0 & macho::RF_Scattered);
963
964 // Target of a scattered relocation is an address. In the interest of
965 // generating pretty output, scan through the symbol table looking for a
966 // symbol that aligns with that address. If we find one, print it.
967 // Otherwise, we just print the hex address of the target.
968 if (isScattered) {
969 uint32_t Val = RE->Word1;
970
971 error_code ec;
972 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
973 SI.increment(ec)) {
974 if (ec) report_fatal_error(ec.message());
975
976 uint64_t Addr;
977 StringRef Name;
978
979 if ((ec = SI->getAddress(Addr)))
980 report_fatal_error(ec.message());
981 if (Addr != Val) continue;
982 if ((ec = SI->getName(Name)))
983 report_fatal_error(ec.message());
984 fmt << Name;
985 return;
986 }
987
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000988 // If we couldn't find a symbol that this relocation refers to, try
989 // to find a section beginning instead.
990 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
991 SI.increment(ec)) {
992 if (ec) report_fatal_error(ec.message());
993
994 uint64_t Addr;
995 StringRef Name;
996
997 if ((ec = SI->getAddress(Addr)))
998 report_fatal_error(ec.message());
999 if (Addr != Val) continue;
1000 if ((ec = SI->getName(Name)))
1001 report_fatal_error(ec.message());
1002 fmt << Name;
1003 return;
1004 }
1005
Owen Anderson1832f4d2011-10-26 20:42:54 +00001006 fmt << format("0x%x", Val);
1007 return;
1008 }
1009
1010 StringRef S;
1011 bool isExtern = (RE->Word1 >> 27) & 1;
1012 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001013
1014 if (isExtern) {
1015 symbol_iterator SI = begin_symbols();
1016 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001017 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001018 } else {
1019 section_iterator SI = begin_sections();
1020 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001021 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001022 }
1023
Owen Anderson1832f4d2011-10-26 20:42:54 +00001024 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001025}
1026
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001027error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1028 SmallVectorImpl<char> &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001029 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +00001030
Owen Anderson1832f4d2011-10-26 20:42:54 +00001031 unsigned Arch = getArch();
1032 bool isScattered = (Arch != Triple::x86_64) &&
1033 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001034
Owen Anderson013d7562011-10-25 18:48:41 +00001035 std::string fmtbuf;
1036 raw_string_ostream fmt(fmtbuf);
1037
Owen Anderson1832f4d2011-10-26 20:42:54 +00001038 unsigned Type;
1039 if (isScattered)
1040 Type = (RE->Word0 >> 24) & 0xF;
1041 else
1042 Type = (RE->Word1 >> 28) & 0xF;
1043
Owen Andersoneb6bd332011-10-27 20:46:09 +00001044 bool isPCRel;
1045 if (isScattered)
1046 isPCRel = ((RE->Word0 >> 30) & 1);
1047 else
1048 isPCRel = ((RE->Word1 >> 24) & 1);
1049
Owen Andersond8fa76d2011-10-24 23:20:07 +00001050 // Determine any addends that should be displayed with the relocation.
1051 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +00001052
1053 // X86_64 has entirely custom relocation types.
1054 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +00001055 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +00001056
Owen Andersond8fa76d2011-10-24 23:20:07 +00001057 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001058 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1059 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1060 printRelocationTargetName(RE, fmt);
1061 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +00001062 if (isPCRel) fmt << "PCREL";
1063 break;
1064 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001065 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +00001066 DataRefImpl RelNext = Rel;
1067 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001068 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001069
1070 // X86_64_SUBTRACTOR must be followed by a relocation of type
1071 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001072 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +00001073 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001074 if (RType != 0)
1075 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1076 "X86_64_RELOC_SUBTRACTOR.");
1077
Owen Andersonef22f782011-10-26 17:28:49 +00001078 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1079 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001080 printRelocationTargetName(RENext, fmt);
1081 fmt << "-";
1082 printRelocationTargetName(RE, fmt);
Jim Grosbach133f6b82013-01-31 19:46:57 +00001083 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001084 }
Owen Andersoneb6bd332011-10-27 20:46:09 +00001085 case macho::RIT_X86_64_TLV:
1086 printRelocationTargetName(RE, fmt);
1087 fmt << "@TLV";
1088 if (isPCRel) fmt << "P";
1089 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001090 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1091 printRelocationTargetName(RE, fmt);
1092 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001093 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001094 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1095 printRelocationTargetName(RE, fmt);
1096 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001097 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001098 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1099 printRelocationTargetName(RE, fmt);
1100 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +00001101 break;
1102 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001103 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001104 break;
1105 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001106 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001107 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1108 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001109 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001110 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001111 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001112 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001113 DataRefImpl RelNext = Rel;
1114 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001115 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001116
1117 // X86 sect diff's must be followed by a relocation of type
1118 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001119 bool isNextScattered = (Arch != Triple::x86_64) &&
1120 (RENext->Word0 & macho::RF_Scattered);
1121 unsigned RType;
1122 if (isNextScattered)
1123 RType = (RENext->Word0 >> 24) & 0xF;
1124 else
1125 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001126 if (RType != 1)
1127 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001128 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001129
Owen Anderson1832f4d2011-10-26 20:42:54 +00001130 printRelocationTargetName(RE, fmt);
1131 fmt << "-";
1132 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001133 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001134 }
1135 }
Owen Anderson013d7562011-10-25 18:48:41 +00001136
Owen Anderson1832f4d2011-10-26 20:42:54 +00001137 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001138 // All X86 relocations that need special printing were already
1139 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001140 switch (Type) {
1141 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
Owen Andersoneb6bd332011-10-27 20:46:09 +00001142 DataRefImpl RelNext = Rel;
1143 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001144 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersoneb6bd332011-10-27 20:46:09 +00001145
1146 // X86 sect diff's must be followed by a relocation of type
1147 // GENERIC_RELOC_PAIR.
1148 bool isNextScattered = (Arch != Triple::x86_64) &&
1149 (RENext->Word0 & macho::RF_Scattered);
1150 unsigned RType;
1151 if (isNextScattered)
1152 RType = (RENext->Word0 >> 24) & 0xF;
1153 else
1154 RType = (RENext->Word1 >> 28) & 0xF;
1155 if (RType != 1)
1156 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1157 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1158
1159 printRelocationTargetName(RE, fmt);
1160 fmt << "-";
1161 printRelocationTargetName(RENext, fmt);
1162 break;
1163 }
1164 case macho::RIT_Generic_TLV: {
1165 printRelocationTargetName(RE, fmt);
1166 fmt << "@TLV";
1167 if (isPCRel) fmt << "P";
1168 break;
1169 }
1170 default:
1171 printRelocationTargetName(RE, fmt);
1172 }
Owen Anderson013d7562011-10-25 18:48:41 +00001173 } else { // ARM-specific relocations
1174 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001175 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1176 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001177 // Half relocations steal a bit from the length field to encode
1178 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001179 bool isUpper;
1180 if (isScattered)
1181 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001182 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001183 isUpper = (RE->Word1 >> 25) & 1;
1184
1185 if (isUpper)
1186 fmt << ":upper16:(";
1187 else
1188 fmt << ":lower16:(";
1189 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001190
Owen Anderson013d7562011-10-25 18:48:41 +00001191 DataRefImpl RelNext = Rel;
1192 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001193 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Anderson013d7562011-10-25 18:48:41 +00001194
1195 // ARM half relocs must be followed by a relocation of type
1196 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001197 bool isNextScattered = (Arch != Triple::x86_64) &&
1198 (RENext->Word0 & macho::RF_Scattered);
1199 unsigned RType;
1200 if (isNextScattered)
1201 RType = (RENext->Word0 >> 24) & 0xF;
1202 else
1203 RType = (RENext->Word1 >> 28) & 0xF;
1204
Owen Anderson013d7562011-10-25 18:48:41 +00001205 if (RType != 1)
1206 report_fatal_error("Expected ARM_RELOC_PAIR after "
1207 "GENERIC_RELOC_HALF");
1208
Owen Anderson1832f4d2011-10-26 20:42:54 +00001209 // NOTE: The half of the target virtual address is stashed in the
1210 // address field of the secondary relocation, but we can't reverse
1211 // engineer the constant offset from it without decoding the movw/movt
1212 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001213
1214 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1215 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001216 if (Type == macho::RIT_ARM_HalfDifference) {
1217 fmt << "-";
1218 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001219 }
1220
Owen Anderson013d7562011-10-25 18:48:41 +00001221 fmt << ")";
1222 break;
1223 }
1224 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001225 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001226 }
1227 }
1228 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001229 } else
1230 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001231
Owen Anderson0135fe12011-10-24 21:44:00 +00001232 fmt.flush();
1233 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001234 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001235}
1236
Owen Anderson0685e942011-10-25 20:35:53 +00001237error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1238 bool &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001239 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0685e942011-10-25 20:35:53 +00001240
Owen Anderson0685e942011-10-25 20:35:53 +00001241 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001242 bool isScattered = (Arch != Triple::x86_64) &&
1243 (RE->Word0 & macho::RF_Scattered);
1244 unsigned Type;
1245 if (isScattered)
1246 Type = (RE->Word0 >> 24) & 0xF;
1247 else
1248 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001249
1250 Result = false;
1251
1252 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1253 // is always hidden.
1254 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001255 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001256 } else if (Arch == Triple::x86_64) {
1257 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1258 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001259 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001260 DataRefImpl RelPrev = Rel;
1261 RelPrev.d.a--;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001262 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
Owen Anderson0685e942011-10-25 20:35:53 +00001263
1264 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1265
Owen Anderson1832f4d2011-10-26 20:42:54 +00001266 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001267 }
1268 }
1269
1270 return object_error::success;
1271}
1272
David Meyer5c2b4ea2012-03-01 01:36:50 +00001273error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1274 LibraryRef &Res) const {
1275 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1276}
1277
1278error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1279 StringRef &Res) const {
1280 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1281}
1282
1283
Eric Christopher6256b032011-04-22 03:19:48 +00001284/*===-- Miscellaneous -----------------------------------------------------===*/
1285
1286uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001287 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001288}
1289
1290StringRef MachOObjectFile::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001291 if (!is64Bit()) {
Rafael Espindola433611b2013-04-07 19:26:57 +00001292 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001293 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001294 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001295 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001296 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001297 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001298 return "Mach-O 32-bit ppc";
1299 default:
Rafael Espindola433611b2013-04-07 19:26:57 +00001300 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001301 "64-bit object file when we're not 64-bit?");
1302 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001303 }
1304 }
1305
Eric Christopherb3e6b042013-02-28 20:26:17 +00001306 // Make sure the cpu type has the correct mask.
Rafael Espindola433611b2013-04-07 19:26:57 +00001307 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +00001308 == llvm::MachO::CPUArchABI64 &&
1309 "32-bit object file when we're 64-bit?");
1310
Rafael Espindola433611b2013-04-07 19:26:57 +00001311 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001312 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001313 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001314 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001315 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001316 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001317 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001318 }
1319}
1320
1321unsigned MachOObjectFile::getArch() const {
Rafael Espindola433611b2013-04-07 19:26:57 +00001322 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001323 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001324 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001325 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001326 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001327 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001328 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001329 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001330 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001331 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001332 return Triple::ppc64;
1333 default:
1334 return Triple::UnknownArch;
1335 }
1336}
1337
Owen Andersonf7c93a32011-10-11 17:32:27 +00001338} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001339} // end namespace llvm