blob: f011da1e3a04e25c0dbd68d9cfe77a19bb861c28 [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"
Owen Anderson1832f4d2011-10-26 20:42:54 +000018#include "llvm/Support/Format.h"
Eric Christopher6256b032011-04-22 03:19:48 +000019#include "llvm/Support/MemoryBuffer.h"
Eric Christopher6256b032011-04-22 03:19:48 +000020#include <cctype>
21#include <cstring>
22#include <limits>
23
24using namespace llvm;
25using namespace object;
26
27namespace llvm {
Owen Andersonf7c93a32011-10-11 17:32:27 +000028namespace object {
Eric Christopher6256b032011-04-22 03:19:48 +000029
Rafael Espindola6f1f3392013-04-07 16:58:48 +000030MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec)
31 : ObjectFile(Binary::ID_MachO, Object) {
32 // MachOObject takes ownership of the Buffer we passed to it, and
33 // MachOObjectFile does, too, so we need to make sure they don't get the
34 // same object. A MemoryBuffer is cheap (it's just a reference to memory,
35 // not a copy of the memory itself), so just make a new copy here for
36 // the MachOObjectFile.
37 MemoryBuffer *NewBuffer =
38 MemoryBuffer::getMemBuffer(Object->getBuffer(),
39 Object->getBufferIdentifier(), false);
40 std::string ErrorStr;
41 MachOObj.reset(MachOObject::LoadFromBuffer(NewBuffer, &ErrorStr));
42 if (!MachOObj) {
43 ec = object_error::parse_failed;
44 return;
45 }
46
Benjamin Kramer0fcab072011-09-08 20:52:17 +000047 DataRefImpl DRI;
Benjamin Kramer0fcab072011-09-08 20:52:17 +000048 moveToNextSection(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +000049 uint32_t LoadCommandCount = getHeader().NumLoadCommands;
Benjamin Kramer0fcab072011-09-08 20:52:17 +000050 while (DRI.d.a < LoadCommandCount) {
51 Sections.push_back(DRI);
Benjamin Kramer0fcab072011-09-08 20:52:17 +000052 DRI.d.b++;
53 moveToNextSection(DRI);
54 }
55}
56
Rafael Espindola0be4eaf2013-04-07 15:46:05 +000057bool MachOObjectFile::is64Bit() const {
58 return MachOObj->is64Bit();
59}
Benjamin Kramer0fcab072011-09-08 20:52:17 +000060
Rafael Espindola6ab85a82013-04-07 18:42:06 +000061const MachOFormat::LoadCommand *
Rafael Espindola3eff3182013-04-07 16:07:35 +000062MachOObjectFile::getLoadCommandInfo(unsigned Index) const {
Rafael Espindola77638d92013-04-07 18:08:12 +000063 uint64_t Offset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000064 uint64_t NewOffset = getHeaderSize();
Rafael Espindola77638d92013-04-07 18:08:12 +000065 const MachOFormat::LoadCommand *Load;
66 unsigned I = 0;
67 do {
68 Offset = NewOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000069 StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand));
Rafael Espindola77638d92013-04-07 18:08:12 +000070 Load = reinterpret_cast<const MachOFormat::LoadCommand*>(Data.data());
71 NewOffset = Offset + Load->Size;
72 ++I;
73 } while (I != Index + 1);
74
Rafael Espindola6ab85a82013-04-07 18:42:06 +000075 return Load;
Rafael Espindola3eff3182013-04-07 16:07:35 +000076}
77
78void MachOObjectFile::ReadULEB128s(uint64_t Index,
79 SmallVectorImpl<uint64_t> &Out) const {
80 return MachOObj->ReadULEB128s(Index, Out);
81}
82
83const macho::Header &MachOObjectFile::getHeader() const {
84 return MachOObj->getHeader();
85}
86
Rafael Espindola0f08eb12013-04-07 19:05:30 +000087unsigned MachOObjectFile::getHeaderSize() const {
88 return MachOObj->getHeaderSize();
89}
90
91StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const {
92 return MachOObj->getData(Offset, Size);
93}
94
Eric Christopher6256b032011-04-22 03:19:48 +000095ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Michael J. Spencer001c9202011-06-25 17:54:50 +000096 error_code ec;
Rafael Espindola6f1f3392013-04-07 16:58:48 +000097 ObjectFile *Ret = new MachOObjectFile(Buffer, ec);
98 if (ec)
Eric Christopher6256b032011-04-22 03:19:48 +000099 return NULL;
Rafael Espindola6f1f3392013-04-07 16:58:48 +0000100 return Ret;
Eric Christopher6256b032011-04-22 03:19:48 +0000101}
102
103/*===-- Symbols -----------------------------------------------------------===*/
104
105void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000106 uint32_t LoadCommandCount = getHeader().NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000107 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000108 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
109 if (Command->Type == macho::LCT_Symtab) {
Rafael Espindola82a21072013-04-06 03:31:08 +0000110 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000111 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000112 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
113 return;
114 }
115
116 DRI.d.a++;
117 DRI.d.b = 0;
118 }
119}
120
Rafael Espindola00555c12013-04-06 01:59:05 +0000121const MachOFormat::SymbolTableEntry *
122MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000123 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000124 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000125 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000126
Rafael Espindola82a21072013-04-06 03:31:08 +0000127 return getSymbolTableEntry(DRI, SymtabLoadCmd);
128}
Eric Christopher6256b032011-04-22 03:19:48 +0000129
Rafael Espindola82a21072013-04-06 03:31:08 +0000130const MachOFormat::SymbolTableEntry *
131MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
132 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola00555c12013-04-06 01:59:05 +0000133 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
134 unsigned Index = DRI.d.b;
135 uint64_t Offset = (SymbolTableOffset +
136 Index * sizeof(macho::SymbolTableEntry));
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000137 StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry));
Rafael Espindola00555c12013-04-06 01:59:05 +0000138 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000139}
140
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000141const MachOFormat::Symbol64TableEntry*
142MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000143 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000144 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000145 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000146
Rafael Espindola82a21072013-04-06 03:31:08 +0000147 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
148}
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000149
Rafael Espindola82a21072013-04-06 03:31:08 +0000150const MachOFormat::Symbol64TableEntry*
151MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
152 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000153 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
154 unsigned Index = DRI.d.b;
155 uint64_t Offset = (SymbolTableOffset +
156 Index * sizeof(macho::Symbol64TableEntry));
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000157 StringRef Data = getData(Offset, sizeof(MachOFormat::Symbol64TableEntry));
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000158 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000159}
160
Michael J. Spencer25b15772011-06-25 17:55:23 +0000161error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
162 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000163 DRI.d.b++;
164 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000165 Result = SymbolRef(DRI, this);
166 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000167}
168
Michael J. Spencer25b15772011-06-25 17:55:23 +0000169error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
170 StringRef &Result) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000171 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000172 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000173 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Rafael Espindola82a21072013-04-06 03:31:08 +0000174
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000175 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
176 SymtabLoadCmd->StringTableSize);
Rafael Espindola82a21072013-04-06 03:31:08 +0000177
178 uint32_t StringIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000179 if (is64Bit()) {
Rafael Espindola82a21072013-04-06 03:31:08 +0000180 const MachOFormat::Symbol64TableEntry *Entry =
181 getSymbol64TableEntry(DRI, SymtabLoadCmd);
182 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000183 } else {
Rafael Espindola82a21072013-04-06 03:31:08 +0000184 const MachOFormat::SymbolTableEntry *Entry =
185 getSymbolTableEntry(DRI, SymtabLoadCmd);
186 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000187 }
Rafael Espindola82a21072013-04-06 03:31:08 +0000188
189 const char *Start = &StringTable.data()[StringIndex];
190 Result = StringRef(Start);
191
Michael J. Spencer25b15772011-06-25 17:55:23 +0000192 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000193}
194
Danil Malyshevb0436a72011-11-29 17:40:10 +0000195error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
196 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000197 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000198 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000199 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000200 if (Entry->SectionIndex) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000201 const MachOFormat::Section64 *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000202 getSection64(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000203 Result += Section->Offset - Section->Address;
204 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000205 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000206 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000207 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000208 if (Entry->SectionIndex) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000209 const MachOFormat::Section *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000210 getSection(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000211 Result += Section->Offset - Section->Address;
212 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000213 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000214
Michael J. Spencer25b15772011-06-25 17:55:23 +0000215 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000216}
217
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000218error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
219 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000220 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000221 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000222 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000223 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000224 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000225 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000226 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000227 return object_error::success;
228}
229
Michael J. Spencer25b15772011-06-25 17:55:23 +0000230error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
231 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000232 uint32_t LoadCommandCount = getHeader().NumLoadCommands;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000233 uint64_t BeginOffset;
234 uint64_t EndOffset = 0;
235 uint8_t SectionIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000236 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000237 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000238 BeginOffset = Entry->Value;
239 SectionIndex = Entry->SectionIndex;
240 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000241 uint32_t flags = SymbolRef::SF_None;
242 getSymbolFlags(DRI, flags);
243 if (flags & SymbolRef::SF_Common)
244 Result = Entry->Value;
245 else
246 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000247 return object_error::success;
248 }
249 // Unfortunately symbols are unsorted so we need to touch all
250 // symbols from load command
251 DRI.d.b = 0;
252 uint32_t Command = DRI.d.a;
253 while (Command == DRI.d.a) {
254 moveToNextSymbol(DRI);
255 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000256 Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000257 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
258 if (!EndOffset || Entry->Value < EndOffset)
259 EndOffset = Entry->Value;
260 }
261 DRI.d.b++;
262 }
263 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000264 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000265 BeginOffset = Entry->Value;
266 SectionIndex = Entry->SectionIndex;
267 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000268 uint32_t flags = SymbolRef::SF_None;
269 getSymbolFlags(DRI, flags);
270 if (flags & SymbolRef::SF_Common)
271 Result = Entry->Value;
272 else
273 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000274 return object_error::success;
275 }
276 // Unfortunately symbols are unsorted so we need to touch all
277 // symbols from load command
278 DRI.d.b = 0;
279 uint32_t Command = DRI.d.a;
280 while (Command == DRI.d.a) {
281 moveToNextSymbol(DRI);
282 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola00555c12013-04-06 01:59:05 +0000283 Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000284 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
285 if (!EndOffset || Entry->Value < EndOffset)
286 EndOffset = Entry->Value;
287 }
288 DRI.d.b++;
289 }
290 }
291 if (!EndOffset) {
292 uint64_t Size;
293 getSectionSize(Sections[SectionIndex-1], Size);
294 getSectionAddress(Sections[SectionIndex-1], EndOffset);
295 EndOffset += Size;
296 }
297 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000298 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000299}
300
Michael J. Spencer25b15772011-06-25 17:55:23 +0000301error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
302 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000303 uint8_t Type, Flags;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000304 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000305 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000306 Type = Entry->Type;
307 Flags = Entry->Flags;
308 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000309 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000310 Type = Entry->Type;
311 Flags = Entry->Flags;
312 }
Eric Christopher6256b032011-04-22 03:19:48 +0000313
314 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000315 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000316 case macho::STT_Undefined:
317 Char = 'u';
318 break;
319 case macho::STT_Absolute:
320 case macho::STT_Section:
321 Char = 's';
322 break;
323 default:
324 Char = '?';
325 break;
326 }
327
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000328 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000329 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000330 Result = Char;
331 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000332}
333
David Meyerc46255a2012-02-28 23:47:53 +0000334error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
335 uint32_t &Result) const {
336 uint16_t MachOFlags;
337 uint8_t MachOType;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000338 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000339 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000340 MachOFlags = Entry->Flags;
341 MachOType = Entry->Type;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000342 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000343 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000344 MachOFlags = Entry->Flags;
345 MachOType = Entry->Type;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000346 }
347
Preston Gurdc68dda82012-04-12 20:13:57 +0000348 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000349 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000350
351 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
352 Result |= SymbolRef::SF_Undefined;
353
David Meyerc46255a2012-02-28 23:47:53 +0000354 if (MachOFlags & macho::STF_StabsEntryMask)
355 Result |= SymbolRef::SF_FormatSpecific;
356
Preston Gurdc68dda82012-04-12 20:13:57 +0000357 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000358 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000359 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
360 Result |= SymbolRef::SF_Common;
361 }
David Meyerc46255a2012-02-28 23:47:53 +0000362
363 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
364 Result |= SymbolRef::SF_Weak;
365
366 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
367 Result |= SymbolRef::SF_Absolute;
368
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000369 return object_error::success;
370}
371
372error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
373 section_iterator &Res) const {
374 uint8_t index;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000375 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000376 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000377 index = Entry->SectionIndex;
378 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000379 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000380 index = Entry->SectionIndex;
381 }
382
383 if (index == 0)
384 Res = end_sections();
385 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000386 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000387
388 return object_error::success;
389}
390
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000391error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000392 SymbolRef::Type &Res) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000393 uint8_t n_type;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000394 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000395 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000396 n_type = Entry->Type;
397 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000398 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000399 n_type = Entry->Type;
400 }
401 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000402
403 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000404 if (n_type & MachO::NlistMaskStab) {
405 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000406 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000407 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000408
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000409 switch (n_type & MachO::NlistMaskType) {
410 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000411 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000412 break;
413 case MachO::NListTypeSection :
414 Res = SymbolRef::ST_Function;
415 break;
416 }
417 return object_error::success;
418}
419
Tim Northovera41dce32012-10-29 10:47:00 +0000420error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
421 uint64_t &Val) const {
422 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
423}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000424
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000425symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000426 // DRI.d.a = segment number; DRI.d.b = symbol index.
427 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000428 moveToNextSymbol(DRI);
429 return symbol_iterator(SymbolRef(DRI, this));
430}
431
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000432symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000433 DataRefImpl DRI;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000434 DRI.d.a = getHeader().NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000435 return symbol_iterator(SymbolRef(DRI, this));
436}
437
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000438symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
439 // TODO: implement
440 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
441}
442
443symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
444 // TODO: implement
445 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
446}
Eric Christopher6256b032011-04-22 03:19:48 +0000447
David Meyer5c2b4ea2012-03-01 01:36:50 +0000448library_iterator MachOObjectFile::begin_libraries_needed() const {
449 // TODO: implement
450 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
451}
452
453library_iterator MachOObjectFile::end_libraries_needed() const {
454 // TODO: implement
455 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
456}
457
David Meyer97f77872012-03-01 22:19:54 +0000458StringRef MachOObjectFile::getLoadName() const {
459 // TODO: Implement
460 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
461}
462
Eric Christopher6256b032011-04-22 03:19:48 +0000463/*===-- Sections ----------------------------------------------------------===*/
464
465void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000466 uint32_t LoadCommandCount = getHeader().NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000467 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000468 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
469 if (Command->Type == macho::LCT_Segment) {
Rafael Espindola68d287d2013-04-06 03:50:05 +0000470 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000471 reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000472 if (DRI.d.b < SegmentLoadCmd->NumSections)
473 return;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000474 } else if (Command->Type == macho::LCT_Segment64) {
Rafael Espindola68d287d2013-04-06 03:50:05 +0000475 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000476 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000477 if (DRI.d.b < Segment64LoadCmd->NumSections)
478 return;
479 }
480
481 DRI.d.a++;
482 DRI.d.b = 0;
483 }
484}
485
Michael J. Spencer25b15772011-06-25 17:55:23 +0000486error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
487 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000488 DRI.d.b++;
489 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000490 Result = SectionRef(DRI, this);
491 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000492}
493
Rafael Espindolaf3051272013-04-07 17:41:59 +0000494static bool is64BitLoadCommand(const MachOObjectFile *MachOObj,
495 DataRefImpl DRI) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000496 const MachOFormat::LoadCommand *Command =
Rafael Espindola77638d92013-04-07 18:08:12 +0000497 MachOObj->getLoadCommandInfo(DRI.d.a);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000498 if (Command->Type == macho::LCT_Segment64)
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000499 return true;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000500 assert(Command->Type == macho::LCT_Segment && "Unexpected Type.");
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000501 return false;
502}
503
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000504const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000505 assert(!is64BitLoadCommand(this, DRI));
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000506 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
507 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
508 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000509 DRI.d.b * sizeof(MachOFormat::Section);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000510 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
Eric Christopher6256b032011-04-22 03:19:48 +0000511}
512
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000513std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
514 SectionList::const_iterator loc =
515 std::find(Sections.begin(), Sections.end(), Sec);
516 assert(loc != Sections.end() && "Sec is not a valid section!");
517 return std::distance(Sections.begin(), loc);
518}
519
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000520const MachOFormat::Section64 *
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000521MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000522 assert(is64BitLoadCommand(this, DRI));
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000523 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
524 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
525 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000526 DRI.d.b * sizeof(MachOFormat::Section64);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000527 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000528}
529
Rafael Espindolacef81b32012-12-21 03:47:03 +0000530static StringRef parseSegmentOrSectionName(const char *P) {
531 if (P[15] == 0)
532 // Null terminated.
533 return P;
534 // Not null terminated, so this is a 16 char string.
535 return StringRef(P, 16);
536}
537
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000538ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000539 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000540 const MachOFormat::Section64 *sec = getSection64(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000541 return ArrayRef<char>(sec->Name);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000542 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000543 const MachOFormat::Section *sec = getSection(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000544 return ArrayRef<char>(sec->Name);
Rafael Espindolaf9a6bd82012-12-19 14:15:04 +0000545 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000546}
547
548error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
549 StringRef &Result) const {
550 ArrayRef<char> Raw = getSectionRawName(DRI);
551 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000552 return object_error::success;
553}
554
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000555ArrayRef<char>
556MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000557 if (is64BitLoadCommand(this, Sec)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000558 const MachOFormat::Section64 *sec = getSection64(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000559 return ArrayRef<char>(sec->SegmentName, 16);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000560 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000561 const MachOFormat::Section *sec = getSection(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000562 return ArrayRef<char>(sec->SegmentName);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000563 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000564}
565
566StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
567 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
568 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000569}
570
Michael J. Spencer25b15772011-06-25 17:55:23 +0000571error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
572 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000573 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000574 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000575 Result = Sect->Address;
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->Address;
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::getSectionSize(DataRefImpl DRI,
584 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000585 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000586 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000587 Result = Sect->Size;
588 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000589 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000590 Result = Sect->Size;
591 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000592 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000593}
594
Michael J. Spencer25b15772011-06-25 17:55:23 +0000595error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
596 StringRef &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000597 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000598 const MachOFormat::Section64 *Sect = getSection64(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000599 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000600 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000601 const MachOFormat::Section *Sect = getSection(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000602 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000603 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000604 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000605}
606
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000607error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
608 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000609 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000610 const MachOFormat::Section64 *Sect = getSection64(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000611 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000612 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000613 const MachOFormat::Section *Sect = getSection(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000614 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000615 }
616 return object_error::success;
617}
618
Michael J. Spencer25b15772011-06-25 17:55:23 +0000619error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
620 bool &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000621 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000622 const MachOFormat::Section64 *Sect = getSection64(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000623 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000624 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000625 const MachOFormat::Section *Sect = getSection(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000626 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000627 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000628 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000629}
630
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000631error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
632 bool &Result) const {
633 // FIXME: Unimplemented.
634 Result = false;
635 return object_error::success;
636}
637
638error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
639 bool &Result) const {
640 // FIXME: Unimplemented.
641 Result = false;
642 return object_error::success;
643}
644
Preston Gurdc68dda82012-04-12 20:13:57 +0000645error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
646 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000647 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000648 Result = true;
649 return object_error::success;
650}
651
652error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000653 bool &Result) const {
654 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000655 Result = false;
656 return object_error::success;
657}
658
659error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
660 bool &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000661 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000662 const MachOFormat::Section64 *Sect = getSection64(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000663 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
664 Result = (SectionType == MachO::SectionTypeZeroFill ||
665 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000666 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000667 const MachOFormat::Section *Sect = getSection(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000668 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
669 Result = (SectionType == MachO::SectionTypeZeroFill ||
670 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000671 }
672
673 return object_error::success;
674}
675
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000676error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
677 bool &Result) const {
678 // Consider using the code from isSectionText to look for __const sections.
679 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
680 // to use section attributes to distinguish code from data.
681
682 // FIXME: Unimplemented.
683 Result = false;
684 return object_error::success;
685}
686
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000687error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
688 DataRefImpl Symb,
689 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000690 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000691 getSymbolType(Symb, ST);
David Meyer2c677272012-02-29 02:11:55 +0000692 if (ST == SymbolRef::ST_Unknown) {
Owen Andersoncd749882011-10-12 22:21:32 +0000693 Result = false;
694 return object_error::success;
695 }
696
697 uint64_t SectBegin, SectEnd;
698 getSectionAddress(Sec, SectBegin);
699 getSectionSize(Sec, SectEnd);
700 SectEnd += SectBegin;
701
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000702 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000703 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000704 uint64_t SymAddr= Entry->Value;
705 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000706 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000707 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000708 uint64_t SymAddr= Entry->Value;
709 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000710 }
Owen Andersoncd749882011-10-12 22:21:32 +0000711
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000712 return object_error::success;
713}
714
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000715relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
716 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000717 ret.d.b = getSectionIndex(Sec);
718 return relocation_iterator(RelocationRef(ret, this));
719}
720relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
721 uint32_t last_reloc;
Rafael Espindolaf3051272013-04-07 17:41:59 +0000722 if (is64BitLoadCommand(this, Sec)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000723 const MachOFormat::Section64 *Sect = getSection64(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000724 last_reloc = Sect->NumRelocationTableEntries;
725 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000726 const MachOFormat::Section *Sect = getSection(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000727 last_reloc = Sect->NumRelocationTableEntries;
728 }
729 DataRefImpl ret;
730 ret.d.a = last_reloc;
731 ret.d.b = getSectionIndex(Sec);
732 return relocation_iterator(RelocationRef(ret, this));
733}
734
735section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000736 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000737 moveToNextSection(DRI);
738 return section_iterator(SectionRef(DRI, this));
739}
740
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000741section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000742 DataRefImpl DRI;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000743 DRI.d.a = getHeader().NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000744 return section_iterator(SectionRef(DRI, this));
745}
746
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000747/*===-- Relocations -------------------------------------------------------===*/
748
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000749const MachOFormat::RelocationEntry *
750MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000751 uint32_t relOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000752 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000753 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000754 relOffset = Sect->RelocationTableOffset;
755 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000756 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000757 relOffset = Sect->RelocationTableOffset;
758 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000759 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000760 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000761 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000762}
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000763
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000764error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
765 RelocationRef &Res) const {
766 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000767 Res = RelocationRef(Rel, this);
768 return object_error::success;
769}
770error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
771 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000772 const uint8_t* sectAddress = 0;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000773 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000774 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000775 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000776 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000777 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000778 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000779 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000780 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000781
782 unsigned Arch = getArch();
783 bool isScattered = (Arch != Triple::x86_64) &&
784 (RE->Word0 & macho::RF_Scattered);
785 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000786 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000787 RelAddr = RE->Word0 & 0xFFFFFF;
788 else
789 RelAddr = RE->Word0;
790
791 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000792 return object_error::success;
793}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000794error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
795 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000796 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000797
798 unsigned Arch = getArch();
799 bool isScattered = (Arch != Triple::x86_64) &&
800 (RE->Word0 & macho::RF_Scattered);
801 if (isScattered)
802 Res = RE->Word0 & 0xFFFFFF;
803 else
804 Res = RE->Word0;
805 return object_error::success;
806}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000807error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
808 SymbolRef &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000809 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000810 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
811 bool isExtern = (RE->Word1 >> 27) & 1;
812
813 DataRefImpl Sym;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000814 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000815 if (isExtern) {
816 for (unsigned i = 0; i < SymbolIdx; i++) {
817 Sym.d.b++;
818 moveToNextSymbol(Sym);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000819 assert(Sym.d.a < getHeader().NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000820 "Relocation symbol index out of range!");
821 }
822 }
823 Res = SymbolRef(Sym, this);
824 return object_error::success;
825}
826error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000827 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000828 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Andersonf8261e72011-10-26 17:10:22 +0000829 Res = RE->Word0;
830 Res <<= 32;
831 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000832 return object_error::success;
833}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000834error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
835 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000836 // TODO: Support scattered relocations.
837 StringRef res;
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000838 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +0000839
840 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000841 bool isScattered = (Arch != Triple::x86_64) &&
842 (RE->Word0 & macho::RF_Scattered);
843
844 unsigned r_type;
845 if (isScattered)
846 r_type = (RE->Word0 >> 24) & 0xF;
847 else
848 r_type = (RE->Word1 >> 28) & 0xF;
849
Owen Anderson0135fe12011-10-24 21:44:00 +0000850 switch (Arch) {
851 case Triple::x86: {
Craig Toppere3298102012-05-24 06:35:32 +0000852 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000853 "GENERIC_RELOC_VANILLA",
854 "GENERIC_RELOC_PAIR",
855 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000856 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000857 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000858 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000859
Owen Andersoneb6bd332011-10-27 20:46:09 +0000860 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000861 res = "Unknown";
862 else
863 res = Table[r_type];
864 break;
865 }
866 case Triple::x86_64: {
Craig Toppere3298102012-05-24 06:35:32 +0000867 static const char *const Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000868 "X86_64_RELOC_UNSIGNED",
869 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000870 "X86_64_RELOC_BRANCH",
871 "X86_64_RELOC_GOT_LOAD",
872 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000873 "X86_64_RELOC_SUBTRACTOR",
874 "X86_64_RELOC_SIGNED_1",
875 "X86_64_RELOC_SIGNED_2",
876 "X86_64_RELOC_SIGNED_4",
877 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000878
Owen Andersond8fa76d2011-10-24 23:20:07 +0000879 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000880 res = "Unknown";
881 else
882 res = Table[r_type];
883 break;
884 }
885 case Triple::arm: {
Craig Toppere3298102012-05-24 06:35:32 +0000886 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000887 "ARM_RELOC_VANILLA",
888 "ARM_RELOC_PAIR",
889 "ARM_RELOC_SECTDIFF",
890 "ARM_RELOC_LOCAL_SECTDIFF",
891 "ARM_RELOC_PB_LA_PTR",
892 "ARM_RELOC_BR24",
893 "ARM_THUMB_RELOC_BR22",
894 "ARM_THUMB_32BIT_BRANCH",
895 "ARM_RELOC_HALF",
896 "ARM_RELOC_HALF_SECTDIFF" };
897
898 if (r_type > 9)
899 res = "Unknown";
900 else
901 res = Table[r_type];
902 break;
903 }
904 case Triple::ppc: {
Craig Toppere3298102012-05-24 06:35:32 +0000905 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000906 "PPC_RELOC_VANILLA",
907 "PPC_RELOC_PAIR",
908 "PPC_RELOC_BR14",
909 "PPC_RELOC_BR24",
910 "PPC_RELOC_HI16",
911 "PPC_RELOC_LO16",
912 "PPC_RELOC_HA16",
913 "PPC_RELOC_LO14",
914 "PPC_RELOC_SECTDIFF",
915 "PPC_RELOC_PB_LA_PTR",
916 "PPC_RELOC_HI16_SECTDIFF",
917 "PPC_RELOC_LO16_SECTDIFF",
918 "PPC_RELOC_HA16_SECTDIFF",
919 "PPC_RELOC_JBSR",
920 "PPC_RELOC_LO14_SECTDIFF",
921 "PPC_RELOC_LOCAL_SECTDIFF" };
922
923 res = Table[r_type];
924 break;
925 }
926 case Triple::UnknownArch:
927 res = "Unknown";
928 break;
929 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000930 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000931 return object_error::success;
932}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000933error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
934 int64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000935 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000936 bool isExtern = (RE->Word1 >> 27) & 1;
937 Res = 0;
938 if (!isExtern) {
939 const uint8_t* sectAddress = base();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000940 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000941 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000942 sectAddress += Sect->Offset;
943 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000944 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000945 sectAddress += Sect->Offset;
946 }
947 Res = reinterpret_cast<uintptr_t>(sectAddress);
948 }
949 return object_error::success;
950}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000951
952// Helper to advance a section or symbol iterator multiple increments at a time.
953template<class T>
954error_code advance(T &it, size_t Val) {
955 error_code ec;
956 while (Val--) {
957 it.increment(ec);
958 }
959 return ec;
960}
961
962template<class T>
963void advanceTo(T &it, size_t Val) {
964 if (error_code ec = advance(it, Val))
965 report_fatal_error(ec.message());
966}
967
Owen Anderson1832f4d2011-10-26 20:42:54 +0000968void MachOObjectFile::printRelocationTargetName(
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000969 const MachOFormat::RelocationEntry *RE,
Owen Anderson1832f4d2011-10-26 20:42:54 +0000970 raw_string_ostream &fmt) const {
971 unsigned Arch = getArch();
972 bool isScattered = (Arch != Triple::x86_64) &&
973 (RE->Word0 & macho::RF_Scattered);
974
975 // Target of a scattered relocation is an address. In the interest of
976 // generating pretty output, scan through the symbol table looking for a
977 // symbol that aligns with that address. If we find one, print it.
978 // Otherwise, we just print the hex address of the target.
979 if (isScattered) {
980 uint32_t Val = RE->Word1;
981
982 error_code ec;
983 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
984 SI.increment(ec)) {
985 if (ec) report_fatal_error(ec.message());
986
987 uint64_t Addr;
988 StringRef Name;
989
990 if ((ec = SI->getAddress(Addr)))
991 report_fatal_error(ec.message());
992 if (Addr != Val) continue;
993 if ((ec = SI->getName(Name)))
994 report_fatal_error(ec.message());
995 fmt << Name;
996 return;
997 }
998
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000999 // If we couldn't find a symbol that this relocation refers to, try
1000 // to find a section beginning instead.
1001 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
1002 SI.increment(ec)) {
1003 if (ec) report_fatal_error(ec.message());
1004
1005 uint64_t Addr;
1006 StringRef Name;
1007
1008 if ((ec = SI->getAddress(Addr)))
1009 report_fatal_error(ec.message());
1010 if (Addr != Val) continue;
1011 if ((ec = SI->getName(Name)))
1012 report_fatal_error(ec.message());
1013 fmt << Name;
1014 return;
1015 }
1016
Owen Anderson1832f4d2011-10-26 20:42:54 +00001017 fmt << format("0x%x", Val);
1018 return;
1019 }
1020
1021 StringRef S;
1022 bool isExtern = (RE->Word1 >> 27) & 1;
1023 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001024
1025 if (isExtern) {
1026 symbol_iterator SI = begin_symbols();
1027 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001028 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001029 } else {
1030 section_iterator SI = begin_sections();
1031 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001032 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001033 }
1034
Owen Anderson1832f4d2011-10-26 20:42:54 +00001035 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001036}
1037
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001038error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1039 SmallVectorImpl<char> &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001040 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +00001041
Owen Anderson1832f4d2011-10-26 20:42:54 +00001042 unsigned Arch = getArch();
1043 bool isScattered = (Arch != Triple::x86_64) &&
1044 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001045
Owen Anderson013d7562011-10-25 18:48:41 +00001046 std::string fmtbuf;
1047 raw_string_ostream fmt(fmtbuf);
1048
Owen Anderson1832f4d2011-10-26 20:42:54 +00001049 unsigned Type;
1050 if (isScattered)
1051 Type = (RE->Word0 >> 24) & 0xF;
1052 else
1053 Type = (RE->Word1 >> 28) & 0xF;
1054
Owen Andersoneb6bd332011-10-27 20:46:09 +00001055 bool isPCRel;
1056 if (isScattered)
1057 isPCRel = ((RE->Word0 >> 30) & 1);
1058 else
1059 isPCRel = ((RE->Word1 >> 24) & 1);
1060
Owen Andersond8fa76d2011-10-24 23:20:07 +00001061 // Determine any addends that should be displayed with the relocation.
1062 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +00001063
1064 // X86_64 has entirely custom relocation types.
1065 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +00001066 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +00001067
Owen Andersond8fa76d2011-10-24 23:20:07 +00001068 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001069 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1070 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1071 printRelocationTargetName(RE, fmt);
1072 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +00001073 if (isPCRel) fmt << "PCREL";
1074 break;
1075 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001076 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +00001077 DataRefImpl RelNext = Rel;
1078 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001079 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001080
1081 // X86_64_SUBTRACTOR must be followed by a relocation of type
1082 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001083 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +00001084 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001085 if (RType != 0)
1086 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1087 "X86_64_RELOC_SUBTRACTOR.");
1088
Owen Andersonef22f782011-10-26 17:28:49 +00001089 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1090 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001091 printRelocationTargetName(RENext, fmt);
1092 fmt << "-";
1093 printRelocationTargetName(RE, fmt);
Jim Grosbach133f6b82013-01-31 19:46:57 +00001094 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001095 }
Owen Andersoneb6bd332011-10-27 20:46:09 +00001096 case macho::RIT_X86_64_TLV:
1097 printRelocationTargetName(RE, fmt);
1098 fmt << "@TLV";
1099 if (isPCRel) fmt << "P";
1100 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001101 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1102 printRelocationTargetName(RE, fmt);
1103 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001104 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001105 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1106 printRelocationTargetName(RE, fmt);
1107 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001108 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001109 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1110 printRelocationTargetName(RE, fmt);
1111 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +00001112 break;
1113 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001114 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001115 break;
1116 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001117 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001118 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1119 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001120 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001121 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001122 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001123 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001124 DataRefImpl RelNext = Rel;
1125 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001126 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001127
1128 // X86 sect diff's must be followed by a relocation of type
1129 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001130 bool isNextScattered = (Arch != Triple::x86_64) &&
1131 (RENext->Word0 & macho::RF_Scattered);
1132 unsigned RType;
1133 if (isNextScattered)
1134 RType = (RENext->Word0 >> 24) & 0xF;
1135 else
1136 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001137 if (RType != 1)
1138 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001139 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001140
Owen Anderson1832f4d2011-10-26 20:42:54 +00001141 printRelocationTargetName(RE, fmt);
1142 fmt << "-";
1143 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001144 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001145 }
1146 }
Owen Anderson013d7562011-10-25 18:48:41 +00001147
Owen Anderson1832f4d2011-10-26 20:42:54 +00001148 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001149 // All X86 relocations that need special printing were already
1150 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001151 switch (Type) {
1152 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
Owen Andersoneb6bd332011-10-27 20:46:09 +00001153 DataRefImpl RelNext = Rel;
1154 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001155 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersoneb6bd332011-10-27 20:46:09 +00001156
1157 // X86 sect diff's must be followed by a relocation of type
1158 // GENERIC_RELOC_PAIR.
1159 bool isNextScattered = (Arch != Triple::x86_64) &&
1160 (RENext->Word0 & macho::RF_Scattered);
1161 unsigned RType;
1162 if (isNextScattered)
1163 RType = (RENext->Word0 >> 24) & 0xF;
1164 else
1165 RType = (RENext->Word1 >> 28) & 0xF;
1166 if (RType != 1)
1167 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1168 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1169
1170 printRelocationTargetName(RE, fmt);
1171 fmt << "-";
1172 printRelocationTargetName(RENext, fmt);
1173 break;
1174 }
1175 case macho::RIT_Generic_TLV: {
1176 printRelocationTargetName(RE, fmt);
1177 fmt << "@TLV";
1178 if (isPCRel) fmt << "P";
1179 break;
1180 }
1181 default:
1182 printRelocationTargetName(RE, fmt);
1183 }
Owen Anderson013d7562011-10-25 18:48:41 +00001184 } else { // ARM-specific relocations
1185 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001186 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1187 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001188 // Half relocations steal a bit from the length field to encode
1189 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001190 bool isUpper;
1191 if (isScattered)
1192 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001193 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001194 isUpper = (RE->Word1 >> 25) & 1;
1195
1196 if (isUpper)
1197 fmt << ":upper16:(";
1198 else
1199 fmt << ":lower16:(";
1200 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001201
Owen Anderson013d7562011-10-25 18:48:41 +00001202 DataRefImpl RelNext = Rel;
1203 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001204 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Anderson013d7562011-10-25 18:48:41 +00001205
1206 // ARM half relocs must be followed by a relocation of type
1207 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001208 bool isNextScattered = (Arch != Triple::x86_64) &&
1209 (RENext->Word0 & macho::RF_Scattered);
1210 unsigned RType;
1211 if (isNextScattered)
1212 RType = (RENext->Word0 >> 24) & 0xF;
1213 else
1214 RType = (RENext->Word1 >> 28) & 0xF;
1215
Owen Anderson013d7562011-10-25 18:48:41 +00001216 if (RType != 1)
1217 report_fatal_error("Expected ARM_RELOC_PAIR after "
1218 "GENERIC_RELOC_HALF");
1219
Owen Anderson1832f4d2011-10-26 20:42:54 +00001220 // NOTE: The half of the target virtual address is stashed in the
1221 // address field of the secondary relocation, but we can't reverse
1222 // engineer the constant offset from it without decoding the movw/movt
1223 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001224
1225 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1226 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001227 if (Type == macho::RIT_ARM_HalfDifference) {
1228 fmt << "-";
1229 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001230 }
1231
Owen Anderson013d7562011-10-25 18:48:41 +00001232 fmt << ")";
1233 break;
1234 }
1235 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001236 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001237 }
1238 }
1239 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001240 } else
1241 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001242
Owen Anderson0135fe12011-10-24 21:44:00 +00001243 fmt.flush();
1244 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001245 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001246}
1247
Owen Anderson0685e942011-10-25 20:35:53 +00001248error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1249 bool &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001250 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0685e942011-10-25 20:35:53 +00001251
Owen Anderson0685e942011-10-25 20:35:53 +00001252 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001253 bool isScattered = (Arch != Triple::x86_64) &&
1254 (RE->Word0 & macho::RF_Scattered);
1255 unsigned Type;
1256 if (isScattered)
1257 Type = (RE->Word0 >> 24) & 0xF;
1258 else
1259 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001260
1261 Result = false;
1262
1263 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1264 // is always hidden.
1265 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001266 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001267 } else if (Arch == Triple::x86_64) {
1268 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1269 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001270 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001271 DataRefImpl RelPrev = Rel;
1272 RelPrev.d.a--;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001273 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
Owen Anderson0685e942011-10-25 20:35:53 +00001274
1275 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1276
Owen Anderson1832f4d2011-10-26 20:42:54 +00001277 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001278 }
1279 }
1280
1281 return object_error::success;
1282}
1283
David Meyer5c2b4ea2012-03-01 01:36:50 +00001284error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1285 LibraryRef &Res) const {
1286 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1287}
1288
1289error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1290 StringRef &Res) const {
1291 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1292}
1293
1294
Eric Christopher6256b032011-04-22 03:19:48 +00001295/*===-- Miscellaneous -----------------------------------------------------===*/
1296
1297uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001298 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001299}
1300
1301StringRef MachOObjectFile::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001302 if (!is64Bit()) {
1303 switch (getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001304 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001305 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001306 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001307 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001308 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001309 return "Mach-O 32-bit ppc";
1310 default:
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001311 assert((getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001312 "64-bit object file when we're not 64-bit?");
1313 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001314 }
1315 }
1316
Eric Christopherb3e6b042013-02-28 20:26:17 +00001317 // Make sure the cpu type has the correct mask.
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001318 assert((getHeader().CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +00001319 == llvm::MachO::CPUArchABI64 &&
1320 "32-bit object file when we're 64-bit?");
1321
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001322 switch (getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001323 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001324 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001325 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001326 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001327 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001328 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001329 }
1330}
1331
1332unsigned MachOObjectFile::getArch() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001333 switch (getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001334 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001335 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001336 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001337 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001338 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001339 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001340 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001341 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001342 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001343 return Triple::ppc64;
1344 default:
1345 return Triple::UnknownArch;
1346 }
1347}
1348
Owen Andersonf7c93a32011-10-11 17:32:27 +00001349} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001350} // end namespace llvm