blob: 86499cf0748e7951329d6300ca81c198d7166252 [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 Espindola00555c12013-04-06 01:59:05 +0000119const MachOFormat::SymbolTableEntry *
120MachOObjectFile::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 Espindola82a21072013-04-06 03:31:08 +0000128const MachOFormat::SymbolTableEntry *
129MachOObjectFile::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 +
134 Index * sizeof(macho::SymbolTableEntry));
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000135 StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry));
Rafael Espindola00555c12013-04-06 01:59:05 +0000136 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000137}
138
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000139const MachOFormat::Symbol64TableEntry*
140MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000141 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000142 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000143 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000144
Rafael Espindola82a21072013-04-06 03:31:08 +0000145 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
146}
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000147
Rafael Espindola82a21072013-04-06 03:31:08 +0000148const MachOFormat::Symbol64TableEntry*
149MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
150 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000151 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
152 unsigned Index = DRI.d.b;
153 uint64_t Offset = (SymbolTableOffset +
154 Index * sizeof(macho::Symbol64TableEntry));
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000155 StringRef Data = getData(Offset, sizeof(MachOFormat::Symbol64TableEntry));
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000156 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000157}
158
Michael J. Spencer25b15772011-06-25 17:55:23 +0000159error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
160 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000161 DRI.d.b++;
162 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000163 Result = SymbolRef(DRI, this);
164 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000165}
166
Michael J. Spencer25b15772011-06-25 17:55:23 +0000167error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
168 StringRef &Result) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000169 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000170 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000171 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Rafael Espindola82a21072013-04-06 03:31:08 +0000172
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000173 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
174 SymtabLoadCmd->StringTableSize);
Rafael Espindola82a21072013-04-06 03:31:08 +0000175
176 uint32_t StringIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000177 if (is64Bit()) {
Rafael Espindola82a21072013-04-06 03:31:08 +0000178 const MachOFormat::Symbol64TableEntry *Entry =
179 getSymbol64TableEntry(DRI, SymtabLoadCmd);
180 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000181 } else {
Rafael Espindola82a21072013-04-06 03:31:08 +0000182 const MachOFormat::SymbolTableEntry *Entry =
183 getSymbolTableEntry(DRI, SymtabLoadCmd);
184 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000185 }
Rafael Espindola82a21072013-04-06 03:31:08 +0000186
187 const char *Start = &StringTable.data()[StringIndex];
188 Result = StringRef(Start);
189
Michael J. Spencer25b15772011-06-25 17:55:23 +0000190 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000191}
192
Danil Malyshevb0436a72011-11-29 17:40:10 +0000193error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
194 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000195 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000196 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000197 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000198 if (Entry->SectionIndex) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000199 const MachOFormat::Section64 *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000200 getSection64(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000201 Result += Section->Offset - Section->Address;
202 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000203 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000204 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000205 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000206 if (Entry->SectionIndex) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000207 const MachOFormat::Section *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000208 getSection(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000209 Result += Section->Offset - Section->Address;
210 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000211 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000212
Michael J. Spencer25b15772011-06-25 17:55:23 +0000213 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000214}
215
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000216error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
217 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000218 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000219 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000220 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000221 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000222 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000223 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000224 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000225 return object_error::success;
226}
227
Michael J. Spencer25b15772011-06-25 17:55:23 +0000228error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
229 uint64_t &Result) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000230 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000231 uint64_t BeginOffset;
232 uint64_t EndOffset = 0;
233 uint8_t SectionIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000234 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000235 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000236 BeginOffset = Entry->Value;
237 SectionIndex = Entry->SectionIndex;
238 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000239 uint32_t flags = SymbolRef::SF_None;
240 getSymbolFlags(DRI, flags);
241 if (flags & SymbolRef::SF_Common)
242 Result = Entry->Value;
243 else
244 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000245 return object_error::success;
246 }
247 // Unfortunately symbols are unsorted so we need to touch all
248 // symbols from load command
249 DRI.d.b = 0;
250 uint32_t Command = DRI.d.a;
251 while (Command == DRI.d.a) {
252 moveToNextSymbol(DRI);
253 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000254 Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000255 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
256 if (!EndOffset || Entry->Value < EndOffset)
257 EndOffset = Entry->Value;
258 }
259 DRI.d.b++;
260 }
261 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000262 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000263 BeginOffset = Entry->Value;
264 SectionIndex = Entry->SectionIndex;
265 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000266 uint32_t flags = SymbolRef::SF_None;
267 getSymbolFlags(DRI, flags);
268 if (flags & SymbolRef::SF_Common)
269 Result = Entry->Value;
270 else
271 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000272 return object_error::success;
273 }
274 // Unfortunately symbols are unsorted so we need to touch all
275 // symbols from load command
276 DRI.d.b = 0;
277 uint32_t Command = DRI.d.a;
278 while (Command == DRI.d.a) {
279 moveToNextSymbol(DRI);
280 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola00555c12013-04-06 01:59:05 +0000281 Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000282 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
283 if (!EndOffset || Entry->Value < EndOffset)
284 EndOffset = Entry->Value;
285 }
286 DRI.d.b++;
287 }
288 }
289 if (!EndOffset) {
290 uint64_t Size;
291 getSectionSize(Sections[SectionIndex-1], Size);
292 getSectionAddress(Sections[SectionIndex-1], EndOffset);
293 EndOffset += Size;
294 }
295 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000296 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000297}
298
Michael J. Spencer25b15772011-06-25 17:55:23 +0000299error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
300 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000301 uint8_t Type, Flags;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000302 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000303 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000304 Type = Entry->Type;
305 Flags = Entry->Flags;
306 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000307 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000308 Type = Entry->Type;
309 Flags = Entry->Flags;
310 }
Eric Christopher6256b032011-04-22 03:19:48 +0000311
312 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000313 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000314 case macho::STT_Undefined:
315 Char = 'u';
316 break;
317 case macho::STT_Absolute:
318 case macho::STT_Section:
319 Char = 's';
320 break;
321 default:
322 Char = '?';
323 break;
324 }
325
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000326 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000327 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000328 Result = Char;
329 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000330}
331
David Meyerc46255a2012-02-28 23:47:53 +0000332error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
333 uint32_t &Result) const {
334 uint16_t MachOFlags;
335 uint8_t MachOType;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000336 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000337 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000338 MachOFlags = Entry->Flags;
339 MachOType = Entry->Type;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000340 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000341 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000342 MachOFlags = Entry->Flags;
343 MachOType = Entry->Type;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000344 }
345
Preston Gurdc68dda82012-04-12 20:13:57 +0000346 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000347 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000348
349 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
350 Result |= SymbolRef::SF_Undefined;
351
David Meyerc46255a2012-02-28 23:47:53 +0000352 if (MachOFlags & macho::STF_StabsEntryMask)
353 Result |= SymbolRef::SF_FormatSpecific;
354
Preston Gurdc68dda82012-04-12 20:13:57 +0000355 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000356 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000357 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
358 Result |= SymbolRef::SF_Common;
359 }
David Meyerc46255a2012-02-28 23:47:53 +0000360
361 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
362 Result |= SymbolRef::SF_Weak;
363
364 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
365 Result |= SymbolRef::SF_Absolute;
366
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000367 return object_error::success;
368}
369
370error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
371 section_iterator &Res) const {
372 uint8_t index;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000373 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000374 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000375 index = Entry->SectionIndex;
376 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000377 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000378 index = Entry->SectionIndex;
379 }
380
381 if (index == 0)
382 Res = end_sections();
383 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000384 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000385
386 return object_error::success;
387}
388
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000389error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000390 SymbolRef::Type &Res) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000391 uint8_t n_type;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000392 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000393 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000394 n_type = Entry->Type;
395 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000396 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000397 n_type = Entry->Type;
398 }
399 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000400
401 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000402 if (n_type & MachO::NlistMaskStab) {
403 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000404 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000405 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000406
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000407 switch (n_type & MachO::NlistMaskType) {
408 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000409 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000410 break;
411 case MachO::NListTypeSection :
412 Res = SymbolRef::ST_Function;
413 break;
414 }
415 return object_error::success;
416}
417
Tim Northovera41dce32012-10-29 10:47:00 +0000418error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
419 uint64_t &Val) const {
420 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
421}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000422
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000423symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000424 // DRI.d.a = segment number; DRI.d.b = symbol index.
425 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000426 moveToNextSymbol(DRI);
427 return symbol_iterator(SymbolRef(DRI, this));
428}
429
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000430symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000431 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000432 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000433 return symbol_iterator(SymbolRef(DRI, this));
434}
435
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000436symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
437 // TODO: implement
438 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
439}
440
441symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
442 // TODO: implement
443 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
444}
Eric Christopher6256b032011-04-22 03:19:48 +0000445
David Meyer5c2b4ea2012-03-01 01:36:50 +0000446library_iterator MachOObjectFile::begin_libraries_needed() const {
447 // TODO: implement
448 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
449}
450
451library_iterator MachOObjectFile::end_libraries_needed() const {
452 // TODO: implement
453 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
454}
455
David Meyer97f77872012-03-01 22:19:54 +0000456StringRef MachOObjectFile::getLoadName() const {
457 // TODO: Implement
458 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
459}
460
Eric Christopher6256b032011-04-22 03:19:48 +0000461/*===-- Sections ----------------------------------------------------------===*/
462
463void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000464 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000465 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000466 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
467 if (Command->Type == macho::LCT_Segment) {
Rafael Espindola68d287d2013-04-06 03:50:05 +0000468 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000469 reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000470 if (DRI.d.b < SegmentLoadCmd->NumSections)
471 return;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000472 } else if (Command->Type == macho::LCT_Segment64) {
Rafael Espindola68d287d2013-04-06 03:50:05 +0000473 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000474 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000475 if (DRI.d.b < Segment64LoadCmd->NumSections)
476 return;
477 }
478
479 DRI.d.a++;
480 DRI.d.b = 0;
481 }
482}
483
Michael J. Spencer25b15772011-06-25 17:55:23 +0000484error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
485 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000486 DRI.d.b++;
487 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000488 Result = SectionRef(DRI, this);
489 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000490}
491
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000492const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000493 assert(!is64Bit());
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000494 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
495 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
496 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000497 DRI.d.b * sizeof(MachOFormat::Section);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000498 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
Eric Christopher6256b032011-04-22 03:19:48 +0000499}
500
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000501std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
502 SectionList::const_iterator loc =
503 std::find(Sections.begin(), Sections.end(), Sec);
504 assert(loc != Sections.end() && "Sec is not a valid section!");
505 return std::distance(Sections.begin(), loc);
506}
507
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000508const MachOFormat::Section64 *
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000509MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000510 assert(is64Bit());
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000511 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
512 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
513 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000514 DRI.d.b * sizeof(MachOFormat::Section64);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000515 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000516}
517
Rafael Espindolacef81b32012-12-21 03:47:03 +0000518static StringRef parseSegmentOrSectionName(const char *P) {
519 if (P[15] == 0)
520 // Null terminated.
521 return P;
522 // Not null terminated, so this is a 16 char string.
523 return StringRef(P, 16);
524}
525
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000526ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000527 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000528 const MachOFormat::Section64 *sec = getSection64(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000529 return ArrayRef<char>(sec->Name);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000530 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000531 const MachOFormat::Section *sec = getSection(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000532 return ArrayRef<char>(sec->Name);
Rafael Espindolaf9a6bd82012-12-19 14:15:04 +0000533 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000534}
535
536error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
537 StringRef &Result) const {
538 ArrayRef<char> Raw = getSectionRawName(DRI);
539 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000540 return object_error::success;
541}
542
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000543ArrayRef<char>
544MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000545 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000546 const MachOFormat::Section64 *sec = getSection64(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000547 return ArrayRef<char>(sec->SegmentName, 16);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000548 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000549 const MachOFormat::Section *sec = getSection(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000550 return ArrayRef<char>(sec->SegmentName);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000551 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000552}
553
554StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
555 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
556 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000557}
558
Michael J. Spencer25b15772011-06-25 17:55:23 +0000559error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
560 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000561 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000562 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000563 Result = Sect->Address;
564 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000565 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000566 Result = Sect->Address;
567 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000568 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000569}
570
Michael J. Spencer25b15772011-06-25 17:55:23 +0000571error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
572 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000573 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000574 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000575 Result = Sect->Size;
576 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000577 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000578 Result = Sect->Size;
579 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000580 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000581}
582
Michael J. Spencer25b15772011-06-25 17:55:23 +0000583error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
584 StringRef &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000585 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000586 const MachOFormat::Section64 *Sect = getSection64(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000587 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000588 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000589 const MachOFormat::Section *Sect = getSection(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000590 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000591 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000592 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000593}
594
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000595error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
596 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000597 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000598 const MachOFormat::Section64 *Sect = getSection64(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000599 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000600 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000601 const MachOFormat::Section *Sect = getSection(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000602 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000603 }
604 return object_error::success;
605}
606
Michael J. Spencer25b15772011-06-25 17:55:23 +0000607error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
608 bool &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000609 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000610 const MachOFormat::Section64 *Sect = getSection64(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000611 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000612 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000613 const MachOFormat::Section *Sect = getSection(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000614 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000615 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000616 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000617}
618
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000619error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
620 bool &Result) const {
621 // FIXME: Unimplemented.
622 Result = false;
623 return object_error::success;
624}
625
626error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
627 bool &Result) const {
628 // FIXME: Unimplemented.
629 Result = false;
630 return object_error::success;
631}
632
Preston Gurdc68dda82012-04-12 20:13:57 +0000633error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
634 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000635 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000636 Result = true;
637 return object_error::success;
638}
639
640error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000641 bool &Result) const {
642 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000643 Result = false;
644 return object_error::success;
645}
646
647error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
648 bool &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000649 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000650 const MachOFormat::Section64 *Sect = getSection64(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000651 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
652 Result = (SectionType == MachO::SectionTypeZeroFill ||
653 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000654 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000655 const MachOFormat::Section *Sect = getSection(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000656 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
657 Result = (SectionType == MachO::SectionTypeZeroFill ||
658 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000659 }
660
661 return object_error::success;
662}
663
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000664error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
665 bool &Result) const {
666 // Consider using the code from isSectionText to look for __const sections.
667 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
668 // to use section attributes to distinguish code from data.
669
670 // FIXME: Unimplemented.
671 Result = false;
672 return object_error::success;
673}
674
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000675error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
676 DataRefImpl Symb,
677 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000678 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000679 getSymbolType(Symb, ST);
David Meyer2c677272012-02-29 02:11:55 +0000680 if (ST == SymbolRef::ST_Unknown) {
Owen Andersoncd749882011-10-12 22:21:32 +0000681 Result = false;
682 return object_error::success;
683 }
684
685 uint64_t SectBegin, SectEnd;
686 getSectionAddress(Sec, SectBegin);
687 getSectionSize(Sec, SectEnd);
688 SectEnd += SectBegin;
689
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000690 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000691 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000692 uint64_t SymAddr= Entry->Value;
693 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000694 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000695 const MachOFormat::SymbolTableEntry *Entry = 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}
708relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
709 uint32_t last_reloc;
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000710 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000711 const MachOFormat::Section64 *Sect = getSection64(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000712 last_reloc = Sect->NumRelocationTableEntries;
713 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000714 const MachOFormat::Section *Sect = getSection(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000715 last_reloc = Sect->NumRelocationTableEntries;
716 }
717 DataRefImpl ret;
718 ret.d.a = last_reloc;
719 ret.d.b = getSectionIndex(Sec);
720 return relocation_iterator(RelocationRef(ret, this));
721}
722
723section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000724 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000725 moveToNextSection(DRI);
726 return section_iterator(SectionRef(DRI, this));
727}
728
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000729section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000730 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000731 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000732 return section_iterator(SectionRef(DRI, this));
733}
734
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000735/*===-- Relocations -------------------------------------------------------===*/
736
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000737const MachOFormat::RelocationEntry *
738MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000739 uint32_t relOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000740 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000741 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000742 relOffset = Sect->RelocationTableOffset;
743 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000744 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000745 relOffset = Sect->RelocationTableOffset;
746 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000747 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000748 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000749 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000750}
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000751
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000752error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
753 RelocationRef &Res) const {
754 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000755 Res = RelocationRef(Rel, this);
756 return object_error::success;
757}
758error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
759 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000760 const uint8_t* sectAddress = 0;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000761 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000762 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000763 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000764 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000765 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000766 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000767 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000768 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000769
770 unsigned Arch = getArch();
771 bool isScattered = (Arch != Triple::x86_64) &&
772 (RE->Word0 & macho::RF_Scattered);
773 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000774 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000775 RelAddr = RE->Word0 & 0xFFFFFF;
776 else
777 RelAddr = RE->Word0;
778
779 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000780 return object_error::success;
781}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000782error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
783 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000784 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000785
786 unsigned Arch = getArch();
787 bool isScattered = (Arch != Triple::x86_64) &&
788 (RE->Word0 & macho::RF_Scattered);
789 if (isScattered)
790 Res = RE->Word0 & 0xFFFFFF;
791 else
792 Res = RE->Word0;
793 return object_error::success;
794}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000795error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
796 SymbolRef &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000797 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000798 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
799 bool isExtern = (RE->Word1 >> 27) & 1;
800
801 DataRefImpl Sym;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000802 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000803 if (isExtern) {
804 for (unsigned i = 0; i < SymbolIdx; i++) {
805 Sym.d.b++;
806 moveToNextSymbol(Sym);
Rafael Espindola433611b2013-04-07 19:26:57 +0000807 assert(Sym.d.a < getHeader()->NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000808 "Relocation symbol index out of range!");
809 }
810 }
811 Res = SymbolRef(Sym, this);
812 return object_error::success;
813}
814error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000815 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000816 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Andersonf8261e72011-10-26 17:10:22 +0000817 Res = RE->Word0;
818 Res <<= 32;
819 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000820 return object_error::success;
821}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000822error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
823 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000824 // TODO: Support scattered relocations.
825 StringRef res;
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000826 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +0000827
828 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000829 bool isScattered = (Arch != Triple::x86_64) &&
830 (RE->Word0 & macho::RF_Scattered);
831
832 unsigned r_type;
833 if (isScattered)
834 r_type = (RE->Word0 >> 24) & 0xF;
835 else
836 r_type = (RE->Word1 >> 28) & 0xF;
837
Owen Anderson0135fe12011-10-24 21:44:00 +0000838 switch (Arch) {
839 case Triple::x86: {
Craig Toppere3298102012-05-24 06:35:32 +0000840 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000841 "GENERIC_RELOC_VANILLA",
842 "GENERIC_RELOC_PAIR",
843 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000844 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000845 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000846 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000847
Owen Andersoneb6bd332011-10-27 20:46:09 +0000848 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000849 res = "Unknown";
850 else
851 res = Table[r_type];
852 break;
853 }
854 case Triple::x86_64: {
Craig Toppere3298102012-05-24 06:35:32 +0000855 static const char *const Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000856 "X86_64_RELOC_UNSIGNED",
857 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000858 "X86_64_RELOC_BRANCH",
859 "X86_64_RELOC_GOT_LOAD",
860 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000861 "X86_64_RELOC_SUBTRACTOR",
862 "X86_64_RELOC_SIGNED_1",
863 "X86_64_RELOC_SIGNED_2",
864 "X86_64_RELOC_SIGNED_4",
865 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000866
Owen Andersond8fa76d2011-10-24 23:20:07 +0000867 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000868 res = "Unknown";
869 else
870 res = Table[r_type];
871 break;
872 }
873 case Triple::arm: {
Craig Toppere3298102012-05-24 06:35:32 +0000874 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000875 "ARM_RELOC_VANILLA",
876 "ARM_RELOC_PAIR",
877 "ARM_RELOC_SECTDIFF",
878 "ARM_RELOC_LOCAL_SECTDIFF",
879 "ARM_RELOC_PB_LA_PTR",
880 "ARM_RELOC_BR24",
881 "ARM_THUMB_RELOC_BR22",
882 "ARM_THUMB_32BIT_BRANCH",
883 "ARM_RELOC_HALF",
884 "ARM_RELOC_HALF_SECTDIFF" };
885
886 if (r_type > 9)
887 res = "Unknown";
888 else
889 res = Table[r_type];
890 break;
891 }
892 case Triple::ppc: {
Craig Toppere3298102012-05-24 06:35:32 +0000893 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000894 "PPC_RELOC_VANILLA",
895 "PPC_RELOC_PAIR",
896 "PPC_RELOC_BR14",
897 "PPC_RELOC_BR24",
898 "PPC_RELOC_HI16",
899 "PPC_RELOC_LO16",
900 "PPC_RELOC_HA16",
901 "PPC_RELOC_LO14",
902 "PPC_RELOC_SECTDIFF",
903 "PPC_RELOC_PB_LA_PTR",
904 "PPC_RELOC_HI16_SECTDIFF",
905 "PPC_RELOC_LO16_SECTDIFF",
906 "PPC_RELOC_HA16_SECTDIFF",
907 "PPC_RELOC_JBSR",
908 "PPC_RELOC_LO14_SECTDIFF",
909 "PPC_RELOC_LOCAL_SECTDIFF" };
910
911 res = Table[r_type];
912 break;
913 }
914 case Triple::UnknownArch:
915 res = "Unknown";
916 break;
917 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000918 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000919 return object_error::success;
920}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000921error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
922 int64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000923 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000924 bool isExtern = (RE->Word1 >> 27) & 1;
925 Res = 0;
926 if (!isExtern) {
927 const uint8_t* sectAddress = base();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000928 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000929 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000930 sectAddress += Sect->Offset;
931 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000932 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000933 sectAddress += Sect->Offset;
934 }
935 Res = reinterpret_cast<uintptr_t>(sectAddress);
936 }
937 return object_error::success;
938}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000939
940// Helper to advance a section or symbol iterator multiple increments at a time.
941template<class T>
942error_code advance(T &it, size_t Val) {
943 error_code ec;
944 while (Val--) {
945 it.increment(ec);
946 }
947 return ec;
948}
949
950template<class T>
951void advanceTo(T &it, size_t Val) {
952 if (error_code ec = advance(it, Val))
953 report_fatal_error(ec.message());
954}
955
Owen Anderson1832f4d2011-10-26 20:42:54 +0000956void MachOObjectFile::printRelocationTargetName(
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000957 const MachOFormat::RelocationEntry *RE,
Owen Anderson1832f4d2011-10-26 20:42:54 +0000958 raw_string_ostream &fmt) const {
959 unsigned Arch = getArch();
960 bool isScattered = (Arch != Triple::x86_64) &&
961 (RE->Word0 & macho::RF_Scattered);
962
963 // Target of a scattered relocation is an address. In the interest of
964 // generating pretty output, scan through the symbol table looking for a
965 // symbol that aligns with that address. If we find one, print it.
966 // Otherwise, we just print the hex address of the target.
967 if (isScattered) {
968 uint32_t Val = RE->Word1;
969
970 error_code ec;
971 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
972 SI.increment(ec)) {
973 if (ec) report_fatal_error(ec.message());
974
975 uint64_t Addr;
976 StringRef Name;
977
978 if ((ec = SI->getAddress(Addr)))
979 report_fatal_error(ec.message());
980 if (Addr != Val) continue;
981 if ((ec = SI->getName(Name)))
982 report_fatal_error(ec.message());
983 fmt << Name;
984 return;
985 }
986
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000987 // If we couldn't find a symbol that this relocation refers to, try
988 // to find a section beginning instead.
989 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
990 SI.increment(ec)) {
991 if (ec) report_fatal_error(ec.message());
992
993 uint64_t Addr;
994 StringRef Name;
995
996 if ((ec = SI->getAddress(Addr)))
997 report_fatal_error(ec.message());
998 if (Addr != Val) continue;
999 if ((ec = SI->getName(Name)))
1000 report_fatal_error(ec.message());
1001 fmt << Name;
1002 return;
1003 }
1004
Owen Anderson1832f4d2011-10-26 20:42:54 +00001005 fmt << format("0x%x", Val);
1006 return;
1007 }
1008
1009 StringRef S;
1010 bool isExtern = (RE->Word1 >> 27) & 1;
1011 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001012
1013 if (isExtern) {
1014 symbol_iterator SI = begin_symbols();
1015 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001016 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001017 } else {
1018 section_iterator SI = begin_sections();
1019 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001020 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001021 }
1022
Owen Anderson1832f4d2011-10-26 20:42:54 +00001023 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001024}
1025
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001026error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1027 SmallVectorImpl<char> &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001028 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +00001029
Owen Anderson1832f4d2011-10-26 20:42:54 +00001030 unsigned Arch = getArch();
1031 bool isScattered = (Arch != Triple::x86_64) &&
1032 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001033
Owen Anderson013d7562011-10-25 18:48:41 +00001034 std::string fmtbuf;
1035 raw_string_ostream fmt(fmtbuf);
1036
Owen Anderson1832f4d2011-10-26 20:42:54 +00001037 unsigned Type;
1038 if (isScattered)
1039 Type = (RE->Word0 >> 24) & 0xF;
1040 else
1041 Type = (RE->Word1 >> 28) & 0xF;
1042
Owen Andersoneb6bd332011-10-27 20:46:09 +00001043 bool isPCRel;
1044 if (isScattered)
1045 isPCRel = ((RE->Word0 >> 30) & 1);
1046 else
1047 isPCRel = ((RE->Word1 >> 24) & 1);
1048
Owen Andersond8fa76d2011-10-24 23:20:07 +00001049 // Determine any addends that should be displayed with the relocation.
1050 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +00001051
1052 // X86_64 has entirely custom relocation types.
1053 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +00001054 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +00001055
Owen Andersond8fa76d2011-10-24 23:20:07 +00001056 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001057 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1058 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1059 printRelocationTargetName(RE, fmt);
1060 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +00001061 if (isPCRel) fmt << "PCREL";
1062 break;
1063 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001064 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +00001065 DataRefImpl RelNext = Rel;
1066 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001067 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001068
1069 // X86_64_SUBTRACTOR must be followed by a relocation of type
1070 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001071 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +00001072 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001073 if (RType != 0)
1074 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1075 "X86_64_RELOC_SUBTRACTOR.");
1076
Owen Andersonef22f782011-10-26 17:28:49 +00001077 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1078 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001079 printRelocationTargetName(RENext, fmt);
1080 fmt << "-";
1081 printRelocationTargetName(RE, fmt);
Jim Grosbach133f6b82013-01-31 19:46:57 +00001082 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001083 }
Owen Andersoneb6bd332011-10-27 20:46:09 +00001084 case macho::RIT_X86_64_TLV:
1085 printRelocationTargetName(RE, fmt);
1086 fmt << "@TLV";
1087 if (isPCRel) fmt << "P";
1088 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001089 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1090 printRelocationTargetName(RE, fmt);
1091 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001092 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001093 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1094 printRelocationTargetName(RE, fmt);
1095 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001096 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001097 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1098 printRelocationTargetName(RE, fmt);
1099 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +00001100 break;
1101 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001102 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001103 break;
1104 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001105 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001106 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1107 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001108 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001109 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001110 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001111 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001112 DataRefImpl RelNext = Rel;
1113 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001114 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001115
1116 // X86 sect diff's must be followed by a relocation of type
1117 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001118 bool isNextScattered = (Arch != Triple::x86_64) &&
1119 (RENext->Word0 & macho::RF_Scattered);
1120 unsigned RType;
1121 if (isNextScattered)
1122 RType = (RENext->Word0 >> 24) & 0xF;
1123 else
1124 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001125 if (RType != 1)
1126 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001127 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001128
Owen Anderson1832f4d2011-10-26 20:42:54 +00001129 printRelocationTargetName(RE, fmt);
1130 fmt << "-";
1131 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001132 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001133 }
1134 }
Owen Anderson013d7562011-10-25 18:48:41 +00001135
Owen Anderson1832f4d2011-10-26 20:42:54 +00001136 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001137 // All X86 relocations that need special printing were already
1138 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001139 switch (Type) {
1140 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
Owen Andersoneb6bd332011-10-27 20:46:09 +00001141 DataRefImpl RelNext = Rel;
1142 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001143 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersoneb6bd332011-10-27 20:46:09 +00001144
1145 // X86 sect diff's must be followed by a relocation of type
1146 // GENERIC_RELOC_PAIR.
1147 bool isNextScattered = (Arch != Triple::x86_64) &&
1148 (RENext->Word0 & macho::RF_Scattered);
1149 unsigned RType;
1150 if (isNextScattered)
1151 RType = (RENext->Word0 >> 24) & 0xF;
1152 else
1153 RType = (RENext->Word1 >> 28) & 0xF;
1154 if (RType != 1)
1155 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1156 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1157
1158 printRelocationTargetName(RE, fmt);
1159 fmt << "-";
1160 printRelocationTargetName(RENext, fmt);
1161 break;
1162 }
1163 case macho::RIT_Generic_TLV: {
1164 printRelocationTargetName(RE, fmt);
1165 fmt << "@TLV";
1166 if (isPCRel) fmt << "P";
1167 break;
1168 }
1169 default:
1170 printRelocationTargetName(RE, fmt);
1171 }
Owen Anderson013d7562011-10-25 18:48:41 +00001172 } else { // ARM-specific relocations
1173 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001174 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1175 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001176 // Half relocations steal a bit from the length field to encode
1177 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001178 bool isUpper;
1179 if (isScattered)
1180 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001181 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001182 isUpper = (RE->Word1 >> 25) & 1;
1183
1184 if (isUpper)
1185 fmt << ":upper16:(";
1186 else
1187 fmt << ":lower16:(";
1188 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001189
Owen Anderson013d7562011-10-25 18:48:41 +00001190 DataRefImpl RelNext = Rel;
1191 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001192 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Anderson013d7562011-10-25 18:48:41 +00001193
1194 // ARM half relocs must be followed by a relocation of type
1195 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001196 bool isNextScattered = (Arch != Triple::x86_64) &&
1197 (RENext->Word0 & macho::RF_Scattered);
1198 unsigned RType;
1199 if (isNextScattered)
1200 RType = (RENext->Word0 >> 24) & 0xF;
1201 else
1202 RType = (RENext->Word1 >> 28) & 0xF;
1203
Owen Anderson013d7562011-10-25 18:48:41 +00001204 if (RType != 1)
1205 report_fatal_error("Expected ARM_RELOC_PAIR after "
1206 "GENERIC_RELOC_HALF");
1207
Owen Anderson1832f4d2011-10-26 20:42:54 +00001208 // NOTE: The half of the target virtual address is stashed in the
1209 // address field of the secondary relocation, but we can't reverse
1210 // engineer the constant offset from it without decoding the movw/movt
1211 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001212
1213 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1214 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001215 if (Type == macho::RIT_ARM_HalfDifference) {
1216 fmt << "-";
1217 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001218 }
1219
Owen Anderson013d7562011-10-25 18:48:41 +00001220 fmt << ")";
1221 break;
1222 }
1223 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001224 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001225 }
1226 }
1227 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001228 } else
1229 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001230
Owen Anderson0135fe12011-10-24 21:44:00 +00001231 fmt.flush();
1232 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001233 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001234}
1235
Owen Anderson0685e942011-10-25 20:35:53 +00001236error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1237 bool &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001238 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0685e942011-10-25 20:35:53 +00001239
Owen Anderson0685e942011-10-25 20:35:53 +00001240 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001241 bool isScattered = (Arch != Triple::x86_64) &&
1242 (RE->Word0 & macho::RF_Scattered);
1243 unsigned Type;
1244 if (isScattered)
1245 Type = (RE->Word0 >> 24) & 0xF;
1246 else
1247 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001248
1249 Result = false;
1250
1251 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1252 // is always hidden.
1253 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001254 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001255 } else if (Arch == Triple::x86_64) {
1256 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1257 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001258 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001259 DataRefImpl RelPrev = Rel;
1260 RelPrev.d.a--;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001261 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
Owen Anderson0685e942011-10-25 20:35:53 +00001262
1263 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1264
Owen Anderson1832f4d2011-10-26 20:42:54 +00001265 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001266 }
1267 }
1268
1269 return object_error::success;
1270}
1271
David Meyer5c2b4ea2012-03-01 01:36:50 +00001272error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1273 LibraryRef &Res) const {
1274 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1275}
1276
1277error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1278 StringRef &Res) const {
1279 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1280}
1281
1282
Eric Christopher6256b032011-04-22 03:19:48 +00001283/*===-- Miscellaneous -----------------------------------------------------===*/
1284
1285uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001286 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001287}
1288
1289StringRef MachOObjectFile::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001290 if (!is64Bit()) {
Rafael Espindola433611b2013-04-07 19:26:57 +00001291 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001292 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001293 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001294 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001295 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001296 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001297 return "Mach-O 32-bit ppc";
1298 default:
Rafael Espindola433611b2013-04-07 19:26:57 +00001299 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001300 "64-bit object file when we're not 64-bit?");
1301 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001302 }
1303 }
1304
Eric Christopherb3e6b042013-02-28 20:26:17 +00001305 // Make sure the cpu type has the correct mask.
Rafael Espindola433611b2013-04-07 19:26:57 +00001306 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +00001307 == llvm::MachO::CPUArchABI64 &&
1308 "32-bit object file when we're 64-bit?");
1309
Rafael Espindola433611b2013-04-07 19:26:57 +00001310 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001311 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001312 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001313 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001314 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001315 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001316 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001317 }
1318}
1319
1320unsigned MachOObjectFile::getArch() const {
Rafael Espindola433611b2013-04-07 19:26:57 +00001321 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001322 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001323 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001324 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001325 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001326 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001327 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001328 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001329 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001330 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001331 return Triple::ppc64;
1332 default:
1333 return Triple::UnknownArch;
1334 }
1335}
1336
Owen Andersonf7c93a32011-10-11 17:32:27 +00001337} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001338} // end namespace llvm