blob: 30ab00f450c1035f0dfb306547678905fdfa36a1 [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 Espindola335f1d42013-04-08 20:45:01 +0000119const MachOFormat::SymbolTableEntry<false> *
Rafael Espindola00555c12013-04-06 01:59:05 +0000120MachOObjectFile::getSymbolTableEntry(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);
Eric Christopher6256b032011-04-22 03:19:48 +0000124
Rafael Espindola82a21072013-04-06 03:31:08 +0000125 return getSymbolTableEntry(DRI, SymtabLoadCmd);
126}
Eric Christopher6256b032011-04-22 03:19:48 +0000127
Rafael Espindola335f1d42013-04-08 20:45:01 +0000128const MachOFormat::SymbolTableEntry<false> *
Rafael Espindola82a21072013-04-06 03:31:08 +0000129MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
130 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola00555c12013-04-06 01:59:05 +0000131 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
132 unsigned Index = DRI.d.b;
133 uint64_t Offset = (SymbolTableOffset +
Rafael Espindola335f1d42013-04-08 20:45:01 +0000134 Index * sizeof(MachOFormat::SymbolTableEntry<false>));
135 StringRef Data =
136 getData(Offset, sizeof(MachOFormat::SymbolTableEntry<false>));
137 return
138 reinterpret_cast<const MachOFormat::SymbolTableEntry<false>*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000139}
140
Rafael Espindola335f1d42013-04-08 20:45:01 +0000141const MachOFormat::SymbolTableEntry<true>*
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000142MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000143 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000144 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000145 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000146
Rafael Espindola82a21072013-04-06 03:31:08 +0000147 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
148}
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000149
Rafael Espindola335f1d42013-04-08 20:45:01 +0000150const MachOFormat::SymbolTableEntry<true>*
Rafael Espindola82a21072013-04-06 03:31:08 +0000151MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
152 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000153 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
154 unsigned Index = DRI.d.b;
155 uint64_t Offset = (SymbolTableOffset +
Rafael Espindola335f1d42013-04-08 20:45:01 +0000156 Index * sizeof(MachOFormat::SymbolTableEntry<true>));
157 StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry<true>));
158 return
159 reinterpret_cast<const MachOFormat::SymbolTableEntry<true>*>(Data.data());
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000160}
161
Michael J. Spencer25b15772011-06-25 17:55:23 +0000162error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
163 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000164 DRI.d.b++;
165 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000166 Result = SymbolRef(DRI, this);
167 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000168}
169
Michael J. Spencer25b15772011-06-25 17:55:23 +0000170error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
171 StringRef &Result) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000172 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000173 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000174 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Rafael Espindola82a21072013-04-06 03:31:08 +0000175
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000176 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
177 SymtabLoadCmd->StringTableSize);
Rafael Espindola82a21072013-04-06 03:31:08 +0000178
179 uint32_t StringIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000180 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000181 const MachOFormat::SymbolTableEntry<true> *Entry =
Rafael Espindola82a21072013-04-06 03:31:08 +0000182 getSymbol64TableEntry(DRI, SymtabLoadCmd);
183 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000184 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000185 const MachOFormat::SymbolTableEntry<false> *Entry =
Rafael Espindola82a21072013-04-06 03:31:08 +0000186 getSymbolTableEntry(DRI, SymtabLoadCmd);
187 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000188 }
Rafael Espindola82a21072013-04-06 03:31:08 +0000189
190 const char *Start = &StringTable.data()[StringIndex];
191 Result = StringRef(Start);
192
Michael J. Spencer25b15772011-06-25 17:55:23 +0000193 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000194}
195
Danil Malyshevb0436a72011-11-29 17:40:10 +0000196error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
197 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000198 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000199 const MachOFormat::SymbolTableEntry<true> *Entry =
200 getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000201 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000202 if (Entry->SectionIndex) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000203 const MachOFormat::Section<true> *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000204 getSection64(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000205 Result += Section->Offset - Section->Address;
206 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000207 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000208 const MachOFormat::SymbolTableEntry<false> *Entry =
209 getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000210 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000211 if (Entry->SectionIndex) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000212 const MachOFormat::Section<false> *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000213 getSection(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000214 Result += Section->Offset - Section->Address;
215 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000216 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000217
Michael J. Spencer25b15772011-06-25 17:55:23 +0000218 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000219}
220
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000221error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
222 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000223 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000224 const MachOFormat::SymbolTableEntry<true> *Entry =
225 getSymbol64TableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000226 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000227 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000228 const MachOFormat::SymbolTableEntry<false> *Entry =
229 getSymbolTableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000230 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000231 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000232 return object_error::success;
233}
234
Michael J. Spencer25b15772011-06-25 17:55:23 +0000235error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
236 uint64_t &Result) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000237 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000238 uint64_t BeginOffset;
239 uint64_t EndOffset = 0;
240 uint8_t SectionIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000241 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000242 const MachOFormat::SymbolTableEntry<true> *Entry =
243 getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000244 BeginOffset = Entry->Value;
245 SectionIndex = Entry->SectionIndex;
246 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000247 uint32_t flags = SymbolRef::SF_None;
248 getSymbolFlags(DRI, flags);
249 if (flags & SymbolRef::SF_Common)
250 Result = Entry->Value;
251 else
252 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000253 return object_error::success;
254 }
255 // Unfortunately symbols are unsorted so we need to touch all
256 // symbols from load command
257 DRI.d.b = 0;
258 uint32_t Command = DRI.d.a;
259 while (Command == DRI.d.a) {
260 moveToNextSymbol(DRI);
261 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000262 Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000263 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
264 if (!EndOffset || Entry->Value < EndOffset)
265 EndOffset = Entry->Value;
266 }
267 DRI.d.b++;
268 }
269 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000270 const MachOFormat::SymbolTableEntry<false> *Entry =
271 getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000272 BeginOffset = Entry->Value;
273 SectionIndex = Entry->SectionIndex;
274 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000275 uint32_t flags = SymbolRef::SF_None;
276 getSymbolFlags(DRI, flags);
277 if (flags & SymbolRef::SF_Common)
278 Result = Entry->Value;
279 else
280 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000281 return object_error::success;
282 }
283 // Unfortunately symbols are unsorted so we need to touch all
284 // symbols from load command
285 DRI.d.b = 0;
286 uint32_t Command = DRI.d.a;
287 while (Command == DRI.d.a) {
288 moveToNextSymbol(DRI);
289 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola00555c12013-04-06 01:59:05 +0000290 Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000291 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
292 if (!EndOffset || Entry->Value < EndOffset)
293 EndOffset = Entry->Value;
294 }
295 DRI.d.b++;
296 }
297 }
298 if (!EndOffset) {
299 uint64_t Size;
300 getSectionSize(Sections[SectionIndex-1], Size);
301 getSectionAddress(Sections[SectionIndex-1], EndOffset);
302 EndOffset += Size;
303 }
304 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000305 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000306}
307
Michael J. Spencer25b15772011-06-25 17:55:23 +0000308error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
309 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000310 uint8_t Type, Flags;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000311 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000312 const MachOFormat::SymbolTableEntry<true> *Entry =
313 getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000314 Type = Entry->Type;
315 Flags = Entry->Flags;
316 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000317 const MachOFormat::SymbolTableEntry<false> *Entry =
318 getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000319 Type = Entry->Type;
320 Flags = Entry->Flags;
321 }
Eric Christopher6256b032011-04-22 03:19:48 +0000322
323 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000324 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000325 case macho::STT_Undefined:
326 Char = 'u';
327 break;
328 case macho::STT_Absolute:
329 case macho::STT_Section:
330 Char = 's';
331 break;
332 default:
333 Char = '?';
334 break;
335 }
336
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000337 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000338 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000339 Result = Char;
340 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000341}
342
David Meyerc46255a2012-02-28 23:47:53 +0000343error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
344 uint32_t &Result) const {
345 uint16_t MachOFlags;
346 uint8_t MachOType;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000347 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000348 const MachOFormat::SymbolTableEntry<true> *Entry =
349 getSymbol64TableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000350 MachOFlags = Entry->Flags;
351 MachOType = Entry->Type;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000352 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000353 const MachOFormat::SymbolTableEntry<false> *Entry =
354 getSymbolTableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000355 MachOFlags = Entry->Flags;
356 MachOType = Entry->Type;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000357 }
358
Preston Gurdc68dda82012-04-12 20:13:57 +0000359 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000360 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000361
362 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
363 Result |= SymbolRef::SF_Undefined;
364
David Meyerc46255a2012-02-28 23:47:53 +0000365 if (MachOFlags & macho::STF_StabsEntryMask)
366 Result |= SymbolRef::SF_FormatSpecific;
367
Preston Gurdc68dda82012-04-12 20:13:57 +0000368 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000369 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000370 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
371 Result |= SymbolRef::SF_Common;
372 }
David Meyerc46255a2012-02-28 23:47:53 +0000373
374 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
375 Result |= SymbolRef::SF_Weak;
376
377 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
378 Result |= SymbolRef::SF_Absolute;
379
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000380 return object_error::success;
381}
382
383error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
384 section_iterator &Res) const {
385 uint8_t index;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000386 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000387 const MachOFormat::SymbolTableEntry<true> *Entry =
388 getSymbol64TableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000389 index = Entry->SectionIndex;
390 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000391 const MachOFormat::SymbolTableEntry<false> *Entry =
392 getSymbolTableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000393 index = Entry->SectionIndex;
394 }
395
396 if (index == 0)
397 Res = end_sections();
398 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000399 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000400
401 return object_error::success;
402}
403
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000404error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000405 SymbolRef::Type &Res) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000406 uint8_t n_type;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000407 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000408 const MachOFormat::SymbolTableEntry<true> *Entry =
409 getSymbol64TableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000410 n_type = Entry->Type;
411 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000412 const MachOFormat::SymbolTableEntry<false> *Entry =
413 getSymbolTableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000414 n_type = Entry->Type;
415 }
416 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000417
418 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000419 if (n_type & MachO::NlistMaskStab) {
420 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000421 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000422 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000423
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000424 switch (n_type & MachO::NlistMaskType) {
425 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000426 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000427 break;
428 case MachO::NListTypeSection :
429 Res = SymbolRef::ST_Function;
430 break;
431 }
432 return object_error::success;
433}
434
Tim Northovera41dce32012-10-29 10:47:00 +0000435error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
436 uint64_t &Val) const {
437 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
438}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000439
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000440symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000441 // DRI.d.a = segment number; DRI.d.b = symbol index.
442 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000443 moveToNextSymbol(DRI);
444 return symbol_iterator(SymbolRef(DRI, this));
445}
446
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000447symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000448 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000449 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000450 return symbol_iterator(SymbolRef(DRI, this));
451}
452
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000453symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
454 // TODO: implement
455 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
456}
457
458symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
459 // TODO: implement
460 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
461}
Eric Christopher6256b032011-04-22 03:19:48 +0000462
David Meyer5c2b4ea2012-03-01 01:36:50 +0000463library_iterator MachOObjectFile::begin_libraries_needed() const {
464 // TODO: implement
465 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
466}
467
468library_iterator MachOObjectFile::end_libraries_needed() const {
469 // TODO: implement
470 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
471}
472
David Meyer97f77872012-03-01 22:19:54 +0000473StringRef MachOObjectFile::getLoadName() const {
474 // TODO: Implement
475 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
476}
477
Eric Christopher6256b032011-04-22 03:19:48 +0000478/*===-- Sections ----------------------------------------------------------===*/
479
480void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000481 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000482 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000483 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
484 if (Command->Type == macho::LCT_Segment) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000485 const MachOFormat::SegmentLoadCommand<false> *SegmentLoadCmd =
486 reinterpret_cast<const MachOFormat::SegmentLoadCommand<false>*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000487 if (DRI.d.b < SegmentLoadCmd->NumSections)
488 return;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000489 } else if (Command->Type == macho::LCT_Segment64) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000490 const MachOFormat::SegmentLoadCommand<true> *SegmentLoadCmd =
491 reinterpret_cast<const MachOFormat::SegmentLoadCommand<true>*>(Command);
492 if (DRI.d.b < SegmentLoadCmd->NumSections)
Eric Christopher6256b032011-04-22 03:19:48 +0000493 return;
494 }
495
496 DRI.d.a++;
497 DRI.d.b = 0;
498 }
499}
500
Michael J. Spencer25b15772011-06-25 17:55:23 +0000501error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
502 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000503 DRI.d.b++;
504 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000505 Result = SectionRef(DRI, this);
506 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000507}
508
Rafael Espindola335f1d42013-04-08 20:45:01 +0000509const MachOFormat::Section<false> *
510MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000511 assert(!is64Bit());
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000512 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
513 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
514 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
Rafael Espindola335f1d42013-04-08 20:45:01 +0000515 DRI.d.b * sizeof(MachOFormat::Section<false>);
516 return reinterpret_cast<const MachOFormat::Section<false>*>(SectionAddr);
Eric Christopher6256b032011-04-22 03:19:48 +0000517}
518
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000519std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
520 SectionList::const_iterator loc =
521 std::find(Sections.begin(), Sections.end(), Sec);
522 assert(loc != Sections.end() && "Sec is not a valid section!");
523 return std::distance(Sections.begin(), loc);
524}
525
Rafael Espindola335f1d42013-04-08 20:45:01 +0000526const MachOFormat::Section<true> *
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000527MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000528 assert(is64Bit());
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000529 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
530 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
531 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
Rafael Espindola335f1d42013-04-08 20:45:01 +0000532 DRI.d.b * sizeof(MachOFormat::Section<true>);
533 return reinterpret_cast<const MachOFormat::Section<true>*>(SectionAddr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000534}
535
Rafael Espindolacef81b32012-12-21 03:47:03 +0000536static StringRef parseSegmentOrSectionName(const char *P) {
537 if (P[15] == 0)
538 // Null terminated.
539 return P;
540 // Not null terminated, so this is a 16 char string.
541 return StringRef(P, 16);
542}
543
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000544ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000545 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000546 const MachOFormat::Section<true> *sec = getSection64(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000547 return ArrayRef<char>(sec->Name);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000548 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000549 const MachOFormat::Section<false> *sec = getSection(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000550 return ArrayRef<char>(sec->Name);
Rafael Espindolaf9a6bd82012-12-19 14:15:04 +0000551 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000552}
553
554error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
555 StringRef &Result) const {
556 ArrayRef<char> Raw = getSectionRawName(DRI);
557 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000558 return object_error::success;
559}
560
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000561ArrayRef<char>
562MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000563 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000564 const MachOFormat::Section<true> *sec = getSection64(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000565 return ArrayRef<char>(sec->SegmentName, 16);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000566 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000567 const MachOFormat::Section<false> *sec = getSection(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000568 return ArrayRef<char>(sec->SegmentName);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000569 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000570}
571
572StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
573 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
574 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000575}
576
Michael J. Spencer25b15772011-06-25 17:55:23 +0000577error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
578 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000579 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000580 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000581 Result = Sect->Address;
582 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000583 const MachOFormat::Section<false> *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000584 Result = Sect->Address;
585 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000586 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000587}
588
Michael J. Spencer25b15772011-06-25 17:55:23 +0000589error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
590 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000591 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000592 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000593 Result = Sect->Size;
594 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000595 const MachOFormat::Section<false> *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000596 Result = Sect->Size;
597 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000598 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000599}
600
Michael J. Spencer25b15772011-06-25 17:55:23 +0000601error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
602 StringRef &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000603 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000604 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000605 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000606 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000607 const MachOFormat::Section<false> *Sect = getSection(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000608 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000609 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000610 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000611}
612
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000613error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
614 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000615 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000616 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000617 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000618 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000619 const MachOFormat::Section<false> *Sect = getSection(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000620 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000621 }
622 return object_error::success;
623}
624
Michael J. Spencer25b15772011-06-25 17:55:23 +0000625error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
626 bool &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000627 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000628 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000629 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000630 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000631 const MachOFormat::Section<false> *Sect = getSection(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000632 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000633 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000634 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000635}
636
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000637error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
638 bool &Result) const {
639 // FIXME: Unimplemented.
640 Result = false;
641 return object_error::success;
642}
643
644error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
645 bool &Result) const {
646 // FIXME: Unimplemented.
647 Result = false;
648 return object_error::success;
649}
650
Preston Gurdc68dda82012-04-12 20:13:57 +0000651error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
652 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000653 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000654 Result = true;
655 return object_error::success;
656}
657
658error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000659 bool &Result) const {
660 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000661 Result = false;
662 return object_error::success;
663}
664
665error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
666 bool &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000667 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000668 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000669 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
670 Result = (SectionType == MachO::SectionTypeZeroFill ||
671 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000672 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000673 const MachOFormat::Section<false> *Sect = getSection(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000674 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
675 Result = (SectionType == MachO::SectionTypeZeroFill ||
676 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000677 }
678
679 return object_error::success;
680}
681
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000682error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
683 bool &Result) const {
684 // Consider using the code from isSectionText to look for __const sections.
685 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
686 // to use section attributes to distinguish code from data.
687
688 // FIXME: Unimplemented.
689 Result = false;
690 return object_error::success;
691}
692
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000693error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
694 DataRefImpl Symb,
695 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000696 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000697 getSymbolType(Symb, ST);
David Meyer2c677272012-02-29 02:11:55 +0000698 if (ST == SymbolRef::ST_Unknown) {
Owen Andersoncd749882011-10-12 22:21:32 +0000699 Result = false;
700 return object_error::success;
701 }
702
703 uint64_t SectBegin, SectEnd;
704 getSectionAddress(Sec, SectBegin);
705 getSectionSize(Sec, SectEnd);
706 SectEnd += SectBegin;
707
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000708 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000709 const MachOFormat::SymbolTableEntry<true> *Entry =
710 getSymbol64TableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000711 uint64_t SymAddr= Entry->Value;
712 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000713 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000714 const MachOFormat::SymbolTableEntry<false> *Entry =
715 getSymbolTableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000716 uint64_t SymAddr= Entry->Value;
717 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000718 }
Owen Andersoncd749882011-10-12 22:21:32 +0000719
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000720 return object_error::success;
721}
722
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000723relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
724 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000725 ret.d.b = getSectionIndex(Sec);
726 return relocation_iterator(RelocationRef(ret, this));
727}
Rafael Espindola335f1d42013-04-08 20:45:01 +0000728
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000729relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
730 uint32_t last_reloc;
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000731 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000732 const MachOFormat::Section<true> *Sect = getSection64(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000733 last_reloc = Sect->NumRelocationTableEntries;
734 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000735 const MachOFormat::Section<false> *Sect = getSection(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000736 last_reloc = Sect->NumRelocationTableEntries;
737 }
738 DataRefImpl ret;
739 ret.d.a = last_reloc;
740 ret.d.b = getSectionIndex(Sec);
741 return relocation_iterator(RelocationRef(ret, this));
742}
743
744section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000745 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000746 moveToNextSection(DRI);
747 return section_iterator(SectionRef(DRI, this));
748}
749
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000750section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000751 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000752 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000753 return section_iterator(SectionRef(DRI, this));
754}
755
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000756/*===-- Relocations -------------------------------------------------------===*/
757
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000758const MachOFormat::RelocationEntry *
759MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000760 uint32_t relOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000761 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000762 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000763 relOffset = Sect->RelocationTableOffset;
764 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000765 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000766 relOffset = Sect->RelocationTableOffset;
767 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000768 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000769 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000770 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000771}
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000772
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000773error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
774 RelocationRef &Res) const {
775 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000776 Res = RelocationRef(Rel, this);
777 return object_error::success;
778}
779error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
780 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000781 const uint8_t* sectAddress = 0;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000782 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000783 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000784 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000785 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000786 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000787 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000788 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000789 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000790
791 unsigned Arch = getArch();
792 bool isScattered = (Arch != Triple::x86_64) &&
793 (RE->Word0 & macho::RF_Scattered);
794 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000795 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000796 RelAddr = RE->Word0 & 0xFFFFFF;
797 else
798 RelAddr = RE->Word0;
799
800 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000801 return object_error::success;
802}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000803error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
804 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000805 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000806
807 unsigned Arch = getArch();
808 bool isScattered = (Arch != Triple::x86_64) &&
809 (RE->Word0 & macho::RF_Scattered);
810 if (isScattered)
811 Res = RE->Word0 & 0xFFFFFF;
812 else
813 Res = RE->Word0;
814 return object_error::success;
815}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000816error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
817 SymbolRef &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000818 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000819 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
820 bool isExtern = (RE->Word1 >> 27) & 1;
821
822 DataRefImpl Sym;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000823 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000824 if (isExtern) {
825 for (unsigned i = 0; i < SymbolIdx; i++) {
826 Sym.d.b++;
827 moveToNextSymbol(Sym);
Rafael Espindola433611b2013-04-07 19:26:57 +0000828 assert(Sym.d.a < getHeader()->NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000829 "Relocation symbol index out of range!");
830 }
831 }
832 Res = SymbolRef(Sym, this);
833 return object_error::success;
834}
835error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000836 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000837 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Andersonf8261e72011-10-26 17:10:22 +0000838 Res = RE->Word0;
839 Res <<= 32;
840 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000841 return object_error::success;
842}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000843error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
844 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000845 // TODO: Support scattered relocations.
846 StringRef res;
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000847 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +0000848
849 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000850 bool isScattered = (Arch != Triple::x86_64) &&
851 (RE->Word0 & macho::RF_Scattered);
852
853 unsigned r_type;
854 if (isScattered)
855 r_type = (RE->Word0 >> 24) & 0xF;
856 else
857 r_type = (RE->Word1 >> 28) & 0xF;
858
Owen Anderson0135fe12011-10-24 21:44:00 +0000859 switch (Arch) {
860 case Triple::x86: {
Craig Toppere3298102012-05-24 06:35:32 +0000861 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000862 "GENERIC_RELOC_VANILLA",
863 "GENERIC_RELOC_PAIR",
864 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000865 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000866 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000867 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000868
Owen Andersoneb6bd332011-10-27 20:46:09 +0000869 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000870 res = "Unknown";
871 else
872 res = Table[r_type];
873 break;
874 }
875 case Triple::x86_64: {
Craig Toppere3298102012-05-24 06:35:32 +0000876 static const char *const Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000877 "X86_64_RELOC_UNSIGNED",
878 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000879 "X86_64_RELOC_BRANCH",
880 "X86_64_RELOC_GOT_LOAD",
881 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000882 "X86_64_RELOC_SUBTRACTOR",
883 "X86_64_RELOC_SIGNED_1",
884 "X86_64_RELOC_SIGNED_2",
885 "X86_64_RELOC_SIGNED_4",
886 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000887
Owen Andersond8fa76d2011-10-24 23:20:07 +0000888 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000889 res = "Unknown";
890 else
891 res = Table[r_type];
892 break;
893 }
894 case Triple::arm: {
Craig Toppere3298102012-05-24 06:35:32 +0000895 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000896 "ARM_RELOC_VANILLA",
897 "ARM_RELOC_PAIR",
898 "ARM_RELOC_SECTDIFF",
899 "ARM_RELOC_LOCAL_SECTDIFF",
900 "ARM_RELOC_PB_LA_PTR",
901 "ARM_RELOC_BR24",
902 "ARM_THUMB_RELOC_BR22",
903 "ARM_THUMB_32BIT_BRANCH",
904 "ARM_RELOC_HALF",
905 "ARM_RELOC_HALF_SECTDIFF" };
906
907 if (r_type > 9)
908 res = "Unknown";
909 else
910 res = Table[r_type];
911 break;
912 }
913 case Triple::ppc: {
Craig Toppere3298102012-05-24 06:35:32 +0000914 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000915 "PPC_RELOC_VANILLA",
916 "PPC_RELOC_PAIR",
917 "PPC_RELOC_BR14",
918 "PPC_RELOC_BR24",
919 "PPC_RELOC_HI16",
920 "PPC_RELOC_LO16",
921 "PPC_RELOC_HA16",
922 "PPC_RELOC_LO14",
923 "PPC_RELOC_SECTDIFF",
924 "PPC_RELOC_PB_LA_PTR",
925 "PPC_RELOC_HI16_SECTDIFF",
926 "PPC_RELOC_LO16_SECTDIFF",
927 "PPC_RELOC_HA16_SECTDIFF",
928 "PPC_RELOC_JBSR",
929 "PPC_RELOC_LO14_SECTDIFF",
930 "PPC_RELOC_LOCAL_SECTDIFF" };
931
932 res = Table[r_type];
933 break;
934 }
935 case Triple::UnknownArch:
936 res = "Unknown";
937 break;
938 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000939 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000940 return object_error::success;
941}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000942error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
943 int64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000944 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000945 bool isExtern = (RE->Word1 >> 27) & 1;
946 Res = 0;
947 if (!isExtern) {
948 const uint8_t* sectAddress = base();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000949 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000950 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000951 sectAddress += Sect->Offset;
952 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000953 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000954 sectAddress += Sect->Offset;
955 }
956 Res = reinterpret_cast<uintptr_t>(sectAddress);
957 }
958 return object_error::success;
959}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000960
961// Helper to advance a section or symbol iterator multiple increments at a time.
962template<class T>
963error_code advance(T &it, size_t Val) {
964 error_code ec;
965 while (Val--) {
966 it.increment(ec);
967 }
968 return ec;
969}
970
971template<class T>
972void advanceTo(T &it, size_t Val) {
973 if (error_code ec = advance(it, Val))
974 report_fatal_error(ec.message());
975}
976
Owen Anderson1832f4d2011-10-26 20:42:54 +0000977void MachOObjectFile::printRelocationTargetName(
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000978 const MachOFormat::RelocationEntry *RE,
Owen Anderson1832f4d2011-10-26 20:42:54 +0000979 raw_string_ostream &fmt) const {
980 unsigned Arch = getArch();
981 bool isScattered = (Arch != Triple::x86_64) &&
982 (RE->Word0 & macho::RF_Scattered);
983
984 // Target of a scattered relocation is an address. In the interest of
985 // generating pretty output, scan through the symbol table looking for a
986 // symbol that aligns with that address. If we find one, print it.
987 // Otherwise, we just print the hex address of the target.
988 if (isScattered) {
989 uint32_t Val = RE->Word1;
990
991 error_code ec;
992 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
993 SI.increment(ec)) {
994 if (ec) report_fatal_error(ec.message());
995
996 uint64_t Addr;
997 StringRef Name;
998
999 if ((ec = SI->getAddress(Addr)))
1000 report_fatal_error(ec.message());
1001 if (Addr != Val) continue;
1002 if ((ec = SI->getName(Name)))
1003 report_fatal_error(ec.message());
1004 fmt << Name;
1005 return;
1006 }
1007
Owen Andersonb28bdbf2011-10-27 21:53:50 +00001008 // If we couldn't find a symbol that this relocation refers to, try
1009 // to find a section beginning instead.
1010 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
1011 SI.increment(ec)) {
1012 if (ec) report_fatal_error(ec.message());
1013
1014 uint64_t Addr;
1015 StringRef Name;
1016
1017 if ((ec = SI->getAddress(Addr)))
1018 report_fatal_error(ec.message());
1019 if (Addr != Val) continue;
1020 if ((ec = SI->getName(Name)))
1021 report_fatal_error(ec.message());
1022 fmt << Name;
1023 return;
1024 }
1025
Owen Anderson1832f4d2011-10-26 20:42:54 +00001026 fmt << format("0x%x", Val);
1027 return;
1028 }
1029
1030 StringRef S;
1031 bool isExtern = (RE->Word1 >> 27) & 1;
1032 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001033
1034 if (isExtern) {
1035 symbol_iterator SI = begin_symbols();
1036 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001037 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001038 } else {
1039 section_iterator SI = begin_sections();
1040 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001041 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001042 }
1043
Owen Anderson1832f4d2011-10-26 20:42:54 +00001044 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001045}
1046
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001047error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1048 SmallVectorImpl<char> &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001049 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +00001050
Owen Anderson1832f4d2011-10-26 20:42:54 +00001051 unsigned Arch = getArch();
1052 bool isScattered = (Arch != Triple::x86_64) &&
1053 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001054
Owen Anderson013d7562011-10-25 18:48:41 +00001055 std::string fmtbuf;
1056 raw_string_ostream fmt(fmtbuf);
1057
Owen Anderson1832f4d2011-10-26 20:42:54 +00001058 unsigned Type;
1059 if (isScattered)
1060 Type = (RE->Word0 >> 24) & 0xF;
1061 else
1062 Type = (RE->Word1 >> 28) & 0xF;
1063
Owen Andersoneb6bd332011-10-27 20:46:09 +00001064 bool isPCRel;
1065 if (isScattered)
1066 isPCRel = ((RE->Word0 >> 30) & 1);
1067 else
1068 isPCRel = ((RE->Word1 >> 24) & 1);
1069
Owen Andersond8fa76d2011-10-24 23:20:07 +00001070 // Determine any addends that should be displayed with the relocation.
1071 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +00001072
1073 // X86_64 has entirely custom relocation types.
1074 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +00001075 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +00001076
Owen Andersond8fa76d2011-10-24 23:20:07 +00001077 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001078 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1079 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1080 printRelocationTargetName(RE, fmt);
1081 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +00001082 if (isPCRel) fmt << "PCREL";
1083 break;
1084 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001085 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +00001086 DataRefImpl RelNext = Rel;
1087 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001088 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001089
1090 // X86_64_SUBTRACTOR must be followed by a relocation of type
1091 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001092 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +00001093 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001094 if (RType != 0)
1095 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1096 "X86_64_RELOC_SUBTRACTOR.");
1097
Owen Andersonef22f782011-10-26 17:28:49 +00001098 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1099 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001100 printRelocationTargetName(RENext, fmt);
1101 fmt << "-";
1102 printRelocationTargetName(RE, fmt);
Jim Grosbach133f6b82013-01-31 19:46:57 +00001103 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001104 }
Owen Andersoneb6bd332011-10-27 20:46:09 +00001105 case macho::RIT_X86_64_TLV:
1106 printRelocationTargetName(RE, fmt);
1107 fmt << "@TLV";
1108 if (isPCRel) fmt << "P";
1109 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001110 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1111 printRelocationTargetName(RE, fmt);
1112 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001113 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001114 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1115 printRelocationTargetName(RE, fmt);
1116 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001117 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001118 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1119 printRelocationTargetName(RE, fmt);
1120 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +00001121 break;
1122 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001123 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001124 break;
1125 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001126 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001127 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1128 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001129 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001130 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001131 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001132 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001133 DataRefImpl RelNext = Rel;
1134 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001135 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001136
1137 // X86 sect diff's must be followed by a relocation of type
1138 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001139 bool isNextScattered = (Arch != Triple::x86_64) &&
1140 (RENext->Word0 & macho::RF_Scattered);
1141 unsigned RType;
1142 if (isNextScattered)
1143 RType = (RENext->Word0 >> 24) & 0xF;
1144 else
1145 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001146 if (RType != 1)
1147 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001148 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001149
Owen Anderson1832f4d2011-10-26 20:42:54 +00001150 printRelocationTargetName(RE, fmt);
1151 fmt << "-";
1152 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001153 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001154 }
1155 }
Owen Anderson013d7562011-10-25 18:48:41 +00001156
Owen Anderson1832f4d2011-10-26 20:42:54 +00001157 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001158 // All X86 relocations that need special printing were already
1159 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001160 switch (Type) {
1161 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
Owen Andersoneb6bd332011-10-27 20:46:09 +00001162 DataRefImpl RelNext = Rel;
1163 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001164 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersoneb6bd332011-10-27 20:46:09 +00001165
1166 // X86 sect diff's must be followed by a relocation of type
1167 // GENERIC_RELOC_PAIR.
1168 bool isNextScattered = (Arch != Triple::x86_64) &&
1169 (RENext->Word0 & macho::RF_Scattered);
1170 unsigned RType;
1171 if (isNextScattered)
1172 RType = (RENext->Word0 >> 24) & 0xF;
1173 else
1174 RType = (RENext->Word1 >> 28) & 0xF;
1175 if (RType != 1)
1176 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1177 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1178
1179 printRelocationTargetName(RE, fmt);
1180 fmt << "-";
1181 printRelocationTargetName(RENext, fmt);
1182 break;
1183 }
1184 case macho::RIT_Generic_TLV: {
1185 printRelocationTargetName(RE, fmt);
1186 fmt << "@TLV";
1187 if (isPCRel) fmt << "P";
1188 break;
1189 }
1190 default:
1191 printRelocationTargetName(RE, fmt);
1192 }
Owen Anderson013d7562011-10-25 18:48:41 +00001193 } else { // ARM-specific relocations
1194 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001195 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1196 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001197 // Half relocations steal a bit from the length field to encode
1198 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001199 bool isUpper;
1200 if (isScattered)
1201 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001202 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001203 isUpper = (RE->Word1 >> 25) & 1;
1204
1205 if (isUpper)
1206 fmt << ":upper16:(";
1207 else
1208 fmt << ":lower16:(";
1209 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001210
Owen Anderson013d7562011-10-25 18:48:41 +00001211 DataRefImpl RelNext = Rel;
1212 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001213 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Anderson013d7562011-10-25 18:48:41 +00001214
1215 // ARM half relocs must be followed by a relocation of type
1216 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001217 bool isNextScattered = (Arch != Triple::x86_64) &&
1218 (RENext->Word0 & macho::RF_Scattered);
1219 unsigned RType;
1220 if (isNextScattered)
1221 RType = (RENext->Word0 >> 24) & 0xF;
1222 else
1223 RType = (RENext->Word1 >> 28) & 0xF;
1224
Owen Anderson013d7562011-10-25 18:48:41 +00001225 if (RType != 1)
1226 report_fatal_error("Expected ARM_RELOC_PAIR after "
1227 "GENERIC_RELOC_HALF");
1228
Owen Anderson1832f4d2011-10-26 20:42:54 +00001229 // NOTE: The half of the target virtual address is stashed in the
1230 // address field of the secondary relocation, but we can't reverse
1231 // engineer the constant offset from it without decoding the movw/movt
1232 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001233
1234 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1235 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001236 if (Type == macho::RIT_ARM_HalfDifference) {
1237 fmt << "-";
1238 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001239 }
1240
Owen Anderson013d7562011-10-25 18:48:41 +00001241 fmt << ")";
1242 break;
1243 }
1244 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001245 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001246 }
1247 }
1248 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001249 } else
1250 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001251
Owen Anderson0135fe12011-10-24 21:44:00 +00001252 fmt.flush();
1253 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001254 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001255}
1256
Owen Anderson0685e942011-10-25 20:35:53 +00001257error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1258 bool &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001259 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0685e942011-10-25 20:35:53 +00001260
Owen Anderson0685e942011-10-25 20:35:53 +00001261 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001262 bool isScattered = (Arch != Triple::x86_64) &&
1263 (RE->Word0 & macho::RF_Scattered);
1264 unsigned Type;
1265 if (isScattered)
1266 Type = (RE->Word0 >> 24) & 0xF;
1267 else
1268 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001269
1270 Result = false;
1271
1272 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1273 // is always hidden.
1274 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001275 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001276 } else if (Arch == Triple::x86_64) {
1277 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1278 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001279 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001280 DataRefImpl RelPrev = Rel;
1281 RelPrev.d.a--;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001282 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
Owen Anderson0685e942011-10-25 20:35:53 +00001283
1284 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1285
Owen Anderson1832f4d2011-10-26 20:42:54 +00001286 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001287 }
1288 }
1289
1290 return object_error::success;
1291}
1292
David Meyer5c2b4ea2012-03-01 01:36:50 +00001293error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1294 LibraryRef &Res) const {
1295 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1296}
1297
1298error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1299 StringRef &Res) const {
1300 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1301}
1302
1303
Eric Christopher6256b032011-04-22 03:19:48 +00001304/*===-- Miscellaneous -----------------------------------------------------===*/
1305
1306uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001307 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001308}
1309
1310StringRef MachOObjectFile::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001311 if (!is64Bit()) {
Rafael Espindola433611b2013-04-07 19:26:57 +00001312 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001313 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001314 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001315 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001316 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001317 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001318 return "Mach-O 32-bit ppc";
1319 default:
Rafael Espindola433611b2013-04-07 19:26:57 +00001320 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001321 "64-bit object file when we're not 64-bit?");
1322 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001323 }
1324 }
1325
Eric Christopherb3e6b042013-02-28 20:26:17 +00001326 // Make sure the cpu type has the correct mask.
Rafael Espindola433611b2013-04-07 19:26:57 +00001327 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +00001328 == llvm::MachO::CPUArchABI64 &&
1329 "32-bit object file when we're 64-bit?");
1330
Rafael Espindola433611b2013-04-07 19:26:57 +00001331 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001332 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001333 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001334 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001335 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001336 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001337 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001338 }
1339}
1340
1341unsigned MachOObjectFile::getArch() const {
Rafael Espindola433611b2013-04-07 19:26:57 +00001342 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001343 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001344 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001345 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001346 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001347 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001348 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001349 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001350 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001351 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001352 return Triple::ppc64;
1353 default:
1354 return Triple::UnknownArch;
1355 }
1356}
1357
Owen Andersonf7c93a32011-10-11 17:32:27 +00001358} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001359} // end namespace llvm