blob: 1eb14f31ff43922b17871c017d68932bb6c43dd5 [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
Benjamin Kramer0fcab072011-09-08 20:52:17 +000030MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
31 error_code &ec)
David Meyer6f9489a2012-03-09 20:41:57 +000032 : ObjectFile(Binary::ID_MachO, Object, ec),
Rafael Espindola82a21072013-04-06 03:31:08 +000033 MachOObj(MOO) {
Benjamin Kramer0fcab072011-09-08 20:52:17 +000034 DataRefImpl DRI;
Benjamin Kramer0fcab072011-09-08 20:52:17 +000035 moveToNextSection(DRI);
36 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
37 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
44
Eric Christopher6256b032011-04-22 03:19:48 +000045ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Michael J. Spencer001c9202011-06-25 17:54:50 +000046 error_code ec;
Eric Christopher6256b032011-04-22 03:19:48 +000047 std::string Err;
48 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
49 if (!MachOObj)
50 return NULL;
Jim Grosbach596e4742012-11-29 19:14:11 +000051 // MachOObject takes ownership of the Buffer we passed to it, and
52 // MachOObjectFile does, too, so we need to make sure they don't get the
53 // same object. A MemoryBuffer is cheap (it's just a reference to memory,
54 // not a copy of the memory itself), so just make a new copy here for
55 // the MachOObjectFile.
56 MemoryBuffer *NewBuffer =
Benjamin Kramerf56c3e22012-11-29 20:08:03 +000057 MemoryBuffer::getMemBuffer(Buffer->getBuffer(),
58 Buffer->getBufferIdentifier(), false);
Jim Grosbach596e4742012-11-29 19:14:11 +000059 return new MachOObjectFile(NewBuffer, MachOObj, ec);
Eric Christopher6256b032011-04-22 03:19:48 +000060}
61
62/*===-- Symbols -----------------------------------------------------------===*/
63
Rafael Espindola82a21072013-04-06 03:31:08 +000064const MachOFormat::SymtabLoadCommand *
65MachOObjectFile::getSymtabLoadCommand(LoadCommandInfo LCI) const {
66 StringRef Data = MachOObj->getData(LCI.Offset,
67 sizeof(MachOFormat::SymtabLoadCommand));
68 return reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Data.data());
69}
70
Rafael Espindola68d287d2013-04-06 03:50:05 +000071const MachOFormat::SegmentLoadCommand *
72MachOObjectFile::getSegmentLoadCommand(LoadCommandInfo LCI) const {
73 StringRef Data = MachOObj->getData(LCI.Offset,
74 sizeof(MachOFormat::SegmentLoadCommand));
75 return reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Data.data());
76}
77
78const MachOFormat::Segment64LoadCommand *
79MachOObjectFile::getSegment64LoadCommand(LoadCommandInfo LCI) const {
80 StringRef Data = MachOObj->getData(LCI.Offset,
81 sizeof(MachOFormat::Segment64LoadCommand));
82 return
83 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Data.data());
84}
85
Eric Christopher6256b032011-04-22 03:19:48 +000086void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
87 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
88 while (DRI.d.a < LoadCommandCount) {
89 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
90 if (LCI.Command.Type == macho::LCT_Symtab) {
Rafael Espindola82a21072013-04-06 03:31:08 +000091 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
92 getSymtabLoadCommand(LCI);
Eric Christopher6256b032011-04-22 03:19:48 +000093 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
94 return;
95 }
96
97 DRI.d.a++;
98 DRI.d.b = 0;
99 }
100}
101
Rafael Espindola00555c12013-04-06 01:59:05 +0000102const MachOFormat::SymbolTableEntry *
103MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000104 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000105 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
106 getSymtabLoadCommand(LCI);
Eric Christopher6256b032011-04-22 03:19:48 +0000107
Rafael Espindola82a21072013-04-06 03:31:08 +0000108 return getSymbolTableEntry(DRI, SymtabLoadCmd);
109}
Eric Christopher6256b032011-04-22 03:19:48 +0000110
Rafael Espindola82a21072013-04-06 03:31:08 +0000111const MachOFormat::SymbolTableEntry *
112MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
113 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola00555c12013-04-06 01:59:05 +0000114 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
115 unsigned Index = DRI.d.b;
116 uint64_t Offset = (SymbolTableOffset +
117 Index * sizeof(macho::SymbolTableEntry));
118 StringRef Data = MachOObj->getData(Offset,
119 sizeof(MachOFormat::SymbolTableEntry));
120 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000121}
122
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000123const MachOFormat::Symbol64TableEntry*
124MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000125 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
Rafael Espindola82a21072013-04-06 03:31:08 +0000126 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
127 getSymtabLoadCommand(LCI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000128
Rafael Espindola82a21072013-04-06 03:31:08 +0000129 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
130}
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000131
Rafael Espindola82a21072013-04-06 03:31:08 +0000132const MachOFormat::Symbol64TableEntry*
133MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
134 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000135 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
136 unsigned Index = DRI.d.b;
137 uint64_t Offset = (SymbolTableOffset +
138 Index * sizeof(macho::Symbol64TableEntry));
139 StringRef Data = MachOObj->getData(Offset,
140 sizeof(MachOFormat::Symbol64TableEntry));
141 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000142}
143
Michael J. Spencer25b15772011-06-25 17:55:23 +0000144error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
145 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000146 DRI.d.b++;
147 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000148 Result = SymbolRef(DRI, this);
149 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000150}
151
Michael J. Spencer25b15772011-06-25 17:55:23 +0000152error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
153 StringRef &Result) const {
Rafael Espindola82a21072013-04-06 03:31:08 +0000154 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
155 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
156 getSymtabLoadCommand(LCI);
157
158 StringRef StringTable =
159 MachOObj->getData(SymtabLoadCmd->StringTableOffset,
160 SymtabLoadCmd->StringTableSize);
161
162 uint32_t StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000163 if (MachOObj->is64Bit()) {
Rafael Espindola82a21072013-04-06 03:31:08 +0000164 const MachOFormat::Symbol64TableEntry *Entry =
165 getSymbol64TableEntry(DRI, SymtabLoadCmd);
166 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000167 } else {
Rafael Espindola82a21072013-04-06 03:31:08 +0000168 const MachOFormat::SymbolTableEntry *Entry =
169 getSymbolTableEntry(DRI, SymtabLoadCmd);
170 StringIndex = Entry->StringIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000171 }
Rafael Espindola82a21072013-04-06 03:31:08 +0000172
173 const char *Start = &StringTable.data()[StringIndex];
174 Result = StringRef(Start);
175
Michael J. Spencer25b15772011-06-25 17:55:23 +0000176 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000177}
178
Danil Malyshevb0436a72011-11-29 17:40:10 +0000179error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
180 uint64_t &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000181 if (MachOObj->is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000182 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000183 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000184 if (Entry->SectionIndex) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000185 const MachOFormat::Section64 *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000186 getSection64(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000187 Result += Section->Offset - Section->Address;
188 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000189 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000190 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000191 Result = Entry->Value;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000192 if (Entry->SectionIndex) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000193 const MachOFormat::Section *Section =
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000194 getSection(Sections[Entry->SectionIndex-1]);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000195 Result += Section->Offset - Section->Address;
196 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000197 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000198
Michael J. Spencer25b15772011-06-25 17:55:23 +0000199 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000200}
201
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000202error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
203 uint64_t &Result) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000204 if (MachOObj->is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000205 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000206 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000207 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000208 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Owen Anderson95f8db42011-10-12 22:37:10 +0000209 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000210 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000211 return object_error::success;
212}
213
Michael J. Spencer25b15772011-06-25 17:55:23 +0000214error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
215 uint64_t &Result) const {
Danil Malyshevb0436a72011-11-29 17:40:10 +0000216 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
217 uint64_t BeginOffset;
218 uint64_t EndOffset = 0;
219 uint8_t SectionIndex;
220 if (MachOObj->is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000221 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000222 BeginOffset = Entry->Value;
223 SectionIndex = Entry->SectionIndex;
224 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000225 uint32_t flags = SymbolRef::SF_None;
226 getSymbolFlags(DRI, flags);
227 if (flags & SymbolRef::SF_Common)
228 Result = Entry->Value;
229 else
230 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000231 return object_error::success;
232 }
233 // Unfortunately symbols are unsorted so we need to touch all
234 // symbols from load command
235 DRI.d.b = 0;
236 uint32_t Command = DRI.d.a;
237 while (Command == DRI.d.a) {
238 moveToNextSymbol(DRI);
239 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000240 Entry = getSymbol64TableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000241 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
242 if (!EndOffset || Entry->Value < EndOffset)
243 EndOffset = Entry->Value;
244 }
245 DRI.d.b++;
246 }
247 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000248 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000249 BeginOffset = Entry->Value;
250 SectionIndex = Entry->SectionIndex;
251 if (!SectionIndex) {
Preston Gurdc68dda82012-04-12 20:13:57 +0000252 uint32_t flags = SymbolRef::SF_None;
253 getSymbolFlags(DRI, flags);
254 if (flags & SymbolRef::SF_Common)
255 Result = Entry->Value;
256 else
257 Result = UnknownAddressOrSize;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000258 return object_error::success;
259 }
260 // Unfortunately symbols are unsorted so we need to touch all
261 // symbols from load command
262 DRI.d.b = 0;
263 uint32_t Command = DRI.d.a;
264 while (Command == DRI.d.a) {
265 moveToNextSymbol(DRI);
266 if (DRI.d.a < LoadCommandCount) {
Rafael Espindola00555c12013-04-06 01:59:05 +0000267 Entry = getSymbolTableEntry(DRI);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000268 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
269 if (!EndOffset || Entry->Value < EndOffset)
270 EndOffset = Entry->Value;
271 }
272 DRI.d.b++;
273 }
274 }
275 if (!EndOffset) {
276 uint64_t Size;
277 getSectionSize(Sections[SectionIndex-1], Size);
278 getSectionAddress(Sections[SectionIndex-1], EndOffset);
279 EndOffset += Size;
280 }
281 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000282 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000283}
284
Michael J. Spencer25b15772011-06-25 17:55:23 +0000285error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
286 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000287 uint8_t Type, Flags;
288 if (MachOObj->is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000289 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000290 Type = Entry->Type;
291 Flags = Entry->Flags;
292 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000293 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000294 Type = Entry->Type;
295 Flags = Entry->Flags;
296 }
Eric Christopher6256b032011-04-22 03:19:48 +0000297
298 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000299 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000300 case macho::STT_Undefined:
301 Char = 'u';
302 break;
303 case macho::STT_Absolute:
304 case macho::STT_Section:
305 Char = 's';
306 break;
307 default:
308 Char = '?';
309 break;
310 }
311
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000312 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000313 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000314 Result = Char;
315 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000316}
317
David Meyerc46255a2012-02-28 23:47:53 +0000318error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
319 uint32_t &Result) const {
320 uint16_t MachOFlags;
321 uint8_t MachOType;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000322 if (MachOObj->is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000323 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000324 MachOFlags = Entry->Flags;
325 MachOType = Entry->Type;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000326 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000327 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
David Meyerc46255a2012-02-28 23:47:53 +0000328 MachOFlags = Entry->Flags;
329 MachOType = Entry->Type;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000330 }
331
Preston Gurdc68dda82012-04-12 20:13:57 +0000332 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000333 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000334
335 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
336 Result |= SymbolRef::SF_Undefined;
337
David Meyerc46255a2012-02-28 23:47:53 +0000338 if (MachOFlags & macho::STF_StabsEntryMask)
339 Result |= SymbolRef::SF_FormatSpecific;
340
Preston Gurdc68dda82012-04-12 20:13:57 +0000341 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000342 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000343 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
344 Result |= SymbolRef::SF_Common;
345 }
David Meyerc46255a2012-02-28 23:47:53 +0000346
347 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
348 Result |= SymbolRef::SF_Weak;
349
350 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
351 Result |= SymbolRef::SF_Absolute;
352
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000353 return object_error::success;
354}
355
356error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
357 section_iterator &Res) const {
358 uint8_t index;
359 if (MachOObj->is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000360 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000361 index = Entry->SectionIndex;
362 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000363 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000364 index = Entry->SectionIndex;
365 }
366
367 if (index == 0)
368 Res = end_sections();
369 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000370 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000371
372 return object_error::success;
373}
374
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000375error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000376 SymbolRef::Type &Res) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000377 uint8_t n_type;
378 if (MachOObj->is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000379 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000380 n_type = Entry->Type;
381 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000382 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000383 n_type = Entry->Type;
384 }
385 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000386
387 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000388 if (n_type & MachO::NlistMaskStab) {
389 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000390 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000391 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000392
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000393 switch (n_type & MachO::NlistMaskType) {
394 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000395 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000396 break;
397 case MachO::NListTypeSection :
398 Res = SymbolRef::ST_Function;
399 break;
400 }
401 return object_error::success;
402}
403
Tim Northovera41dce32012-10-29 10:47:00 +0000404error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
405 uint64_t &Val) const {
406 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
407}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000408
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000409symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000410 // DRI.d.a = segment number; DRI.d.b = symbol index.
411 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000412 moveToNextSymbol(DRI);
413 return symbol_iterator(SymbolRef(DRI, this));
414}
415
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000416symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000417 DataRefImpl DRI;
418 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000419 return symbol_iterator(SymbolRef(DRI, this));
420}
421
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000422symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
423 // TODO: implement
424 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
425}
426
427symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
428 // TODO: implement
429 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
430}
Eric Christopher6256b032011-04-22 03:19:48 +0000431
David Meyer5c2b4ea2012-03-01 01:36:50 +0000432library_iterator MachOObjectFile::begin_libraries_needed() const {
433 // TODO: implement
434 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
435}
436
437library_iterator MachOObjectFile::end_libraries_needed() const {
438 // TODO: implement
439 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
440}
441
David Meyer97f77872012-03-01 22:19:54 +0000442StringRef MachOObjectFile::getLoadName() const {
443 // TODO: Implement
444 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
445}
446
Eric Christopher6256b032011-04-22 03:19:48 +0000447/*===-- Sections ----------------------------------------------------------===*/
448
449void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
450 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
451 while (DRI.d.a < LoadCommandCount) {
452 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
453 if (LCI.Command.Type == macho::LCT_Segment) {
Rafael Espindola68d287d2013-04-06 03:50:05 +0000454 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
455 getSegmentLoadCommand(LCI);
Eric Christopher6256b032011-04-22 03:19:48 +0000456 if (DRI.d.b < SegmentLoadCmd->NumSections)
457 return;
458 } else if (LCI.Command.Type == macho::LCT_Segment64) {
Rafael Espindola68d287d2013-04-06 03:50:05 +0000459 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
460 getSegment64LoadCommand(LCI);
Eric Christopher6256b032011-04-22 03:19:48 +0000461 if (DRI.d.b < Segment64LoadCmd->NumSections)
462 return;
463 }
464
465 DRI.d.a++;
466 DRI.d.b = 0;
467 }
468}
469
Michael J. Spencer25b15772011-06-25 17:55:23 +0000470error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
471 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000472 DRI.d.b++;
473 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000474 Result = SectionRef(DRI, this);
475 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000476}
477
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000478static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
Eric Christopher6256b032011-04-22 03:19:48 +0000479 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000480 if (LCI.Command.Type == macho::LCT_Segment64)
481 return true;
482 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
483 return false;
484}
485
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000486const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000487 assert(!is64BitLoadCommand(MachOObj.get(), DRI));
488 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
489 unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000490 DRI.d.b * sizeof(MachOFormat::Section);
491 StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section));
492 return reinterpret_cast<const MachOFormat::Section*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000493}
494
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000495std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
496 SectionList::const_iterator loc =
497 std::find(Sections.begin(), Sections.end(), Sec);
498 assert(loc != Sections.end() && "Sec is not a valid section!");
499 return std::distance(Sections.begin(), loc);
500}
501
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000502const MachOFormat::Section64 *
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000503MachOObjectFile::getSection64(DataRefImpl DRI) const {
504 assert(is64BitLoadCommand(MachOObj.get(), DRI));
Benjamin Kramer7d145782011-07-15 00:14:48 +0000505 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000506 unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) +
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000507 DRI.d.b * sizeof(MachOFormat::Section64);
508 StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section64));
509 return reinterpret_cast<const MachOFormat::Section64*>(Data.data());
Benjamin Kramer7d145782011-07-15 00:14:48 +0000510}
511
Rafael Espindolacef81b32012-12-21 03:47:03 +0000512static StringRef parseSegmentOrSectionName(const char *P) {
513 if (P[15] == 0)
514 // Null terminated.
515 return P;
516 // Not null terminated, so this is a 16 char string.
517 return StringRef(P, 16);
518}
519
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000520ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
Jim Grosbach596e4742012-11-29 19:14:11 +0000521 if (is64BitLoadCommand(MachOObj.get(), DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000522 const MachOFormat::Section64 *sec = getSection64(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000523 return ArrayRef<char>(sec->Name);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000524 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000525 const MachOFormat::Section *sec = getSection(DRI);
Rafael Espindolac1cd6aa2013-04-05 18:18:19 +0000526 return ArrayRef<char>(sec->Name);
Rafael Espindolaf9a6bd82012-12-19 14:15:04 +0000527 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000528}
529
530error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
531 StringRef &Result) const {
532 ArrayRef<char> Raw = getSectionRawName(DRI);
533 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000534 return object_error::success;
535}
536
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000537ArrayRef<char>
538MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindolacef81b32012-12-21 03:47:03 +0000539 if (is64BitLoadCommand(MachOObj.get(), Sec)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000540 const MachOFormat::Section64 *sec = getSection64(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000541 return ArrayRef<char>(sec->SegmentName, 16);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000542 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000543 const MachOFormat::Section *sec = getSection(Sec);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000544 return ArrayRef<char>(sec->SegmentName);
Rafael Espindolacef81b32012-12-21 03:47:03 +0000545 }
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000546}
547
548StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
549 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
550 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000551}
552
Michael J. Spencer25b15772011-06-25 17:55:23 +0000553error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
554 uint64_t &Result) const {
Jim Grosbach596e4742012-11-29 19:14:11 +0000555 if (is64BitLoadCommand(MachOObj.get(), DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000556 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000557 Result = Sect->Address;
558 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000559 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000560 Result = Sect->Address;
561 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000562 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000563}
564
Michael J. Spencer25b15772011-06-25 17:55:23 +0000565error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
566 uint64_t &Result) const {
Jim Grosbach596e4742012-11-29 19:14:11 +0000567 if (is64BitLoadCommand(MachOObj.get(), DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000568 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000569 Result = Sect->Size;
570 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000571 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000572 Result = Sect->Size;
573 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000574 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000575}
576
Michael J. Spencer25b15772011-06-25 17:55:23 +0000577error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
578 StringRef &Result) const {
Jim Grosbach596e4742012-11-29 19:14:11 +0000579 if (is64BitLoadCommand(MachOObj.get(), DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000580 const MachOFormat::Section64 *Sect = getSection64(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000581 Result = MachOObj->getData(Sect->Offset, Sect->Size);
582 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000583 const MachOFormat::Section *Sect = getSection(DRI);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000584 Result = MachOObj->getData(Sect->Offset, Sect->Size);
585 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000586 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000587}
588
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000589error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
590 uint64_t &Result) const {
Jim Grosbach596e4742012-11-29 19:14:11 +0000591 if (is64BitLoadCommand(MachOObj.get(), DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000592 const MachOFormat::Section64 *Sect = getSection64(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000593 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000594 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000595 const MachOFormat::Section *Sect = getSection(DRI);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000596 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000597 }
598 return object_error::success;
599}
600
Michael J. Spencer25b15772011-06-25 17:55:23 +0000601error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
602 bool &Result) const {
Jim Grosbach596e4742012-11-29 19:14:11 +0000603 if (is64BitLoadCommand(MachOObj.get(), DRI)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000604 const MachOFormat::Section64 *Sect = getSection64(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000605 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000606 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000607 const MachOFormat::Section *Sect = getSection(DRI);
Tim Northover1c2b2f92012-12-17 17:59:32 +0000608 Result = Sect->Flags & macho::SF_PureInstructions;
Benjamin Kramer7d145782011-07-15 00:14:48 +0000609 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000610 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000611}
612
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000613error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
614 bool &Result) const {
615 // FIXME: Unimplemented.
616 Result = false;
617 return object_error::success;
618}
619
620error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
621 bool &Result) const {
622 // FIXME: Unimplemented.
623 Result = false;
624 return object_error::success;
625}
626
Preston Gurdc68dda82012-04-12 20:13:57 +0000627error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
628 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000629 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000630 Result = true;
631 return object_error::success;
632}
633
634error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000635 bool &Result) const {
636 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000637 Result = false;
638 return object_error::success;
639}
640
641error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
642 bool &Result) const {
643 if (MachOObj->is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000644 const MachOFormat::Section64 *Sect = getSection64(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000645 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
646 Result = (SectionType == MachO::SectionTypeZeroFill ||
647 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000648 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000649 const MachOFormat::Section *Sect = getSection(DRI);
Eli Friedman41827f92012-05-02 02:31:28 +0000650 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
651 Result = (SectionType == MachO::SectionTypeZeroFill ||
652 SectionType == MachO::SectionTypeZeroFillLarge);
Preston Gurdc68dda82012-04-12 20:13:57 +0000653 }
654
655 return object_error::success;
656}
657
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000658error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
659 bool &Result) const {
660 // Consider using the code from isSectionText to look for __const sections.
661 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
662 // to use section attributes to distinguish code from data.
663
664 // FIXME: Unimplemented.
665 Result = false;
666 return object_error::success;
667}
668
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000669error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
670 DataRefImpl Symb,
671 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000672 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000673 getSymbolType(Symb, ST);
David Meyer2c677272012-02-29 02:11:55 +0000674 if (ST == SymbolRef::ST_Unknown) {
Owen Andersoncd749882011-10-12 22:21:32 +0000675 Result = false;
676 return object_error::success;
677 }
678
679 uint64_t SectBegin, SectEnd;
680 getSectionAddress(Sec, SectBegin);
681 getSectionSize(Sec, SectEnd);
682 SectEnd += SectBegin;
683
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000684 if (MachOObj->is64Bit()) {
Rafael Espindola05b5bdd2013-04-06 02:15:44 +0000685 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000686 uint64_t SymAddr= Entry->Value;
687 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000688 } else {
Rafael Espindola00555c12013-04-06 01:59:05 +0000689 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
Owen Andersoncd749882011-10-12 22:21:32 +0000690 uint64_t SymAddr= Entry->Value;
691 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000692 }
Owen Andersoncd749882011-10-12 22:21:32 +0000693
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000694 return object_error::success;
695}
696
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000697relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
698 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000699 ret.d.b = getSectionIndex(Sec);
700 return relocation_iterator(RelocationRef(ret, this));
701}
702relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
703 uint32_t last_reloc;
Jim Grosbach596e4742012-11-29 19:14:11 +0000704 if (is64BitLoadCommand(MachOObj.get(), Sec)) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000705 const MachOFormat::Section64 *Sect = getSection64(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000706 last_reloc = Sect->NumRelocationTableEntries;
707 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000708 const MachOFormat::Section *Sect = getSection(Sec);
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000709 last_reloc = Sect->NumRelocationTableEntries;
710 }
711 DataRefImpl ret;
712 ret.d.a = last_reloc;
713 ret.d.b = getSectionIndex(Sec);
714 return relocation_iterator(RelocationRef(ret, this));
715}
716
717section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000718 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000719 moveToNextSection(DRI);
720 return section_iterator(SectionRef(DRI, this));
721}
722
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000723section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000724 DataRefImpl DRI;
725 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000726 return section_iterator(SectionRef(DRI, this));
727}
728
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000729/*===-- Relocations -------------------------------------------------------===*/
730
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000731const MachOFormat::RelocationEntry *
732MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000733 uint32_t relOffset;
734 if (MachOObj->is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000735 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000736 relOffset = Sect->RelocationTableOffset;
737 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000738 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000739 relOffset = Sect->RelocationTableOffset;
740 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000741 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
742 StringRef Data =
743 MachOObj->getData(Offset, sizeof(MachOFormat::RelocationEntry));
744 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000745}
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000746
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000747error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
748 RelocationRef &Res) const {
749 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000750 Res = RelocationRef(Rel, this);
751 return object_error::success;
752}
753error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
754 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000755 const uint8_t* sectAddress = 0;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000756 if (MachOObj->is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000757 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000758 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000759 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000760 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Owen Anderson0135fe12011-10-24 21:44:00 +0000761 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000762 }
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000763 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000764
765 unsigned Arch = getArch();
766 bool isScattered = (Arch != Triple::x86_64) &&
767 (RE->Word0 & macho::RF_Scattered);
768 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000769 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000770 RelAddr = RE->Word0 & 0xFFFFFF;
771 else
772 RelAddr = RE->Word0;
773
774 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000775 return object_error::success;
776}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000777error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
778 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000779 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Danil Malyshevb0436a72011-11-29 17:40:10 +0000780
781 unsigned Arch = getArch();
782 bool isScattered = (Arch != Triple::x86_64) &&
783 (RE->Word0 & macho::RF_Scattered);
784 if (isScattered)
785 Res = RE->Word0 & 0xFFFFFF;
786 else
787 Res = RE->Word0;
788 return object_error::success;
789}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000790error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
791 SymbolRef &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000792 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000793 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
794 bool isExtern = (RE->Word1 >> 27) & 1;
795
796 DataRefImpl Sym;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000797 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000798 if (isExtern) {
799 for (unsigned i = 0; i < SymbolIdx; i++) {
800 Sym.d.b++;
801 moveToNextSymbol(Sym);
Nick Lewycky58856ea2011-09-09 00:16:50 +0000802 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000803 "Relocation symbol index out of range!");
804 }
805 }
806 Res = SymbolRef(Sym, this);
807 return object_error::success;
808}
809error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000810 uint64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000811 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Andersonf8261e72011-10-26 17:10:22 +0000812 Res = RE->Word0;
813 Res <<= 32;
814 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000815 return object_error::success;
816}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000817error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
818 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000819 // TODO: Support scattered relocations.
820 StringRef res;
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000821 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +0000822
823 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000824 bool isScattered = (Arch != Triple::x86_64) &&
825 (RE->Word0 & macho::RF_Scattered);
826
827 unsigned r_type;
828 if (isScattered)
829 r_type = (RE->Word0 >> 24) & 0xF;
830 else
831 r_type = (RE->Word1 >> 28) & 0xF;
832
Owen Anderson0135fe12011-10-24 21:44:00 +0000833 switch (Arch) {
834 case Triple::x86: {
Craig Toppere3298102012-05-24 06:35:32 +0000835 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000836 "GENERIC_RELOC_VANILLA",
837 "GENERIC_RELOC_PAIR",
838 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000839 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000840 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000841 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000842
Owen Andersoneb6bd332011-10-27 20:46:09 +0000843 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000844 res = "Unknown";
845 else
846 res = Table[r_type];
847 break;
848 }
849 case Triple::x86_64: {
Craig Toppere3298102012-05-24 06:35:32 +0000850 static const char *const Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000851 "X86_64_RELOC_UNSIGNED",
852 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000853 "X86_64_RELOC_BRANCH",
854 "X86_64_RELOC_GOT_LOAD",
855 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000856 "X86_64_RELOC_SUBTRACTOR",
857 "X86_64_RELOC_SIGNED_1",
858 "X86_64_RELOC_SIGNED_2",
859 "X86_64_RELOC_SIGNED_4",
860 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000861
Owen Andersond8fa76d2011-10-24 23:20:07 +0000862 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000863 res = "Unknown";
864 else
865 res = Table[r_type];
866 break;
867 }
868 case Triple::arm: {
Craig Toppere3298102012-05-24 06:35:32 +0000869 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000870 "ARM_RELOC_VANILLA",
871 "ARM_RELOC_PAIR",
872 "ARM_RELOC_SECTDIFF",
873 "ARM_RELOC_LOCAL_SECTDIFF",
874 "ARM_RELOC_PB_LA_PTR",
875 "ARM_RELOC_BR24",
876 "ARM_THUMB_RELOC_BR22",
877 "ARM_THUMB_32BIT_BRANCH",
878 "ARM_RELOC_HALF",
879 "ARM_RELOC_HALF_SECTDIFF" };
880
881 if (r_type > 9)
882 res = "Unknown";
883 else
884 res = Table[r_type];
885 break;
886 }
887 case Triple::ppc: {
Craig Toppere3298102012-05-24 06:35:32 +0000888 static const char *const Table[] = {
Owen Anderson0135fe12011-10-24 21:44:00 +0000889 "PPC_RELOC_VANILLA",
890 "PPC_RELOC_PAIR",
891 "PPC_RELOC_BR14",
892 "PPC_RELOC_BR24",
893 "PPC_RELOC_HI16",
894 "PPC_RELOC_LO16",
895 "PPC_RELOC_HA16",
896 "PPC_RELOC_LO14",
897 "PPC_RELOC_SECTDIFF",
898 "PPC_RELOC_PB_LA_PTR",
899 "PPC_RELOC_HI16_SECTDIFF",
900 "PPC_RELOC_LO16_SECTDIFF",
901 "PPC_RELOC_HA16_SECTDIFF",
902 "PPC_RELOC_JBSR",
903 "PPC_RELOC_LO14_SECTDIFF",
904 "PPC_RELOC_LOCAL_SECTDIFF" };
905
906 res = Table[r_type];
907 break;
908 }
909 case Triple::UnknownArch:
910 res = "Unknown";
911 break;
912 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000913 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000914 return object_error::success;
915}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000916error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
917 int64_t &Res) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000918 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000919 bool isExtern = (RE->Word1 >> 27) & 1;
920 Res = 0;
921 if (!isExtern) {
922 const uint8_t* sectAddress = base();
923 if (MachOObj->is64Bit()) {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000924 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000925 sectAddress += Sect->Offset;
926 } else {
Rafael Espindola0e5dc8a2013-04-05 18:45:28 +0000927 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000928 sectAddress += Sect->Offset;
929 }
930 Res = reinterpret_cast<uintptr_t>(sectAddress);
931 }
932 return object_error::success;
933}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000934
935// Helper to advance a section or symbol iterator multiple increments at a time.
936template<class T>
937error_code advance(T &it, size_t Val) {
938 error_code ec;
939 while (Val--) {
940 it.increment(ec);
941 }
942 return ec;
943}
944
945template<class T>
946void advanceTo(T &it, size_t Val) {
947 if (error_code ec = advance(it, Val))
948 report_fatal_error(ec.message());
949}
950
Owen Anderson1832f4d2011-10-26 20:42:54 +0000951void MachOObjectFile::printRelocationTargetName(
Rafael Espindola5cf0f512013-04-06 01:24:11 +0000952 const MachOFormat::RelocationEntry *RE,
Owen Anderson1832f4d2011-10-26 20:42:54 +0000953 raw_string_ostream &fmt) const {
954 unsigned Arch = getArch();
955 bool isScattered = (Arch != Triple::x86_64) &&
956 (RE->Word0 & macho::RF_Scattered);
957
958 // Target of a scattered relocation is an address. In the interest of
959 // generating pretty output, scan through the symbol table looking for a
960 // symbol that aligns with that address. If we find one, print it.
961 // Otherwise, we just print the hex address of the target.
962 if (isScattered) {
963 uint32_t Val = RE->Word1;
964
965 error_code ec;
966 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
967 SI.increment(ec)) {
968 if (ec) report_fatal_error(ec.message());
969
970 uint64_t Addr;
971 StringRef Name;
972
973 if ((ec = SI->getAddress(Addr)))
974 report_fatal_error(ec.message());
975 if (Addr != Val) continue;
976 if ((ec = SI->getName(Name)))
977 report_fatal_error(ec.message());
978 fmt << Name;
979 return;
980 }
981
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000982 // If we couldn't find a symbol that this relocation refers to, try
983 // to find a section beginning instead.
984 for (section_iterator SI = begin_sections(), SE = end_sections(); 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 Anderson1832f4d2011-10-26 20:42:54 +00001000 fmt << format("0x%x", Val);
1001 return;
1002 }
1003
1004 StringRef S;
1005 bool isExtern = (RE->Word1 >> 27) & 1;
1006 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001007
1008 if (isExtern) {
1009 symbol_iterator SI = begin_symbols();
1010 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001011 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001012 } else {
1013 section_iterator SI = begin_sections();
1014 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +00001015 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001016 }
1017
Owen Anderson1832f4d2011-10-26 20:42:54 +00001018 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001019}
1020
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001021error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1022 SmallVectorImpl<char> &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001023 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0135fe12011-10-24 21:44:00 +00001024
Owen Anderson1832f4d2011-10-26 20:42:54 +00001025 unsigned Arch = getArch();
1026 bool isScattered = (Arch != Triple::x86_64) &&
1027 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001028
Owen Anderson013d7562011-10-25 18:48:41 +00001029 std::string fmtbuf;
1030 raw_string_ostream fmt(fmtbuf);
1031
Owen Anderson1832f4d2011-10-26 20:42:54 +00001032 unsigned Type;
1033 if (isScattered)
1034 Type = (RE->Word0 >> 24) & 0xF;
1035 else
1036 Type = (RE->Word1 >> 28) & 0xF;
1037
Owen Andersoneb6bd332011-10-27 20:46:09 +00001038 bool isPCRel;
1039 if (isScattered)
1040 isPCRel = ((RE->Word0 >> 30) & 1);
1041 else
1042 isPCRel = ((RE->Word1 >> 24) & 1);
1043
Owen Andersond8fa76d2011-10-24 23:20:07 +00001044 // Determine any addends that should be displayed with the relocation.
1045 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +00001046
1047 // X86_64 has entirely custom relocation types.
1048 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +00001049 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +00001050
Owen Andersond8fa76d2011-10-24 23:20:07 +00001051 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001052 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1053 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1054 printRelocationTargetName(RE, fmt);
1055 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +00001056 if (isPCRel) fmt << "PCREL";
1057 break;
1058 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001059 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +00001060 DataRefImpl RelNext = Rel;
1061 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001062 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001063
1064 // X86_64_SUBTRACTOR must be followed by a relocation of type
1065 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001066 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +00001067 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001068 if (RType != 0)
1069 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1070 "X86_64_RELOC_SUBTRACTOR.");
1071
Owen Andersonef22f782011-10-26 17:28:49 +00001072 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1073 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001074 printRelocationTargetName(RENext, fmt);
1075 fmt << "-";
1076 printRelocationTargetName(RE, fmt);
Jim Grosbach133f6b82013-01-31 19:46:57 +00001077 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001078 }
Owen Andersoneb6bd332011-10-27 20:46:09 +00001079 case macho::RIT_X86_64_TLV:
1080 printRelocationTargetName(RE, fmt);
1081 fmt << "@TLV";
1082 if (isPCRel) fmt << "P";
1083 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001084 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1085 printRelocationTargetName(RE, fmt);
1086 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001087 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001088 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1089 printRelocationTargetName(RE, fmt);
1090 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +00001091 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +00001092 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1093 printRelocationTargetName(RE, fmt);
1094 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +00001095 break;
1096 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001097 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001098 break;
1099 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001100 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001101 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1102 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001103 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001104 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001105 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001106 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001107 DataRefImpl RelNext = Rel;
1108 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001109 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001110
1111 // X86 sect diff's must be followed by a relocation of type
1112 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001113 bool isNextScattered = (Arch != Triple::x86_64) &&
1114 (RENext->Word0 & macho::RF_Scattered);
1115 unsigned RType;
1116 if (isNextScattered)
1117 RType = (RENext->Word0 >> 24) & 0xF;
1118 else
1119 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001120 if (RType != 1)
1121 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001122 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001123
Owen Anderson1832f4d2011-10-26 20:42:54 +00001124 printRelocationTargetName(RE, fmt);
1125 fmt << "-";
1126 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001127 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001128 }
1129 }
Owen Anderson013d7562011-10-25 18:48:41 +00001130
Owen Anderson1832f4d2011-10-26 20:42:54 +00001131 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001132 // All X86 relocations that need special printing were already
1133 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001134 switch (Type) {
1135 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
Owen Andersoneb6bd332011-10-27 20:46:09 +00001136 DataRefImpl RelNext = Rel;
1137 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001138 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Andersoneb6bd332011-10-27 20:46:09 +00001139
1140 // X86 sect diff's must be followed by a relocation of type
1141 // GENERIC_RELOC_PAIR.
1142 bool isNextScattered = (Arch != Triple::x86_64) &&
1143 (RENext->Word0 & macho::RF_Scattered);
1144 unsigned RType;
1145 if (isNextScattered)
1146 RType = (RENext->Word0 >> 24) & 0xF;
1147 else
1148 RType = (RENext->Word1 >> 28) & 0xF;
1149 if (RType != 1)
1150 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1151 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1152
1153 printRelocationTargetName(RE, fmt);
1154 fmt << "-";
1155 printRelocationTargetName(RENext, fmt);
1156 break;
1157 }
1158 case macho::RIT_Generic_TLV: {
1159 printRelocationTargetName(RE, fmt);
1160 fmt << "@TLV";
1161 if (isPCRel) fmt << "P";
1162 break;
1163 }
1164 default:
1165 printRelocationTargetName(RE, fmt);
1166 }
Owen Anderson013d7562011-10-25 18:48:41 +00001167 } else { // ARM-specific relocations
1168 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001169 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1170 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001171 // Half relocations steal a bit from the length field to encode
1172 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001173 bool isUpper;
1174 if (isScattered)
1175 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001176 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001177 isUpper = (RE->Word1 >> 25) & 1;
1178
1179 if (isUpper)
1180 fmt << ":upper16:(";
1181 else
1182 fmt << ":lower16:(";
1183 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001184
Owen Anderson013d7562011-10-25 18:48:41 +00001185 DataRefImpl RelNext = Rel;
1186 RelNext.d.a++;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001187 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
Owen Anderson013d7562011-10-25 18:48:41 +00001188
1189 // ARM half relocs must be followed by a relocation of type
1190 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001191 bool isNextScattered = (Arch != Triple::x86_64) &&
1192 (RENext->Word0 & macho::RF_Scattered);
1193 unsigned RType;
1194 if (isNextScattered)
1195 RType = (RENext->Word0 >> 24) & 0xF;
1196 else
1197 RType = (RENext->Word1 >> 28) & 0xF;
1198
Owen Anderson013d7562011-10-25 18:48:41 +00001199 if (RType != 1)
1200 report_fatal_error("Expected ARM_RELOC_PAIR after "
1201 "GENERIC_RELOC_HALF");
1202
Owen Anderson1832f4d2011-10-26 20:42:54 +00001203 // NOTE: The half of the target virtual address is stashed in the
1204 // address field of the secondary relocation, but we can't reverse
1205 // engineer the constant offset from it without decoding the movw/movt
1206 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001207
1208 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1209 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001210 if (Type == macho::RIT_ARM_HalfDifference) {
1211 fmt << "-";
1212 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001213 }
1214
Owen Anderson013d7562011-10-25 18:48:41 +00001215 fmt << ")";
1216 break;
1217 }
1218 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001219 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001220 }
1221 }
1222 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001223 } else
1224 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001225
Owen Anderson0135fe12011-10-24 21:44:00 +00001226 fmt.flush();
1227 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001228 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001229}
1230
Owen Anderson0685e942011-10-25 20:35:53 +00001231error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1232 bool &Result) const {
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001233 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
Owen Anderson0685e942011-10-25 20:35:53 +00001234
Owen Anderson0685e942011-10-25 20:35:53 +00001235 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001236 bool isScattered = (Arch != Triple::x86_64) &&
1237 (RE->Word0 & macho::RF_Scattered);
1238 unsigned Type;
1239 if (isScattered)
1240 Type = (RE->Word0 >> 24) & 0xF;
1241 else
1242 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001243
1244 Result = false;
1245
1246 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1247 // is always hidden.
1248 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001249 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001250 } else if (Arch == Triple::x86_64) {
1251 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1252 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001253 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001254 DataRefImpl RelPrev = Rel;
1255 RelPrev.d.a--;
Rafael Espindola5cf0f512013-04-06 01:24:11 +00001256 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
Owen Anderson0685e942011-10-25 20:35:53 +00001257
1258 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1259
Owen Anderson1832f4d2011-10-26 20:42:54 +00001260 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001261 }
1262 }
1263
1264 return object_error::success;
1265}
1266
David Meyer5c2b4ea2012-03-01 01:36:50 +00001267error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1268 LibraryRef &Res) const {
1269 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1270}
1271
1272error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1273 StringRef &Res) const {
1274 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1275}
1276
1277
Eric Christopher6256b032011-04-22 03:19:48 +00001278/*===-- Miscellaneous -----------------------------------------------------===*/
1279
1280uint8_t MachOObjectFile::getBytesInAddress() const {
1281 return MachOObj->is64Bit() ? 8 : 4;
1282}
1283
1284StringRef MachOObjectFile::getFileFormatName() const {
1285 if (!MachOObj->is64Bit()) {
1286 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001287 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001288 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001289 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001290 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001291 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001292 return "Mach-O 32-bit ppc";
1293 default:
Eric Christopherf4b2f932011-04-22 06:34:01 +00001294 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001295 "64-bit object file when we're not 64-bit?");
1296 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001297 }
1298 }
1299
Eric Christopherb3e6b042013-02-28 20:26:17 +00001300 // Make sure the cpu type has the correct mask.
1301 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64)
1302 == llvm::MachO::CPUArchABI64 &&
1303 "32-bit object file when we're 64-bit?");
1304
Eric Christopher6256b032011-04-22 03:19:48 +00001305 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001306 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001307 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001308 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001309 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001310 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001311 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001312 }
1313}
1314
1315unsigned MachOObjectFile::getArch() const {
1316 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001317 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001318 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001319 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001320 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001321 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001322 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001323 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001324 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001325 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001326 return Triple::ppc64;
1327 default:
1328 return Triple::UnknownArch;
1329 }
1330}
1331
Owen Andersonf7c93a32011-10-11 17:32:27 +00001332} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001333} // end namespace llvm