blob: 24c916c32380ef3f5c3214b165af0f2ebb24c489 [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 Espindolaf3051272013-04-07 17:41:59 +0000492static bool is64BitLoadCommand(const MachOObjectFile *MachOObj,
493 DataRefImpl DRI) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000494 const MachOFormat::LoadCommand *Command =
Rafael Espindola77638d92013-04-07 18:08:12 +0000495 MachOObj->getLoadCommandInfo(DRI.d.a);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000496 if (Command->Type == macho::LCT_Segment64)
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000497 return true;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000498 assert(Command->Type == macho::LCT_Segment && "Unexpected Type.");
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000499 return false;
500}
501
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000502const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000503 assert(!is64BitLoadCommand(this, DRI));
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000504 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
505 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
506 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000507 DRI.d.b * sizeof(MachOFormat::Section);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000508 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
Eric Christopher6256b032011-04-22 03:19:48 +0000509}
510
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000511std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
512 SectionList::const_iterator loc =
513 std::find(Sections.begin(), Sections.end(), Sec);
514 assert(loc != Sections.end() && "Sec is not a valid section!");
515 return std::distance(Sections.begin(), loc);
516}
517
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000518const MachOFormat::Section64 *
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000519MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000520 assert(is64BitLoadCommand(this, DRI));
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000521 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
522 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
523 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000524 DRI.d.b * sizeof(MachOFormat::Section64);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000525 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000526}
527
Rafael Espindolacef81b32012-12-21 03:47:03 +0000528static StringRef parseSegmentOrSectionName(const char *P) {
529 if (P[15] == 0)
530 // Null terminated.
531 return P;
532 // Not null terminated, so this is a 16 char string.
533 return StringRef(P, 16);
534}
535
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000536ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000537 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000538 const MachOFormat::Section64 *sec = getSection64(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000539 return ArrayRef<char>(sec->Name);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000540 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000541 const MachOFormat::Section *sec = getSection(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000542 return ArrayRef<char>(sec->Name);
Rafael Espindolaf9a6bd82012-12-19 14:15:04 +0000543 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000544}
545
546error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
547 StringRef &Result) const {
548 ArrayRef<char> Raw = getSectionRawName(DRI);
549 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000550 return object_error::success;
551}
552
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000553ArrayRef<char>
554MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000555 if (is64BitLoadCommand(this, Sec)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000556 const MachOFormat::Section64 *sec = getSection64(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000557 return ArrayRef<char>(sec->SegmentName, 16);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000558 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000559 const MachOFormat::Section *sec = getSection(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000560 return ArrayRef<char>(sec->SegmentName);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000561 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000562}
563
564StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
565 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
566 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000567}
568
Michael J. Spencer25b15772011-06-25 17:55:23 +0000569error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
570 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000571 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000572 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000573 Result = Sect->Address;
574 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000575 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000576 Result = Sect->Address;
577 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000578 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000579}
580
Michael J. Spencer25b15772011-06-25 17:55:23 +0000581error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
582 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000583 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000584 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000585 Result = Sect->Size;
586 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000587 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000588 Result = Sect->Size;
589 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000590 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000591}
592
Michael J. Spencer25b15772011-06-25 17:55:23 +0000593error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
594 StringRef &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000595 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000596 const MachOFormat::Section64 *Sect = getSection64(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000597 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000598 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000599 const MachOFormat::Section *Sect = getSection(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000600 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000601 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000602 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000603}
604
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000605error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
606 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000607 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000608 const MachOFormat::Section64 *Sect = getSection64(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000609 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000610 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000611 const MachOFormat::Section *Sect = getSection(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000612 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000613 }
614 return object_error::success;
615}
616
Michael J. Spencer25b15772011-06-25 17:55:23 +0000617error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
618 bool &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000619 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000620 const MachOFormat::Section64 *Sect = getSection64(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000621 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000622 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000623 const MachOFormat::Section *Sect = getSection(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000624 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000625 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000626 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000627}
628
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000629error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
630 bool &Result) const {
631 // FIXME: Unimplemented.
632 Result = false;
633 return object_error::success;
634}
635
636error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
637 bool &Result) const {
638 // FIXME: Unimplemented.
639 Result = false;
640 return object_error::success;
641}
642
Preston Gurdc68dda82012-04-12 20:13:57 +0000643error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
644 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000645 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000646 Result = true;
647 return object_error::success;
648}
649
650error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000651 bool &Result) const {
652 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000653 Result = false;
654 return object_error::success;
655}
656
657error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
658 bool &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000659 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000660 const MachOFormat::Section64 *Sect = getSection64(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000661 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
662 Result = (SectionType == MachO::SectionTypeZeroFill ||
663 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000664 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000665 const MachOFormat::Section *Sect = getSection(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000666 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
667 Result = (SectionType == MachO::SectionTypeZeroFill ||
668 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000669 }
670
671 return object_error::success;
672}
673
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000674error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
675 bool &Result) const {
676 // Consider using the code from isSectionText to look for __const sections.
677 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
678 // to use section attributes to distinguish code from data.
679
680 // FIXME: Unimplemented.
681 Result = false;
682 return object_error::success;
683}
684
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000685error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
686 DataRefImpl Symb,
687 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000688 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000689 getSymbolType(Symb, ST);
David Meyer2c677272012-02-29 02:11:55 +0000690 if (ST == SymbolRef::ST_Unknown) {
Owen Andersoncd749882011-10-12 22:21:32 +0000691 Result = false;
692 return object_error::success;
693 }
694
695 uint64_t SectBegin, SectEnd;
696 getSectionAddress(Sec, SectBegin);
697 getSectionSize(Sec, SectEnd);
698 SectEnd += SectBegin;
699
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000700 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000701 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000702 uint64_t SymAddr= Entry->Value;
703 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000704 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000705 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000706 uint64_t SymAddr= Entry->Value;
707 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000708 }
Owen Andersoncd749882011-10-12 22:21:32 +0000709
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000710 return object_error::success;
711}
712
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000713relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
714 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000715 ret.d.b = getSectionIndex(Sec);
716 return relocation_iterator(RelocationRef(ret, this));
717}
718relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
719 uint32_t last_reloc;
Rafael Espindolaf3051272013-04-07 17:41:59 +0000720 if (is64BitLoadCommand(this, Sec)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000721 const MachOFormat::Section64 *Sect = getSection64(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000722 last_reloc = Sect->NumRelocationTableEntries;
723 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000724 const MachOFormat::Section *Sect = getSection(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000725 last_reloc = Sect->NumRelocationTableEntries;
726 }
727 DataRefImpl ret;
728 ret.d.a = last_reloc;
729 ret.d.b = getSectionIndex(Sec);
730 return relocation_iterator(RelocationRef(ret, this));
731}
732
733section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000734 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000735 moveToNextSection(DRI);
736 return section_iterator(SectionRef(DRI, this));
737}
738
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000739section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000740 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000741 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000742 return section_iterator(SectionRef(DRI, this));
743}
744
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000745/*===-- Relocations -------------------------------------------------------===*/
746
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000747const MachOFormat::RelocationEntry *
748MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000749 uint32_t relOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000750 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000751 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000752 relOffset = Sect->RelocationTableOffset;
753 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000754 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000755 relOffset = Sect->RelocationTableOffset;
756 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000757 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000758 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000759 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000760}
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000761
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000762error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
763 RelocationRef &Res) const {
764 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000765 Res = RelocationRef(Rel, this);
766 return object_error::success;
767}
768error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
769 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000770 const uint8_t* sectAddress = 0;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000771 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000772 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000773 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000774 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000775 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000776 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000777 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000778 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000779
780 unsigned Arch = getArch();
781 bool isScattered = (Arch != Triple::x86_64) &&
782 (RE->Word0 & macho::RF_Scattered);
783 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000784 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000785 RelAddr = RE->Word0 & 0xFFFFFF;
786 else
787 RelAddr = RE->Word0;
788
789 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000790 return object_error::success;
791}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000792error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
793 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000794 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000795
796 unsigned Arch = getArch();
797 bool isScattered = (Arch != Triple::x86_64) &&
798 (RE->Word0 & macho::RF_Scattered);
799 if (isScattered)
800 Res = RE->Word0 & 0xFFFFFF;
801 else
802 Res = RE->Word0;
803 return object_error::success;
804}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000805error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
806 SymbolRef &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000807 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000808 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
809 bool isExtern = (RE->Word1 >> 27) & 1;
810
811 DataRefImpl Sym;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000812 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000813 if (isExtern) {
814 for (unsigned i = 0; i < SymbolIdx; i++) {
815 Sym.d.b++;
816 moveToNextSymbol(Sym);
Rafael Espindola433611b2013-04-07 19:26:57 +0000817 assert(Sym.d.a < getHeader()->NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000818 "Relocation symbol index out of range!");
819 }
820 }
821 Res = SymbolRef(Sym, this);
822 return object_error::success;
823}
824error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000825 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000826 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Andersonf8261e72011-10-26 17:10:22 +0000827 Res = RE->Word0;
828 Res <<= 32;
829 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000830 return object_error::success;
831}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000832error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
833 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000834 // TODO: Support scattered relocations.
835 StringRef res;
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000836 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +0000837
838 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000839 bool isScattered = (Arch != Triple::x86_64) &&
840 (RE->Word0 & macho::RF_Scattered);
841
842 unsigned r_type;
843 if (isScattered)
844 r_type = (RE->Word0 >> 24) & 0xF;
845 else
846 r_type = (RE->Word1 >> 28) & 0xF;
847
Owen Anderson0135fe12011-10-24 21:44:00 +0000848 switch (Arch) {
849 case Triple::x86: {
Craig Toppere3298102012-05-24 06:35:32 +0000850 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000851 "GENERIC_RELOC_VANILLA",
852 "GENERIC_RELOC_PAIR",
853 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000854 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000855 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000856 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000857
Owen Andersoneb6bd332011-10-27 20:46:09 +0000858 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000859 res = "Unknown";
860 else
861 res = Table[r_type];
862 break;
863 }
864 case Triple::x86_64: {
Craig Toppere3298102012-05-24 06:35:32 +0000865 static const char *const Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000866 "X86_64_RELOC_UNSIGNED",
867 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000868 "X86_64_RELOC_BRANCH",
869 "X86_64_RELOC_GOT_LOAD",
870 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000871 "X86_64_RELOC_SUBTRACTOR",
872 "X86_64_RELOC_SIGNED_1",
873 "X86_64_RELOC_SIGNED_2",
874 "X86_64_RELOC_SIGNED_4",
875 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000876
Owen Andersond8fa76d2011-10-24 23:20:07 +0000877 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000878 res = "Unknown";
879 else
880 res = Table[r_type];
881 break;
882 }
883 case Triple::arm: {
Craig Toppere3298102012-05-24 06:35:32 +0000884 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000885 "ARM_RELOC_VANILLA",
886 "ARM_RELOC_PAIR",
887 "ARM_RELOC_SECTDIFF",
888 "ARM_RELOC_LOCAL_SECTDIFF",
889 "ARM_RELOC_PB_LA_PTR",
890 "ARM_RELOC_BR24",
891 "ARM_THUMB_RELOC_BR22",
892 "ARM_THUMB_32BIT_BRANCH",
893 "ARM_RELOC_HALF",
894 "ARM_RELOC_HALF_SECTDIFF" };
895
896 if (r_type > 9)
897 res = "Unknown";
898 else
899 res = Table[r_type];
900 break;
901 }
902 case Triple::ppc: {
Craig Toppere3298102012-05-24 06:35:32 +0000903 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000904 "PPC_RELOC_VANILLA",
905 "PPC_RELOC_PAIR",
906 "PPC_RELOC_BR14",
907 "PPC_RELOC_BR24",
908 "PPC_RELOC_HI16",
909 "PPC_RELOC_LO16",
910 "PPC_RELOC_HA16",
911 "PPC_RELOC_LO14",
912 "PPC_RELOC_SECTDIFF",
913 "PPC_RELOC_PB_LA_PTR",
914 "PPC_RELOC_HI16_SECTDIFF",
915 "PPC_RELOC_LO16_SECTDIFF",
916 "PPC_RELOC_HA16_SECTDIFF",
917 "PPC_RELOC_JBSR",
918 "PPC_RELOC_LO14_SECTDIFF",
919 "PPC_RELOC_LOCAL_SECTDIFF" };
920
921 res = Table[r_type];
922 break;
923 }
924 case Triple::UnknownArch:
925 res = "Unknown";
926 break;
927 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000928 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000929 return object_error::success;
930}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000931error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
932 int64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000933 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000934 bool isExtern = (RE->Word1 >> 27) & 1;
935 Res = 0;
936 if (!isExtern) {
937 const uint8_t* sectAddress = base();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000938 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000939 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000940 sectAddress += Sect->Offset;
941 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000942 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000943 sectAddress += Sect->Offset;
944 }
945 Res = reinterpret_cast<uintptr_t>(sectAddress);
946 }
947 return object_error::success;
948}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000949
950// Helper to advance a section or symbol iterator multiple increments at a time.
951template<class T>
952error_code advance(T &it, size_t Val) {
953 error_code ec;
954 while (Val--) {
955 it.increment(ec);
956 }
957 return ec;
958}
959
960template<class T>
961void advanceTo(T &it, size_t Val) {
962 if (error_code ec = advance(it, Val))
963 report_fatal_error(ec.message());
964}
965
Owen Anderson1832f4d2011-10-26 20:42:54 +0000966void MachOObjectFile::printRelocationTargetName(
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000967 const MachOFormat::RelocationEntry *RE,
Owen Anderson1832f4d2011-10-26 20:42:54 +0000968 raw_string_ostream &fmt) const {
969 unsigned Arch = getArch();
970 bool isScattered = (Arch != Triple::x86_64) &&
971 (RE->Word0 & macho::RF_Scattered);
972
973 // Target of a scattered relocation is an address. In the interest of
974 // generating pretty output, scan through the symbol table looking for a
975 // symbol that aligns with that address. If we find one, print it.
976 // Otherwise, we just print the hex address of the target.
977 if (isScattered) {
978 uint32_t Val = RE->Word1;
979
980 error_code ec;
981 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
982 SI.increment(ec)) {
983 if (ec) report_fatal_error(ec.message());
984
985 uint64_t Addr;
986 StringRef Name;
987
988 if ((ec = SI->getAddress(Addr)))
989 report_fatal_error(ec.message());
990 if (Addr != Val) continue;
991 if ((ec = SI->getName(Name)))
992 report_fatal_error(ec.message());
993 fmt << Name;
994 return;
995 }
996
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000997 // If we couldn't find a symbol that this relocation refers to, try
998 // to find a section beginning instead.
999 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
1000 SI.increment(ec)) {
1001 if (ec) report_fatal_error(ec.message());
1002
1003 uint64_t Addr;
1004 StringRef Name;
1005
1006 if ((ec = SI->getAddress(Addr)))
1007 report_fatal_error(ec.message());
1008 if (Addr != Val) continue;
1009 if ((ec = SI->getName(Name)))
1010 report_fatal_error(ec.message());
1011 fmt << Name;
1012 return;
1013 }
1014
Owen Anderson1832f4d2011-10-26 20:42:54 +00001015 fmt << format("0x%x", Val);
1016 return;
1017 }
1018
1019 StringRef S;
1020 bool isExtern = (RE->Word1 >> 27) & 1;
1021 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001022
1023 if (isExtern) {
1024 symbol_iterator SI = begin_symbols();
1025 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001026 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001027 } else {
1028 section_iterator SI = begin_sections();
1029 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001030 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001031 }
1032
Owen Anderson1832f4d2011-10-26 20:42:54 +00001033 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001034}
1035
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001036error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1037 SmallVectorImpl<char> &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001038 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +00001039
Owen Anderson1832f4d2011-10-26 20:42:54 +00001040 unsigned Arch = getArch();
1041 bool isScattered = (Arch != Triple::x86_64) &&
1042 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001043
Owen Anderson013d7562011-10-25 18:48:41 +00001044 std::string fmtbuf;
1045 raw_string_ostream fmt(fmtbuf);
1046
Owen Anderson1832f4d2011-10-26 20:42:54 +00001047 unsigned Type;
1048 if (isScattered)
1049 Type = (RE->Word0 >> 24) & 0xF;
1050 else
1051 Type = (RE->Word1 >> 28) & 0xF;
1052
Owen Andersoneb6bd332011-10-27 20:46:09 +00001053 bool isPCRel;
1054 if (isScattered)
1055 isPCRel = ((RE->Word0 >> 30) & 1);
1056 else
1057 isPCRel = ((RE->Word1 >> 24) & 1);
1058
Owen Andersond8fa76d2011-10-24 23:20:07 +00001059 // Determine any addends that should be displayed with the relocation.
1060 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +00001061
1062 // X86_64 has entirely custom relocation types.
1063 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +00001064 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +00001065
Owen Andersond8fa76d2011-10-24 23:20:07 +00001066 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001067 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1068 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1069 printRelocationTargetName(RE, fmt);
1070 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +00001071 if (isPCRel) fmt << "PCREL";
1072 break;
1073 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001074 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +00001075 DataRefImpl RelNext = Rel;
1076 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001077 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001078
1079 // X86_64_SUBTRACTOR must be followed by a relocation of type
1080 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001081 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +00001082 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001083 if (RType != 0)
1084 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1085 "X86_64_RELOC_SUBTRACTOR.");
1086
Owen Andersonef22f782011-10-26 17:28:49 +00001087 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1088 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001089 printRelocationTargetName(RENext, fmt);
1090 fmt << "-";
1091 printRelocationTargetName(RE, fmt);
Jim Grosbach133f6b82013-01-31 19:46:57 +00001092 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001093 }
Owen Andersoneb6bd332011-10-27 20:46:09 +00001094 case macho::RIT_X86_64_TLV:
1095 printRelocationTargetName(RE, fmt);
1096 fmt << "@TLV";
1097 if (isPCRel) fmt << "P";
1098 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001099 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1100 printRelocationTargetName(RE, fmt);
1101 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001102 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001103 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1104 printRelocationTargetName(RE, fmt);
1105 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001106 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001107 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1108 printRelocationTargetName(RE, fmt);
1109 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +00001110 break;
1111 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001112 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001113 break;
1114 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001115 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001116 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1117 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001118 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001119 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001120 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001121 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001122 DataRefImpl RelNext = Rel;
1123 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001124 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001125
1126 // X86 sect diff's must be followed by a relocation of type
1127 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001128 bool isNextScattered = (Arch != Triple::x86_64) &&
1129 (RENext->Word0 & macho::RF_Scattered);
1130 unsigned RType;
1131 if (isNextScattered)
1132 RType = (RENext->Word0 >> 24) & 0xF;
1133 else
1134 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001135 if (RType != 1)
1136 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001137 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001138
Owen Anderson1832f4d2011-10-26 20:42:54 +00001139 printRelocationTargetName(RE, fmt);
1140 fmt << "-";
1141 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001142 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001143 }
1144 }
Owen Anderson013d7562011-10-25 18:48:41 +00001145
Owen Anderson1832f4d2011-10-26 20:42:54 +00001146 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001147 // All X86 relocations that need special printing were already
1148 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001149 switch (Type) {
1150 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
Owen Andersoneb6bd332011-10-27 20:46:09 +00001151 DataRefImpl RelNext = Rel;
1152 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001153 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersoneb6bd332011-10-27 20:46:09 +00001154
1155 // X86 sect diff's must be followed by a relocation of type
1156 // GENERIC_RELOC_PAIR.
1157 bool isNextScattered = (Arch != Triple::x86_64) &&
1158 (RENext->Word0 & macho::RF_Scattered);
1159 unsigned RType;
1160 if (isNextScattered)
1161 RType = (RENext->Word0 >> 24) & 0xF;
1162 else
1163 RType = (RENext->Word1 >> 28) & 0xF;
1164 if (RType != 1)
1165 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1166 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1167
1168 printRelocationTargetName(RE, fmt);
1169 fmt << "-";
1170 printRelocationTargetName(RENext, fmt);
1171 break;
1172 }
1173 case macho::RIT_Generic_TLV: {
1174 printRelocationTargetName(RE, fmt);
1175 fmt << "@TLV";
1176 if (isPCRel) fmt << "P";
1177 break;
1178 }
1179 default:
1180 printRelocationTargetName(RE, fmt);
1181 }
Owen Anderson013d7562011-10-25 18:48:41 +00001182 } else { // ARM-specific relocations
1183 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001184 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1185 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001186 // Half relocations steal a bit from the length field to encode
1187 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001188 bool isUpper;
1189 if (isScattered)
1190 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001191 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001192 isUpper = (RE->Word1 >> 25) & 1;
1193
1194 if (isUpper)
1195 fmt << ":upper16:(";
1196 else
1197 fmt << ":lower16:(";
1198 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001199
Owen Anderson013d7562011-10-25 18:48:41 +00001200 DataRefImpl RelNext = Rel;
1201 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001202 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Anderson013d7562011-10-25 18:48:41 +00001203
1204 // ARM half relocs must be followed by a relocation of type
1205 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001206 bool isNextScattered = (Arch != Triple::x86_64) &&
1207 (RENext->Word0 & macho::RF_Scattered);
1208 unsigned RType;
1209 if (isNextScattered)
1210 RType = (RENext->Word0 >> 24) & 0xF;
1211 else
1212 RType = (RENext->Word1 >> 28) & 0xF;
1213
Owen Anderson013d7562011-10-25 18:48:41 +00001214 if (RType != 1)
1215 report_fatal_error("Expected ARM_RELOC_PAIR after "
1216 "GENERIC_RELOC_HALF");
1217
Owen Anderson1832f4d2011-10-26 20:42:54 +00001218 // NOTE: The half of the target virtual address is stashed in the
1219 // address field of the secondary relocation, but we can't reverse
1220 // engineer the constant offset from it without decoding the movw/movt
1221 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001222
1223 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1224 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001225 if (Type == macho::RIT_ARM_HalfDifference) {
1226 fmt << "-";
1227 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001228 }
1229
Owen Anderson013d7562011-10-25 18:48:41 +00001230 fmt << ")";
1231 break;
1232 }
1233 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001234 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001235 }
1236 }
1237 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001238 } else
1239 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001240
Owen Anderson0135fe12011-10-24 21:44:00 +00001241 fmt.flush();
1242 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001243 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001244}
1245
Owen Anderson0685e942011-10-25 20:35:53 +00001246error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1247 bool &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001248 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0685e942011-10-25 20:35:53 +00001249
Owen Anderson0685e942011-10-25 20:35:53 +00001250 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001251 bool isScattered = (Arch != Triple::x86_64) &&
1252 (RE->Word0 & macho::RF_Scattered);
1253 unsigned Type;
1254 if (isScattered)
1255 Type = (RE->Word0 >> 24) & 0xF;
1256 else
1257 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001258
1259 Result = false;
1260
1261 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1262 // is always hidden.
1263 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001264 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001265 } else if (Arch == Triple::x86_64) {
1266 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1267 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001268 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001269 DataRefImpl RelPrev = Rel;
1270 RelPrev.d.a--;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001271 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
Owen Anderson0685e942011-10-25 20:35:53 +00001272
1273 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1274
Owen Anderson1832f4d2011-10-26 20:42:54 +00001275 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001276 }
1277 }
1278
1279 return object_error::success;
1280}
1281
David Meyer5c2b4ea2012-03-01 01:36:50 +00001282error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1283 LibraryRef &Res) const {
1284 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1285}
1286
1287error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1288 StringRef &Res) const {
1289 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1290}
1291
1292
Eric Christopher6256b032011-04-22 03:19:48 +00001293/*===-- Miscellaneous -----------------------------------------------------===*/
1294
1295uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001296 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001297}
1298
1299StringRef MachOObjectFile::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001300 if (!is64Bit()) {
Rafael Espindola433611b2013-04-07 19:26:57 +00001301 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001302 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001303 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001304 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001305 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001306 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001307 return "Mach-O 32-bit ppc";
1308 default:
Rafael Espindola433611b2013-04-07 19:26:57 +00001309 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001310 "64-bit object file when we're not 64-bit?");
1311 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001312 }
1313 }
1314
Eric Christopherb3e6b042013-02-28 20:26:17 +00001315 // Make sure the cpu type has the correct mask.
Rafael Espindola433611b2013-04-07 19:26:57 +00001316 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +00001317 == llvm::MachO::CPUArchABI64 &&
1318 "32-bit object file when we're 64-bit?");
1319
Rafael Espindola433611b2013-04-07 19:26:57 +00001320 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001321 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001322 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001323 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001324 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001325 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001326 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001327 }
1328}
1329
1330unsigned MachOObjectFile::getArch() const {
Rafael Espindola433611b2013-04-07 19:26:57 +00001331 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001332 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001333 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001334 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001335 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001336 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001337 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001338 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001339 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001340 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001341 return Triple::ppc64;
1342 default:
1343 return Triple::UnknownArch;
1344 }
1345}
1346
Owen Andersonf7c93a32011-10-11 17:32:27 +00001347} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001348} // end namespace llvm