blob: e1eec36598372fbbb58cec9329e6f745babcecfa [file] [log] [blame]
Eric Christopher6256b032011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Andersonf7c93a32011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000016#include "llvm/ADT/Triple.h"
Eric Christopher6256b032011-04-22 03:19:48 +000017#include "llvm/Object/MachOFormat.h"
Rafael Espindola8764c892013-04-07 20:01:29 +000018#include "llvm/Support/DataExtractor.h"
Owen Anderson1832f4d2011-10-26 20:42:54 +000019#include "llvm/Support/Format.h"
Eric Christopher6256b032011-04-22 03:19:48 +000020#include "llvm/Support/MemoryBuffer.h"
Eric Christopher6256b032011-04-22 03:19:48 +000021#include <cctype>
22#include <cstring>
23#include <limits>
24
25using namespace llvm;
26using namespace object;
27
28namespace llvm {
Owen Andersonf7c93a32011-10-11 17:32:27 +000029namespace object {
Eric Christopher6256b032011-04-22 03:19:48 +000030
Rafael Espindola9d55c092013-04-08 13:25:33 +000031MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool Is64bits,
32 error_code &ec)
33 : ObjectFile(getMachOType(true, Is64bits), Object) {
Benjamin Kramer0fcab072011-09-08 20:52:17 +000034 DataRefImpl DRI;
Benjamin Kramer0fcab072011-09-08 20:52:17 +000035 moveToNextSection(DRI);
Rafael Espindola433611b2013-04-07 19:26:57 +000036 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Benjamin Kramer0fcab072011-09-08 20:52:17 +000037 while (DRI.d.a < LoadCommandCount) {
38 Sections.push_back(DRI);
Benjamin Kramer0fcab072011-09-08 20:52:17 +000039 DRI.d.b++;
40 moveToNextSection(DRI);
41 }
42}
43
Rafael Espindola0be4eaf2013-04-07 15:46:05 +000044bool MachOObjectFile::is64Bit() const {
Rafael Espindola9d55c092013-04-08 13:25:33 +000045 unsigned int Type = getType();
46 return Type == ID_MachO64L || Type == ID_MachO64B;
Rafael Espindola0be4eaf2013-04-07 15:46:05 +000047}
Benjamin Kramer0fcab072011-09-08 20:52:17 +000048
Rafael Espindola6ab85a82013-04-07 18:42:06 +000049const MachOFormat::LoadCommand *
Rafael Espindola3eff3182013-04-07 16:07:35 +000050MachOObjectFile::getLoadCommandInfo(unsigned Index) const {
Rafael Espindola77638d92013-04-07 18:08:12 +000051 uint64_t Offset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000052 uint64_t NewOffset = getHeaderSize();
Rafael Espindola77638d92013-04-07 18:08:12 +000053 const MachOFormat::LoadCommand *Load;
54 unsigned I = 0;
55 do {
56 Offset = NewOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000057 StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand));
Rafael Espindola77638d92013-04-07 18:08:12 +000058 Load = reinterpret_cast<const MachOFormat::LoadCommand*>(Data.data());
59 NewOffset = Offset + Load->Size;
60 ++I;
61 } while (I != Index + 1);
62
Rafael Espindola6ab85a82013-04-07 18:42:06 +000063 return Load;
Rafael Espindola3eff3182013-04-07 16:07:35 +000064}
65
66void MachOObjectFile::ReadULEB128s(uint64_t Index,
67 SmallVectorImpl<uint64_t> &Out) const {
Rafael Espindola8764c892013-04-07 20:01:29 +000068 DataExtractor extractor(ObjectFile::getData(), true, 0);
69
70 uint32_t offset = Index;
71 uint64_t data = 0;
72 while (uint64_t delta = extractor.getULEB128(&offset)) {
73 data += delta;
74 Out.push_back(data);
75 }
Rafael Espindola3eff3182013-04-07 16:07:35 +000076}
77
Rafael Espindola433611b2013-04-07 19:26:57 +000078const MachOFormat::Header *MachOObjectFile::getHeader() const {
79 StringRef Data = getData(0, sizeof(MachOFormat::Header));
80 return reinterpret_cast<const MachOFormat::Header*>(Data.data());
Rafael Espindola3eff3182013-04-07 16:07:35 +000081}
82
Rafael Espindola0f08eb12013-04-07 19:05:30 +000083unsigned MachOObjectFile::getHeaderSize() const {
Rafael Espindolac90cc182013-04-07 19:31:49 +000084 return is64Bit() ? macho::Header64Size : macho::Header32Size;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000085}
86
87StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const {
Rafael Espindolaf1cc8002013-04-07 19:42:15 +000088 return ObjectFile::getData().substr(Offset, Size);
Rafael Espindola0f08eb12013-04-07 19:05:30 +000089}
90
Eric Christopher6256b032011-04-22 03:19:48 +000091ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Rafael Espindola9d55c092013-04-08 13:25:33 +000092 StringRef Magic = Buffer->getBuffer().slice(0, 4);
Michael J. Spencer001c9202011-06-25 17:54:50 +000093 error_code ec;
Rafael Espindola9d55c092013-04-08 13:25:33 +000094 bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
95 ObjectFile *Ret = new MachOObjectFile(Buffer, Is64Bits, ec);
Rafael Espindola6f1f3392013-04-07 16:58:48 +000096 if (ec)
Eric Christopher6256b032011-04-22 03:19:48 +000097 return NULL;
Rafael Espindola6f1f3392013-04-07 16:58:48 +000098 return Ret;
Eric Christopher6256b032011-04-22 03:19:48 +000099}
100
101/*===-- Symbols -----------------------------------------------------------===*/
102
103void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000104 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000105 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000106 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
107 if (Command->Type == macho::LCT_Symtab) {
Rafael Espindola82a21072013-04-06 03:31:08 +0000108 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000109 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000110 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
111 return;
112 }
113
114 DRI.d.a++;
115 DRI.d.b = 0;
116 }
117}
118
Rafael Espindola7df9c572013-04-09 00:22:58 +0000119const MachOFormat::SymbolTableEntryBase *
120MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000121 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000122 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000123 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Rafael Espindola7df9c572013-04-09 00:22:58 +0000124 return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
Rafael Espindola82a21072013-04-06 03:31:08 +0000125}
Eric Christopher6256b032011-04-22 03:19:48 +0000126
Rafael Espindola335f1d42013-04-08 20:45:01 +0000127const MachOFormat::SymbolTableEntry<false> *
Rafael Espindola7df9c572013-04-09 00:22:58 +0000128MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
129 const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
130 return reinterpret_cast<const MachOFormat::SymbolTableEntry<false>*>(Base);
131}
132
133const MachOFormat::SymbolTableEntryBase *
134MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI,
Rafael Espindola82a21072013-04-06 03:31:08 +0000135 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola00555c12013-04-06 01:59:05 +0000136 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
137 unsigned Index = DRI.d.b;
Rafael Espindola7df9c572013-04-09 00:22:58 +0000138
139 unsigned SymbolTableEntrySize = is64Bit() ?
140 sizeof(MachOFormat::SymbolTableEntry<true>) :
141 sizeof(MachOFormat::SymbolTableEntry<false>);
142
143 uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
144 StringRef Data = getData(Offset, SymbolTableEntrySize);
Rafael Espindola335f1d42013-04-08 20:45:01 +0000145 return
Rafael Espindola7df9c572013-04-09 00:22:58 +0000146 reinterpret_cast<const MachOFormat::SymbolTableEntryBase*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000147}
148
Rafael Espindola335f1d42013-04-08 20:45:01 +0000149const MachOFormat::SymbolTableEntry<true>*
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000150MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola7df9c572013-04-09 00:22:58 +0000151 const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
152 return reinterpret_cast<const MachOFormat::SymbolTableEntry<true>*>(Base);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000153}
154
Michael J. Spencer25b15772011-06-25 17:55:23 +0000155error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
156 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000157 DRI.d.b++;
158 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000159 Result = SymbolRef(DRI, this);
160 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000161}
162
Michael J. Spencer25b15772011-06-25 17:55:23 +0000163error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
164 StringRef &Result) const {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000165 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000166 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000167 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
Rafael Espindola82a21072013-04-06 03:31:08 +0000168
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000169 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
170 SymtabLoadCmd->StringTableSize);
Rafael Espindola82a21072013-04-06 03:31:08 +0000171
Rafael Espindola7df9c572013-04-09 00:22:58 +0000172 const MachOFormat::SymbolTableEntryBase *Entry =
173 getSymbolTableEntryBase(DRI, SymtabLoadCmd);
174 uint32_t StringIndex = Entry->StringIndex;
Rafael Espindola82a21072013-04-06 03:31:08 +0000175
176 const char *Start = &StringTable.data()[StringIndex];
177 Result = StringRef(Start);
178
Michael J. Spencer25b15772011-06-25 17:55:23 +0000179 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000180}
181
Danil Malyshevb0436a72011-11-29 17:40:10 +0000182error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
183 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000184 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000185 const MachOFormat::SymbolTableEntry<true> *Entry =
186 getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000187 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000188 if (Entry->SectionIndex) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000189 const MachOFormat::Section<true> *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000190 getSection64(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000191 Result += Section->Offset - Section->Address;
192 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000193 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000194 const MachOFormat::SymbolTableEntry<false> *Entry =
195 getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000196 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000197 if (Entry->SectionIndex) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000198 const MachOFormat::Section<false> *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000199 getSection(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000200 Result += Section->Offset - Section->Address;
201 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000202 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000203
Michael J. Spencer25b15772011-06-25 17:55:23 +0000204 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000205}
206
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000207error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
208 uint64_t &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000209 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000210 const MachOFormat::SymbolTableEntry<true> *Entry =
211 getSymbol64TableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000212 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000213 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000214 const MachOFormat::SymbolTableEntry<false> *Entry =
215 getSymbolTableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000216 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000217 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000218 return object_error::success;
219}
220
Michael J. Spencer25b15772011-06-25 17:55:23 +0000221error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
222 uint64_t &Result) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000223 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000224 uint64_t BeginOffset;
225 uint64_t EndOffset = 0;
226 uint8_t SectionIndex;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000227 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000228 const MachOFormat::SymbolTableEntry<true> *Entry =
229 getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000230 BeginOffset = Entry->Value;
231 SectionIndex = Entry->SectionIndex;
232 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000233 uint32_t flags = SymbolRef::SF_None;
234 getSymbolFlags(DRI, flags);
235 if (flags & SymbolRef::SF_Common)
236 Result = Entry->Value;
237 else
238 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000239 return object_error::success;
240 }
241 // Unfortunately symbols are unsorted so we need to touch all
242 // symbols from load command
243 DRI.d.b = 0;
244 uint32_t Command = DRI.d.a;
245 while (Command == DRI.d.a) {
246 moveToNextSymbol(DRI);
247 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000248 Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000249 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
250 if (!EndOffset || Entry->Value < EndOffset)
251 EndOffset = Entry->Value;
252 }
253 DRI.d.b++;
254 }
255 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000256 const MachOFormat::SymbolTableEntry<false> *Entry =
257 getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000258 BeginOffset = Entry->Value;
259 SectionIndex = Entry->SectionIndex;
260 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000261 uint32_t flags = SymbolRef::SF_None;
262 getSymbolFlags(DRI, flags);
263 if (flags & SymbolRef::SF_Common)
264 Result = Entry->Value;
265 else
266 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000267 return object_error::success;
268 }
269 // Unfortunately symbols are unsorted so we need to touch all
270 // symbols from load command
271 DRI.d.b = 0;
272 uint32_t Command = DRI.d.a;
273 while (Command == DRI.d.a) {
274 moveToNextSymbol(DRI);
275 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola00555c12013-04-06 01:59:05 +0000276 Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000277 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
278 if (!EndOffset || Entry->Value < EndOffset)
279 EndOffset = Entry->Value;
280 }
281 DRI.d.b++;
282 }
283 }
284 if (!EndOffset) {
285 uint64_t Size;
286 getSectionSize(Sections[SectionIndex-1], Size);
287 getSectionAddress(Sections[SectionIndex-1], EndOffset);
288 EndOffset += Size;
289 }
290 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000291 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000292}
293
Michael J. Spencer25b15772011-06-25 17:55:23 +0000294error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
295 char &Result) const {
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000296 const MachOFormat::SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
297 uint8_t Type = Entry->Type;
298 uint16_t Flags = Entry->Flags;
Eric Christopher6256b032011-04-22 03:19:48 +0000299
300 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000301 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000302 case macho::STT_Undefined:
303 Char = 'u';
304 break;
305 case macho::STT_Absolute:
306 case macho::STT_Section:
307 Char = 's';
308 break;
309 default:
310 Char = '?';
311 break;
312 }
313
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000314 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000315 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000316 Result = Char;
317 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000318}
319
David Meyerc46255a2012-02-28 23:47:53 +0000320error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
321 uint32_t &Result) const {
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000322 const MachOFormat::SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
323 uint8_t MachOType = Entry->Type;
324 uint16_t MachOFlags = Entry->Flags;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000325
Preston Gurdc68dda82012-04-12 20:13:57 +0000326 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000327 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000328
329 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
330 Result |= SymbolRef::SF_Undefined;
331
David Meyerc46255a2012-02-28 23:47:53 +0000332 if (MachOFlags & macho::STF_StabsEntryMask)
333 Result |= SymbolRef::SF_FormatSpecific;
334
Preston Gurdc68dda82012-04-12 20:13:57 +0000335 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000336 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000337 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
338 Result |= SymbolRef::SF_Common;
339 }
David Meyerc46255a2012-02-28 23:47:53 +0000340
341 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
342 Result |= SymbolRef::SF_Weak;
343
344 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
345 Result |= SymbolRef::SF_Absolute;
346
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000347 return object_error::success;
348}
349
350error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
351 section_iterator &Res) const {
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000352 const MachOFormat::SymbolTableEntryBase *Entry =
353 getSymbolTableEntryBase(Symb);
354 uint8_t index = Entry->SectionIndex;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000355
356 if (index == 0)
357 Res = end_sections();
358 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000359 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000360
361 return object_error::success;
362}
363
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000364error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000365 SymbolRef::Type &Res) const {
Rafael Espindola7df9c572013-04-09 00:22:58 +0000366 const MachOFormat::SymbolTableEntryBase *Entry =
367 getSymbolTableEntryBase(Symb);
368 uint8_t n_type = Entry->Type;
369
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000370 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000371
372 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000373 if (n_type & MachO::NlistMaskStab) {
374 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000375 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000376 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000377
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000378 switch (n_type & MachO::NlistMaskType) {
379 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000380 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000381 break;
382 case MachO::NListTypeSection :
383 Res = SymbolRef::ST_Function;
384 break;
385 }
386 return object_error::success;
387}
388
Tim Northovera41dce32012-10-29 10:47:00 +0000389error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
390 uint64_t &Val) const {
391 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
392}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000393
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000394symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000395 // DRI.d.a = segment number; DRI.d.b = symbol index.
396 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000397 moveToNextSymbol(DRI);
398 return symbol_iterator(SymbolRef(DRI, this));
399}
400
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000401symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000402 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000403 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000404 return symbol_iterator(SymbolRef(DRI, this));
405}
406
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000407symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
408 // TODO: implement
409 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
410}
411
412symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
413 // TODO: implement
414 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
415}
Eric Christopher6256b032011-04-22 03:19:48 +0000416
David Meyer5c2b4ea2012-03-01 01:36:50 +0000417library_iterator MachOObjectFile::begin_libraries_needed() const {
418 // TODO: implement
419 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
420}
421
422library_iterator MachOObjectFile::end_libraries_needed() const {
423 // TODO: implement
424 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
425}
426
David Meyer97f77872012-03-01 22:19:54 +0000427StringRef MachOObjectFile::getLoadName() const {
428 // TODO: Implement
429 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
430}
431
Eric Christopher6256b032011-04-22 03:19:48 +0000432/*===-- Sections ----------------------------------------------------------===*/
433
434void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000435 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000436 while (DRI.d.a < LoadCommandCount) {
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000437 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
438 if (Command->Type == macho::LCT_Segment) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000439 const MachOFormat::SegmentLoadCommand<false> *SegmentLoadCmd =
440 reinterpret_cast<const MachOFormat::SegmentLoadCommand<false>*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000441 if (DRI.d.b < SegmentLoadCmd->NumSections)
442 return;
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000443 } else if (Command->Type == macho::LCT_Segment64) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000444 const MachOFormat::SegmentLoadCommand<true> *SegmentLoadCmd =
445 reinterpret_cast<const MachOFormat::SegmentLoadCommand<true>*>(Command);
446 if (DRI.d.b < SegmentLoadCmd->NumSections)
Eric Christopher6256b032011-04-22 03:19:48 +0000447 return;
448 }
449
450 DRI.d.a++;
451 DRI.d.b = 0;
452 }
453}
454
Michael J. Spencer25b15772011-06-25 17:55:23 +0000455error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
456 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000457 DRI.d.b++;
458 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000459 Result = SectionRef(DRI, this);
460 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000461}
462
Rafael Espindola335f1d42013-04-08 20:45:01 +0000463const MachOFormat::Section<false> *
464MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000465 assert(!is64Bit());
Rafael Espindola33885892013-04-08 23:57:13 +0000466 const MachOFormat::SectionBase *Addr = getSectionBase(DRI);
467 return reinterpret_cast<const MachOFormat::Section<false>*>(Addr);
Eric Christopher6256b032011-04-22 03:19:48 +0000468}
469
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000470std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
471 SectionList::const_iterator loc =
472 std::find(Sections.begin(), Sections.end(), Sec);
473 assert(loc != Sections.end() && "Sec is not a valid section!");
474 return std::distance(Sections.begin(), loc);
475}
476
Rafael Espindola33885892013-04-08 23:57:13 +0000477const MachOFormat::SectionBase*
478MachOObjectFile::getSectionBase(DataRefImpl DRI) const {
479 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
480 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
481
482 bool Is64 = is64Bit();
483 unsigned SegmentLoadSize =
484 Is64 ? sizeof(MachOFormat::SegmentLoadCommand<true>) :
485 sizeof(MachOFormat::SegmentLoadCommand<false>);
486 unsigned SectionSize = Is64 ? sizeof(MachOFormat::Section<true>) :
487 sizeof(MachOFormat::Section<false>);
488
489 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
490 return reinterpret_cast<const MachOFormat::SectionBase*>(SectionAddr);
491}
492
Rafael Espindola335f1d42013-04-08 20:45:01 +0000493const MachOFormat::Section<true> *
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000494MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000495 assert(is64Bit());
Rafael Espindola33885892013-04-08 23:57:13 +0000496 const MachOFormat::SectionBase *Addr = getSectionBase(DRI);
497 return reinterpret_cast<const MachOFormat::Section<true>*>(Addr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000498}
499
Rafael Espindolacef81b32012-12-21 03:47:03 +0000500static StringRef parseSegmentOrSectionName(const char *P) {
501 if (P[15] == 0)
502 // Null terminated.
503 return P;
504 // Not null terminated, so this is a 16 char string.
505 return StringRef(P, 16);
506}
507
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000508ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
Rafael Espindola33885892013-04-08 23:57:13 +0000509 const MachOFormat::SectionBase *Base = getSectionBase(DRI);
510 return ArrayRef<char>(Base->Name);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000511}
512
513error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
514 StringRef &Result) const {
515 ArrayRef<char> Raw = getSectionRawName(DRI);
516 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000517 return object_error::success;
518}
519
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000520ArrayRef<char>
521MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola33885892013-04-08 23:57:13 +0000522 const MachOFormat::SectionBase *Base = getSectionBase(Sec);
523 return ArrayRef<char>(Base->SegmentName);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000524}
525
526StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
527 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
528 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000529}
530
Michael J. Spencer25b15772011-06-25 17:55:23 +0000531error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
532 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000533 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000534 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000535 Result = Sect->Address;
536 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000537 const MachOFormat::Section<false> *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000538 Result = Sect->Address;
539 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000540 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000541}
542
Michael J. Spencer25b15772011-06-25 17:55:23 +0000543error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
544 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000545 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000546 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000547 Result = Sect->Size;
548 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000549 const MachOFormat::Section<false> *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000550 Result = Sect->Size;
551 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000552 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000553}
554
Michael J. Spencer25b15772011-06-25 17:55:23 +0000555error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
556 StringRef &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000557 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000558 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000559 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000560 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000561 const MachOFormat::Section<false> *Sect = getSection(DRI);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000562 Result = getData(Sect->Offset, Sect->Size);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000563 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000564 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000565}
566
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000567error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
568 uint64_t &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000569 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000570 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000571 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000572 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000573 const MachOFormat::Section<false> *Sect = getSection(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000574 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000575 }
576 return object_error::success;
577}
578
Michael J. Spencer25b15772011-06-25 17:55:23 +0000579error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
580 bool &Result) const {
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000581 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000582 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000583 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000584 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000585 const MachOFormat::Section<false> *Sect = getSection(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000586 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000587 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000588 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000589}
590
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000591error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
592 bool &Result) const {
593 // FIXME: Unimplemented.
594 Result = false;
595 return object_error::success;
596}
597
598error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
599 bool &Result) const {
600 // FIXME: Unimplemented.
601 Result = false;
602 return object_error::success;
603}
604
Preston Gurdc68dda82012-04-12 20:13:57 +0000605error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
606 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000607 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000608 Result = true;
609 return object_error::success;
610}
611
612error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000613 bool &Result) const {
614 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000615 Result = false;
616 return object_error::success;
617}
618
619error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
620 bool &Result) const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000621 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000622 const MachOFormat::Section<true> *Sect = getSection64(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000623 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
624 Result = (SectionType == MachO::SectionTypeZeroFill ||
625 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000626 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000627 const MachOFormat::Section<false> *Sect = getSection(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000628 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
629 Result = (SectionType == MachO::SectionTypeZeroFill ||
630 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000631 }
632
633 return object_error::success;
634}
635
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000636error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
637 bool &Result) const {
638 // Consider using the code from isSectionText to look for __const sections.
639 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
640 // to use section attributes to distinguish code from data.
641
642 // FIXME: Unimplemented.
643 Result = false;
644 return object_error::success;
645}
646
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000647error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
648 DataRefImpl Symb,
649 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000650 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000651 getSymbolType(Symb, ST);
David Meyer2c677272012-02-29 02:11:55 +0000652 if (ST == SymbolRef::ST_Unknown) {
Owen Andersoncd749882011-10-12 22:21:32 +0000653 Result = false;
654 return object_error::success;
655 }
656
657 uint64_t SectBegin, SectEnd;
658 getSectionAddress(Sec, SectBegin);
659 getSectionSize(Sec, SectEnd);
660 SectEnd += SectBegin;
661
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000662 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000663 const MachOFormat::SymbolTableEntry<true> *Entry =
664 getSymbol64TableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000665 uint64_t SymAddr= Entry->Value;
666 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000667 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000668 const MachOFormat::SymbolTableEntry<false> *Entry =
669 getSymbolTableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000670 uint64_t SymAddr= Entry->Value;
671 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000672 }
Owen Andersoncd749882011-10-12 22:21:32 +0000673
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000674 return object_error::success;
675}
676
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000677relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
678 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000679 ret.d.b = getSectionIndex(Sec);
680 return relocation_iterator(RelocationRef(ret, this));
681}
Rafael Espindola335f1d42013-04-08 20:45:01 +0000682
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000683relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
684 uint32_t last_reloc;
Rafael Espindolaa9408ba2013-04-08 20:18:53 +0000685 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000686 const MachOFormat::Section<true> *Sect = getSection64(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000687 last_reloc = Sect->NumRelocationTableEntries;
688 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000689 const MachOFormat::Section<false> *Sect = getSection(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000690 last_reloc = Sect->NumRelocationTableEntries;
691 }
692 DataRefImpl ret;
693 ret.d.a = last_reloc;
694 ret.d.b = getSectionIndex(Sec);
695 return relocation_iterator(RelocationRef(ret, this));
696}
697
698section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000699 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000700 moveToNextSection(DRI);
701 return section_iterator(SectionRef(DRI, this));
702}
703
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000704section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000705 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000706 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000707 return section_iterator(SectionRef(DRI, this));
708}
709
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000710/*===-- Relocations -------------------------------------------------------===*/
711
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000712const MachOFormat::RelocationEntry *
713MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000714 uint32_t relOffset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000715 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000716 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000717 relOffset = Sect->RelocationTableOffset;
718 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000719 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000720 relOffset = Sect->RelocationTableOffset;
721 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000722 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000723 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000724 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000725}
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000726
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000727error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
728 RelocationRef &Res) const {
729 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000730 Res = RelocationRef(Rel, this);
731 return object_error::success;
732}
733error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
734 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000735 const uint8_t* sectAddress = 0;
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000736 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000737 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000738 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000739 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000740 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000741 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000742 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000743 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000744
745 unsigned Arch = getArch();
746 bool isScattered = (Arch != Triple::x86_64) &&
747 (RE->Word0 & macho::RF_Scattered);
748 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000749 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000750 RelAddr = RE->Word0 & 0xFFFFFF;
751 else
752 RelAddr = RE->Word0;
753
754 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000755 return object_error::success;
756}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000757error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
758 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000759 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000760
761 unsigned Arch = getArch();
762 bool isScattered = (Arch != Triple::x86_64) &&
763 (RE->Word0 & macho::RF_Scattered);
764 if (isScattered)
765 Res = RE->Word0 & 0xFFFFFF;
766 else
767 Res = RE->Word0;
768 return object_error::success;
769}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000770error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
771 SymbolRef &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000772 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000773 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
774 bool isExtern = (RE->Word1 >> 27) & 1;
775
776 DataRefImpl Sym;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000777 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000778 if (isExtern) {
779 for (unsigned i = 0; i < SymbolIdx; i++) {
780 Sym.d.b++;
781 moveToNextSymbol(Sym);
Rafael Espindola433611b2013-04-07 19:26:57 +0000782 assert(Sym.d.a < getHeader()->NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000783 "Relocation symbol index out of range!");
784 }
785 }
786 Res = SymbolRef(Sym, this);
787 return object_error::success;
788}
789error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000790 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000791 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Andersonf8261e72011-10-26 17:10:22 +0000792 Res = RE->Word0;
793 Res <<= 32;
794 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000795 return object_error::success;
796}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000797error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
798 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000799 // TODO: Support scattered relocations.
800 StringRef res;
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000801 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +0000802
803 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000804 bool isScattered = (Arch != Triple::x86_64) &&
805 (RE->Word0 & macho::RF_Scattered);
806
807 unsigned r_type;
808 if (isScattered)
809 r_type = (RE->Word0 >> 24) & 0xF;
810 else
811 r_type = (RE->Word1 >> 28) & 0xF;
812
Owen Anderson0135fe12011-10-24 21:44:00 +0000813 switch (Arch) {
814 case Triple::x86: {
Craig Toppere3298102012-05-24 06:35:32 +0000815 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000816 "GENERIC_RELOC_VANILLA",
817 "GENERIC_RELOC_PAIR",
818 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000819 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000820 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000821 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000822
Owen Andersoneb6bd332011-10-27 20:46:09 +0000823 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000824 res = "Unknown";
825 else
826 res = Table[r_type];
827 break;
828 }
829 case Triple::x86_64: {
Craig Toppere3298102012-05-24 06:35:32 +0000830 static const char *const Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000831 "X86_64_RELOC_UNSIGNED",
832 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000833 "X86_64_RELOC_BRANCH",
834 "X86_64_RELOC_GOT_LOAD",
835 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000836 "X86_64_RELOC_SUBTRACTOR",
837 "X86_64_RELOC_SIGNED_1",
838 "X86_64_RELOC_SIGNED_2",
839 "X86_64_RELOC_SIGNED_4",
840 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000841
Owen Andersond8fa76d2011-10-24 23:20:07 +0000842 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000843 res = "Unknown";
844 else
845 res = Table[r_type];
846 break;
847 }
848 case Triple::arm: {
Craig Toppere3298102012-05-24 06:35:32 +0000849 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000850 "ARM_RELOC_VANILLA",
851 "ARM_RELOC_PAIR",
852 "ARM_RELOC_SECTDIFF",
853 "ARM_RELOC_LOCAL_SECTDIFF",
854 "ARM_RELOC_PB_LA_PTR",
855 "ARM_RELOC_BR24",
856 "ARM_THUMB_RELOC_BR22",
857 "ARM_THUMB_32BIT_BRANCH",
858 "ARM_RELOC_HALF",
859 "ARM_RELOC_HALF_SECTDIFF" };
860
861 if (r_type > 9)
862 res = "Unknown";
863 else
864 res = Table[r_type];
865 break;
866 }
867 case Triple::ppc: {
Craig Toppere3298102012-05-24 06:35:32 +0000868 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000869 "PPC_RELOC_VANILLA",
870 "PPC_RELOC_PAIR",
871 "PPC_RELOC_BR14",
872 "PPC_RELOC_BR24",
873 "PPC_RELOC_HI16",
874 "PPC_RELOC_LO16",
875 "PPC_RELOC_HA16",
876 "PPC_RELOC_LO14",
877 "PPC_RELOC_SECTDIFF",
878 "PPC_RELOC_PB_LA_PTR",
879 "PPC_RELOC_HI16_SECTDIFF",
880 "PPC_RELOC_LO16_SECTDIFF",
881 "PPC_RELOC_HA16_SECTDIFF",
882 "PPC_RELOC_JBSR",
883 "PPC_RELOC_LO14_SECTDIFF",
884 "PPC_RELOC_LOCAL_SECTDIFF" };
885
886 res = Table[r_type];
887 break;
888 }
889 case Triple::UnknownArch:
890 res = "Unknown";
891 break;
892 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000893 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000894 return object_error::success;
895}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000896error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
897 int64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000898 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000899 bool isExtern = (RE->Word1 >> 27) & 1;
900 Res = 0;
901 if (!isExtern) {
902 const uint8_t* sectAddress = base();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000903 if (is64Bit()) {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000904 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000905 sectAddress += Sect->Offset;
906 } else {
Rafael Espindola335f1d42013-04-08 20:45:01 +0000907 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000908 sectAddress += Sect->Offset;
909 }
910 Res = reinterpret_cast<uintptr_t>(sectAddress);
911 }
912 return object_error::success;
913}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000914
915// Helper to advance a section or symbol iterator multiple increments at a time.
916template<class T>
917error_code advance(T &it, size_t Val) {
918 error_code ec;
919 while (Val--) {
920 it.increment(ec);
921 }
922 return ec;
923}
924
925template<class T>
926void advanceTo(T &it, size_t Val) {
927 if (error_code ec = advance(it, Val))
928 report_fatal_error(ec.message());
929}
930
Owen Anderson1832f4d2011-10-26 20:42:54 +0000931void MachOObjectFile::printRelocationTargetName(
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000932 const MachOFormat::RelocationEntry *RE,
Owen Anderson1832f4d2011-10-26 20:42:54 +0000933 raw_string_ostream &fmt) const {
934 unsigned Arch = getArch();
935 bool isScattered = (Arch != Triple::x86_64) &&
936 (RE->Word0 & macho::RF_Scattered);
937
938 // Target of a scattered relocation is an address. In the interest of
939 // generating pretty output, scan through the symbol table looking for a
940 // symbol that aligns with that address. If we find one, print it.
941 // Otherwise, we just print the hex address of the target.
942 if (isScattered) {
943 uint32_t Val = RE->Word1;
944
945 error_code ec;
946 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
947 SI.increment(ec)) {
948 if (ec) report_fatal_error(ec.message());
949
950 uint64_t Addr;
951 StringRef Name;
952
953 if ((ec = SI->getAddress(Addr)))
954 report_fatal_error(ec.message());
955 if (Addr != Val) continue;
956 if ((ec = SI->getName(Name)))
957 report_fatal_error(ec.message());
958 fmt << Name;
959 return;
960 }
961
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000962 // If we couldn't find a symbol that this relocation refers to, try
963 // to find a section beginning instead.
964 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
965 SI.increment(ec)) {
966 if (ec) report_fatal_error(ec.message());
967
968 uint64_t Addr;
969 StringRef Name;
970
971 if ((ec = SI->getAddress(Addr)))
972 report_fatal_error(ec.message());
973 if (Addr != Val) continue;
974 if ((ec = SI->getName(Name)))
975 report_fatal_error(ec.message());
976 fmt << Name;
977 return;
978 }
979
Owen Anderson1832f4d2011-10-26 20:42:54 +0000980 fmt << format("0x%x", Val);
981 return;
982 }
983
984 StringRef S;
985 bool isExtern = (RE->Word1 >> 27) & 1;
986 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000987
988 if (isExtern) {
989 symbol_iterator SI = begin_symbols();
990 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000991 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000992 } else {
993 section_iterator SI = begin_sections();
994 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000995 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000996 }
997
Owen Anderson1832f4d2011-10-26 20:42:54 +0000998 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000999}
1000
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001001error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1002 SmallVectorImpl<char> &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001003 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +00001004
Owen Anderson1832f4d2011-10-26 20:42:54 +00001005 unsigned Arch = getArch();
1006 bool isScattered = (Arch != Triple::x86_64) &&
1007 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001008
Owen Anderson013d7562011-10-25 18:48:41 +00001009 std::string fmtbuf;
1010 raw_string_ostream fmt(fmtbuf);
1011
Owen Anderson1832f4d2011-10-26 20:42:54 +00001012 unsigned Type;
1013 if (isScattered)
1014 Type = (RE->Word0 >> 24) & 0xF;
1015 else
1016 Type = (RE->Word1 >> 28) & 0xF;
1017
Owen Andersoneb6bd332011-10-27 20:46:09 +00001018 bool isPCRel;
1019 if (isScattered)
1020 isPCRel = ((RE->Word0 >> 30) & 1);
1021 else
1022 isPCRel = ((RE->Word1 >> 24) & 1);
1023
Owen Andersond8fa76d2011-10-24 23:20:07 +00001024 // Determine any addends that should be displayed with the relocation.
1025 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +00001026
1027 // X86_64 has entirely custom relocation types.
1028 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +00001029 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +00001030
Owen Andersond8fa76d2011-10-24 23:20:07 +00001031 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001032 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1033 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1034 printRelocationTargetName(RE, fmt);
1035 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +00001036 if (isPCRel) fmt << "PCREL";
1037 break;
1038 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001039 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +00001040 DataRefImpl RelNext = Rel;
1041 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001042 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001043
1044 // X86_64_SUBTRACTOR must be followed by a relocation of type
1045 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001046 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +00001047 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001048 if (RType != 0)
1049 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1050 "X86_64_RELOC_SUBTRACTOR.");
1051
Owen Andersonef22f782011-10-26 17:28:49 +00001052 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1053 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001054 printRelocationTargetName(RENext, fmt);
1055 fmt << "-";
1056 printRelocationTargetName(RE, fmt);
Jim Grosbach133f6b82013-01-31 19:46:57 +00001057 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001058 }
Owen Andersoneb6bd332011-10-27 20:46:09 +00001059 case macho::RIT_X86_64_TLV:
1060 printRelocationTargetName(RE, fmt);
1061 fmt << "@TLV";
1062 if (isPCRel) fmt << "P";
1063 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001064 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1065 printRelocationTargetName(RE, fmt);
1066 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001067 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001068 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1069 printRelocationTargetName(RE, fmt);
1070 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001071 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001072 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1073 printRelocationTargetName(RE, fmt);
1074 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +00001075 break;
1076 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001077 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001078 break;
1079 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001080 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001081 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1082 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001083 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001084 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001085 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001086 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001087 DataRefImpl RelNext = Rel;
1088 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001089 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001090
1091 // X86 sect diff's must be followed by a relocation of type
1092 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001093 bool isNextScattered = (Arch != Triple::x86_64) &&
1094 (RENext->Word0 & macho::RF_Scattered);
1095 unsigned RType;
1096 if (isNextScattered)
1097 RType = (RENext->Word0 >> 24) & 0xF;
1098 else
1099 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001100 if (RType != 1)
1101 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001102 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001103
Owen Anderson1832f4d2011-10-26 20:42:54 +00001104 printRelocationTargetName(RE, fmt);
1105 fmt << "-";
1106 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001107 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001108 }
1109 }
Owen Anderson013d7562011-10-25 18:48:41 +00001110
Owen Anderson1832f4d2011-10-26 20:42:54 +00001111 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001112 // All X86 relocations that need special printing were already
1113 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001114 switch (Type) {
1115 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
Owen Andersoneb6bd332011-10-27 20:46:09 +00001116 DataRefImpl RelNext = Rel;
1117 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001118 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersoneb6bd332011-10-27 20:46:09 +00001119
1120 // X86 sect diff's must be followed by a relocation of type
1121 // GENERIC_RELOC_PAIR.
1122 bool isNextScattered = (Arch != Triple::x86_64) &&
1123 (RENext->Word0 & macho::RF_Scattered);
1124 unsigned RType;
1125 if (isNextScattered)
1126 RType = (RENext->Word0 >> 24) & 0xF;
1127 else
1128 RType = (RENext->Word1 >> 28) & 0xF;
1129 if (RType != 1)
1130 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1131 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1132
1133 printRelocationTargetName(RE, fmt);
1134 fmt << "-";
1135 printRelocationTargetName(RENext, fmt);
1136 break;
1137 }
1138 case macho::RIT_Generic_TLV: {
1139 printRelocationTargetName(RE, fmt);
1140 fmt << "@TLV";
1141 if (isPCRel) fmt << "P";
1142 break;
1143 }
1144 default:
1145 printRelocationTargetName(RE, fmt);
1146 }
Owen Anderson013d7562011-10-25 18:48:41 +00001147 } else { // ARM-specific relocations
1148 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001149 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1150 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001151 // Half relocations steal a bit from the length field to encode
1152 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001153 bool isUpper;
1154 if (isScattered)
1155 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001156 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001157 isUpper = (RE->Word1 >> 25) & 1;
1158
1159 if (isUpper)
1160 fmt << ":upper16:(";
1161 else
1162 fmt << ":lower16:(";
1163 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001164
Owen Anderson013d7562011-10-25 18:48:41 +00001165 DataRefImpl RelNext = Rel;
1166 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001167 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Anderson013d7562011-10-25 18:48:41 +00001168
1169 // ARM half relocs must be followed by a relocation of type
1170 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001171 bool isNextScattered = (Arch != Triple::x86_64) &&
1172 (RENext->Word0 & macho::RF_Scattered);
1173 unsigned RType;
1174 if (isNextScattered)
1175 RType = (RENext->Word0 >> 24) & 0xF;
1176 else
1177 RType = (RENext->Word1 >> 28) & 0xF;
1178
Owen Anderson013d7562011-10-25 18:48:41 +00001179 if (RType != 1)
1180 report_fatal_error("Expected ARM_RELOC_PAIR after "
1181 "GENERIC_RELOC_HALF");
1182
Owen Anderson1832f4d2011-10-26 20:42:54 +00001183 // NOTE: The half of the target virtual address is stashed in the
1184 // address field of the secondary relocation, but we can't reverse
1185 // engineer the constant offset from it without decoding the movw/movt
1186 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001187
1188 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1189 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001190 if (Type == macho::RIT_ARM_HalfDifference) {
1191 fmt << "-";
1192 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001193 }
1194
Owen Anderson013d7562011-10-25 18:48:41 +00001195 fmt << ")";
1196 break;
1197 }
1198 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001199 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001200 }
1201 }
1202 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001203 } else
1204 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001205
Owen Anderson0135fe12011-10-24 21:44:00 +00001206 fmt.flush();
1207 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001208 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001209}
1210
Owen Anderson0685e942011-10-25 20:35:53 +00001211error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1212 bool &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001213 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0685e942011-10-25 20:35:53 +00001214
Owen Anderson0685e942011-10-25 20:35:53 +00001215 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001216 bool isScattered = (Arch != Triple::x86_64) &&
1217 (RE->Word0 & macho::RF_Scattered);
1218 unsigned Type;
1219 if (isScattered)
1220 Type = (RE->Word0 >> 24) & 0xF;
1221 else
1222 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001223
1224 Result = false;
1225
1226 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1227 // is always hidden.
1228 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001229 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001230 } else if (Arch == Triple::x86_64) {
1231 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1232 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001233 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001234 DataRefImpl RelPrev = Rel;
1235 RelPrev.d.a--;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001236 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
Owen Anderson0685e942011-10-25 20:35:53 +00001237
1238 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1239
Owen Anderson1832f4d2011-10-26 20:42:54 +00001240 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001241 }
1242 }
1243
1244 return object_error::success;
1245}
1246
David Meyer5c2b4ea2012-03-01 01:36:50 +00001247error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1248 LibraryRef &Res) const {
1249 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1250}
1251
1252error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1253 StringRef &Res) const {
1254 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1255}
1256
1257
Eric Christopher6256b032011-04-22 03:19:48 +00001258/*===-- Miscellaneous -----------------------------------------------------===*/
1259
1260uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001261 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001262}
1263
1264StringRef MachOObjectFile::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001265 if (!is64Bit()) {
Rafael Espindola433611b2013-04-07 19:26:57 +00001266 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001267 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001268 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001269 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001270 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001271 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001272 return "Mach-O 32-bit ppc";
1273 default:
Rafael Espindola433611b2013-04-07 19:26:57 +00001274 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001275 "64-bit object file when we're not 64-bit?");
1276 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001277 }
1278 }
1279
Eric Christopherb3e6b042013-02-28 20:26:17 +00001280 // Make sure the cpu type has the correct mask.
Rafael Espindola433611b2013-04-07 19:26:57 +00001281 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +00001282 == llvm::MachO::CPUArchABI64 &&
1283 "32-bit object file when we're 64-bit?");
1284
Rafael Espindola433611b2013-04-07 19:26:57 +00001285 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001286 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001287 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001288 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001289 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001290 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001291 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001292 }
1293}
1294
1295unsigned MachOObjectFile::getArch() const {
Rafael Espindola433611b2013-04-07 19:26:57 +00001296 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001297 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001298 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001299 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001300 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001301 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001302 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001303 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001304 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001305 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001306 return Triple::ppc64;
1307 default:
1308 return Triple::UnknownArch;
1309 }
1310}
1311
Owen Andersonf7c93a32011-10-11 17:32:27 +00001312} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001313} // end namespace llvm