blob: 099ac2c37f930a6c89366abc44159e4ce4c43397 [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
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000128error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI,
Michael J. Spencer25b15772011-06-25 17:55:23 +0000129 uint64_t &Result) const {
Owen Anderson95f8db42011-10-12 22:37:10 +0000130 uint64_t SectionOffset;
131 uint8_t SectionIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000132 if (MachOObj->is64Bit()) {
133 InMemoryStruct<macho::Symbol64TableEntry> Entry;
134 getSymbol64TableEntry(DRI, Entry);
135 Result = Entry->Value;
Owen Anderson95f8db42011-10-12 22:37:10 +0000136 SectionIndex = Entry->SectionIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000137 } else {
138 InMemoryStruct<macho::SymbolTableEntry> Entry;
139 getSymbolTableEntry(DRI, Entry);
140 Result = Entry->Value;
Owen Anderson95f8db42011-10-12 22:37:10 +0000141 SectionIndex = Entry->SectionIndex;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000142 }
Owen Anderson95f8db42011-10-12 22:37:10 +0000143 getSectionAddress(Sections[SectionIndex-1], SectionOffset);
144 Result -= SectionOffset;
145
Michael J. Spencer25b15772011-06-25 17:55:23 +0000146 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000147}
148
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000149error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
150 uint64_t &Result) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000151 if (MachOObj->is64Bit()) {
152 InMemoryStruct<macho::Symbol64TableEntry> Entry;
153 getSymbol64TableEntry(DRI, Entry);
Owen Anderson95f8db42011-10-12 22:37:10 +0000154 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000155 } else {
156 InMemoryStruct<macho::SymbolTableEntry> Entry;
157 getSymbolTableEntry(DRI, Entry);
Owen Anderson95f8db42011-10-12 22:37:10 +0000158 Result = Entry->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000159 }
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000160 return object_error::success;
161}
162
Michael J. Spencer25b15772011-06-25 17:55:23 +0000163error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
164 uint64_t &Result) const {
165 Result = UnknownAddressOrSize;
166 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000167}
168
Michael J. Spencer25b15772011-06-25 17:55:23 +0000169error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
170 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000171 uint8_t Type, Flags;
172 if (MachOObj->is64Bit()) {
173 InMemoryStruct<macho::Symbol64TableEntry> Entry;
174 getSymbol64TableEntry(DRI, Entry);
175 Type = Entry->Type;
176 Flags = Entry->Flags;
177 } else {
178 InMemoryStruct<macho::SymbolTableEntry> Entry;
179 getSymbolTableEntry(DRI, Entry);
180 Type = Entry->Type;
181 Flags = Entry->Flags;
182 }
Eric Christopher6256b032011-04-22 03:19:48 +0000183
184 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000185 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000186 case macho::STT_Undefined:
187 Char = 'u';
188 break;
189 case macho::STT_Absolute:
190 case macho::STT_Section:
191 Char = 's';
192 break;
193 default:
194 Char = '?';
195 break;
196 }
197
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000198 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Eric Christopher6256b032011-04-22 03:19:48 +0000199 Char = toupper(Char);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000200 Result = Char;
201 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000202}
203
Michael J. Spencer25b15772011-06-25 17:55:23 +0000204error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
205 bool &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000206 if (MachOObj->is64Bit()) {
207 InMemoryStruct<macho::Symbol64TableEntry> Entry;
208 getSymbol64TableEntry(DRI, Entry);
209 Result = Entry->Flags & macho::STF_StabsEntryMask;
210 } else {
211 InMemoryStruct<macho::SymbolTableEntry> Entry;
212 getSymbolTableEntry(DRI, Entry);
213 Result = Entry->Flags & macho::STF_StabsEntryMask;
214 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000215 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000216}
217
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000218error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
219
220 if (MachOObj->is64Bit()) {
221 InMemoryStruct<macho::Symbol64TableEntry> Entry;
222 getSymbol64TableEntry(Symb, Entry);
223 Res = Entry->Type & MachO::NlistMaskExternal;
224 } else {
225 InMemoryStruct<macho::SymbolTableEntry> Entry;
226 getSymbolTableEntry(Symb, Entry);
227 Res = Entry->Type & MachO::NlistMaskExternal;
228 }
229 return object_error::success;
230}
231
Michael J. Spencerc38c36a2011-10-17 23:54:22 +0000232error_code MachOObjectFile::isSymbolWeak(DataRefImpl Symb, bool &Res) const {
233
234 if (MachOObj->is64Bit()) {
235 InMemoryStruct<macho::Symbol64TableEntry> Entry;
236 getSymbol64TableEntry(Symb, Entry);
237 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
238 } else {
239 InMemoryStruct<macho::SymbolTableEntry> Entry;
240 getSymbolTableEntry(Symb, Entry);
241 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
242 }
243 return object_error::success;
244}
245
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000246error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{
247 uint8_t n_type;
248 if (MachOObj->is64Bit()) {
249 InMemoryStruct<macho::Symbol64TableEntry> Entry;
250 getSymbol64TableEntry(Symb, Entry);
251 n_type = Entry->Type;
252 } else {
253 InMemoryStruct<macho::SymbolTableEntry> Entry;
254 getSymbolTableEntry(Symb, Entry);
255 n_type = Entry->Type;
256 }
257
258 Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute;
259 return object_error::success;
260}
261
262error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
263 section_iterator &Res) const {
264 uint8_t index;
265 if (MachOObj->is64Bit()) {
266 InMemoryStruct<macho::Symbol64TableEntry> Entry;
267 getSymbol64TableEntry(Symb, Entry);
268 index = Entry->SectionIndex;
269 } else {
270 InMemoryStruct<macho::SymbolTableEntry> Entry;
271 getSymbolTableEntry(Symb, Entry);
272 index = Entry->SectionIndex;
273 }
274
275 if (index == 0)
276 Res = end_sections();
277 else
278 Res = section_iterator(SectionRef(Sections[index], this));
279
280 return object_error::success;
281}
282
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000283error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000284 SymbolRef::Type &Res) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000285 uint8_t n_type;
286 if (MachOObj->is64Bit()) {
287 InMemoryStruct<macho::Symbol64TableEntry> Entry;
288 getSymbol64TableEntry(Symb, Entry);
289 n_type = Entry->Type;
290 } else {
291 InMemoryStruct<macho::SymbolTableEntry> Entry;
292 getSymbolTableEntry(Symb, Entry);
293 n_type = Entry->Type;
294 }
295 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000296
297 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000298 if (n_type & MachO::NlistMaskStab) {
299 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000300 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000301 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000302
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000303 switch (n_type & MachO::NlistMaskType) {
304 case MachO::NListTypeUndefined :
305 Res = SymbolRef::ST_External;
306 break;
307 case MachO::NListTypeSection :
308 Res = SymbolRef::ST_Function;
309 break;
310 }
311 return object_error::success;
312}
313
314
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000315symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000316 // DRI.d.a = segment number; DRI.d.b = symbol index.
317 DataRefImpl DRI;
318 DRI.d.a = DRI.d.b = 0;
319 moveToNextSymbol(DRI);
320 return symbol_iterator(SymbolRef(DRI, this));
321}
322
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000323symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000324 DataRefImpl DRI;
325 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
326 DRI.d.b = 0;
327 return symbol_iterator(SymbolRef(DRI, this));
328}
329
330
331/*===-- Sections ----------------------------------------------------------===*/
332
333void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
334 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
335 while (DRI.d.a < LoadCommandCount) {
336 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
337 if (LCI.Command.Type == macho::LCT_Segment) {
338 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
339 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
340 if (DRI.d.b < SegmentLoadCmd->NumSections)
341 return;
342 } else if (LCI.Command.Type == macho::LCT_Segment64) {
343 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
344 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
345 if (DRI.d.b < Segment64LoadCmd->NumSections)
346 return;
347 }
348
349 DRI.d.a++;
350 DRI.d.b = 0;
351 }
352}
353
Michael J. Spencer25b15772011-06-25 17:55:23 +0000354error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
355 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000356 DRI.d.b++;
357 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000358 Result = SectionRef(DRI, this);
359 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000360}
361
362void
363MachOObjectFile::getSection(DataRefImpl DRI,
364 InMemoryStruct<macho::Section> &Res) const {
365 InMemoryStruct<macho::SegmentLoadCommand> SLC;
366 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
367 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
368 MachOObj->ReadSection(LCI, DRI.d.b, Res);
369}
370
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000371std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
372 SectionList::const_iterator loc =
373 std::find(Sections.begin(), Sections.end(), Sec);
374 assert(loc != Sections.end() && "Sec is not a valid section!");
375 return std::distance(Sections.begin(), loc);
376}
377
Benjamin Kramer7d145782011-07-15 00:14:48 +0000378void
379MachOObjectFile::getSection64(DataRefImpl DRI,
380 InMemoryStruct<macho::Section64> &Res) const {
381 InMemoryStruct<macho::Segment64LoadCommand> SLC;
382 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
383 MachOObj->ReadSegment64LoadCommand(LCI, SLC);
384 MachOObj->ReadSection64(LCI, DRI.d.b, Res);
385}
386
387static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
388 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
389 if (LCI.Command.Type == macho::LCT_Segment64)
390 return true;
391 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
392 return false;
393}
394
Michael J. Spencer25b15772011-06-25 17:55:23 +0000395error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
396 StringRef &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000397 // FIXME: thread safety.
Michael J. Spencer25b15772011-06-25 17:55:23 +0000398 static char result[34];
Benjamin Kramer7d145782011-07-15 00:14:48 +0000399 if (is64BitLoadCommand(MachOObj, DRI)) {
400 InMemoryStruct<macho::Segment64LoadCommand> SLC;
401 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
402 MachOObj->ReadSegment64LoadCommand(LCI, SLC);
403 InMemoryStruct<macho::Section64> Sect;
404 MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
405
Benjamin Kramer291e7672011-07-15 00:29:02 +0000406 strcpy(result, Sect->SegmentName);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000407 strcat(result, ",");
408 strcat(result, Sect->Name);
409 } else {
410 InMemoryStruct<macho::SegmentLoadCommand> SLC;
411 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
412 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
413 InMemoryStruct<macho::Section> Sect;
414 MachOObj->ReadSection(LCI, DRI.d.b, Sect);
415
Benjamin Kramer291e7672011-07-15 00:29:02 +0000416 strcpy(result, Sect->SegmentName);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000417 strcat(result, ",");
418 strcat(result, Sect->Name);
419 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000420 Result = StringRef(result);
421 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000422}
423
Michael J. Spencer25b15772011-06-25 17:55:23 +0000424error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
425 uint64_t &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000426 if (is64BitLoadCommand(MachOObj, DRI)) {
427 InMemoryStruct<macho::Section64> Sect;
428 getSection64(DRI, Sect);
429 Result = Sect->Address;
430 } else {
431 InMemoryStruct<macho::Section> Sect;
432 getSection(DRI, Sect);
433 Result = Sect->Address;
434 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000435 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000436}
437
Michael J. Spencer25b15772011-06-25 17:55:23 +0000438error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
439 uint64_t &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000440 if (is64BitLoadCommand(MachOObj, DRI)) {
441 InMemoryStruct<macho::Section64> Sect;
442 getSection64(DRI, Sect);
443 Result = Sect->Size;
444 } else {
445 InMemoryStruct<macho::Section> Sect;
446 getSection(DRI, Sect);
447 Result = Sect->Size;
448 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000449 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000450}
451
Michael J. Spencer25b15772011-06-25 17:55:23 +0000452error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
453 StringRef &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000454 if (is64BitLoadCommand(MachOObj, DRI)) {
455 InMemoryStruct<macho::Section64> Sect;
456 getSection64(DRI, Sect);
457 Result = MachOObj->getData(Sect->Offset, Sect->Size);
458 } else {
459 InMemoryStruct<macho::Section> Sect;
460 getSection(DRI, Sect);
461 Result = MachOObj->getData(Sect->Offset, Sect->Size);
462 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000463 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000464}
465
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000466error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
467 uint64_t &Result) const {
468 if (is64BitLoadCommand(MachOObj, DRI)) {
469 InMemoryStruct<macho::Section64> Sect;
470 getSection64(DRI, Sect);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000471 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000472 } else {
473 InMemoryStruct<macho::Section> Sect;
474 getSection(DRI, Sect);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000475 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000476 }
477 return object_error::success;
478}
479
Michael J. Spencer25b15772011-06-25 17:55:23 +0000480error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
481 bool &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000482 if (is64BitLoadCommand(MachOObj, DRI)) {
483 InMemoryStruct<macho::Section64> Sect;
484 getSection64(DRI, Sect);
485 Result = !strcmp(Sect->Name, "__text");
486 } else {
487 InMemoryStruct<macho::Section> Sect;
488 getSection(DRI, Sect);
489 Result = !strcmp(Sect->Name, "__text");
490 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000491 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000492}
493
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000494error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
495 bool &Result) const {
496 // FIXME: Unimplemented.
497 Result = false;
498 return object_error::success;
499}
500
501error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
502 bool &Result) const {
503 // FIXME: Unimplemented.
504 Result = false;
505 return object_error::success;
506}
507
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000508error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
509 DataRefImpl Symb,
510 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000511 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000512 getSymbolType(Symb, ST);
513 if (ST == SymbolRef::ST_External) {
514 Result = false;
515 return object_error::success;
516 }
517
518 uint64_t SectBegin, SectEnd;
519 getSectionAddress(Sec, SectBegin);
520 getSectionSize(Sec, SectEnd);
521 SectEnd += SectBegin;
522
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000523 if (MachOObj->is64Bit()) {
524 InMemoryStruct<macho::Symbol64TableEntry> Entry;
525 getSymbol64TableEntry(Symb, Entry);
Owen Andersoncd749882011-10-12 22:21:32 +0000526 uint64_t SymAddr= Entry->Value;
527 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000528 } else {
529 InMemoryStruct<macho::SymbolTableEntry> Entry;
530 getSymbolTableEntry(Symb, Entry);
Owen Andersoncd749882011-10-12 22:21:32 +0000531 uint64_t SymAddr= Entry->Value;
532 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000533 }
Owen Andersoncd749882011-10-12 22:21:32 +0000534
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000535 return object_error::success;
536}
537
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000538relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
539 DataRefImpl ret;
540 ret.d.a = 0;
541 ret.d.b = getSectionIndex(Sec);
542 return relocation_iterator(RelocationRef(ret, this));
543}
544relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
545 uint32_t last_reloc;
546 if (is64BitLoadCommand(MachOObj, Sec)) {
547 InMemoryStruct<macho::Section64> Sect;
548 getSection64(Sec, Sect);
549 last_reloc = Sect->NumRelocationTableEntries;
550 } else {
551 InMemoryStruct<macho::Section> Sect;
552 getSection(Sec, Sect);
553 last_reloc = Sect->NumRelocationTableEntries;
554 }
555 DataRefImpl ret;
556 ret.d.a = last_reloc;
557 ret.d.b = getSectionIndex(Sec);
558 return relocation_iterator(RelocationRef(ret, this));
559}
560
561section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000562 DataRefImpl DRI;
563 DRI.d.a = DRI.d.b = 0;
564 moveToNextSection(DRI);
565 return section_iterator(SectionRef(DRI, this));
566}
567
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000568section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000569 DataRefImpl DRI;
570 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
571 DRI.d.b = 0;
572 return section_iterator(SectionRef(DRI, this));
573}
574
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000575/*===-- Relocations -------------------------------------------------------===*/
576
577void MachOObjectFile::
578getRelocation(DataRefImpl Rel,
579 InMemoryStruct<macho::RelocationEntry> &Res) const {
580 uint32_t relOffset;
581 if (MachOObj->is64Bit()) {
582 InMemoryStruct<macho::Section64> Sect;
583 getSection64(Sections[Rel.d.b], Sect);
584 relOffset = Sect->RelocationTableOffset;
585 } else {
586 InMemoryStruct<macho::Section> Sect;
587 getSection(Sections[Rel.d.b], Sect);
588 relOffset = Sect->RelocationTableOffset;
589 }
590 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
591}
592error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
593 RelocationRef &Res) const {
594 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000595 Res = RelocationRef(Rel, this);
596 return object_error::success;
597}
598error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
599 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000600 const uint8_t* sectAddress = 0;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000601 if (MachOObj->is64Bit()) {
602 InMemoryStruct<macho::Section64> Sect;
603 getSection64(Sections[Rel.d.b], Sect);
Owen Anderson0135fe12011-10-24 21:44:00 +0000604 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000605 } else {
606 InMemoryStruct<macho::Section> Sect;
607 getSection(Sections[Rel.d.b], Sect);
Owen Anderson0135fe12011-10-24 21:44:00 +0000608 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000609 }
610 InMemoryStruct<macho::RelocationEntry> RE;
611 getRelocation(Rel, RE);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000612
613 unsigned Arch = getArch();
614 bool isScattered = (Arch != Triple::x86_64) &&
615 (RE->Word0 & macho::RF_Scattered);
616 uint64_t RelAddr = 0;
617 if (isScattered)
618 RelAddr = RE->Word0 & 0xFFFFFF;
619 else
620 RelAddr = RE->Word0;
621
622 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000623 return object_error::success;
624}
625error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
626 SymbolRef &Res) const {
627 InMemoryStruct<macho::RelocationEntry> RE;
628 getRelocation(Rel, RE);
629 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
630 bool isExtern = (RE->Word1 >> 27) & 1;
631
632 DataRefImpl Sym;
633 Sym.d.a = Sym.d.b = 0;
634 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000635 if (isExtern) {
636 for (unsigned i = 0; i < SymbolIdx; i++) {
637 Sym.d.b++;
638 moveToNextSymbol(Sym);
Nick Lewycky58856ea2011-09-09 00:16:50 +0000639 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000640 "Relocation symbol index out of range!");
641 }
642 }
643 Res = SymbolRef(Sym, this);
644 return object_error::success;
645}
646error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000647 uint64_t &Res) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000648 InMemoryStruct<macho::RelocationEntry> RE;
649 getRelocation(Rel, RE);
Owen Andersonf8261e72011-10-26 17:10:22 +0000650 Res = RE->Word0;
651 Res <<= 32;
652 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000653 return object_error::success;
654}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000655error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
656 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000657 // TODO: Support scattered relocations.
658 StringRef res;
659 InMemoryStruct<macho::RelocationEntry> RE;
660 getRelocation(Rel, RE);
Owen Anderson0135fe12011-10-24 21:44:00 +0000661
662 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000663 bool isScattered = (Arch != Triple::x86_64) &&
664 (RE->Word0 & macho::RF_Scattered);
665
666 unsigned r_type;
667 if (isScattered)
668 r_type = (RE->Word0 >> 24) & 0xF;
669 else
670 r_type = (RE->Word1 >> 28) & 0xF;
671
Owen Anderson0135fe12011-10-24 21:44:00 +0000672 switch (Arch) {
673 case Triple::x86: {
674 const char* Table[] = {
675 "GENERIC_RELOC_VANILLA",
676 "GENERIC_RELOC_PAIR",
677 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000678 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000679 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000680 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000681
Owen Andersoneb6bd332011-10-27 20:46:09 +0000682 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000683 res = "Unknown";
684 else
685 res = Table[r_type];
686 break;
687 }
688 case Triple::x86_64: {
689 const char* Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000690 "X86_64_RELOC_UNSIGNED",
691 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000692 "X86_64_RELOC_BRANCH",
693 "X86_64_RELOC_GOT_LOAD",
694 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000695 "X86_64_RELOC_SUBTRACTOR",
696 "X86_64_RELOC_SIGNED_1",
697 "X86_64_RELOC_SIGNED_2",
698 "X86_64_RELOC_SIGNED_4",
699 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000700
Owen Andersond8fa76d2011-10-24 23:20:07 +0000701 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000702 res = "Unknown";
703 else
704 res = Table[r_type];
705 break;
706 }
707 case Triple::arm: {
708 const char* Table[] = {
709 "ARM_RELOC_VANILLA",
710 "ARM_RELOC_PAIR",
711 "ARM_RELOC_SECTDIFF",
712 "ARM_RELOC_LOCAL_SECTDIFF",
713 "ARM_RELOC_PB_LA_PTR",
714 "ARM_RELOC_BR24",
715 "ARM_THUMB_RELOC_BR22",
716 "ARM_THUMB_32BIT_BRANCH",
717 "ARM_RELOC_HALF",
718 "ARM_RELOC_HALF_SECTDIFF" };
719
720 if (r_type > 9)
721 res = "Unknown";
722 else
723 res = Table[r_type];
724 break;
725 }
726 case Triple::ppc: {
727 const char* Table[] = {
728 "PPC_RELOC_VANILLA",
729 "PPC_RELOC_PAIR",
730 "PPC_RELOC_BR14",
731 "PPC_RELOC_BR24",
732 "PPC_RELOC_HI16",
733 "PPC_RELOC_LO16",
734 "PPC_RELOC_HA16",
735 "PPC_RELOC_LO14",
736 "PPC_RELOC_SECTDIFF",
737 "PPC_RELOC_PB_LA_PTR",
738 "PPC_RELOC_HI16_SECTDIFF",
739 "PPC_RELOC_LO16_SECTDIFF",
740 "PPC_RELOC_HA16_SECTDIFF",
741 "PPC_RELOC_JBSR",
742 "PPC_RELOC_LO14_SECTDIFF",
743 "PPC_RELOC_LOCAL_SECTDIFF" };
744
745 res = Table[r_type];
746 break;
747 }
748 case Triple::UnknownArch:
749 res = "Unknown";
750 break;
751 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000752 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000753 return object_error::success;
754}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000755error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
756 int64_t &Res) const {
757 InMemoryStruct<macho::RelocationEntry> RE;
758 getRelocation(Rel, RE);
759 bool isExtern = (RE->Word1 >> 27) & 1;
760 Res = 0;
761 if (!isExtern) {
762 const uint8_t* sectAddress = base();
763 if (MachOObj->is64Bit()) {
764 InMemoryStruct<macho::Section64> Sect;
765 getSection64(Sections[Rel.d.b], Sect);
766 sectAddress += Sect->Offset;
767 } else {
768 InMemoryStruct<macho::Section> Sect;
769 getSection(Sections[Rel.d.b], Sect);
770 sectAddress += Sect->Offset;
771 }
772 Res = reinterpret_cast<uintptr_t>(sectAddress);
773 }
774 return object_error::success;
775}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000776
777// Helper to advance a section or symbol iterator multiple increments at a time.
778template<class T>
779error_code advance(T &it, size_t Val) {
780 error_code ec;
781 while (Val--) {
782 it.increment(ec);
783 }
784 return ec;
785}
786
787template<class T>
788void advanceTo(T &it, size_t Val) {
789 if (error_code ec = advance(it, Val))
790 report_fatal_error(ec.message());
791}
792
Owen Anderson1832f4d2011-10-26 20:42:54 +0000793void MachOObjectFile::printRelocationTargetName(
794 InMemoryStruct<macho::RelocationEntry>& RE,
795 raw_string_ostream &fmt) const {
796 unsigned Arch = getArch();
797 bool isScattered = (Arch != Triple::x86_64) &&
798 (RE->Word0 & macho::RF_Scattered);
799
800 // Target of a scattered relocation is an address. In the interest of
801 // generating pretty output, scan through the symbol table looking for a
802 // symbol that aligns with that address. If we find one, print it.
803 // Otherwise, we just print the hex address of the target.
804 if (isScattered) {
805 uint32_t Val = RE->Word1;
806
807 error_code ec;
808 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
809 SI.increment(ec)) {
810 if (ec) report_fatal_error(ec.message());
811
812 uint64_t Addr;
813 StringRef Name;
814
815 if ((ec = SI->getAddress(Addr)))
816 report_fatal_error(ec.message());
817 if (Addr != Val) continue;
818 if ((ec = SI->getName(Name)))
819 report_fatal_error(ec.message());
820 fmt << Name;
821 return;
822 }
823
824 fmt << format("0x%x", Val);
825 return;
826 }
827
828 StringRef S;
829 bool isExtern = (RE->Word1 >> 27) & 1;
830 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000831
832 if (isExtern) {
833 symbol_iterator SI = begin_symbols();
834 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000835 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000836 } else {
837 section_iterator SI = begin_sections();
838 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000839 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000840 }
841
Owen Anderson1832f4d2011-10-26 20:42:54 +0000842 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000843}
844
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000845error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
846 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000847 InMemoryStruct<macho::RelocationEntry> RE;
848 getRelocation(Rel, RE);
849
Owen Anderson1832f4d2011-10-26 20:42:54 +0000850 unsigned Arch = getArch();
851 bool isScattered = (Arch != Triple::x86_64) &&
852 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000853
Owen Anderson013d7562011-10-25 18:48:41 +0000854 std::string fmtbuf;
855 raw_string_ostream fmt(fmtbuf);
856
Owen Anderson1832f4d2011-10-26 20:42:54 +0000857 unsigned Type;
858 if (isScattered)
859 Type = (RE->Word0 >> 24) & 0xF;
860 else
861 Type = (RE->Word1 >> 28) & 0xF;
862
Owen Andersoneb6bd332011-10-27 20:46:09 +0000863 bool isPCRel;
864 if (isScattered)
865 isPCRel = ((RE->Word0 >> 30) & 1);
866 else
867 isPCRel = ((RE->Word1 >> 24) & 1);
868
Owen Andersond8fa76d2011-10-24 23:20:07 +0000869 // Determine any addends that should be displayed with the relocation.
870 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +0000871
872 // X86_64 has entirely custom relocation types.
873 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +0000874 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +0000875
Owen Andersond8fa76d2011-10-24 23:20:07 +0000876 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +0000877 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
878 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
879 printRelocationTargetName(RE, fmt);
880 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +0000881 if (isPCRel) fmt << "PCREL";
882 break;
883 }
Owen Anderson1832f4d2011-10-26 20:42:54 +0000884 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +0000885 InMemoryStruct<macho::RelocationEntry> RENext;
886 DataRefImpl RelNext = Rel;
887 RelNext.d.a++;
888 getRelocation(RelNext, RENext);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000889
890 // X86_64_SUBTRACTOR must be followed by a relocation of type
891 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +0000892 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +0000893 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000894 if (RType != 0)
895 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
896 "X86_64_RELOC_SUBTRACTOR.");
897
Owen Andersonef22f782011-10-26 17:28:49 +0000898 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
899 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +0000900 printRelocationTargetName(RENext, fmt);
901 fmt << "-";
902 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000903 }
Owen Andersoneb6bd332011-10-27 20:46:09 +0000904 case macho::RIT_X86_64_TLV:
905 printRelocationTargetName(RE, fmt);
906 fmt << "@TLV";
907 if (isPCRel) fmt << "P";
908 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000909 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
910 printRelocationTargetName(RE, fmt);
911 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +0000912 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000913 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
914 printRelocationTargetName(RE, fmt);
915 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +0000916 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000917 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
918 printRelocationTargetName(RE, fmt);
919 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +0000920 break;
921 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +0000922 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000923 break;
924 }
Owen Andersond8fa76d2011-10-24 23:20:07 +0000925 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +0000926 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
927 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +0000928 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +0000929 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +0000930 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +0000931 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +0000932 InMemoryStruct<macho::RelocationEntry> RENext;
933 DataRefImpl RelNext = Rel;
934 RelNext.d.a++;
935 getRelocation(RelNext, RENext);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000936
937 // X86 sect diff's must be followed by a relocation of type
938 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +0000939 bool isNextScattered = (Arch != Triple::x86_64) &&
940 (RENext->Word0 & macho::RF_Scattered);
941 unsigned RType;
942 if (isNextScattered)
943 RType = (RENext->Word0 >> 24) & 0xF;
944 else
945 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000946 if (RType != 1)
947 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +0000948 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +0000949
Owen Anderson1832f4d2011-10-26 20:42:54 +0000950 printRelocationTargetName(RE, fmt);
951 fmt << "-";
952 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +0000953 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000954 }
955 }
Owen Anderson013d7562011-10-25 18:48:41 +0000956
Owen Anderson1832f4d2011-10-26 20:42:54 +0000957 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +0000958 // All X86 relocations that need special printing were already
959 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +0000960 switch (Type) {
961 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
962 InMemoryStruct<macho::RelocationEntry> RENext;
963 DataRefImpl RelNext = Rel;
964 RelNext.d.a++;
965 getRelocation(RelNext, RENext);
966
967 // X86 sect diff's must be followed by a relocation of type
968 // GENERIC_RELOC_PAIR.
969 bool isNextScattered = (Arch != Triple::x86_64) &&
970 (RENext->Word0 & macho::RF_Scattered);
971 unsigned RType;
972 if (isNextScattered)
973 RType = (RENext->Word0 >> 24) & 0xF;
974 else
975 RType = (RENext->Word1 >> 28) & 0xF;
976 if (RType != 1)
977 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
978 "GENERIC_RELOC_LOCAL_SECTDIFF.");
979
980 printRelocationTargetName(RE, fmt);
981 fmt << "-";
982 printRelocationTargetName(RENext, fmt);
983 break;
984 }
985 case macho::RIT_Generic_TLV: {
986 printRelocationTargetName(RE, fmt);
987 fmt << "@TLV";
988 if (isPCRel) fmt << "P";
989 break;
990 }
991 default:
992 printRelocationTargetName(RE, fmt);
993 }
Owen Anderson013d7562011-10-25 18:48:41 +0000994 } else { // ARM-specific relocations
995 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +0000996 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
997 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +0000998 // Half relocations steal a bit from the length field to encode
999 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001000 bool isUpper;
1001 if (isScattered)
1002 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001003 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001004 isUpper = (RE->Word1 >> 25) & 1;
1005
1006 if (isUpper)
1007 fmt << ":upper16:(";
1008 else
1009 fmt << ":lower16:(";
1010 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001011
1012 InMemoryStruct<macho::RelocationEntry> RENext;
1013 DataRefImpl RelNext = Rel;
1014 RelNext.d.a++;
1015 getRelocation(RelNext, RENext);
1016
1017 // ARM half relocs must be followed by a relocation of type
1018 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001019 bool isNextScattered = (Arch != Triple::x86_64) &&
1020 (RENext->Word0 & macho::RF_Scattered);
1021 unsigned RType;
1022 if (isNextScattered)
1023 RType = (RENext->Word0 >> 24) & 0xF;
1024 else
1025 RType = (RENext->Word1 >> 28) & 0xF;
1026
Owen Anderson013d7562011-10-25 18:48:41 +00001027 if (RType != 1)
1028 report_fatal_error("Expected ARM_RELOC_PAIR after "
1029 "GENERIC_RELOC_HALF");
1030
Owen Anderson1832f4d2011-10-26 20:42:54 +00001031 // NOTE: The half of the target virtual address is stashed in the
1032 // address field of the secondary relocation, but we can't reverse
1033 // engineer the constant offset from it without decoding the movw/movt
1034 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001035
1036 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1037 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001038 if (Type == macho::RIT_ARM_HalfDifference) {
1039 fmt << "-";
1040 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001041 }
1042
Owen Anderson013d7562011-10-25 18:48:41 +00001043 fmt << ")";
1044 break;
1045 }
1046 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001047 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001048 }
1049 }
1050 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001051 } else
1052 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001053
Owen Anderson0135fe12011-10-24 21:44:00 +00001054 fmt.flush();
1055 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001056 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001057}
1058
Owen Anderson0685e942011-10-25 20:35:53 +00001059error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1060 bool &Result) const {
1061 InMemoryStruct<macho::RelocationEntry> RE;
1062 getRelocation(Rel, RE);
1063
Owen Anderson0685e942011-10-25 20:35:53 +00001064 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001065 bool isScattered = (Arch != Triple::x86_64) &&
1066 (RE->Word0 & macho::RF_Scattered);
1067 unsigned Type;
1068 if (isScattered)
1069 Type = (RE->Word0 >> 24) & 0xF;
1070 else
1071 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001072
1073 Result = false;
1074
1075 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1076 // is always hidden.
1077 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001078 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001079 } else if (Arch == Triple::x86_64) {
1080 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1081 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001082 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001083 DataRefImpl RelPrev = Rel;
1084 RelPrev.d.a--;
1085 InMemoryStruct<macho::RelocationEntry> REPrev;
1086 getRelocation(RelPrev, REPrev);
1087
1088 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1089
Owen Anderson1832f4d2011-10-26 20:42:54 +00001090 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001091 }
1092 }
1093
1094 return object_error::success;
1095}
1096
Eric Christopher6256b032011-04-22 03:19:48 +00001097/*===-- Miscellaneous -----------------------------------------------------===*/
1098
1099uint8_t MachOObjectFile::getBytesInAddress() const {
1100 return MachOObj->is64Bit() ? 8 : 4;
1101}
1102
1103StringRef MachOObjectFile::getFileFormatName() const {
1104 if (!MachOObj->is64Bit()) {
1105 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001106 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001107 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001108 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001109 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001110 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001111 return "Mach-O 32-bit ppc";
1112 default:
Eric Christopherf4b2f932011-04-22 06:34:01 +00001113 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001114 "64-bit object file when we're not 64-bit?");
1115 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001116 }
1117 }
1118
1119 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001120 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001121 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001122 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001123 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001124 default:
Eric Christopherf4b2f932011-04-22 06:34:01 +00001125 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001126 "32-bit object file when we're 64-bit?");
1127 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001128 }
1129}
1130
1131unsigned MachOObjectFile::getArch() const {
1132 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001133 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001134 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001135 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001136 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001137 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001138 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001139 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001140 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001141 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001142 return Triple::ppc64;
1143 default:
1144 return Triple::UnknownArch;
1145 }
1146}
1147
Owen Andersonf7c93a32011-10-11 17:32:27 +00001148} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001149} // end namespace llvm