blob: 31e8be0f94b147f66cc88c9fd7a68bcd6889a02c [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 Espindola433611b2013-04-07 19:26:57 +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
Rafael Espindola433611b2013-04-07 19:26:57 +000083const MachOFormat::Header *MachOObjectFile::getHeader() const {
84 StringRef Data = getData(0, sizeof(MachOFormat::Header));
85 return reinterpret_cast<const MachOFormat::Header*>(Data.data());
Rafael Espindola3eff3182013-04-07 16:07:35 +000086}
87
Rafael Espindola0f08eb12013-04-07 19:05:30 +000088unsigned MachOObjectFile::getHeaderSize() const {
89 return MachOObj->getHeaderSize();
90}
91
92StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const {
93 return MachOObj->getData(Offset, Size);
94}
95
Eric Christopher6256b032011-04-22 03:19:48 +000096ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Michael J. Spencer001c9202011-06-25 17:54:50 +000097 error_code ec;
Rafael Espindola6f1f3392013-04-07 16:58:48 +000098 ObjectFile *Ret = new MachOObjectFile(Buffer, ec);
99 if (ec)
Eric Christopher6256b032011-04-22 03:19:48 +0000100 return NULL;
Rafael Espindola6f1f3392013-04-07 16:58:48 +0000101 return Ret;
Eric Christopher6256b032011-04-22 03:19:48 +0000102}
103
104/*===-- Symbols -----------------------------------------------------------===*/
105
106void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000107 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000108 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000109 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
110 if (Command->Type == macho::LCT_Symtab) {
Rafael Espindola82a21072013-04-06 03:31:08 +0000111 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000112 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000113 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
114 return;
115 }
116
117 DRI.d.a++;
118 DRI.d.b = 0;
119 }
120}
121
Rafael Espindola00555c12013-04-06 01:59:05 +0000122const MachOFormat::SymbolTableEntry *
123MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000124 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000125 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000126 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000127
Rafael Espindola82a21072013-04-06 03:31:08 +0000128 return getSymbolTableEntry(DRI, SymtabLoadCmd);
129}
Eric Christopher6256b032011-04-22 03:19:48 +0000130
Rafael Espindola82a21072013-04-06 03:31:08 +0000131const MachOFormat::SymbolTableEntry *
132MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
133 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola00555c12013-04-06 01:59:05 +0000134 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
135 unsigned Index = DRI.d.b;
136 uint64_t Offset = (SymbolTableOffset +
137 Index * sizeof(macho::SymbolTableEntry));
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000138 StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry));
Rafael Espindola00555c12013-04-06 01:59:05 +0000139 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000140}
141
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000142const MachOFormat::Symbol64TableEntry*
143MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000144 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000145 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000146 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000147
Rafael Espindola82a21072013-04-06 03:31:08 +0000148 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
149}
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000150
Rafael Espindola82a21072013-04-06 03:31:08 +0000151const MachOFormat::Symbol64TableEntry*
152MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
153 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000154 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
155 unsigned Index = DRI.d.b;
156 uint64_t Offset = (SymbolTableOffset +
157 Index * sizeof(macho::Symbol64TableEntry));
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000158 StringRef Data = getData(Offset, sizeof(MachOFormat::Symbol64TableEntry));
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000159 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000160}
161
Michael J. Spencer25b15772011-06-25 17:55:23 +0000162error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
163 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000164 DRI.d.b++;
165 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000166 Result = SymbolRef(DRI, this);
167 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000168}
169
Michael J. Spencer25b15772011-06-25 17:55:23 +0000170error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
171 StringRef &Result) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000172 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000173 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000174 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Rafael Espindola82a21072013-04-06 03:31:08 +0000175
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000176 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
177 SymtabLoadCmd->StringTableSize);
Rafael Espindola82a21072013-04-06 03:31:08 +0000178
179 uint32_t StringIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000180 if (is64Bit()) {
Rafael Espindola82a21072013-04-06 03:31:08 +0000181 const MachOFormat::Symbol64TableEntry *Entry =
182 getSymbol64TableEntry(DRI, SymtabLoadCmd);
183 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000184 } else {
Rafael Espindola82a21072013-04-06 03:31:08 +0000185 const MachOFormat::SymbolTableEntry *Entry =
186 getSymbolTableEntry(DRI, SymtabLoadCmd);
187 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000188 }
Rafael Espindola82a21072013-04-06 03:31:08 +0000189
190 const char *Start = &StringTable.data()[StringIndex];
191 Result = StringRef(Start);
192
Michael J. Spencer25b15772011-06-25 17:55:23 +0000193 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000194}
195
Danil Malyshevb0436a72011-11-29 17:40:10 +0000196error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
197 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000198 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000199 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000200 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000201 if (Entry->SectionIndex) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000202 const MachOFormat::Section64 *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000203 getSection64(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000204 Result += Section->Offset - Section->Address;
205 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000206 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000207 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000208 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000209 if (Entry->SectionIndex) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000210 const MachOFormat::Section *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000211 getSection(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000212 Result += Section->Offset - Section->Address;
213 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000214 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000215
Michael J. Spencer25b15772011-06-25 17:55:23 +0000216 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000217}
218
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000219error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
220 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000221 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000222 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000223 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000224 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000225 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000226 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000227 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000228 return object_error::success;
229}
230
Michael J. Spencer25b15772011-06-25 17:55:23 +0000231error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
232 uint64_t &Result) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000233 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000234 uint64_t BeginOffset;
235 uint64_t EndOffset = 0;
236 uint8_t SectionIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000237 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000238 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000239 BeginOffset = Entry->Value;
240 SectionIndex = Entry->SectionIndex;
241 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000242 uint32_t flags = SymbolRef::SF_None;
243 getSymbolFlags(DRI, flags);
244 if (flags & SymbolRef::SF_Common)
245 Result = Entry->Value;
246 else
247 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000248 return object_error::success;
249 }
250 // Unfortunately symbols are unsorted so we need to touch all
251 // symbols from load command
252 DRI.d.b = 0;
253 uint32_t Command = DRI.d.a;
254 while (Command == DRI.d.a) {
255 moveToNextSymbol(DRI);
256 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000257 Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000258 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
259 if (!EndOffset || Entry->Value < EndOffset)
260 EndOffset = Entry->Value;
261 }
262 DRI.d.b++;
263 }
264 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000265 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000266 BeginOffset = Entry->Value;
267 SectionIndex = Entry->SectionIndex;
268 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000269 uint32_t flags = SymbolRef::SF_None;
270 getSymbolFlags(DRI, flags);
271 if (flags & SymbolRef::SF_Common)
272 Result = Entry->Value;
273 else
274 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000275 return object_error::success;
276 }
277 // Unfortunately symbols are unsorted so we need to touch all
278 // symbols from load command
279 DRI.d.b = 0;
280 uint32_t Command = DRI.d.a;
281 while (Command == DRI.d.a) {
282 moveToNextSymbol(DRI);
283 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola00555c12013-04-06 01:59:05 +0000284 Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000285 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
286 if (!EndOffset || Entry->Value < EndOffset)
287 EndOffset = Entry->Value;
288 }
289 DRI.d.b++;
290 }
291 }
292 if (!EndOffset) {
293 uint64_t Size;
294 getSectionSize(Sections[SectionIndex-1], Size);
295 getSectionAddress(Sections[SectionIndex-1], EndOffset);
296 EndOffset += Size;
297 }
298 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000299 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000300}
301
Michael J. Spencer25b15772011-06-25 17:55:23 +0000302error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
303 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000304 uint8_t Type, Flags;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000305 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000306 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000307 Type = Entry->Type;
308 Flags = Entry->Flags;
309 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000310 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000311 Type = Entry->Type;
312 Flags = Entry->Flags;
313 }
Eric Christopher6256b032011-04-22 03:19:48 +0000314
315 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000316 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000317 case macho::STT_Undefined:
318 Char = 'u';
319 break;
320 case macho::STT_Absolute:
321 case macho::STT_Section:
322 Char = 's';
323 break;
324 default:
325 Char = '?';
326 break;
327 }
328
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000329 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000330 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000331 Result = Char;
332 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000333}
334
David Meyerc46255a2012-02-28 23:47:53 +0000335error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
336 uint32_t &Result) const {
337 uint16_t MachOFlags;
338 uint8_t MachOType;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000339 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000340 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000341 MachOFlags = Entry->Flags;
342 MachOType = Entry->Type;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000343 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000344 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000345 MachOFlags = Entry->Flags;
346 MachOType = Entry->Type;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000347 }
348
Preston Gurdc68dda82012-04-12 20:13:57 +0000349 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000350 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000351
352 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
353 Result |= SymbolRef::SF_Undefined;
354
David Meyerc46255a2012-02-28 23:47:53 +0000355 if (MachOFlags & macho::STF_StabsEntryMask)
356 Result |= SymbolRef::SF_FormatSpecific;
357
Preston Gurdc68dda82012-04-12 20:13:57 +0000358 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000359 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000360 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
361 Result |= SymbolRef::SF_Common;
362 }
David Meyerc46255a2012-02-28 23:47:53 +0000363
364 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
365 Result |= SymbolRef::SF_Weak;
366
367 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
368 Result |= SymbolRef::SF_Absolute;
369
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000370 return object_error::success;
371}
372
373error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
374 section_iterator &Res) const {
375 uint8_t index;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000376 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000377 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000378 index = Entry->SectionIndex;
379 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000380 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000381 index = Entry->SectionIndex;
382 }
383
384 if (index == 0)
385 Res = end_sections();
386 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000387 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000388
389 return object_error::success;
390}
391
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000392error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000393 SymbolRef::Type &Res) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000394 uint8_t n_type;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000395 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000396 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000397 n_type = Entry->Type;
398 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000399 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000400 n_type = Entry->Type;
401 }
402 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000403
404 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000405 if (n_type & MachO::NlistMaskStab) {
406 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000407 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000408 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000409
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000410 switch (n_type & MachO::NlistMaskType) {
411 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000412 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000413 break;
414 case MachO::NListTypeSection :
415 Res = SymbolRef::ST_Function;
416 break;
417 }
418 return object_error::success;
419}
420
Tim Northovera41dce32012-10-29 10:47:00 +0000421error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
422 uint64_t &Val) const {
423 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
424}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000425
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000426symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000427 // DRI.d.a = segment number; DRI.d.b = symbol index.
428 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000429 moveToNextSymbol(DRI);
430 return symbol_iterator(SymbolRef(DRI, this));
431}
432
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000433symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000434 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000435 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000436 return symbol_iterator(SymbolRef(DRI, this));
437}
438
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000439symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
440 // TODO: implement
441 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
442}
443
444symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
445 // TODO: implement
446 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
447}
Eric Christopher6256b032011-04-22 03:19:48 +0000448
David Meyer5c2b4ea2012-03-01 01:36:50 +0000449library_iterator MachOObjectFile::begin_libraries_needed() const {
450 // TODO: implement
451 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
452}
453
454library_iterator MachOObjectFile::end_libraries_needed() const {
455 // TODO: implement
456 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
457}
458
David Meyer97f77872012-03-01 22:19:54 +0000459StringRef MachOObjectFile::getLoadName() const {
460 // TODO: Implement
461 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
462}
463
Eric Christopher6256b032011-04-22 03:19:48 +0000464/*===-- Sections ----------------------------------------------------------===*/
465
466void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000467 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000468 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000469 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
470 if (Command->Type == macho::LCT_Segment) {
Rafael Espindola68d287d2013-04-06 03:50:05 +0000471 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000472 reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000473 if (DRI.d.b < SegmentLoadCmd->NumSections)
474 return;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000475 } else if (Command->Type == macho::LCT_Segment64) {
Rafael Espindola68d287d2013-04-06 03:50:05 +0000476 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000477 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000478 if (DRI.d.b < Segment64LoadCmd->NumSections)
479 return;
480 }
481
482 DRI.d.a++;
483 DRI.d.b = 0;
484 }
485}
486
Michael J. Spencer25b15772011-06-25 17:55:23 +0000487error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
488 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000489 DRI.d.b++;
490 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000491 Result = SectionRef(DRI, this);
492 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000493}
494
Rafael Espindolaf3051272013-04-07 17:41:59 +0000495static bool is64BitLoadCommand(const MachOObjectFile *MachOObj,
496 DataRefImpl DRI) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000497 const MachOFormat::LoadCommand *Command =
Rafael Espindola77638d92013-04-07 18:08:12 +0000498 MachOObj->getLoadCommandInfo(DRI.d.a);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000499 if (Command->Type == macho::LCT_Segment64)
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000500 return true;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000501 assert(Command->Type == macho::LCT_Segment && "Unexpected Type.");
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000502 return false;
503}
504
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000505const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000506 assert(!is64BitLoadCommand(this, DRI));
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000507 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
508 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
509 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000510 DRI.d.b * sizeof(MachOFormat::Section);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000511 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
Eric Christopher6256b032011-04-22 03:19:48 +0000512}
513
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000514std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
515 SectionList::const_iterator loc =
516 std::find(Sections.begin(), Sections.end(), Sec);
517 assert(loc != Sections.end() && "Sec is not a valid section!");
518 return std::distance(Sections.begin(), loc);
519}
520
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000521const MachOFormat::Section64 *
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000522MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000523 assert(is64BitLoadCommand(this, DRI));
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000524 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
525 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
526 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000527 DRI.d.b * sizeof(MachOFormat::Section64);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000528 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000529}
530
Rafael Espindolacef81b32012-12-21 03:47:03 +0000531static StringRef parseSegmentOrSectionName(const char *P) {
532 if (P[15] == 0)
533 // Null terminated.
534 return P;
535 // Not null terminated, so this is a 16 char string.
536 return StringRef(P, 16);
537}
538
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000539ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000540 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000541 const MachOFormat::Section64 *sec = getSection64(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000542 return ArrayRef<char>(sec->Name);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000543 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000544 const MachOFormat::Section *sec = getSection(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000545 return ArrayRef<char>(sec->Name);
Rafael Espindolaf9a6bd82012-12-19 14:15:04 +0000546 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000547}
548
549error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
550 StringRef &Result) const {
551 ArrayRef<char> Raw = getSectionRawName(DRI);
552 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000553 return object_error::success;
554}
555
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000556ArrayRef<char>
557MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000558 if (is64BitLoadCommand(this, Sec)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000559 const MachOFormat::Section64 *sec = getSection64(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000560 return ArrayRef<char>(sec->SegmentName, 16);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000561 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000562 const MachOFormat::Section *sec = getSection(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000563 return ArrayRef<char>(sec->SegmentName);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000564 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000565}
566
567StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
568 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
569 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000570}
571
Michael J. Spencer25b15772011-06-25 17:55:23 +0000572error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
573 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000574 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000575 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000576 Result = Sect->Address;
577 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000578 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000579 Result = Sect->Address;
580 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000581 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000582}
583
Michael J. Spencer25b15772011-06-25 17:55:23 +0000584error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
585 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000586 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000587 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000588 Result = Sect->Size;
589 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000590 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000591 Result = Sect->Size;
592 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000593 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000594}
595
Michael J. Spencer25b15772011-06-25 17:55:23 +0000596error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
597 StringRef &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000598 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000599 const MachOFormat::Section64 *Sect = getSection64(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000600 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000601 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000602 const MachOFormat::Section *Sect = getSection(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000603 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000604 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000605 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000606}
607
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000608error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
609 uint64_t &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000610 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000611 const MachOFormat::Section64 *Sect = getSection64(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 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000614 const MachOFormat::Section *Sect = getSection(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000615 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000616 }
617 return object_error::success;
618}
619
Michael J. Spencer25b15772011-06-25 17:55:23 +0000620error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
621 bool &Result) const {
Rafael Espindolaf3051272013-04-07 17:41:59 +0000622 if (is64BitLoadCommand(this, DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000623 const MachOFormat::Section64 *Sect = getSection64(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000624 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000625 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000626 const MachOFormat::Section *Sect = getSection(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000627 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000628 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000629 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000630}
631
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000632error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
633 bool &Result) const {
634 // FIXME: Unimplemented.
635 Result = false;
636 return object_error::success;
637}
638
639error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
640 bool &Result) const {
641 // FIXME: Unimplemented.
642 Result = false;
643 return object_error::success;
644}
645
Preston Gurdc68dda82012-04-12 20:13:57 +0000646error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
647 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000648 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000649 Result = true;
650 return object_error::success;
651}
652
653error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000654 bool &Result) const {
655 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000656 Result = false;
657 return object_error::success;
658}
659
660error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
661 bool &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000662 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000663 const MachOFormat::Section64 *Sect = getSection64(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000664 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
665 Result = (SectionType == MachO::SectionTypeZeroFill ||
666 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000667 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000668 const MachOFormat::Section *Sect = getSection(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000669 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
670 Result = (SectionType == MachO::SectionTypeZeroFill ||
671 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000672 }
673
674 return object_error::success;
675}
676
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000677error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
678 bool &Result) const {
679 // Consider using the code from isSectionText to look for __const sections.
680 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
681 // to use section attributes to distinguish code from data.
682
683 // FIXME: Unimplemented.
684 Result = false;
685 return object_error::success;
686}
687
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000688error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
689 DataRefImpl Symb,
690 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000691 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000692 getSymbolType(Symb, ST);
David Meyer2c677272012-02-29 02:11:55 +0000693 if (ST == SymbolRef::ST_Unknown) {
Owen Andersoncd749882011-10-12 22:21:32 +0000694 Result = false;
695 return object_error::success;
696 }
697
698 uint64_t SectBegin, SectEnd;
699 getSectionAddress(Sec, SectBegin);
700 getSectionSize(Sec, SectEnd);
701 SectEnd += SectBegin;
702
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000703 if (is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000704 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000705 uint64_t SymAddr= Entry->Value;
706 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000707 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000708 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000709 uint64_t SymAddr= Entry->Value;
710 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000711 }
Owen Andersoncd749882011-10-12 22:21:32 +0000712
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000713 return object_error::success;
714}
715
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000716relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
717 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000718 ret.d.b = getSectionIndex(Sec);
719 return relocation_iterator(RelocationRef(ret, this));
720}
721relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
722 uint32_t last_reloc;
Rafael Espindolaf3051272013-04-07 17:41:59 +0000723 if (is64BitLoadCommand(this, Sec)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000724 const MachOFormat::Section64 *Sect = getSection64(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000725 last_reloc = Sect->NumRelocationTableEntries;
726 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000727 const MachOFormat::Section *Sect = getSection(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000728 last_reloc = Sect->NumRelocationTableEntries;
729 }
730 DataRefImpl ret;
731 ret.d.a = last_reloc;
732 ret.d.b = getSectionIndex(Sec);
733 return relocation_iterator(RelocationRef(ret, this));
734}
735
736section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000737 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000738 moveToNextSection(DRI);
739 return section_iterator(SectionRef(DRI, this));
740}
741
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000742section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000743 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000744 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000745 return section_iterator(SectionRef(DRI, this));
746}
747
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000748/*===-- Relocations -------------------------------------------------------===*/
749
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000750const MachOFormat::RelocationEntry *
751MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000752 uint32_t relOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000753 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000754 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000755 relOffset = Sect->RelocationTableOffset;
756 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000757 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000758 relOffset = Sect->RelocationTableOffset;
759 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000760 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000761 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000762 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000763}
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000764
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000765error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
766 RelocationRef &Res) const {
767 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000768 Res = RelocationRef(Rel, this);
769 return object_error::success;
770}
771error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
772 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000773 const uint8_t* sectAddress = 0;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000774 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000775 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000776 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000777 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000778 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000779 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000780 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000781 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000782
783 unsigned Arch = getArch();
784 bool isScattered = (Arch != Triple::x86_64) &&
785 (RE->Word0 & macho::RF_Scattered);
786 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000787 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000788 RelAddr = RE->Word0 & 0xFFFFFF;
789 else
790 RelAddr = RE->Word0;
791
792 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000793 return object_error::success;
794}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000795error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
796 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000797 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000798
799 unsigned Arch = getArch();
800 bool isScattered = (Arch != Triple::x86_64) &&
801 (RE->Word0 & macho::RF_Scattered);
802 if (isScattered)
803 Res = RE->Word0 & 0xFFFFFF;
804 else
805 Res = RE->Word0;
806 return object_error::success;
807}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000808error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
809 SymbolRef &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000810 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000811 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
812 bool isExtern = (RE->Word1 >> 27) & 1;
813
814 DataRefImpl Sym;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000815 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000816 if (isExtern) {
817 for (unsigned i = 0; i < SymbolIdx; i++) {
818 Sym.d.b++;
819 moveToNextSymbol(Sym);
Rafael Espindola433611b2013-04-07 19:26:57 +0000820 assert(Sym.d.a < getHeader()->NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000821 "Relocation symbol index out of range!");
822 }
823 }
824 Res = SymbolRef(Sym, this);
825 return object_error::success;
826}
827error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000828 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000829 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Andersonf8261e72011-10-26 17:10:22 +0000830 Res = RE->Word0;
831 Res <<= 32;
832 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000833 return object_error::success;
834}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000835error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
836 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000837 // TODO: Support scattered relocations.
838 StringRef res;
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000839 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +0000840
841 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000842 bool isScattered = (Arch != Triple::x86_64) &&
843 (RE->Word0 & macho::RF_Scattered);
844
845 unsigned r_type;
846 if (isScattered)
847 r_type = (RE->Word0 >> 24) & 0xF;
848 else
849 r_type = (RE->Word1 >> 28) & 0xF;
850
Owen Anderson0135fe12011-10-24 21:44:00 +0000851 switch (Arch) {
852 case Triple::x86: {
Craig Toppere3298102012-05-24 06:35:32 +0000853 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000854 "GENERIC_RELOC_VANILLA",
855 "GENERIC_RELOC_PAIR",
856 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000857 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000858 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000859 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000860
Owen Andersoneb6bd332011-10-27 20:46:09 +0000861 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000862 res = "Unknown";
863 else
864 res = Table[r_type];
865 break;
866 }
867 case Triple::x86_64: {
Craig Toppere3298102012-05-24 06:35:32 +0000868 static const char *const Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000869 "X86_64_RELOC_UNSIGNED",
870 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000871 "X86_64_RELOC_BRANCH",
872 "X86_64_RELOC_GOT_LOAD",
873 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000874 "X86_64_RELOC_SUBTRACTOR",
875 "X86_64_RELOC_SIGNED_1",
876 "X86_64_RELOC_SIGNED_2",
877 "X86_64_RELOC_SIGNED_4",
878 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000879
Owen Andersond8fa76d2011-10-24 23:20:07 +0000880 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000881 res = "Unknown";
882 else
883 res = Table[r_type];
884 break;
885 }
886 case Triple::arm: {
Craig Toppere3298102012-05-24 06:35:32 +0000887 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000888 "ARM_RELOC_VANILLA",
889 "ARM_RELOC_PAIR",
890 "ARM_RELOC_SECTDIFF",
891 "ARM_RELOC_LOCAL_SECTDIFF",
892 "ARM_RELOC_PB_LA_PTR",
893 "ARM_RELOC_BR24",
894 "ARM_THUMB_RELOC_BR22",
895 "ARM_THUMB_32BIT_BRANCH",
896 "ARM_RELOC_HALF",
897 "ARM_RELOC_HALF_SECTDIFF" };
898
899 if (r_type > 9)
900 res = "Unknown";
901 else
902 res = Table[r_type];
903 break;
904 }
905 case Triple::ppc: {
Craig Toppere3298102012-05-24 06:35:32 +0000906 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000907 "PPC_RELOC_VANILLA",
908 "PPC_RELOC_PAIR",
909 "PPC_RELOC_BR14",
910 "PPC_RELOC_BR24",
911 "PPC_RELOC_HI16",
912 "PPC_RELOC_LO16",
913 "PPC_RELOC_HA16",
914 "PPC_RELOC_LO14",
915 "PPC_RELOC_SECTDIFF",
916 "PPC_RELOC_PB_LA_PTR",
917 "PPC_RELOC_HI16_SECTDIFF",
918 "PPC_RELOC_LO16_SECTDIFF",
919 "PPC_RELOC_HA16_SECTDIFF",
920 "PPC_RELOC_JBSR",
921 "PPC_RELOC_LO14_SECTDIFF",
922 "PPC_RELOC_LOCAL_SECTDIFF" };
923
924 res = Table[r_type];
925 break;
926 }
927 case Triple::UnknownArch:
928 res = "Unknown";
929 break;
930 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000931 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000932 return object_error::success;
933}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000934error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
935 int64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000936 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000937 bool isExtern = (RE->Word1 >> 27) & 1;
938 Res = 0;
939 if (!isExtern) {
940 const uint8_t* sectAddress = base();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000941 if (is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000942 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000943 sectAddress += Sect->Offset;
944 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000945 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000946 sectAddress += Sect->Offset;
947 }
948 Res = reinterpret_cast<uintptr_t>(sectAddress);
949 }
950 return object_error::success;
951}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000952
953// Helper to advance a section or symbol iterator multiple increments at a time.
954template<class T>
955error_code advance(T &it, size_t Val) {
956 error_code ec;
957 while (Val--) {
958 it.increment(ec);
959 }
960 return ec;
961}
962
963template<class T>
964void advanceTo(T &it, size_t Val) {
965 if (error_code ec = advance(it, Val))
966 report_fatal_error(ec.message());
967}
968
Owen Anderson1832f4d2011-10-26 20:42:54 +0000969void MachOObjectFile::printRelocationTargetName(
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000970 const MachOFormat::RelocationEntry *RE,
Owen Anderson1832f4d2011-10-26 20:42:54 +0000971 raw_string_ostream &fmt) const {
972 unsigned Arch = getArch();
973 bool isScattered = (Arch != Triple::x86_64) &&
974 (RE->Word0 & macho::RF_Scattered);
975
976 // Target of a scattered relocation is an address. In the interest of
977 // generating pretty output, scan through the symbol table looking for a
978 // symbol that aligns with that address. If we find one, print it.
979 // Otherwise, we just print the hex address of the target.
980 if (isScattered) {
981 uint32_t Val = RE->Word1;
982
983 error_code ec;
984 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
985 SI.increment(ec)) {
986 if (ec) report_fatal_error(ec.message());
987
988 uint64_t Addr;
989 StringRef Name;
990
991 if ((ec = SI->getAddress(Addr)))
992 report_fatal_error(ec.message());
993 if (Addr != Val) continue;
994 if ((ec = SI->getName(Name)))
995 report_fatal_error(ec.message());
996 fmt << Name;
997 return;
998 }
999
Owen Andersonb28bdbf2011-10-27 21:53:50 +00001000 // If we couldn't find a symbol that this relocation refers to, try
1001 // to find a section beginning instead.
1002 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
1003 SI.increment(ec)) {
1004 if (ec) report_fatal_error(ec.message());
1005
1006 uint64_t Addr;
1007 StringRef Name;
1008
1009 if ((ec = SI->getAddress(Addr)))
1010 report_fatal_error(ec.message());
1011 if (Addr != Val) continue;
1012 if ((ec = SI->getName(Name)))
1013 report_fatal_error(ec.message());
1014 fmt << Name;
1015 return;
1016 }
1017
Owen Anderson1832f4d2011-10-26 20:42:54 +00001018 fmt << format("0x%x", Val);
1019 return;
1020 }
1021
1022 StringRef S;
1023 bool isExtern = (RE->Word1 >> 27) & 1;
1024 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001025
1026 if (isExtern) {
1027 symbol_iterator SI = begin_symbols();
1028 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001029 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001030 } else {
1031 section_iterator SI = begin_sections();
1032 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001033 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001034 }
1035
Owen Anderson1832f4d2011-10-26 20:42:54 +00001036 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001037}
1038
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001039error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1040 SmallVectorImpl<char> &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001041 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +00001042
Owen Anderson1832f4d2011-10-26 20:42:54 +00001043 unsigned Arch = getArch();
1044 bool isScattered = (Arch != Triple::x86_64) &&
1045 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001046
Owen Anderson013d7562011-10-25 18:48:41 +00001047 std::string fmtbuf;
1048 raw_string_ostream fmt(fmtbuf);
1049
Owen Anderson1832f4d2011-10-26 20:42:54 +00001050 unsigned Type;
1051 if (isScattered)
1052 Type = (RE->Word0 >> 24) & 0xF;
1053 else
1054 Type = (RE->Word1 >> 28) & 0xF;
1055
Owen Andersoneb6bd332011-10-27 20:46:09 +00001056 bool isPCRel;
1057 if (isScattered)
1058 isPCRel = ((RE->Word0 >> 30) & 1);
1059 else
1060 isPCRel = ((RE->Word1 >> 24) & 1);
1061
Owen Andersond8fa76d2011-10-24 23:20:07 +00001062 // Determine any addends that should be displayed with the relocation.
1063 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +00001064
1065 // X86_64 has entirely custom relocation types.
1066 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +00001067 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +00001068
Owen Andersond8fa76d2011-10-24 23:20:07 +00001069 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001070 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1071 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1072 printRelocationTargetName(RE, fmt);
1073 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +00001074 if (isPCRel) fmt << "PCREL";
1075 break;
1076 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001077 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +00001078 DataRefImpl RelNext = Rel;
1079 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001080 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001081
1082 // X86_64_SUBTRACTOR must be followed by a relocation of type
1083 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001084 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +00001085 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001086 if (RType != 0)
1087 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1088 "X86_64_RELOC_SUBTRACTOR.");
1089
Owen Andersonef22f782011-10-26 17:28:49 +00001090 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1091 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001092 printRelocationTargetName(RENext, fmt);
1093 fmt << "-";
1094 printRelocationTargetName(RE, fmt);
Jim Grosbach133f6b82013-01-31 19:46:57 +00001095 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001096 }
Owen Andersoneb6bd332011-10-27 20:46:09 +00001097 case macho::RIT_X86_64_TLV:
1098 printRelocationTargetName(RE, fmt);
1099 fmt << "@TLV";
1100 if (isPCRel) fmt << "P";
1101 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001102 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1103 printRelocationTargetName(RE, fmt);
1104 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001105 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001106 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1107 printRelocationTargetName(RE, fmt);
1108 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001109 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001110 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1111 printRelocationTargetName(RE, fmt);
1112 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +00001113 break;
1114 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001115 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001116 break;
1117 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001118 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001119 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1120 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001121 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001122 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001123 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001124 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001125 DataRefImpl RelNext = Rel;
1126 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001127 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001128
1129 // X86 sect diff's must be followed by a relocation of type
1130 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001131 bool isNextScattered = (Arch != Triple::x86_64) &&
1132 (RENext->Word0 & macho::RF_Scattered);
1133 unsigned RType;
1134 if (isNextScattered)
1135 RType = (RENext->Word0 >> 24) & 0xF;
1136 else
1137 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001138 if (RType != 1)
1139 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001140 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001141
Owen Anderson1832f4d2011-10-26 20:42:54 +00001142 printRelocationTargetName(RE, fmt);
1143 fmt << "-";
1144 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001145 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001146 }
1147 }
Owen Anderson013d7562011-10-25 18:48:41 +00001148
Owen Anderson1832f4d2011-10-26 20:42:54 +00001149 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001150 // All X86 relocations that need special printing were already
1151 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001152 switch (Type) {
1153 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
Owen Andersoneb6bd332011-10-27 20:46:09 +00001154 DataRefImpl RelNext = Rel;
1155 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001156 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersoneb6bd332011-10-27 20:46:09 +00001157
1158 // X86 sect diff's must be followed by a relocation of type
1159 // GENERIC_RELOC_PAIR.
1160 bool isNextScattered = (Arch != Triple::x86_64) &&
1161 (RENext->Word0 & macho::RF_Scattered);
1162 unsigned RType;
1163 if (isNextScattered)
1164 RType = (RENext->Word0 >> 24) & 0xF;
1165 else
1166 RType = (RENext->Word1 >> 28) & 0xF;
1167 if (RType != 1)
1168 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1169 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1170
1171 printRelocationTargetName(RE, fmt);
1172 fmt << "-";
1173 printRelocationTargetName(RENext, fmt);
1174 break;
1175 }
1176 case macho::RIT_Generic_TLV: {
1177 printRelocationTargetName(RE, fmt);
1178 fmt << "@TLV";
1179 if (isPCRel) fmt << "P";
1180 break;
1181 }
1182 default:
1183 printRelocationTargetName(RE, fmt);
1184 }
Owen Anderson013d7562011-10-25 18:48:41 +00001185 } else { // ARM-specific relocations
1186 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001187 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1188 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001189 // Half relocations steal a bit from the length field to encode
1190 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001191 bool isUpper;
1192 if (isScattered)
1193 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001194 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001195 isUpper = (RE->Word1 >> 25) & 1;
1196
1197 if (isUpper)
1198 fmt << ":upper16:(";
1199 else
1200 fmt << ":lower16:(";
1201 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001202
Owen Anderson013d7562011-10-25 18:48:41 +00001203 DataRefImpl RelNext = Rel;
1204 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001205 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Anderson013d7562011-10-25 18:48:41 +00001206
1207 // ARM half relocs must be followed by a relocation of type
1208 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001209 bool isNextScattered = (Arch != Triple::x86_64) &&
1210 (RENext->Word0 & macho::RF_Scattered);
1211 unsigned RType;
1212 if (isNextScattered)
1213 RType = (RENext->Word0 >> 24) & 0xF;
1214 else
1215 RType = (RENext->Word1 >> 28) & 0xF;
1216
Owen Anderson013d7562011-10-25 18:48:41 +00001217 if (RType != 1)
1218 report_fatal_error("Expected ARM_RELOC_PAIR after "
1219 "GENERIC_RELOC_HALF");
1220
Owen Anderson1832f4d2011-10-26 20:42:54 +00001221 // NOTE: The half of the target virtual address is stashed in the
1222 // address field of the secondary relocation, but we can't reverse
1223 // engineer the constant offset from it without decoding the movw/movt
1224 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001225
1226 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1227 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001228 if (Type == macho::RIT_ARM_HalfDifference) {
1229 fmt << "-";
1230 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001231 }
1232
Owen Anderson013d7562011-10-25 18:48:41 +00001233 fmt << ")";
1234 break;
1235 }
1236 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001237 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001238 }
1239 }
1240 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001241 } else
1242 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001243
Owen Anderson0135fe12011-10-24 21:44:00 +00001244 fmt.flush();
1245 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001246 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001247}
1248
Owen Anderson0685e942011-10-25 20:35:53 +00001249error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1250 bool &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001251 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0685e942011-10-25 20:35:53 +00001252
Owen Anderson0685e942011-10-25 20:35:53 +00001253 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001254 bool isScattered = (Arch != Triple::x86_64) &&
1255 (RE->Word0 & macho::RF_Scattered);
1256 unsigned Type;
1257 if (isScattered)
1258 Type = (RE->Word0 >> 24) & 0xF;
1259 else
1260 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001261
1262 Result = false;
1263
1264 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1265 // is always hidden.
1266 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001267 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001268 } else if (Arch == Triple::x86_64) {
1269 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1270 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001271 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001272 DataRefImpl RelPrev = Rel;
1273 RelPrev.d.a--;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001274 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
Owen Anderson0685e942011-10-25 20:35:53 +00001275
1276 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1277
Owen Anderson1832f4d2011-10-26 20:42:54 +00001278 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001279 }
1280 }
1281
1282 return object_error::success;
1283}
1284
David Meyer5c2b4ea2012-03-01 01:36:50 +00001285error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1286 LibraryRef &Res) const {
1287 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1288}
1289
1290error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1291 StringRef &Res) const {
1292 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1293}
1294
1295
Eric Christopher6256b032011-04-22 03:19:48 +00001296/*===-- Miscellaneous -----------------------------------------------------===*/
1297
1298uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001299 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001300}
1301
1302StringRef MachOObjectFile::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001303 if (!is64Bit()) {
Rafael Espindola433611b2013-04-07 19:26:57 +00001304 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001305 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001306 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001307 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001308 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001309 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001310 return "Mach-O 32-bit ppc";
1311 default:
Rafael Espindola433611b2013-04-07 19:26:57 +00001312 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001313 "64-bit object file when we're not 64-bit?");
1314 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001315 }
1316 }
1317
Eric Christopherb3e6b042013-02-28 20:26:17 +00001318 // Make sure the cpu type has the correct mask.
Rafael Espindola433611b2013-04-07 19:26:57 +00001319 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +00001320 == llvm::MachO::CPUArchABI64 &&
1321 "32-bit object file when we're 64-bit?");
1322
Rafael Espindola433611b2013-04-07 19:26:57 +00001323 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001324 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001325 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001326 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001327 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001328 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001329 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001330 }
1331}
1332
1333unsigned MachOObjectFile::getArch() const {
Rafael Espindola433611b2013-04-07 19:26:57 +00001334 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001335 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001336 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001337 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001338 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001339 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001340 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001341 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001342 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001343 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001344 return Triple::ppc64;
1345 default:
1346 return Triple::UnknownArch;
1347 }
1348}
1349
Owen Andersonf7c93a32011-10-11 17:32:27 +00001350} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001351} // end namespace llvm