blob: bb4f6a275b0f7ed90107f0377e9b502438f6b93c [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
15#include "llvm/ADT/Triple.h"
Owen Andersonf7c93a32011-10-11 17:32:27 +000016#include "llvm/Object/MachO.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"
20
21#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
Benjamin Kramer0fcab072011-09-08 20:52:17 +000031MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
32 error_code &ec)
33 : ObjectFile(Binary::isMachO, Object, ec),
34 MachOObj(MOO),
35 RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
36 DataRefImpl DRI;
37 DRI.d.a = DRI.d.b = 0;
38 moveToNextSection(DRI);
39 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
40 while (DRI.d.a < LoadCommandCount) {
41 Sections.push_back(DRI);
Benjamin Kramer0fcab072011-09-08 20:52:17 +000042 DRI.d.b++;
43 moveToNextSection(DRI);
44 }
45}
46
47
Eric Christopher6256b032011-04-22 03:19:48 +000048ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Michael J. Spencer001c9202011-06-25 17:54:50 +000049 error_code ec;
Eric Christopher6256b032011-04-22 03:19:48 +000050 std::string Err;
51 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
52 if (!MachOObj)
53 return NULL;
Michael J. Spencer001c9202011-06-25 17:54:50 +000054 return new MachOObjectFile(Buffer, MachOObj, ec);
Eric Christopher6256b032011-04-22 03:19:48 +000055}
56
57/*===-- Symbols -----------------------------------------------------------===*/
58
59void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
60 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
61 while (DRI.d.a < LoadCommandCount) {
62 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
63 if (LCI.Command.Type == macho::LCT_Symtab) {
64 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
65 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
66 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
67 return;
68 }
69
70 DRI.d.a++;
71 DRI.d.b = 0;
72 }
73}
74
75void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
76 InMemoryStruct<macho::SymbolTableEntry> &Res) const {
77 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
78 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
79 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
80
81 if (RegisteredStringTable != DRI.d.a) {
82 MachOObj->RegisterStringTable(*SymtabLoadCmd);
83 RegisteredStringTable = DRI.d.a;
84 }
85
86 MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
87 Res);
88}
89
Benjamin Kramer32fb2af2011-07-15 17:32:45 +000090void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
91 InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
92 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
93 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
94 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
95
96 if (RegisteredStringTable != DRI.d.a) {
97 MachOObj->RegisterStringTable(*SymtabLoadCmd);
98 RegisteredStringTable = DRI.d.a;
99 }
100
101 MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
102 Res);
103}
104
Eric Christopher6256b032011-04-22 03:19:48 +0000105
Michael J. Spencer25b15772011-06-25 17:55:23 +0000106error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
107 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000108 DRI.d.b++;
109 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000110 Result = SymbolRef(DRI, this);
111 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000112}
113
Michael J. Spencer25b15772011-06-25 17:55:23 +0000114error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
115 StringRef &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000116 if (MachOObj->is64Bit()) {
117 InMemoryStruct<macho::Symbol64TableEntry> Entry;
118 getSymbol64TableEntry(DRI, Entry);
119 Result = MachOObj->getStringAtIndex(Entry->StringIndex);
120 } else {
121 InMemoryStruct<macho::SymbolTableEntry> Entry;
122 getSymbolTableEntry(DRI, Entry);
123 Result = MachOObj->getStringAtIndex(Entry->StringIndex);
124 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000125 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000126}
127
Danil Malyshev9b247382011-11-27 10:12:52 +0000128error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
129 uint64_t &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000130 if (MachOObj->is64Bit()) {
131 InMemoryStruct<macho::Symbol64TableEntry> Entry;
132 getSymbol64TableEntry(DRI, Entry);
133 Result = Entry->Value;
Danil Malyshev9b247382011-11-27 10:12:52 +0000134 if (Entry->SectionIndex) {
135 InMemoryStruct<macho::Section64> Section;
136 getSection64(Sections[Entry->SectionIndex-1], Section);
137 Result += Section->Offset - Section->Address;
138 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000139 } else {
140 InMemoryStruct<macho::SymbolTableEntry> Entry;
141 getSymbolTableEntry(DRI, Entry);
142 Result = Entry->Value;
Danil Malyshev9b247382011-11-27 10:12:52 +0000143 if (Entry->SectionIndex) {
144 InMemoryStruct<macho::Section> Section;
145 getSection(Sections[Entry->SectionIndex-1], Section);
146 Result += Section->Offset - Section->Address;
147 }
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000148 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000149
Michael J. Spencer25b15772011-06-25 17:55:23 +0000150 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000151}
152
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000153error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
154 uint64_t &Result) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000155 if (MachOObj->is64Bit()) {
156 InMemoryStruct<macho::Symbol64TableEntry> Entry;
157 getSymbol64TableEntry(DRI, Entry);
Owen Anderson95f8db42011-10-12 22:37:10 +0000158 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000159 } else {
160 InMemoryStruct<macho::SymbolTableEntry> Entry;
161 getSymbolTableEntry(DRI, Entry);
Owen Anderson95f8db42011-10-12 22:37:10 +0000162 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000163 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000164 return object_error::success;
165}
166
Michael J. Spencer25b15772011-06-25 17:55:23 +0000167error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
168 uint64_t &Result) const {
Danil Malyshev9b247382011-11-27 10:12:52 +0000169 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
170 uint64_t BeginOffset;
171 uint64_t EndOffset = 0;
172 uint8_t SectionIndex;
173 if (MachOObj->is64Bit()) {
174 InMemoryStruct<macho::Symbol64TableEntry> Entry;
175 getSymbol64TableEntry(DRI, Entry);
176 BeginOffset = Entry->Value;
177 SectionIndex = Entry->SectionIndex;
178 if (!SectionIndex) {
179 Result = UnknownAddressOrSize;
180 return object_error::success;
181 }
182 DRI.d.b++;
183 moveToNextSymbol(DRI);
184 if (DRI.d.a < LoadCommandCount) {
185 getSymbol64TableEntry(DRI, Entry);
186 if (Entry->SectionIndex == SectionIndex)
187 EndOffset += Entry->Value;
188 }
189 } else {
190 InMemoryStruct<macho::SymbolTableEntry> Entry;
191 getSymbolTableEntry(DRI, Entry);
192 BeginOffset = Entry->Value;
193 SectionIndex = Entry->SectionIndex;
194 if (!SectionIndex) {
195 Result = UnknownAddressOrSize;
196 return object_error::success;
197 }
198 DRI.d.b++;
199 moveToNextSymbol(DRI);
200 if (DRI.d.a < LoadCommandCount) {
201 getSymbolTableEntry(DRI, Entry);
202 if (Entry->SectionIndex == SectionIndex)
203 EndOffset += Entry->Value;
204 }
205 }
206 if (!EndOffset) {
207 uint64_t Size;
208 getSectionSize(Sections[SectionIndex-1], Size);
209 getSectionAddress(Sections[SectionIndex-1], EndOffset);
210 EndOffset += Size;
211 }
212 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000213 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000214}
215
Michael J. Spencer25b15772011-06-25 17:55:23 +0000216error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
217 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000218 uint8_t Type, Flags;
219 if (MachOObj->is64Bit()) {
220 InMemoryStruct<macho::Symbol64TableEntry> Entry;
221 getSymbol64TableEntry(DRI, Entry);
222 Type = Entry->Type;
223 Flags = Entry->Flags;
224 } else {
225 InMemoryStruct<macho::SymbolTableEntry> Entry;
226 getSymbolTableEntry(DRI, Entry);
227 Type = Entry->Type;
228 Flags = Entry->Flags;
229 }
Eric Christopher6256b032011-04-22 03:19:48 +0000230
231 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000232 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000233 case macho::STT_Undefined:
234 Char = 'u';
235 break;
236 case macho::STT_Absolute:
237 case macho::STT_Section:
238 Char = 's';
239 break;
240 default:
241 Char = '?';
242 break;
243 }
244
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000245 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Eric Christopher6256b032011-04-22 03:19:48 +0000246 Char = toupper(Char);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000247 Result = Char;
248 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000249}
250
Michael J. Spencer25b15772011-06-25 17:55:23 +0000251error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
252 bool &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000253 if (MachOObj->is64Bit()) {
254 InMemoryStruct<macho::Symbol64TableEntry> Entry;
255 getSymbol64TableEntry(DRI, Entry);
256 Result = Entry->Flags & macho::STF_StabsEntryMask;
257 } else {
258 InMemoryStruct<macho::SymbolTableEntry> Entry;
259 getSymbolTableEntry(DRI, Entry);
260 Result = Entry->Flags & macho::STF_StabsEntryMask;
261 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000262 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000263}
264
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000265error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
266
267 if (MachOObj->is64Bit()) {
268 InMemoryStruct<macho::Symbol64TableEntry> Entry;
269 getSymbol64TableEntry(Symb, Entry);
270 Res = Entry->Type & MachO::NlistMaskExternal;
271 } else {
272 InMemoryStruct<macho::SymbolTableEntry> Entry;
273 getSymbolTableEntry(Symb, Entry);
274 Res = Entry->Type & MachO::NlistMaskExternal;
275 }
276 return object_error::success;
277}
278
Michael J. Spencerc38c36a2011-10-17 23:54:22 +0000279error_code MachOObjectFile::isSymbolWeak(DataRefImpl Symb, bool &Res) const {
280
281 if (MachOObj->is64Bit()) {
282 InMemoryStruct<macho::Symbol64TableEntry> Entry;
283 getSymbol64TableEntry(Symb, Entry);
284 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
285 } else {
286 InMemoryStruct<macho::SymbolTableEntry> Entry;
287 getSymbolTableEntry(Symb, Entry);
288 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
289 }
290 return object_error::success;
291}
292
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000293error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{
294 uint8_t n_type;
295 if (MachOObj->is64Bit()) {
296 InMemoryStruct<macho::Symbol64TableEntry> Entry;
297 getSymbol64TableEntry(Symb, Entry);
298 n_type = Entry->Type;
299 } else {
300 InMemoryStruct<macho::SymbolTableEntry> Entry;
301 getSymbolTableEntry(Symb, Entry);
302 n_type = Entry->Type;
303 }
304
305 Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute;
306 return object_error::success;
307}
308
309error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
310 section_iterator &Res) const {
311 uint8_t index;
312 if (MachOObj->is64Bit()) {
313 InMemoryStruct<macho::Symbol64TableEntry> Entry;
314 getSymbol64TableEntry(Symb, Entry);
315 index = Entry->SectionIndex;
316 } else {
317 InMemoryStruct<macho::SymbolTableEntry> Entry;
318 getSymbolTableEntry(Symb, Entry);
319 index = Entry->SectionIndex;
320 }
321
322 if (index == 0)
323 Res = end_sections();
324 else
Danil Malyshev9b247382011-11-27 10:12:52 +0000325 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000326
327 return object_error::success;
328}
329
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000330error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000331 SymbolRef::Type &Res) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000332 uint8_t n_type;
333 if (MachOObj->is64Bit()) {
334 InMemoryStruct<macho::Symbol64TableEntry> Entry;
335 getSymbol64TableEntry(Symb, Entry);
336 n_type = Entry->Type;
337 } else {
338 InMemoryStruct<macho::SymbolTableEntry> Entry;
339 getSymbolTableEntry(Symb, Entry);
340 n_type = Entry->Type;
341 }
342 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000343
344 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000345 if (n_type & MachO::NlistMaskStab) {
346 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000347 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000348 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000349
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000350 switch (n_type & MachO::NlistMaskType) {
351 case MachO::NListTypeUndefined :
352 Res = SymbolRef::ST_External;
353 break;
354 case MachO::NListTypeSection :
355 Res = SymbolRef::ST_Function;
356 break;
357 }
358 return object_error::success;
359}
360
361
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000362symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000363 // DRI.d.a = segment number; DRI.d.b = symbol index.
364 DataRefImpl DRI;
365 DRI.d.a = DRI.d.b = 0;
366 moveToNextSymbol(DRI);
367 return symbol_iterator(SymbolRef(DRI, this));
368}
369
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000370symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000371 DataRefImpl DRI;
372 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
373 DRI.d.b = 0;
374 return symbol_iterator(SymbolRef(DRI, this));
375}
376
377
378/*===-- Sections ----------------------------------------------------------===*/
379
380void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
381 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
382 while (DRI.d.a < LoadCommandCount) {
383 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
384 if (LCI.Command.Type == macho::LCT_Segment) {
385 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
386 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
387 if (DRI.d.b < SegmentLoadCmd->NumSections)
388 return;
389 } else if (LCI.Command.Type == macho::LCT_Segment64) {
390 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
391 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
392 if (DRI.d.b < Segment64LoadCmd->NumSections)
393 return;
394 }
395
396 DRI.d.a++;
397 DRI.d.b = 0;
398 }
399}
400
Michael J. Spencer25b15772011-06-25 17:55:23 +0000401error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
402 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000403 DRI.d.b++;
404 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000405 Result = SectionRef(DRI, this);
406 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000407}
408
409void
410MachOObjectFile::getSection(DataRefImpl DRI,
411 InMemoryStruct<macho::Section> &Res) const {
412 InMemoryStruct<macho::SegmentLoadCommand> SLC;
413 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
414 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
415 MachOObj->ReadSection(LCI, DRI.d.b, Res);
416}
417
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000418std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
419 SectionList::const_iterator loc =
420 std::find(Sections.begin(), Sections.end(), Sec);
421 assert(loc != Sections.end() && "Sec is not a valid section!");
422 return std::distance(Sections.begin(), loc);
423}
424
Benjamin Kramer7d145782011-07-15 00:14:48 +0000425void
426MachOObjectFile::getSection64(DataRefImpl DRI,
427 InMemoryStruct<macho::Section64> &Res) const {
428 InMemoryStruct<macho::Segment64LoadCommand> SLC;
429 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
430 MachOObj->ReadSegment64LoadCommand(LCI, SLC);
431 MachOObj->ReadSection64(LCI, DRI.d.b, Res);
432}
433
434static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
435 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
436 if (LCI.Command.Type == macho::LCT_Segment64)
437 return true;
438 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
439 return false;
440}
441
Michael J. Spencer25b15772011-06-25 17:55:23 +0000442error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
443 StringRef &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000444 // FIXME: thread safety.
Michael J. Spencer25b15772011-06-25 17:55:23 +0000445 static char result[34];
Benjamin Kramer7d145782011-07-15 00:14:48 +0000446 if (is64BitLoadCommand(MachOObj, DRI)) {
447 InMemoryStruct<macho::Segment64LoadCommand> SLC;
448 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
449 MachOObj->ReadSegment64LoadCommand(LCI, SLC);
450 InMemoryStruct<macho::Section64> Sect;
451 MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
452
Benjamin Kramer291e7672011-07-15 00:29:02 +0000453 strcpy(result, Sect->SegmentName);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000454 strcat(result, ",");
455 strcat(result, Sect->Name);
456 } else {
457 InMemoryStruct<macho::SegmentLoadCommand> SLC;
458 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
459 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
460 InMemoryStruct<macho::Section> Sect;
461 MachOObj->ReadSection(LCI, DRI.d.b, Sect);
462
Benjamin Kramer291e7672011-07-15 00:29:02 +0000463 strcpy(result, Sect->SegmentName);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000464 strcat(result, ",");
465 strcat(result, Sect->Name);
466 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000467 Result = StringRef(result);
468 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000469}
470
Michael J. Spencer25b15772011-06-25 17:55:23 +0000471error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
472 uint64_t &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000473 if (is64BitLoadCommand(MachOObj, DRI)) {
474 InMemoryStruct<macho::Section64> Sect;
475 getSection64(DRI, Sect);
476 Result = Sect->Address;
477 } else {
478 InMemoryStruct<macho::Section> Sect;
479 getSection(DRI, Sect);
480 Result = Sect->Address;
481 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000482 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000483}
484
Michael J. Spencer25b15772011-06-25 17:55:23 +0000485error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
486 uint64_t &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000487 if (is64BitLoadCommand(MachOObj, DRI)) {
488 InMemoryStruct<macho::Section64> Sect;
489 getSection64(DRI, Sect);
490 Result = Sect->Size;
491 } else {
492 InMemoryStruct<macho::Section> Sect;
493 getSection(DRI, Sect);
494 Result = Sect->Size;
495 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000496 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000497}
498
Michael J. Spencer25b15772011-06-25 17:55:23 +0000499error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
500 StringRef &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000501 if (is64BitLoadCommand(MachOObj, DRI)) {
502 InMemoryStruct<macho::Section64> Sect;
503 getSection64(DRI, Sect);
504 Result = MachOObj->getData(Sect->Offset, Sect->Size);
505 } else {
506 InMemoryStruct<macho::Section> Sect;
507 getSection(DRI, Sect);
508 Result = MachOObj->getData(Sect->Offset, Sect->Size);
509 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000510 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000511}
512
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000513error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
514 uint64_t &Result) const {
515 if (is64BitLoadCommand(MachOObj, DRI)) {
516 InMemoryStruct<macho::Section64> Sect;
517 getSection64(DRI, Sect);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000518 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000519 } else {
520 InMemoryStruct<macho::Section> Sect;
521 getSection(DRI, Sect);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000522 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000523 }
524 return object_error::success;
525}
526
Michael J. Spencer25b15772011-06-25 17:55:23 +0000527error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
528 bool &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000529 if (is64BitLoadCommand(MachOObj, DRI)) {
530 InMemoryStruct<macho::Section64> Sect;
531 getSection64(DRI, Sect);
532 Result = !strcmp(Sect->Name, "__text");
533 } else {
534 InMemoryStruct<macho::Section> Sect;
535 getSection(DRI, Sect);
536 Result = !strcmp(Sect->Name, "__text");
537 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000538 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000539}
540
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000541error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
542 bool &Result) const {
543 // FIXME: Unimplemented.
544 Result = false;
545 return object_error::success;
546}
547
548error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
549 bool &Result) const {
550 // FIXME: Unimplemented.
551 Result = false;
552 return object_error::success;
553}
554
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000555error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
556 DataRefImpl Symb,
557 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000558 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000559 getSymbolType(Symb, ST);
560 if (ST == SymbolRef::ST_External) {
561 Result = false;
562 return object_error::success;
563 }
564
565 uint64_t SectBegin, SectEnd;
566 getSectionAddress(Sec, SectBegin);
567 getSectionSize(Sec, SectEnd);
568 SectEnd += SectBegin;
569
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000570 if (MachOObj->is64Bit()) {
571 InMemoryStruct<macho::Symbol64TableEntry> Entry;
572 getSymbol64TableEntry(Symb, Entry);
Owen Andersoncd749882011-10-12 22:21:32 +0000573 uint64_t SymAddr= Entry->Value;
574 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000575 } else {
576 InMemoryStruct<macho::SymbolTableEntry> Entry;
577 getSymbolTableEntry(Symb, Entry);
Owen Andersoncd749882011-10-12 22:21:32 +0000578 uint64_t SymAddr= Entry->Value;
579 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000580 }
Owen Andersoncd749882011-10-12 22:21:32 +0000581
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000582 return object_error::success;
583}
584
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000585relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
586 DataRefImpl ret;
587 ret.d.a = 0;
588 ret.d.b = getSectionIndex(Sec);
589 return relocation_iterator(RelocationRef(ret, this));
590}
591relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
592 uint32_t last_reloc;
593 if (is64BitLoadCommand(MachOObj, Sec)) {
594 InMemoryStruct<macho::Section64> Sect;
595 getSection64(Sec, Sect);
596 last_reloc = Sect->NumRelocationTableEntries;
597 } else {
598 InMemoryStruct<macho::Section> Sect;
599 getSection(Sec, Sect);
600 last_reloc = Sect->NumRelocationTableEntries;
601 }
602 DataRefImpl ret;
603 ret.d.a = last_reloc;
604 ret.d.b = getSectionIndex(Sec);
605 return relocation_iterator(RelocationRef(ret, this));
606}
607
608section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000609 DataRefImpl DRI;
610 DRI.d.a = DRI.d.b = 0;
611 moveToNextSection(DRI);
612 return section_iterator(SectionRef(DRI, this));
613}
614
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000615section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000616 DataRefImpl DRI;
617 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
618 DRI.d.b = 0;
619 return section_iterator(SectionRef(DRI, this));
620}
621
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000622/*===-- Relocations -------------------------------------------------------===*/
623
624void MachOObjectFile::
625getRelocation(DataRefImpl Rel,
626 InMemoryStruct<macho::RelocationEntry> &Res) const {
627 uint32_t relOffset;
628 if (MachOObj->is64Bit()) {
629 InMemoryStruct<macho::Section64> Sect;
630 getSection64(Sections[Rel.d.b], Sect);
631 relOffset = Sect->RelocationTableOffset;
632 } else {
633 InMemoryStruct<macho::Section> Sect;
634 getSection(Sections[Rel.d.b], Sect);
635 relOffset = Sect->RelocationTableOffset;
636 }
637 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
638}
639error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
640 RelocationRef &Res) const {
641 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000642 Res = RelocationRef(Rel, this);
643 return object_error::success;
644}
645error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
646 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000647 const uint8_t* sectAddress = 0;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000648 if (MachOObj->is64Bit()) {
649 InMemoryStruct<macho::Section64> Sect;
650 getSection64(Sections[Rel.d.b], Sect);
Owen Anderson0135fe12011-10-24 21:44:00 +0000651 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000652 } else {
653 InMemoryStruct<macho::Section> Sect;
654 getSection(Sections[Rel.d.b], Sect);
Owen Anderson0135fe12011-10-24 21:44:00 +0000655 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000656 }
657 InMemoryStruct<macho::RelocationEntry> RE;
658 getRelocation(Rel, RE);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000659
660 unsigned Arch = getArch();
661 bool isScattered = (Arch != Triple::x86_64) &&
662 (RE->Word0 & macho::RF_Scattered);
663 uint64_t RelAddr = 0;
Danil Malyshev9b247382011-11-27 10:12:52 +0000664 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000665 RelAddr = RE->Word0 & 0xFFFFFF;
666 else
667 RelAddr = RE->Word0;
668
669 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000670 return object_error::success;
671}
Danil Malyshev9b247382011-11-27 10:12:52 +0000672error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
673 uint64_t &Res) const {
674 InMemoryStruct<macho::RelocationEntry> RE;
675 getRelocation(Rel, RE);
676
677 unsigned Arch = getArch();
678 bool isScattered = (Arch != Triple::x86_64) &&
679 (RE->Word0 & macho::RF_Scattered);
680 if (isScattered)
681 Res = RE->Word0 & 0xFFFFFF;
682 else
683 Res = RE->Word0;
684 return object_error::success;
685}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000686error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
687 SymbolRef &Res) const {
688 InMemoryStruct<macho::RelocationEntry> RE;
689 getRelocation(Rel, RE);
690 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
691 bool isExtern = (RE->Word1 >> 27) & 1;
692
693 DataRefImpl Sym;
694 Sym.d.a = Sym.d.b = 0;
695 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000696 if (isExtern) {
697 for (unsigned i = 0; i < SymbolIdx; i++) {
698 Sym.d.b++;
699 moveToNextSymbol(Sym);
Nick Lewycky58856ea2011-09-09 00:16:50 +0000700 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000701 "Relocation symbol index out of range!");
702 }
703 }
704 Res = SymbolRef(Sym, this);
705 return object_error::success;
706}
707error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000708 uint64_t &Res) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000709 InMemoryStruct<macho::RelocationEntry> RE;
710 getRelocation(Rel, RE);
Owen Andersonf8261e72011-10-26 17:10:22 +0000711 Res = RE->Word0;
712 Res <<= 32;
713 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000714 return object_error::success;
715}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000716error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
717 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000718 // TODO: Support scattered relocations.
719 StringRef res;
720 InMemoryStruct<macho::RelocationEntry> RE;
721 getRelocation(Rel, RE);
Owen Anderson0135fe12011-10-24 21:44:00 +0000722
723 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000724 bool isScattered = (Arch != Triple::x86_64) &&
725 (RE->Word0 & macho::RF_Scattered);
726
727 unsigned r_type;
728 if (isScattered)
729 r_type = (RE->Word0 >> 24) & 0xF;
730 else
731 r_type = (RE->Word1 >> 28) & 0xF;
732
Owen Anderson0135fe12011-10-24 21:44:00 +0000733 switch (Arch) {
734 case Triple::x86: {
735 const char* Table[] = {
736 "GENERIC_RELOC_VANILLA",
737 "GENERIC_RELOC_PAIR",
738 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000739 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000740 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000741 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000742
Owen Andersoneb6bd332011-10-27 20:46:09 +0000743 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000744 res = "Unknown";
745 else
746 res = Table[r_type];
747 break;
748 }
749 case Triple::x86_64: {
750 const char* Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000751 "X86_64_RELOC_UNSIGNED",
752 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000753 "X86_64_RELOC_BRANCH",
754 "X86_64_RELOC_GOT_LOAD",
755 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000756 "X86_64_RELOC_SUBTRACTOR",
757 "X86_64_RELOC_SIGNED_1",
758 "X86_64_RELOC_SIGNED_2",
759 "X86_64_RELOC_SIGNED_4",
760 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000761
Owen Andersond8fa76d2011-10-24 23:20:07 +0000762 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000763 res = "Unknown";
764 else
765 res = Table[r_type];
766 break;
767 }
768 case Triple::arm: {
769 const char* Table[] = {
770 "ARM_RELOC_VANILLA",
771 "ARM_RELOC_PAIR",
772 "ARM_RELOC_SECTDIFF",
773 "ARM_RELOC_LOCAL_SECTDIFF",
774 "ARM_RELOC_PB_LA_PTR",
775 "ARM_RELOC_BR24",
776 "ARM_THUMB_RELOC_BR22",
777 "ARM_THUMB_32BIT_BRANCH",
778 "ARM_RELOC_HALF",
779 "ARM_RELOC_HALF_SECTDIFF" };
780
781 if (r_type > 9)
782 res = "Unknown";
783 else
784 res = Table[r_type];
785 break;
786 }
787 case Triple::ppc: {
788 const char* Table[] = {
789 "PPC_RELOC_VANILLA",
790 "PPC_RELOC_PAIR",
791 "PPC_RELOC_BR14",
792 "PPC_RELOC_BR24",
793 "PPC_RELOC_HI16",
794 "PPC_RELOC_LO16",
795 "PPC_RELOC_HA16",
796 "PPC_RELOC_LO14",
797 "PPC_RELOC_SECTDIFF",
798 "PPC_RELOC_PB_LA_PTR",
799 "PPC_RELOC_HI16_SECTDIFF",
800 "PPC_RELOC_LO16_SECTDIFF",
801 "PPC_RELOC_HA16_SECTDIFF",
802 "PPC_RELOC_JBSR",
803 "PPC_RELOC_LO14_SECTDIFF",
804 "PPC_RELOC_LOCAL_SECTDIFF" };
805
806 res = Table[r_type];
807 break;
808 }
809 case Triple::UnknownArch:
810 res = "Unknown";
811 break;
812 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000813 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000814 return object_error::success;
815}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000816error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
817 int64_t &Res) const {
818 InMemoryStruct<macho::RelocationEntry> RE;
819 getRelocation(Rel, RE);
820 bool isExtern = (RE->Word1 >> 27) & 1;
821 Res = 0;
822 if (!isExtern) {
823 const uint8_t* sectAddress = base();
824 if (MachOObj->is64Bit()) {
825 InMemoryStruct<macho::Section64> Sect;
826 getSection64(Sections[Rel.d.b], Sect);
827 sectAddress += Sect->Offset;
828 } else {
829 InMemoryStruct<macho::Section> Sect;
830 getSection(Sections[Rel.d.b], Sect);
831 sectAddress += Sect->Offset;
832 }
833 Res = reinterpret_cast<uintptr_t>(sectAddress);
834 }
835 return object_error::success;
836}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000837
838// Helper to advance a section or symbol iterator multiple increments at a time.
839template<class T>
840error_code advance(T &it, size_t Val) {
841 error_code ec;
842 while (Val--) {
843 it.increment(ec);
844 }
845 return ec;
846}
847
848template<class T>
849void advanceTo(T &it, size_t Val) {
850 if (error_code ec = advance(it, Val))
851 report_fatal_error(ec.message());
852}
853
Owen Anderson1832f4d2011-10-26 20:42:54 +0000854void MachOObjectFile::printRelocationTargetName(
855 InMemoryStruct<macho::RelocationEntry>& RE,
856 raw_string_ostream &fmt) const {
857 unsigned Arch = getArch();
858 bool isScattered = (Arch != Triple::x86_64) &&
859 (RE->Word0 & macho::RF_Scattered);
860
861 // Target of a scattered relocation is an address. In the interest of
862 // generating pretty output, scan through the symbol table looking for a
863 // symbol that aligns with that address. If we find one, print it.
864 // Otherwise, we just print the hex address of the target.
865 if (isScattered) {
866 uint32_t Val = RE->Word1;
867
868 error_code ec;
869 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
870 SI.increment(ec)) {
871 if (ec) report_fatal_error(ec.message());
872
873 uint64_t Addr;
874 StringRef Name;
875
876 if ((ec = SI->getAddress(Addr)))
877 report_fatal_error(ec.message());
878 if (Addr != Val) continue;
879 if ((ec = SI->getName(Name)))
880 report_fatal_error(ec.message());
881 fmt << Name;
882 return;
883 }
884
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000885 // If we couldn't find a symbol that this relocation refers to, try
886 // to find a section beginning instead.
887 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
888 SI.increment(ec)) {
889 if (ec) report_fatal_error(ec.message());
890
891 uint64_t Addr;
892 StringRef Name;
893
894 if ((ec = SI->getAddress(Addr)))
895 report_fatal_error(ec.message());
896 if (Addr != Val) continue;
897 if ((ec = SI->getName(Name)))
898 report_fatal_error(ec.message());
899 fmt << Name;
900 return;
901 }
902
Owen Anderson1832f4d2011-10-26 20:42:54 +0000903 fmt << format("0x%x", Val);
904 return;
905 }
906
907 StringRef S;
908 bool isExtern = (RE->Word1 >> 27) & 1;
909 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000910
911 if (isExtern) {
912 symbol_iterator SI = begin_symbols();
913 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000914 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000915 } else {
916 section_iterator SI = begin_sections();
917 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000918 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000919 }
920
Owen Anderson1832f4d2011-10-26 20:42:54 +0000921 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000922}
923
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000924error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
925 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000926 InMemoryStruct<macho::RelocationEntry> RE;
927 getRelocation(Rel, RE);
928
Owen Anderson1832f4d2011-10-26 20:42:54 +0000929 unsigned Arch = getArch();
930 bool isScattered = (Arch != Triple::x86_64) &&
931 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000932
Owen Anderson013d7562011-10-25 18:48:41 +0000933 std::string fmtbuf;
934 raw_string_ostream fmt(fmtbuf);
935
Owen Anderson1832f4d2011-10-26 20:42:54 +0000936 unsigned Type;
937 if (isScattered)
938 Type = (RE->Word0 >> 24) & 0xF;
939 else
940 Type = (RE->Word1 >> 28) & 0xF;
941
Owen Andersoneb6bd332011-10-27 20:46:09 +0000942 bool isPCRel;
943 if (isScattered)
944 isPCRel = ((RE->Word0 >> 30) & 1);
945 else
946 isPCRel = ((RE->Word1 >> 24) & 1);
947
Owen Andersond8fa76d2011-10-24 23:20:07 +0000948 // Determine any addends that should be displayed with the relocation.
949 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +0000950
951 // X86_64 has entirely custom relocation types.
952 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +0000953 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +0000954
Owen Andersond8fa76d2011-10-24 23:20:07 +0000955 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +0000956 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
957 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
958 printRelocationTargetName(RE, fmt);
959 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +0000960 if (isPCRel) fmt << "PCREL";
961 break;
962 }
Owen Anderson1832f4d2011-10-26 20:42:54 +0000963 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +0000964 InMemoryStruct<macho::RelocationEntry> RENext;
965 DataRefImpl RelNext = Rel;
966 RelNext.d.a++;
967 getRelocation(RelNext, RENext);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000968
969 // X86_64_SUBTRACTOR must be followed by a relocation of type
970 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +0000971 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +0000972 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000973 if (RType != 0)
974 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
975 "X86_64_RELOC_SUBTRACTOR.");
976
Owen Andersonef22f782011-10-26 17:28:49 +0000977 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
978 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +0000979 printRelocationTargetName(RENext, fmt);
980 fmt << "-";
981 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000982 }
Owen Andersoneb6bd332011-10-27 20:46:09 +0000983 case macho::RIT_X86_64_TLV:
984 printRelocationTargetName(RE, fmt);
985 fmt << "@TLV";
986 if (isPCRel) fmt << "P";
987 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000988 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
989 printRelocationTargetName(RE, fmt);
990 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +0000991 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000992 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
993 printRelocationTargetName(RE, fmt);
994 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +0000995 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000996 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
997 printRelocationTargetName(RE, fmt);
998 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +0000999 break;
1000 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +00001001 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001002 break;
1003 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001004 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001005 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1006 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001007 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001008 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001009 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001010 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001011 InMemoryStruct<macho::RelocationEntry> RENext;
1012 DataRefImpl RelNext = Rel;
1013 RelNext.d.a++;
1014 getRelocation(RelNext, RENext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001015
1016 // X86 sect diff's must be followed by a relocation of type
1017 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001018 bool isNextScattered = (Arch != Triple::x86_64) &&
1019 (RENext->Word0 & macho::RF_Scattered);
1020 unsigned RType;
1021 if (isNextScattered)
1022 RType = (RENext->Word0 >> 24) & 0xF;
1023 else
1024 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001025 if (RType != 1)
1026 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001027 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001028
Owen Anderson1832f4d2011-10-26 20:42:54 +00001029 printRelocationTargetName(RE, fmt);
1030 fmt << "-";
1031 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001032 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001033 }
1034 }
Owen Anderson013d7562011-10-25 18:48:41 +00001035
Owen Anderson1832f4d2011-10-26 20:42:54 +00001036 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001037 // All X86 relocations that need special printing were already
1038 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001039 switch (Type) {
1040 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1041 InMemoryStruct<macho::RelocationEntry> RENext;
1042 DataRefImpl RelNext = Rel;
1043 RelNext.d.a++;
1044 getRelocation(RelNext, RENext);
1045
1046 // X86 sect diff's must be followed by a relocation of type
1047 // GENERIC_RELOC_PAIR.
1048 bool isNextScattered = (Arch != Triple::x86_64) &&
1049 (RENext->Word0 & macho::RF_Scattered);
1050 unsigned RType;
1051 if (isNextScattered)
1052 RType = (RENext->Word0 >> 24) & 0xF;
1053 else
1054 RType = (RENext->Word1 >> 28) & 0xF;
1055 if (RType != 1)
1056 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1057 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1058
1059 printRelocationTargetName(RE, fmt);
1060 fmt << "-";
1061 printRelocationTargetName(RENext, fmt);
1062 break;
1063 }
1064 case macho::RIT_Generic_TLV: {
1065 printRelocationTargetName(RE, fmt);
1066 fmt << "@TLV";
1067 if (isPCRel) fmt << "P";
1068 break;
1069 }
1070 default:
1071 printRelocationTargetName(RE, fmt);
1072 }
Owen Anderson013d7562011-10-25 18:48:41 +00001073 } else { // ARM-specific relocations
1074 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001075 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1076 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001077 // Half relocations steal a bit from the length field to encode
1078 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001079 bool isUpper;
1080 if (isScattered)
1081 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001082 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001083 isUpper = (RE->Word1 >> 25) & 1;
1084
1085 if (isUpper)
1086 fmt << ":upper16:(";
1087 else
1088 fmt << ":lower16:(";
1089 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001090
1091 InMemoryStruct<macho::RelocationEntry> RENext;
1092 DataRefImpl RelNext = Rel;
1093 RelNext.d.a++;
1094 getRelocation(RelNext, RENext);
1095
1096 // ARM half relocs must be followed by a relocation of type
1097 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001098 bool isNextScattered = (Arch != Triple::x86_64) &&
1099 (RENext->Word0 & macho::RF_Scattered);
1100 unsigned RType;
1101 if (isNextScattered)
1102 RType = (RENext->Word0 >> 24) & 0xF;
1103 else
1104 RType = (RENext->Word1 >> 28) & 0xF;
1105
Owen Anderson013d7562011-10-25 18:48:41 +00001106 if (RType != 1)
1107 report_fatal_error("Expected ARM_RELOC_PAIR after "
1108 "GENERIC_RELOC_HALF");
1109
Owen Anderson1832f4d2011-10-26 20:42:54 +00001110 // NOTE: The half of the target virtual address is stashed in the
1111 // address field of the secondary relocation, but we can't reverse
1112 // engineer the constant offset from it without decoding the movw/movt
1113 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001114
1115 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1116 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001117 if (Type == macho::RIT_ARM_HalfDifference) {
1118 fmt << "-";
1119 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001120 }
1121
Owen Anderson013d7562011-10-25 18:48:41 +00001122 fmt << ")";
1123 break;
1124 }
1125 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001126 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001127 }
1128 }
1129 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001130 } else
1131 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001132
Owen Anderson0135fe12011-10-24 21:44:00 +00001133 fmt.flush();
1134 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001135 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001136}
1137
Owen Anderson0685e942011-10-25 20:35:53 +00001138error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1139 bool &Result) const {
1140 InMemoryStruct<macho::RelocationEntry> RE;
1141 getRelocation(Rel, RE);
1142
Owen Anderson0685e942011-10-25 20:35:53 +00001143 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001144 bool isScattered = (Arch != Triple::x86_64) &&
1145 (RE->Word0 & macho::RF_Scattered);
1146 unsigned Type;
1147 if (isScattered)
1148 Type = (RE->Word0 >> 24) & 0xF;
1149 else
1150 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001151
1152 Result = false;
1153
1154 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1155 // is always hidden.
1156 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001157 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001158 } else if (Arch == Triple::x86_64) {
1159 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1160 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001161 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001162 DataRefImpl RelPrev = Rel;
1163 RelPrev.d.a--;
1164 InMemoryStruct<macho::RelocationEntry> REPrev;
1165 getRelocation(RelPrev, REPrev);
1166
1167 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1168
Owen Anderson1832f4d2011-10-26 20:42:54 +00001169 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001170 }
1171 }
1172
1173 return object_error::success;
1174}
1175
Eric Christopher6256b032011-04-22 03:19:48 +00001176/*===-- Miscellaneous -----------------------------------------------------===*/
1177
1178uint8_t MachOObjectFile::getBytesInAddress() const {
1179 return MachOObj->is64Bit() ? 8 : 4;
1180}
1181
1182StringRef MachOObjectFile::getFileFormatName() const {
1183 if (!MachOObj->is64Bit()) {
1184 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001185 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001186 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001187 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001188 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001189 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001190 return "Mach-O 32-bit ppc";
1191 default:
Eric Christopherf4b2f932011-04-22 06:34:01 +00001192 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001193 "64-bit object file when we're not 64-bit?");
1194 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001195 }
1196 }
1197
1198 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001199 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001200 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001201 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001202 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001203 default:
Eric Christopherf4b2f932011-04-22 06:34:01 +00001204 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001205 "32-bit object file when we're 64-bit?");
1206 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001207 }
1208}
1209
1210unsigned MachOObjectFile::getArch() const {
1211 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001212 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001213 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001214 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001215 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001216 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001217 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001218 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001219 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001220 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001221 return Triple::ppc64;
1222 default:
1223 return Triple::UnknownArch;
1224 }
1225}
1226
Owen Andersonf7c93a32011-10-11 17:32:27 +00001227} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001228} // end namespace llvm