blob: cbf6d0b2d864d7cad4872e0fc679e5fc55fab2ab [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 Malyshevb0436a72011-11-29 17:40:10 +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 Malyshevb0436a72011-11-29 17:40:10 +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 Malyshevb0436a72011-11-29 17:40:10 +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 Malyshevb0436a72011-11-29 17:40:10 +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 // Unfortunately symbols are unsorted so we need to touch all
183 // symbols from load command
184 DRI.d.b = 0;
185 uint32_t Command = DRI.d.a;
186 while (Command == DRI.d.a) {
187 moveToNextSymbol(DRI);
188 if (DRI.d.a < LoadCommandCount) {
189 getSymbol64TableEntry(DRI, Entry);
190 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
191 if (!EndOffset || Entry->Value < EndOffset)
192 EndOffset = Entry->Value;
193 }
194 DRI.d.b++;
195 }
196 } else {
197 InMemoryStruct<macho::SymbolTableEntry> Entry;
198 getSymbolTableEntry(DRI, Entry);
199 BeginOffset = Entry->Value;
200 SectionIndex = Entry->SectionIndex;
201 if (!SectionIndex) {
202 Result = UnknownAddressOrSize;
203 return object_error::success;
204 }
205 // Unfortunately symbols are unsorted so we need to touch all
206 // symbols from load command
207 DRI.d.b = 0;
208 uint32_t Command = DRI.d.a;
209 while (Command == DRI.d.a) {
210 moveToNextSymbol(DRI);
211 if (DRI.d.a < LoadCommandCount) {
212 getSymbolTableEntry(DRI, Entry);
213 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
214 if (!EndOffset || Entry->Value < EndOffset)
215 EndOffset = Entry->Value;
216 }
217 DRI.d.b++;
218 }
219 }
220 if (!EndOffset) {
221 uint64_t Size;
222 getSectionSize(Sections[SectionIndex-1], Size);
223 getSectionAddress(Sections[SectionIndex-1], EndOffset);
224 EndOffset += Size;
225 }
226 Result = EndOffset - BeginOffset;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000227 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000228}
229
Michael J. Spencer25b15772011-06-25 17:55:23 +0000230error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
231 char &Result) const {
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000232 uint8_t Type, Flags;
233 if (MachOObj->is64Bit()) {
234 InMemoryStruct<macho::Symbol64TableEntry> Entry;
235 getSymbol64TableEntry(DRI, Entry);
236 Type = Entry->Type;
237 Flags = Entry->Flags;
238 } else {
239 InMemoryStruct<macho::SymbolTableEntry> Entry;
240 getSymbolTableEntry(DRI, Entry);
241 Type = Entry->Type;
242 Flags = Entry->Flags;
243 }
Eric Christopher6256b032011-04-22 03:19:48 +0000244
245 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000246 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000247 case macho::STT_Undefined:
248 Char = 'u';
249 break;
250 case macho::STT_Absolute:
251 case macho::STT_Section:
252 Char = 's';
253 break;
254 default:
255 Char = '?';
256 break;
257 }
258
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000259 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Eric Christopher6256b032011-04-22 03:19:48 +0000260 Char = toupper(Char);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000261 Result = Char;
262 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000263}
264
David Meyerc46255a2012-02-28 23:47:53 +0000265error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
266 uint32_t &Result) const {
267 uint16_t MachOFlags;
268 uint8_t MachOType;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000269 if (MachOObj->is64Bit()) {
270 InMemoryStruct<macho::Symbol64TableEntry> Entry;
271 getSymbol64TableEntry(DRI, Entry);
David Meyerc46255a2012-02-28 23:47:53 +0000272 MachOFlags = Entry->Flags;
273 MachOType = Entry->Type;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000274 } else {
275 InMemoryStruct<macho::SymbolTableEntry> Entry;
276 getSymbolTableEntry(DRI, Entry);
David Meyerc46255a2012-02-28 23:47:53 +0000277 MachOFlags = Entry->Flags;
278 MachOType = Entry->Type;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000279 }
280
David Meyerc46255a2012-02-28 23:47:53 +0000281 Result = SymbolRef::SF_None;
282 if (MachOFlags & macho::STF_StabsEntryMask)
283 Result |= SymbolRef::SF_FormatSpecific;
284
285 if (MachOType & MachO::NlistMaskExternal)
286 Result |= SymbolRef::SF_Global;
287
288 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
289 Result |= SymbolRef::SF_Weak;
290
291 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
292 Result |= SymbolRef::SF_Absolute;
293
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000294 return object_error::success;
295}
296
297error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
298 section_iterator &Res) const {
299 uint8_t index;
300 if (MachOObj->is64Bit()) {
301 InMemoryStruct<macho::Symbol64TableEntry> Entry;
302 getSymbol64TableEntry(Symb, Entry);
303 index = Entry->SectionIndex;
304 } else {
305 InMemoryStruct<macho::SymbolTableEntry> Entry;
306 getSymbolTableEntry(Symb, Entry);
307 index = Entry->SectionIndex;
308 }
309
310 if (index == 0)
311 Res = end_sections();
312 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000313 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000314
315 return object_error::success;
316}
317
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000318error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000319 SymbolRef::Type &Res) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000320 uint8_t n_type;
321 if (MachOObj->is64Bit()) {
322 InMemoryStruct<macho::Symbol64TableEntry> Entry;
323 getSymbol64TableEntry(Symb, Entry);
324 n_type = Entry->Type;
325 } else {
326 InMemoryStruct<macho::SymbolTableEntry> Entry;
327 getSymbolTableEntry(Symb, Entry);
328 n_type = Entry->Type;
329 }
330 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000331
332 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000333 if (n_type & MachO::NlistMaskStab) {
334 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000335 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000336 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000337
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000338 switch (n_type & MachO::NlistMaskType) {
339 case MachO::NListTypeUndefined :
340 Res = SymbolRef::ST_External;
341 break;
342 case MachO::NListTypeSection :
343 Res = SymbolRef::ST_Function;
344 break;
345 }
346 return object_error::success;
347}
348
349
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000350symbol_iterator MachOObjectFile::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000351 // DRI.d.a = segment number; DRI.d.b = symbol index.
352 DataRefImpl DRI;
353 DRI.d.a = DRI.d.b = 0;
354 moveToNextSymbol(DRI);
355 return symbol_iterator(SymbolRef(DRI, this));
356}
357
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000358symbol_iterator MachOObjectFile::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000359 DataRefImpl DRI;
360 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
361 DRI.d.b = 0;
362 return symbol_iterator(SymbolRef(DRI, this));
363}
364
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000365symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
366 // TODO: implement
367 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
368}
369
370symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
371 // TODO: implement
372 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
373}
Eric Christopher6256b032011-04-22 03:19:48 +0000374
375/*===-- Sections ----------------------------------------------------------===*/
376
377void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
378 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
379 while (DRI.d.a < LoadCommandCount) {
380 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
381 if (LCI.Command.Type == macho::LCT_Segment) {
382 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
383 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
384 if (DRI.d.b < SegmentLoadCmd->NumSections)
385 return;
386 } else if (LCI.Command.Type == macho::LCT_Segment64) {
387 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
388 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
389 if (DRI.d.b < Segment64LoadCmd->NumSections)
390 return;
391 }
392
393 DRI.d.a++;
394 DRI.d.b = 0;
395 }
396}
397
Michael J. Spencer25b15772011-06-25 17:55:23 +0000398error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
399 SectionRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000400 DRI.d.b++;
401 moveToNextSection(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000402 Result = SectionRef(DRI, this);
403 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000404}
405
406void
407MachOObjectFile::getSection(DataRefImpl DRI,
408 InMemoryStruct<macho::Section> &Res) const {
409 InMemoryStruct<macho::SegmentLoadCommand> SLC;
410 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
411 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
412 MachOObj->ReadSection(LCI, DRI.d.b, Res);
413}
414
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000415std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
416 SectionList::const_iterator loc =
417 std::find(Sections.begin(), Sections.end(), Sec);
418 assert(loc != Sections.end() && "Sec is not a valid section!");
419 return std::distance(Sections.begin(), loc);
420}
421
Benjamin Kramer7d145782011-07-15 00:14:48 +0000422void
423MachOObjectFile::getSection64(DataRefImpl DRI,
424 InMemoryStruct<macho::Section64> &Res) const {
425 InMemoryStruct<macho::Segment64LoadCommand> SLC;
426 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
427 MachOObj->ReadSegment64LoadCommand(LCI, SLC);
428 MachOObj->ReadSection64(LCI, DRI.d.b, Res);
429}
430
431static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
432 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
433 if (LCI.Command.Type == macho::LCT_Segment64)
434 return true;
435 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
436 return false;
437}
438
Michael J. Spencer25b15772011-06-25 17:55:23 +0000439error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
440 StringRef &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000441 // FIXME: thread safety.
Michael J. Spencer25b15772011-06-25 17:55:23 +0000442 static char result[34];
Benjamin Kramer7d145782011-07-15 00:14:48 +0000443 if (is64BitLoadCommand(MachOObj, DRI)) {
444 InMemoryStruct<macho::Segment64LoadCommand> SLC;
445 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
446 MachOObj->ReadSegment64LoadCommand(LCI, SLC);
447 InMemoryStruct<macho::Section64> Sect;
448 MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
449
Benjamin Kramer291e7672011-07-15 00:29:02 +0000450 strcpy(result, Sect->SegmentName);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000451 strcat(result, ",");
452 strcat(result, Sect->Name);
453 } else {
454 InMemoryStruct<macho::SegmentLoadCommand> SLC;
455 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
456 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
457 InMemoryStruct<macho::Section> Sect;
458 MachOObj->ReadSection(LCI, DRI.d.b, Sect);
459
Benjamin Kramer291e7672011-07-15 00:29:02 +0000460 strcpy(result, Sect->SegmentName);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000461 strcat(result, ",");
462 strcat(result, Sect->Name);
463 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000464 Result = StringRef(result);
465 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000466}
467
Michael J. Spencer25b15772011-06-25 17:55:23 +0000468error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
469 uint64_t &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000470 if (is64BitLoadCommand(MachOObj, DRI)) {
471 InMemoryStruct<macho::Section64> Sect;
472 getSection64(DRI, Sect);
473 Result = Sect->Address;
474 } else {
475 InMemoryStruct<macho::Section> Sect;
476 getSection(DRI, Sect);
477 Result = Sect->Address;
478 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000479 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000480}
481
Michael J. Spencer25b15772011-06-25 17:55:23 +0000482error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
483 uint64_t &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000484 if (is64BitLoadCommand(MachOObj, DRI)) {
485 InMemoryStruct<macho::Section64> Sect;
486 getSection64(DRI, Sect);
487 Result = Sect->Size;
488 } else {
489 InMemoryStruct<macho::Section> Sect;
490 getSection(DRI, Sect);
491 Result = Sect->Size;
492 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000493 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000494}
495
Michael J. Spencer25b15772011-06-25 17:55:23 +0000496error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
497 StringRef &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000498 if (is64BitLoadCommand(MachOObj, DRI)) {
499 InMemoryStruct<macho::Section64> Sect;
500 getSection64(DRI, Sect);
501 Result = MachOObj->getData(Sect->Offset, Sect->Size);
502 } else {
503 InMemoryStruct<macho::Section> Sect;
504 getSection(DRI, Sect);
505 Result = MachOObj->getData(Sect->Offset, Sect->Size);
506 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000507 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000508}
509
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000510error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
511 uint64_t &Result) const {
512 if (is64BitLoadCommand(MachOObj, DRI)) {
513 InMemoryStruct<macho::Section64> Sect;
514 getSection64(DRI, Sect);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000515 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000516 } else {
517 InMemoryStruct<macho::Section> Sect;
518 getSection(DRI, Sect);
Michael J. Spencer15565ad2011-10-10 23:36:56 +0000519 Result = uint64_t(1) << Sect->Align;
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000520 }
521 return object_error::success;
522}
523
Michael J. Spencer25b15772011-06-25 17:55:23 +0000524error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
525 bool &Result) const {
Benjamin Kramer7d145782011-07-15 00:14:48 +0000526 if (is64BitLoadCommand(MachOObj, DRI)) {
527 InMemoryStruct<macho::Section64> Sect;
528 getSection64(DRI, Sect);
529 Result = !strcmp(Sect->Name, "__text");
530 } else {
531 InMemoryStruct<macho::Section> Sect;
532 getSection(DRI, Sect);
533 Result = !strcmp(Sect->Name, "__text");
534 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000535 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000536}
537
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000538error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
539 bool &Result) const {
540 // FIXME: Unimplemented.
541 Result = false;
542 return object_error::success;
543}
544
545error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
546 bool &Result) const {
547 // FIXME: Unimplemented.
548 Result = false;
549 return object_error::success;
550}
551
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000552error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
553 DataRefImpl Symb,
554 bool &Result) const {
Michael J. Spencer1130a792011-10-17 20:19:29 +0000555 SymbolRef::Type ST;
Owen Andersoncd749882011-10-12 22:21:32 +0000556 getSymbolType(Symb, ST);
557 if (ST == SymbolRef::ST_External) {
558 Result = false;
559 return object_error::success;
560 }
561
562 uint64_t SectBegin, SectEnd;
563 getSectionAddress(Sec, SectBegin);
564 getSectionSize(Sec, SectEnd);
565 SectEnd += SectBegin;
566
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000567 if (MachOObj->is64Bit()) {
568 InMemoryStruct<macho::Symbol64TableEntry> Entry;
569 getSymbol64TableEntry(Symb, Entry);
Owen Andersoncd749882011-10-12 22:21:32 +0000570 uint64_t SymAddr= Entry->Value;
571 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000572 } else {
573 InMemoryStruct<macho::SymbolTableEntry> Entry;
574 getSymbolTableEntry(Symb, Entry);
Owen Andersoncd749882011-10-12 22:21:32 +0000575 uint64_t SymAddr= Entry->Value;
576 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000577 }
Owen Andersoncd749882011-10-12 22:21:32 +0000578
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000579 return object_error::success;
580}
581
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000582relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
583 DataRefImpl ret;
584 ret.d.a = 0;
585 ret.d.b = getSectionIndex(Sec);
586 return relocation_iterator(RelocationRef(ret, this));
587}
588relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
589 uint32_t last_reloc;
590 if (is64BitLoadCommand(MachOObj, Sec)) {
591 InMemoryStruct<macho::Section64> Sect;
592 getSection64(Sec, Sect);
593 last_reloc = Sect->NumRelocationTableEntries;
594 } else {
595 InMemoryStruct<macho::Section> Sect;
596 getSection(Sec, Sect);
597 last_reloc = Sect->NumRelocationTableEntries;
598 }
599 DataRefImpl ret;
600 ret.d.a = last_reloc;
601 ret.d.b = getSectionIndex(Sec);
602 return relocation_iterator(RelocationRef(ret, this));
603}
604
605section_iterator MachOObjectFile::begin_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000606 DataRefImpl DRI;
607 DRI.d.a = DRI.d.b = 0;
608 moveToNextSection(DRI);
609 return section_iterator(SectionRef(DRI, this));
610}
611
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000612section_iterator MachOObjectFile::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000613 DataRefImpl DRI;
614 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
615 DRI.d.b = 0;
616 return section_iterator(SectionRef(DRI, this));
617}
618
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000619/*===-- Relocations -------------------------------------------------------===*/
620
621void MachOObjectFile::
622getRelocation(DataRefImpl Rel,
623 InMemoryStruct<macho::RelocationEntry> &Res) const {
624 uint32_t relOffset;
625 if (MachOObj->is64Bit()) {
626 InMemoryStruct<macho::Section64> Sect;
627 getSection64(Sections[Rel.d.b], Sect);
628 relOffset = Sect->RelocationTableOffset;
629 } else {
630 InMemoryStruct<macho::Section> Sect;
631 getSection(Sections[Rel.d.b], Sect);
632 relOffset = Sect->RelocationTableOffset;
633 }
634 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
635}
636error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
637 RelocationRef &Res) const {
638 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000639 Res = RelocationRef(Rel, this);
640 return object_error::success;
641}
642error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
643 uint64_t &Res) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000644 const uint8_t* sectAddress = 0;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000645 if (MachOObj->is64Bit()) {
646 InMemoryStruct<macho::Section64> Sect;
647 getSection64(Sections[Rel.d.b], Sect);
Owen Anderson0135fe12011-10-24 21:44:00 +0000648 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000649 } else {
650 InMemoryStruct<macho::Section> Sect;
651 getSection(Sections[Rel.d.b], Sect);
Owen Anderson0135fe12011-10-24 21:44:00 +0000652 sectAddress += Sect->Address;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000653 }
654 InMemoryStruct<macho::RelocationEntry> RE;
655 getRelocation(Rel, RE);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000656
657 unsigned Arch = getArch();
658 bool isScattered = (Arch != Triple::x86_64) &&
659 (RE->Word0 & macho::RF_Scattered);
660 uint64_t RelAddr = 0;
Danil Malyshevb0436a72011-11-29 17:40:10 +0000661 if (isScattered)
Owen Anderson1832f4d2011-10-26 20:42:54 +0000662 RelAddr = RE->Word0 & 0xFFFFFF;
663 else
664 RelAddr = RE->Word0;
665
666 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000667 return object_error::success;
668}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000669error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
670 uint64_t &Res) const {
671 InMemoryStruct<macho::RelocationEntry> RE;
672 getRelocation(Rel, RE);
673
674 unsigned Arch = getArch();
675 bool isScattered = (Arch != Triple::x86_64) &&
676 (RE->Word0 & macho::RF_Scattered);
677 if (isScattered)
678 Res = RE->Word0 & 0xFFFFFF;
679 else
680 Res = RE->Word0;
681 return object_error::success;
682}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000683error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
684 SymbolRef &Res) const {
685 InMemoryStruct<macho::RelocationEntry> RE;
686 getRelocation(Rel, RE);
687 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
688 bool isExtern = (RE->Word1 >> 27) & 1;
689
690 DataRefImpl Sym;
691 Sym.d.a = Sym.d.b = 0;
692 moveToNextSymbol(Sym);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000693 if (isExtern) {
694 for (unsigned i = 0; i < SymbolIdx; i++) {
695 Sym.d.b++;
696 moveToNextSymbol(Sym);
Nick Lewycky58856ea2011-09-09 00:16:50 +0000697 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000698 "Relocation symbol index out of range!");
699 }
700 }
701 Res = SymbolRef(Sym, this);
702 return object_error::success;
703}
704error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000705 uint64_t &Res) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000706 InMemoryStruct<macho::RelocationEntry> RE;
707 getRelocation(Rel, RE);
Owen Andersonf8261e72011-10-26 17:10:22 +0000708 Res = RE->Word0;
709 Res <<= 32;
710 Res |= RE->Word1;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000711 return object_error::success;
712}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000713error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
714 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000715 // TODO: Support scattered relocations.
716 StringRef res;
717 InMemoryStruct<macho::RelocationEntry> RE;
718 getRelocation(Rel, RE);
Owen Anderson0135fe12011-10-24 21:44:00 +0000719
720 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +0000721 bool isScattered = (Arch != Triple::x86_64) &&
722 (RE->Word0 & macho::RF_Scattered);
723
724 unsigned r_type;
725 if (isScattered)
726 r_type = (RE->Word0 >> 24) & 0xF;
727 else
728 r_type = (RE->Word1 >> 28) & 0xF;
729
Owen Anderson0135fe12011-10-24 21:44:00 +0000730 switch (Arch) {
731 case Triple::x86: {
732 const char* Table[] = {
733 "GENERIC_RELOC_VANILLA",
734 "GENERIC_RELOC_PAIR",
735 "GENERIC_RELOC_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000736 "GENERIC_RELOC_PB_LA_PTR",
Owen Anderson0135fe12011-10-24 21:44:00 +0000737 "GENERIC_RELOC_LOCAL_SECTDIFF",
Owen Andersoneb6bd332011-10-27 20:46:09 +0000738 "GENERIC_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000739
Owen Andersoneb6bd332011-10-27 20:46:09 +0000740 if (r_type > 6)
Owen Anderson0135fe12011-10-24 21:44:00 +0000741 res = "Unknown";
742 else
743 res = Table[r_type];
744 break;
745 }
746 case Triple::x86_64: {
747 const char* Table[] = {
Owen Andersond8fa76d2011-10-24 23:20:07 +0000748 "X86_64_RELOC_UNSIGNED",
749 "X86_64_RELOC_SIGNED",
Owen Anderson0135fe12011-10-24 21:44:00 +0000750 "X86_64_RELOC_BRANCH",
751 "X86_64_RELOC_GOT_LOAD",
752 "X86_64_RELOC_GOT",
Owen Andersond8fa76d2011-10-24 23:20:07 +0000753 "X86_64_RELOC_SUBTRACTOR",
754 "X86_64_RELOC_SIGNED_1",
755 "X86_64_RELOC_SIGNED_2",
756 "X86_64_RELOC_SIGNED_4",
757 "X86_64_RELOC_TLV" };
Owen Anderson0135fe12011-10-24 21:44:00 +0000758
Owen Andersond8fa76d2011-10-24 23:20:07 +0000759 if (r_type > 9)
Owen Anderson0135fe12011-10-24 21:44:00 +0000760 res = "Unknown";
761 else
762 res = Table[r_type];
763 break;
764 }
765 case Triple::arm: {
766 const char* Table[] = {
767 "ARM_RELOC_VANILLA",
768 "ARM_RELOC_PAIR",
769 "ARM_RELOC_SECTDIFF",
770 "ARM_RELOC_LOCAL_SECTDIFF",
771 "ARM_RELOC_PB_LA_PTR",
772 "ARM_RELOC_BR24",
773 "ARM_THUMB_RELOC_BR22",
774 "ARM_THUMB_32BIT_BRANCH",
775 "ARM_RELOC_HALF",
776 "ARM_RELOC_HALF_SECTDIFF" };
777
778 if (r_type > 9)
779 res = "Unknown";
780 else
781 res = Table[r_type];
782 break;
783 }
784 case Triple::ppc: {
785 const char* Table[] = {
786 "PPC_RELOC_VANILLA",
787 "PPC_RELOC_PAIR",
788 "PPC_RELOC_BR14",
789 "PPC_RELOC_BR24",
790 "PPC_RELOC_HI16",
791 "PPC_RELOC_LO16",
792 "PPC_RELOC_HA16",
793 "PPC_RELOC_LO14",
794 "PPC_RELOC_SECTDIFF",
795 "PPC_RELOC_PB_LA_PTR",
796 "PPC_RELOC_HI16_SECTDIFF",
797 "PPC_RELOC_LO16_SECTDIFF",
798 "PPC_RELOC_HA16_SECTDIFF",
799 "PPC_RELOC_JBSR",
800 "PPC_RELOC_LO14_SECTDIFF",
801 "PPC_RELOC_LOCAL_SECTDIFF" };
802
803 res = Table[r_type];
804 break;
805 }
806 case Triple::UnknownArch:
807 res = "Unknown";
808 break;
809 }
Owen Anderson5f4e02c2011-10-24 20:19:18 +0000810 Result.append(res.begin(), res.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000811 return object_error::success;
812}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000813error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
814 int64_t &Res) const {
815 InMemoryStruct<macho::RelocationEntry> RE;
816 getRelocation(Rel, RE);
817 bool isExtern = (RE->Word1 >> 27) & 1;
818 Res = 0;
819 if (!isExtern) {
820 const uint8_t* sectAddress = base();
821 if (MachOObj->is64Bit()) {
822 InMemoryStruct<macho::Section64> Sect;
823 getSection64(Sections[Rel.d.b], Sect);
824 sectAddress += Sect->Offset;
825 } else {
826 InMemoryStruct<macho::Section> Sect;
827 getSection(Sections[Rel.d.b], Sect);
828 sectAddress += Sect->Offset;
829 }
830 Res = reinterpret_cast<uintptr_t>(sectAddress);
831 }
832 return object_error::success;
833}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000834
835// Helper to advance a section or symbol iterator multiple increments at a time.
836template<class T>
837error_code advance(T &it, size_t Val) {
838 error_code ec;
839 while (Val--) {
840 it.increment(ec);
841 }
842 return ec;
843}
844
845template<class T>
846void advanceTo(T &it, size_t Val) {
847 if (error_code ec = advance(it, Val))
848 report_fatal_error(ec.message());
849}
850
Owen Anderson1832f4d2011-10-26 20:42:54 +0000851void MachOObjectFile::printRelocationTargetName(
852 InMemoryStruct<macho::RelocationEntry>& RE,
853 raw_string_ostream &fmt) const {
854 unsigned Arch = getArch();
855 bool isScattered = (Arch != Triple::x86_64) &&
856 (RE->Word0 & macho::RF_Scattered);
857
858 // Target of a scattered relocation is an address. In the interest of
859 // generating pretty output, scan through the symbol table looking for a
860 // symbol that aligns with that address. If we find one, print it.
861 // Otherwise, we just print the hex address of the target.
862 if (isScattered) {
863 uint32_t Val = RE->Word1;
864
865 error_code ec;
866 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
867 SI.increment(ec)) {
868 if (ec) report_fatal_error(ec.message());
869
870 uint64_t Addr;
871 StringRef Name;
872
873 if ((ec = SI->getAddress(Addr)))
874 report_fatal_error(ec.message());
875 if (Addr != Val) continue;
876 if ((ec = SI->getName(Name)))
877 report_fatal_error(ec.message());
878 fmt << Name;
879 return;
880 }
881
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000882 // If we couldn't find a symbol that this relocation refers to, try
883 // to find a section beginning instead.
884 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
885 SI.increment(ec)) {
886 if (ec) report_fatal_error(ec.message());
887
888 uint64_t Addr;
889 StringRef Name;
890
891 if ((ec = SI->getAddress(Addr)))
892 report_fatal_error(ec.message());
893 if (Addr != Val) continue;
894 if ((ec = SI->getName(Name)))
895 report_fatal_error(ec.message());
896 fmt << Name;
897 return;
898 }
899
Owen Anderson1832f4d2011-10-26 20:42:54 +0000900 fmt << format("0x%x", Val);
901 return;
902 }
903
904 StringRef S;
905 bool isExtern = (RE->Word1 >> 27) & 1;
906 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000907
908 if (isExtern) {
909 symbol_iterator SI = begin_symbols();
910 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000911 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000912 } else {
913 section_iterator SI = begin_sections();
914 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000915 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000916 }
917
Owen Anderson1832f4d2011-10-26 20:42:54 +0000918 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000919}
920
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000921error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
922 SmallVectorImpl<char> &Result) const {
Owen Anderson0135fe12011-10-24 21:44:00 +0000923 InMemoryStruct<macho::RelocationEntry> RE;
924 getRelocation(Rel, RE);
925
Owen Anderson1832f4d2011-10-26 20:42:54 +0000926 unsigned Arch = getArch();
927 bool isScattered = (Arch != Triple::x86_64) &&
928 (RE->Word0 & macho::RF_Scattered);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000929
Owen Anderson013d7562011-10-25 18:48:41 +0000930 std::string fmtbuf;
931 raw_string_ostream fmt(fmtbuf);
932
Owen Anderson1832f4d2011-10-26 20:42:54 +0000933 unsigned Type;
934 if (isScattered)
935 Type = (RE->Word0 >> 24) & 0xF;
936 else
937 Type = (RE->Word1 >> 28) & 0xF;
938
Owen Andersoneb6bd332011-10-27 20:46:09 +0000939 bool isPCRel;
940 if (isScattered)
941 isPCRel = ((RE->Word0 >> 30) & 1);
942 else
943 isPCRel = ((RE->Word1 >> 24) & 1);
944
Owen Andersond8fa76d2011-10-24 23:20:07 +0000945 // Determine any addends that should be displayed with the relocation.
946 // These require decoding the relocation type, which is triple-specific.
Owen Andersond8fa76d2011-10-24 23:20:07 +0000947
948 // X86_64 has entirely custom relocation types.
949 if (Arch == Triple::x86_64) {
Owen Anderson929e27c2011-10-26 17:05:20 +0000950 bool isPCRel = ((RE->Word1 >> 24) & 1);
Owen Anderson013d7562011-10-25 18:48:41 +0000951
Owen Andersond8fa76d2011-10-24 23:20:07 +0000952 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +0000953 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
954 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
955 printRelocationTargetName(RE, fmt);
956 fmt << "@GOT";
Owen Anderson929e27c2011-10-26 17:05:20 +0000957 if (isPCRel) fmt << "PCREL";
958 break;
959 }
Owen Anderson1832f4d2011-10-26 20:42:54 +0000960 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
Owen Anderson013d7562011-10-25 18:48:41 +0000961 InMemoryStruct<macho::RelocationEntry> RENext;
962 DataRefImpl RelNext = Rel;
963 RelNext.d.a++;
964 getRelocation(RelNext, RENext);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000965
966 // X86_64_SUBTRACTOR must be followed by a relocation of type
967 // X86_64_RELOC_UNSIGNED.
Owen Anderson1832f4d2011-10-26 20:42:54 +0000968 // NOTE: Scattered relocations don't exist on x86_64.
Owen Anderson013d7562011-10-25 18:48:41 +0000969 unsigned RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000970 if (RType != 0)
971 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
972 "X86_64_RELOC_SUBTRACTOR.");
973
Owen Andersonef22f782011-10-26 17:28:49 +0000974 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
975 // X86_64_SUBTRACTOR contains to the subtrahend.
Owen Anderson1832f4d2011-10-26 20:42:54 +0000976 printRelocationTargetName(RENext, fmt);
977 fmt << "-";
978 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000979 }
Owen Andersoneb6bd332011-10-27 20:46:09 +0000980 case macho::RIT_X86_64_TLV:
981 printRelocationTargetName(RE, fmt);
982 fmt << "@TLV";
983 if (isPCRel) fmt << "P";
984 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000985 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
986 printRelocationTargetName(RE, fmt);
987 fmt << "-1";
Owen Andersond8fa76d2011-10-24 23:20:07 +0000988 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000989 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
990 printRelocationTargetName(RE, fmt);
991 fmt << "-2";
Owen Andersond8fa76d2011-10-24 23:20:07 +0000992 break;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000993 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
994 printRelocationTargetName(RE, fmt);
995 fmt << "-4";
Owen Anderson013d7562011-10-25 18:48:41 +0000996 break;
997 default:
Owen Anderson1832f4d2011-10-26 20:42:54 +0000998 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000999 break;
1000 }
Owen Andersond8fa76d2011-10-24 23:20:07 +00001001 // X86 and ARM share some relocation types in common.
Owen Anderson013d7562011-10-25 18:48:41 +00001002 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1003 // Generic relocation types...
Owen Andersond8fa76d2011-10-24 23:20:07 +00001004 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001005 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
Owen Andersond8fa76d2011-10-24 23:20:07 +00001006 return object_error::success;
Owen Andersoneb6bd332011-10-27 20:46:09 +00001007 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001008 InMemoryStruct<macho::RelocationEntry> RENext;
1009 DataRefImpl RelNext = Rel;
1010 RelNext.d.a++;
1011 getRelocation(RelNext, RENext);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001012
1013 // X86 sect diff's must be followed by a relocation of type
1014 // GENERIC_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001015 bool isNextScattered = (Arch != Triple::x86_64) &&
1016 (RENext->Word0 & macho::RF_Scattered);
1017 unsigned RType;
1018 if (isNextScattered)
1019 RType = (RENext->Word0 >> 24) & 0xF;
1020 else
1021 RType = (RENext->Word1 >> 28) & 0xF;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001022 if (RType != 1)
1023 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
Owen Andersoneb6bd332011-10-27 20:46:09 +00001024 "GENERIC_RELOC_SECTDIFF.");
Owen Andersond8fa76d2011-10-24 23:20:07 +00001025
Owen Anderson1832f4d2011-10-26 20:42:54 +00001026 printRelocationTargetName(RE, fmt);
1027 fmt << "-";
1028 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001029 break;
Owen Andersond8fa76d2011-10-24 23:20:07 +00001030 }
1031 }
Owen Anderson013d7562011-10-25 18:48:41 +00001032
Owen Anderson1832f4d2011-10-26 20:42:54 +00001033 if (Arch == Triple::x86) {
Owen Anderson013d7562011-10-25 18:48:41 +00001034 // All X86 relocations that need special printing were already
1035 // handled in the generic code.
Owen Andersoneb6bd332011-10-27 20:46:09 +00001036 switch (Type) {
1037 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1038 InMemoryStruct<macho::RelocationEntry> RENext;
1039 DataRefImpl RelNext = Rel;
1040 RelNext.d.a++;
1041 getRelocation(RelNext, RENext);
1042
1043 // X86 sect diff's must be followed by a relocation of type
1044 // GENERIC_RELOC_PAIR.
1045 bool isNextScattered = (Arch != Triple::x86_64) &&
1046 (RENext->Word0 & macho::RF_Scattered);
1047 unsigned RType;
1048 if (isNextScattered)
1049 RType = (RENext->Word0 >> 24) & 0xF;
1050 else
1051 RType = (RENext->Word1 >> 28) & 0xF;
1052 if (RType != 1)
1053 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1054 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1055
1056 printRelocationTargetName(RE, fmt);
1057 fmt << "-";
1058 printRelocationTargetName(RENext, fmt);
1059 break;
1060 }
1061 case macho::RIT_Generic_TLV: {
1062 printRelocationTargetName(RE, fmt);
1063 fmt << "@TLV";
1064 if (isPCRel) fmt << "P";
1065 break;
1066 }
1067 default:
1068 printRelocationTargetName(RE, fmt);
1069 }
Owen Anderson013d7562011-10-25 18:48:41 +00001070 } else { // ARM-specific relocations
1071 switch (Type) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001072 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1073 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
Owen Anderson013d7562011-10-25 18:48:41 +00001074 // Half relocations steal a bit from the length field to encode
1075 // whether this is an upper16 or a lower16 relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001076 bool isUpper;
1077 if (isScattered)
1078 isUpper = (RE->Word0 >> 28) & 1;
Owen Anderson013d7562011-10-25 18:48:41 +00001079 else
Owen Anderson1832f4d2011-10-26 20:42:54 +00001080 isUpper = (RE->Word1 >> 25) & 1;
1081
1082 if (isUpper)
1083 fmt << ":upper16:(";
1084 else
1085 fmt << ":lower16:(";
1086 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001087
1088 InMemoryStruct<macho::RelocationEntry> RENext;
1089 DataRefImpl RelNext = Rel;
1090 RelNext.d.a++;
1091 getRelocation(RelNext, RENext);
1092
1093 // ARM half relocs must be followed by a relocation of type
1094 // ARM_RELOC_PAIR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001095 bool isNextScattered = (Arch != Triple::x86_64) &&
1096 (RENext->Word0 & macho::RF_Scattered);
1097 unsigned RType;
1098 if (isNextScattered)
1099 RType = (RENext->Word0 >> 24) & 0xF;
1100 else
1101 RType = (RENext->Word1 >> 28) & 0xF;
1102
Owen Anderson013d7562011-10-25 18:48:41 +00001103 if (RType != 1)
1104 report_fatal_error("Expected ARM_RELOC_PAIR after "
1105 "GENERIC_RELOC_HALF");
1106
Owen Anderson1832f4d2011-10-26 20:42:54 +00001107 // NOTE: The half of the target virtual address is stashed in the
1108 // address field of the secondary relocation, but we can't reverse
1109 // engineer the constant offset from it without decoding the movw/movt
1110 // instruction to find the other half in its immediate field.
Owen Anderson013d7562011-10-25 18:48:41 +00001111
1112 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1113 // symbol/section pointer of the follow-on relocation.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001114 if (Type == macho::RIT_ARM_HalfDifference) {
1115 fmt << "-";
1116 printRelocationTargetName(RENext, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001117 }
1118
Owen Anderson013d7562011-10-25 18:48:41 +00001119 fmt << ")";
1120 break;
1121 }
1122 default: {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001123 printRelocationTargetName(RE, fmt);
Owen Anderson013d7562011-10-25 18:48:41 +00001124 }
1125 }
1126 }
Owen Anderson1832f4d2011-10-26 20:42:54 +00001127 } else
1128 printRelocationTargetName(RE, fmt);
Owen Andersond8fa76d2011-10-24 23:20:07 +00001129
Owen Anderson0135fe12011-10-24 21:44:00 +00001130 fmt.flush();
1131 Result.append(fmtbuf.begin(), fmtbuf.end());
Michael J. Spencer4344b1e2011-10-07 19:25:32 +00001132 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +00001133}
1134
Owen Anderson0685e942011-10-25 20:35:53 +00001135error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1136 bool &Result) const {
1137 InMemoryStruct<macho::RelocationEntry> RE;
1138 getRelocation(Rel, RE);
1139
Owen Anderson0685e942011-10-25 20:35:53 +00001140 unsigned Arch = getArch();
Owen Anderson1832f4d2011-10-26 20:42:54 +00001141 bool isScattered = (Arch != Triple::x86_64) &&
1142 (RE->Word0 & macho::RF_Scattered);
1143 unsigned Type;
1144 if (isScattered)
1145 Type = (RE->Word0 >> 24) & 0xF;
1146 else
1147 Type = (RE->Word1 >> 28) & 0xF;
Owen Anderson0685e942011-10-25 20:35:53 +00001148
1149 Result = false;
1150
1151 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1152 // is always hidden.
1153 if (Arch == Triple::x86 || Arch == Triple::arm) {
Owen Anderson1832f4d2011-10-26 20:42:54 +00001154 if (Type == macho::RIT_Pair) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001155 } else if (Arch == Triple::x86_64) {
1156 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1157 // an X864_64_RELOC_SUBTRACTOR.
Owen Anderson1832f4d2011-10-26 20:42:54 +00001158 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
Owen Anderson0685e942011-10-25 20:35:53 +00001159 DataRefImpl RelPrev = Rel;
1160 RelPrev.d.a--;
1161 InMemoryStruct<macho::RelocationEntry> REPrev;
1162 getRelocation(RelPrev, REPrev);
1163
1164 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1165
Owen Anderson1832f4d2011-10-26 20:42:54 +00001166 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
Owen Anderson0685e942011-10-25 20:35:53 +00001167 }
1168 }
1169
1170 return object_error::success;
1171}
1172
Eric Christopher6256b032011-04-22 03:19:48 +00001173/*===-- Miscellaneous -----------------------------------------------------===*/
1174
1175uint8_t MachOObjectFile::getBytesInAddress() const {
1176 return MachOObj->is64Bit() ? 8 : 4;
1177}
1178
1179StringRef MachOObjectFile::getFileFormatName() const {
1180 if (!MachOObj->is64Bit()) {
1181 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001182 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001183 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001184 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001185 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001186 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001187 return "Mach-O 32-bit ppc";
1188 default:
Eric Christopherf4b2f932011-04-22 06:34:01 +00001189 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001190 "64-bit object file when we're not 64-bit?");
1191 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001192 }
1193 }
1194
1195 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001196 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001197 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +00001198 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001199 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +00001200 default:
Eric Christopherf4b2f932011-04-22 06:34:01 +00001201 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +00001202 "32-bit object file when we're 64-bit?");
1203 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +00001204 }
1205}
1206
1207unsigned MachOObjectFile::getArch() const {
1208 switch (MachOObj->getHeader().CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +00001209 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +00001210 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001211 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +00001212 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001213 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +00001214 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001215 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +00001216 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +00001217 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +00001218 return Triple::ppc64;
1219 default:
1220 return Triple::UnknownArch;
1221 }
1222}
1223
Owen Andersonf7c93a32011-10-11 17:32:27 +00001224} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001225} // end namespace llvm