1 //===- 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 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/Triple.h"
17 #include "llvm/Object/MachOFormat.h"
18 #include "llvm/Support/DataExtractor.h"
19 #include "llvm/Support/Format.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include <cctype>
22 #include <cstring>
23 #include <limits>
25 using namespace llvm;
26 using namespace object;
28 namespace llvm {
29 namespace object {
31 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec)
32 : ObjectFile(Binary::ID_MachO, Object) {
33 DataRefImpl DRI;
34 moveToNextSection(DRI);
35 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
36 while (DRI.d.a < LoadCommandCount) {
37 Sections.push_back(DRI);
38 DRI.d.b++;
39 moveToNextSection(DRI);
40 }
41 }
43 bool MachOObjectFile::is64Bit() const {
44 StringRef Magic = getData(0, 4);
45 return (Magic == "\xFE\xED\xFA\xCF") || (Magic == "\xCF\xFA\xED\xFE");
46 }
48 const MachOFormat::LoadCommand *
49 MachOObjectFile::getLoadCommandInfo(unsigned Index) const {
50 uint64_t Offset;
51 uint64_t NewOffset = getHeaderSize();
52 const MachOFormat::LoadCommand *Load;
53 unsigned I = 0;
54 do {
55 Offset = NewOffset;
56 StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand));
57 Load = reinterpret_cast<const MachOFormat::LoadCommand*>(Data.data());
58 NewOffset = Offset + Load->Size;
59 ++I;
60 } while (I != Index + 1);
62 return Load;
63 }
65 void MachOObjectFile::ReadULEB128s(uint64_t Index,
66 SmallVectorImpl<uint64_t> &Out) const {
67 DataExtractor extractor(ObjectFile::getData(), true, 0);
69 uint32_t offset = Index;
70 uint64_t data = 0;
71 while (uint64_t delta = extractor.getULEB128(&offset)) {
72 data += delta;
73 Out.push_back(data);
74 }
75 }
77 const MachOFormat::Header *MachOObjectFile::getHeader() const {
78 StringRef Data = getData(0, sizeof(MachOFormat::Header));
79 return reinterpret_cast<const MachOFormat::Header*>(Data.data());
80 }
82 unsigned MachOObjectFile::getHeaderSize() const {
83 return is64Bit() ? macho::Header64Size : macho::Header32Size;
84 }
86 StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const {
87 return ObjectFile::getData().substr(Offset, Size);
88 }
90 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
91 error_code ec;
92 ObjectFile *Ret = new MachOObjectFile(Buffer, ec);
93 if (ec)
94 return NULL;
95 return Ret;
96 }
98 /*===-- Symbols -----------------------------------------------------------===*/
100 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
101 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
102 while (DRI.d.a < LoadCommandCount) {
103 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
104 if (Command->Type == macho::LCT_Symtab) {
105 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
106 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
107 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
108 return;
109 }
111 DRI.d.a++;
112 DRI.d.b = 0;
113 }
114 }
116 const MachOFormat::SymbolTableEntry *
117 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
118 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
119 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
120 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
122 return getSymbolTableEntry(DRI, SymtabLoadCmd);
123 }
125 const MachOFormat::SymbolTableEntry *
126 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
127 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
128 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
129 unsigned Index = DRI.d.b;
130 uint64_t Offset = (SymbolTableOffset +
131 Index * sizeof(macho::SymbolTableEntry));
132 StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry));
133 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
134 }
136 const MachOFormat::Symbol64TableEntry*
137 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
138 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
139 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
140 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
142 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
143 }
145 const MachOFormat::Symbol64TableEntry*
146 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
147 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
148 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
149 unsigned Index = DRI.d.b;
150 uint64_t Offset = (SymbolTableOffset +
151 Index * sizeof(macho::Symbol64TableEntry));
152 StringRef Data = getData(Offset, sizeof(MachOFormat::Symbol64TableEntry));
153 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
154 }
156 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
157 SymbolRef &Result) const {
158 DRI.d.b++;
159 moveToNextSymbol(DRI);
160 Result = SymbolRef(DRI, this);
161 return object_error::success;
162 }
164 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
165 StringRef &Result) const {
166 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
167 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
168 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
170 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
171 SymtabLoadCmd->StringTableSize);
173 uint32_t StringIndex;
174 if (is64Bit()) {
175 const MachOFormat::Symbol64TableEntry *Entry =
176 getSymbol64TableEntry(DRI, SymtabLoadCmd);
177 StringIndex = Entry->StringIndex;
178 } else {
179 const MachOFormat::SymbolTableEntry *Entry =
180 getSymbolTableEntry(DRI, SymtabLoadCmd);
181 StringIndex = Entry->StringIndex;
182 }
184 const char *Start = &StringTable.data()[StringIndex];
185 Result = StringRef(Start);
187 return object_error::success;
188 }
190 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
191 uint64_t &Result) const {
192 if (is64Bit()) {
193 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
194 Result = Entry->Value;
195 if (Entry->SectionIndex) {
196 const MachOFormat::Section64 *Section =
197 getSection64(Sections[Entry->SectionIndex-1]);
198 Result += Section->Offset - Section->Address;
199 }
200 } else {
201 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
202 Result = Entry->Value;
203 if (Entry->SectionIndex) {
204 const MachOFormat::Section *Section =
205 getSection(Sections[Entry->SectionIndex-1]);
206 Result += Section->Offset - Section->Address;
207 }
208 }
210 return object_error::success;
211 }
213 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
214 uint64_t &Result) const {
215 if (is64Bit()) {
216 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
217 Result = Entry->Value;
218 } else {
219 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
220 Result = Entry->Value;
221 }
222 return object_error::success;
223 }
225 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
226 uint64_t &Result) const {
227 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
228 uint64_t BeginOffset;
229 uint64_t EndOffset = 0;
230 uint8_t SectionIndex;
231 if (is64Bit()) {
232 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
233 BeginOffset = Entry->Value;
234 SectionIndex = Entry->SectionIndex;
235 if (!SectionIndex) {
236 uint32_t flags = SymbolRef::SF_None;
237 getSymbolFlags(DRI, flags);
238 if (flags & SymbolRef::SF_Common)
239 Result = Entry->Value;
240 else
241 Result = UnknownAddressOrSize;
242 return object_error::success;
243 }
244 // Unfortunately symbols are unsorted so we need to touch all
245 // symbols from load command
246 DRI.d.b = 0;
247 uint32_t Command = DRI.d.a;
248 while (Command == DRI.d.a) {
249 moveToNextSymbol(DRI);
250 if (DRI.d.a < LoadCommandCount) {
251 Entry = getSymbol64TableEntry(DRI);
252 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
253 if (!EndOffset || Entry->Value < EndOffset)
254 EndOffset = Entry->Value;
255 }
256 DRI.d.b++;
257 }
258 } else {
259 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
260 BeginOffset = Entry->Value;
261 SectionIndex = Entry->SectionIndex;
262 if (!SectionIndex) {
263 uint32_t flags = SymbolRef::SF_None;
264 getSymbolFlags(DRI, flags);
265 if (flags & SymbolRef::SF_Common)
266 Result = Entry->Value;
267 else
268 Result = UnknownAddressOrSize;
269 return object_error::success;
270 }
271 // Unfortunately symbols are unsorted so we need to touch all
272 // symbols from load command
273 DRI.d.b = 0;
274 uint32_t Command = DRI.d.a;
275 while (Command == DRI.d.a) {
276 moveToNextSymbol(DRI);
277 if (DRI.d.a < LoadCommandCount) {
278 Entry = getSymbolTableEntry(DRI);
279 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
280 if (!EndOffset || Entry->Value < EndOffset)
281 EndOffset = Entry->Value;
282 }
283 DRI.d.b++;
284 }
285 }
286 if (!EndOffset) {
287 uint64_t Size;
288 getSectionSize(Sections[SectionIndex-1], Size);
289 getSectionAddress(Sections[SectionIndex-1], EndOffset);
290 EndOffset += Size;
291 }
292 Result = EndOffset - BeginOffset;
293 return object_error::success;
294 }
296 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
297 char &Result) const {
298 uint8_t Type, Flags;
299 if (is64Bit()) {
300 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
301 Type = Entry->Type;
302 Flags = Entry->Flags;
303 } else {
304 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
305 Type = Entry->Type;
306 Flags = Entry->Flags;
307 }
309 char Char;
310 switch (Type & macho::STF_TypeMask) {
311 case macho::STT_Undefined:
312 Char = 'u';
313 break;
314 case macho::STT_Absolute:
315 case macho::STT_Section:
316 Char = 's';
317 break;
318 default:
319 Char = '?';
320 break;
321 }
323 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
324 Char = toupper(static_cast<unsigned char>(Char));
325 Result = Char;
326 return object_error::success;
327 }
329 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
330 uint32_t &Result) const {
331 uint16_t MachOFlags;
332 uint8_t MachOType;
333 if (is64Bit()) {
334 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
335 MachOFlags = Entry->Flags;
336 MachOType = Entry->Type;
337 } else {
338 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
339 MachOFlags = Entry->Flags;
340 MachOType = Entry->Type;
341 }
343 // TODO: Correctly set SF_ThreadLocal
344 Result = SymbolRef::SF_None;
346 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
347 Result |= SymbolRef::SF_Undefined;
349 if (MachOFlags & macho::STF_StabsEntryMask)
350 Result |= SymbolRef::SF_FormatSpecific;
352 if (MachOType & MachO::NlistMaskExternal) {
353 Result |= SymbolRef::SF_Global;
354 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
355 Result |= SymbolRef::SF_Common;
356 }
358 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
359 Result |= SymbolRef::SF_Weak;
361 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
362 Result |= SymbolRef::SF_Absolute;
364 return object_error::success;
365 }
367 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
368 section_iterator &Res) const {
369 uint8_t index;
370 if (is64Bit()) {
371 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
372 index = Entry->SectionIndex;
373 } else {
374 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
375 index = Entry->SectionIndex;
376 }
378 if (index == 0)
379 Res = end_sections();
380 else
381 Res = section_iterator(SectionRef(Sections[index-1], this));
383 return object_error::success;
384 }
386 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
387 SymbolRef::Type &Res) const {
388 uint8_t n_type;
389 if (is64Bit()) {
390 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
391 n_type = Entry->Type;
392 } else {
393 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
394 n_type = Entry->Type;
395 }
396 Res = SymbolRef::ST_Other;
398 // If this is a STAB debugging symbol, we can do nothing more.
399 if (n_type & MachO::NlistMaskStab) {
400 Res = SymbolRef::ST_Debug;
401 return object_error::success;
402 }
404 switch (n_type & MachO::NlistMaskType) {
405 case MachO::NListTypeUndefined :
406 Res = SymbolRef::ST_Unknown;
407 break;
408 case MachO::NListTypeSection :
409 Res = SymbolRef::ST_Function;
410 break;
411 }
412 return object_error::success;
413 }
415 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
416 uint64_t &Val) const {
417 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
418 }
420 symbol_iterator MachOObjectFile::begin_symbols() const {
421 // DRI.d.a = segment number; DRI.d.b = symbol index.
422 DataRefImpl DRI;
423 moveToNextSymbol(DRI);
424 return symbol_iterator(SymbolRef(DRI, this));
425 }
427 symbol_iterator MachOObjectFile::end_symbols() const {
428 DataRefImpl DRI;
429 DRI.d.a = getHeader()->NumLoadCommands;
430 return symbol_iterator(SymbolRef(DRI, this));
431 }
433 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
434 // TODO: implement
435 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
436 }
438 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
439 // TODO: implement
440 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
441 }
443 library_iterator MachOObjectFile::begin_libraries_needed() const {
444 // TODO: implement
445 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
446 }
448 library_iterator MachOObjectFile::end_libraries_needed() const {
449 // TODO: implement
450 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
451 }
453 StringRef MachOObjectFile::getLoadName() const {
454 // TODO: Implement
455 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
456 }
458 /*===-- Sections ----------------------------------------------------------===*/
460 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
461 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
462 while (DRI.d.a < LoadCommandCount) {
463 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
464 if (Command->Type == macho::LCT_Segment) {
465 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
466 reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Command);
467 if (DRI.d.b < SegmentLoadCmd->NumSections)
468 return;
469 } else if (Command->Type == macho::LCT_Segment64) {
470 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
471 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Command);
472 if (DRI.d.b < Segment64LoadCmd->NumSections)
473 return;
474 }
476 DRI.d.a++;
477 DRI.d.b = 0;
478 }
479 }
481 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
482 SectionRef &Result) const {
483 DRI.d.b++;
484 moveToNextSection(DRI);
485 Result = SectionRef(DRI, this);
486 return object_error::success;
487 }
489 static bool is64BitLoadCommand(const MachOObjectFile *MachOObj,
490 DataRefImpl DRI) {
491 const MachOFormat::LoadCommand *Command =
492 MachOObj->getLoadCommandInfo(DRI.d.a);
493 if (Command->Type == macho::LCT_Segment64)
494 return true;
495 assert(Command->Type == macho::LCT_Segment && "Unexpected Type.");
496 return false;
497 }
499 const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
500 assert(!is64BitLoadCommand(this, DRI));
501 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
502 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
503 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
504 DRI.d.b * sizeof(MachOFormat::Section);
505 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
506 }
508 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
509 SectionList::const_iterator loc =
510 std::find(Sections.begin(), Sections.end(), Sec);
511 assert(loc != Sections.end() && "Sec is not a valid section!");
512 return std::distance(Sections.begin(), loc);
513 }
515 const MachOFormat::Section64 *
516 MachOObjectFile::getSection64(DataRefImpl DRI) const {
517 assert(is64BitLoadCommand(this, DRI));
518 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
519 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
520 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
521 DRI.d.b * sizeof(MachOFormat::Section64);
522 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
523 }
525 static StringRef parseSegmentOrSectionName(const char *P) {
526 if (P[15] == 0)
527 // Null terminated.
528 return P;
529 // Not null terminated, so this is a 16 char string.
530 return StringRef(P, 16);
531 }
533 ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
534 if (is64BitLoadCommand(this, DRI)) {
535 const MachOFormat::Section64 *sec = getSection64(DRI);
536 return ArrayRef<char>(sec->Name);
537 } else {
538 const MachOFormat::Section *sec = getSection(DRI);
539 return ArrayRef<char>(sec->Name);
540 }
541 }
543 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
544 StringRef &Result) const {
545 ArrayRef<char> Raw = getSectionRawName(DRI);
546 Result = parseSegmentOrSectionName(Raw.data());
547 return object_error::success;
548 }
550 ArrayRef<char>
551 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
552 if (is64BitLoadCommand(this, Sec)) {
553 const MachOFormat::Section64 *sec = getSection64(Sec);
554 return ArrayRef<char>(sec->SegmentName, 16);
555 } else {
556 const MachOFormat::Section *sec = getSection(Sec);
557 return ArrayRef<char>(sec->SegmentName);
558 }
559 }
561 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
562 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
563 return parseSegmentOrSectionName(Raw.data());
564 }
566 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
567 uint64_t &Result) const {
568 if (is64BitLoadCommand(this, DRI)) {
569 const MachOFormat::Section64 *Sect = getSection64(DRI);
570 Result = Sect->Address;
571 } else {
572 const MachOFormat::Section *Sect = getSection(DRI);
573 Result = Sect->Address;
574 }
575 return object_error::success;
576 }
578 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
579 uint64_t &Result) const {
580 if (is64BitLoadCommand(this, DRI)) {
581 const MachOFormat::Section64 *Sect = getSection64(DRI);
582 Result = Sect->Size;
583 } else {
584 const MachOFormat::Section *Sect = getSection(DRI);
585 Result = Sect->Size;
586 }
587 return object_error::success;
588 }
590 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
591 StringRef &Result) const {
592 if (is64BitLoadCommand(this, DRI)) {
593 const MachOFormat::Section64 *Sect = getSection64(DRI);
594 Result = getData(Sect->Offset, Sect->Size);
595 } else {
596 const MachOFormat::Section *Sect = getSection(DRI);
597 Result = getData(Sect->Offset, Sect->Size);
598 }
599 return object_error::success;
600 }
602 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
603 uint64_t &Result) const {
604 if (is64BitLoadCommand(this, DRI)) {
605 const MachOFormat::Section64 *Sect = getSection64(DRI);
606 Result = uint64_t(1) << Sect->Align;
607 } else {
608 const MachOFormat::Section *Sect = getSection(DRI);
609 Result = uint64_t(1) << Sect->Align;
610 }
611 return object_error::success;
612 }
614 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
615 bool &Result) const {
616 if (is64BitLoadCommand(this, DRI)) {
617 const MachOFormat::Section64 *Sect = getSection64(DRI);
618 Result = Sect->Flags & macho::SF_PureInstructions;
619 } else {
620 const MachOFormat::Section *Sect = getSection(DRI);
621 Result = Sect->Flags & macho::SF_PureInstructions;
622 }
623 return object_error::success;
624 }
626 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
627 bool &Result) const {
628 // FIXME: Unimplemented.
629 Result = false;
630 return object_error::success;
631 }
633 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
634 bool &Result) const {
635 // FIXME: Unimplemented.
636 Result = false;
637 return object_error::success;
638 }
640 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
641 bool &Result) const {
642 // FIXME: Unimplemented.
643 Result = true;
644 return object_error::success;
645 }
647 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
648 bool &Result) const {
649 // FIXME: Unimplemented.
650 Result = false;
651 return object_error::success;
652 }
654 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
655 bool &Result) const {
656 if (is64Bit()) {
657 const MachOFormat::Section64 *Sect = getSection64(DRI);
658 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
659 Result = (SectionType == MachO::SectionTypeZeroFill ||
660 SectionType == MachO::SectionTypeZeroFillLarge);
661 } else {
662 const MachOFormat::Section *Sect = getSection(DRI);
663 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
664 Result = (SectionType == MachO::SectionTypeZeroFill ||
665 SectionType == MachO::SectionTypeZeroFillLarge);
666 }
668 return object_error::success;
669 }
671 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
672 bool &Result) const {
673 // Consider using the code from isSectionText to look for __const sections.
674 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
675 // to use section attributes to distinguish code from data.
677 // FIXME: Unimplemented.
678 Result = false;
679 return object_error::success;
680 }
682 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
683 DataRefImpl Symb,
684 bool &Result) const {
685 SymbolRef::Type ST;
686 getSymbolType(Symb, ST);
687 if (ST == SymbolRef::ST_Unknown) {
688 Result = false;
689 return object_error::success;
690 }
692 uint64_t SectBegin, SectEnd;
693 getSectionAddress(Sec, SectBegin);
694 getSectionSize(Sec, SectEnd);
695 SectEnd += SectBegin;
697 if (is64Bit()) {
698 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
699 uint64_t SymAddr= Entry->Value;
700 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
701 } else {
702 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
703 uint64_t SymAddr= Entry->Value;
704 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
705 }
707 return object_error::success;
708 }
710 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
711 DataRefImpl ret;
712 ret.d.b = getSectionIndex(Sec);
713 return relocation_iterator(RelocationRef(ret, this));
714 }
715 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
716 uint32_t last_reloc;
717 if (is64BitLoadCommand(this, Sec)) {
718 const MachOFormat::Section64 *Sect = getSection64(Sec);
719 last_reloc = Sect->NumRelocationTableEntries;
720 } else {
721 const MachOFormat::Section *Sect = getSection(Sec);
722 last_reloc = Sect->NumRelocationTableEntries;
723 }
724 DataRefImpl ret;
725 ret.d.a = last_reloc;
726 ret.d.b = getSectionIndex(Sec);
727 return relocation_iterator(RelocationRef(ret, this));
728 }
730 section_iterator MachOObjectFile::begin_sections() const {
731 DataRefImpl DRI;
732 moveToNextSection(DRI);
733 return section_iterator(SectionRef(DRI, this));
734 }
736 section_iterator MachOObjectFile::end_sections() const {
737 DataRefImpl DRI;
738 DRI.d.a = getHeader()->NumLoadCommands;
739 return section_iterator(SectionRef(DRI, this));
740 }
742 /*===-- Relocations -------------------------------------------------------===*/
744 const MachOFormat::RelocationEntry *
745 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
746 uint32_t relOffset;
747 if (is64Bit()) {
748 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
749 relOffset = Sect->RelocationTableOffset;
750 } else {
751 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
752 relOffset = Sect->RelocationTableOffset;
753 }
754 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
755 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
756 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
757 }
759 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
760 RelocationRef &Res) const {
761 ++Rel.d.a;
762 Res = RelocationRef(Rel, this);
763 return object_error::success;
764 }
765 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
766 uint64_t &Res) const {
767 const uint8_t* sectAddress = 0;
768 if (is64Bit()) {
769 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
770 sectAddress += Sect->Address;
771 } else {
772 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
773 sectAddress += Sect->Address;
774 }
775 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
777 unsigned Arch = getArch();
778 bool isScattered = (Arch != Triple::x86_64) &&
779 (RE->Word0 & macho::RF_Scattered);
780 uint64_t RelAddr = 0;
781 if (isScattered)
782 RelAddr = RE->Word0 & 0xFFFFFF;
783 else
784 RelAddr = RE->Word0;
786 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
787 return object_error::success;
788 }
789 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
790 uint64_t &Res) const {
791 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
793 unsigned Arch = getArch();
794 bool isScattered = (Arch != Triple::x86_64) &&
795 (RE->Word0 & macho::RF_Scattered);
796 if (isScattered)
797 Res = RE->Word0 & 0xFFFFFF;
798 else
799 Res = RE->Word0;
800 return object_error::success;
801 }
802 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
803 SymbolRef &Res) const {
804 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
805 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
806 bool isExtern = (RE->Word1 >> 27) & 1;
808 DataRefImpl Sym;
809 moveToNextSymbol(Sym);
810 if (isExtern) {
811 for (unsigned i = 0; i < SymbolIdx; i++) {
812 Sym.d.b++;
813 moveToNextSymbol(Sym);
814 assert(Sym.d.a < getHeader()->NumLoadCommands &&
815 "Relocation symbol index out of range!");
816 }
817 }
818 Res = SymbolRef(Sym, this);
819 return object_error::success;
820 }
821 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
822 uint64_t &Res) const {
823 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
824 Res = RE->Word0;
825 Res <<= 32;
826 Res |= RE->Word1;
827 return object_error::success;
828 }
829 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
830 SmallVectorImpl<char> &Result) const {
831 // TODO: Support scattered relocations.
832 StringRef res;
833 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
835 unsigned Arch = getArch();
836 bool isScattered = (Arch != Triple::x86_64) &&
837 (RE->Word0 & macho::RF_Scattered);
839 unsigned r_type;
840 if (isScattered)
841 r_type = (RE->Word0 >> 24) & 0xF;
842 else
843 r_type = (RE->Word1 >> 28) & 0xF;
845 switch (Arch) {
846 case Triple::x86: {
847 static const char *const Table[] = {
848 "GENERIC_RELOC_VANILLA",
849 "GENERIC_RELOC_PAIR",
850 "GENERIC_RELOC_SECTDIFF",
851 "GENERIC_RELOC_PB_LA_PTR",
852 "GENERIC_RELOC_LOCAL_SECTDIFF",
853 "GENERIC_RELOC_TLV" };
855 if (r_type > 6)
856 res = "Unknown";
857 else
858 res = Table[r_type];
859 break;
860 }
861 case Triple::x86_64: {
862 static const char *const Table[] = {
863 "X86_64_RELOC_UNSIGNED",
864 "X86_64_RELOC_SIGNED",
865 "X86_64_RELOC_BRANCH",
866 "X86_64_RELOC_GOT_LOAD",
867 "X86_64_RELOC_GOT",
868 "X86_64_RELOC_SUBTRACTOR",
869 "X86_64_RELOC_SIGNED_1",
870 "X86_64_RELOC_SIGNED_2",
871 "X86_64_RELOC_SIGNED_4",
872 "X86_64_RELOC_TLV" };
874 if (r_type > 9)
875 res = "Unknown";
876 else
877 res = Table[r_type];
878 break;
879 }
880 case Triple::arm: {
881 static const char *const Table[] = {
882 "ARM_RELOC_VANILLA",
883 "ARM_RELOC_PAIR",
884 "ARM_RELOC_SECTDIFF",
885 "ARM_RELOC_LOCAL_SECTDIFF",
886 "ARM_RELOC_PB_LA_PTR",
887 "ARM_RELOC_BR24",
888 "ARM_THUMB_RELOC_BR22",
889 "ARM_THUMB_32BIT_BRANCH",
890 "ARM_RELOC_HALF",
891 "ARM_RELOC_HALF_SECTDIFF" };
893 if (r_type > 9)
894 res = "Unknown";
895 else
896 res = Table[r_type];
897 break;
898 }
899 case Triple::ppc: {
900 static const char *const Table[] = {
901 "PPC_RELOC_VANILLA",
902 "PPC_RELOC_PAIR",
903 "PPC_RELOC_BR14",
904 "PPC_RELOC_BR24",
905 "PPC_RELOC_HI16",
906 "PPC_RELOC_LO16",
907 "PPC_RELOC_HA16",
908 "PPC_RELOC_LO14",
909 "PPC_RELOC_SECTDIFF",
910 "PPC_RELOC_PB_LA_PTR",
911 "PPC_RELOC_HI16_SECTDIFF",
912 "PPC_RELOC_LO16_SECTDIFF",
913 "PPC_RELOC_HA16_SECTDIFF",
914 "PPC_RELOC_JBSR",
915 "PPC_RELOC_LO14_SECTDIFF",
916 "PPC_RELOC_LOCAL_SECTDIFF" };
918 res = Table[r_type];
919 break;
920 }
921 case Triple::UnknownArch:
922 res = "Unknown";
923 break;
924 }
925 Result.append(res.begin(), res.end());
926 return object_error::success;
927 }
928 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
929 int64_t &Res) const {
930 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
931 bool isExtern = (RE->Word1 >> 27) & 1;
932 Res = 0;
933 if (!isExtern) {
934 const uint8_t* sectAddress = base();
935 if (is64Bit()) {
936 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
937 sectAddress += Sect->Offset;
938 } else {
939 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
940 sectAddress += Sect->Offset;
941 }
942 Res = reinterpret_cast<uintptr_t>(sectAddress);
943 }
944 return object_error::success;
945 }
947 // Helper to advance a section or symbol iterator multiple increments at a time.
948 template<class T>
949 error_code advance(T &it, size_t Val) {
950 error_code ec;
951 while (Val--) {
952 it.increment(ec);
953 }
954 return ec;
955 }
957 template<class T>
958 void advanceTo(T &it, size_t Val) {
959 if (error_code ec = advance(it, Val))
960 report_fatal_error(ec.message());
961 }
963 void MachOObjectFile::printRelocationTargetName(
964 const MachOFormat::RelocationEntry *RE,
965 raw_string_ostream &fmt) const {
966 unsigned Arch = getArch();
967 bool isScattered = (Arch != Triple::x86_64) &&
968 (RE->Word0 & macho::RF_Scattered);
970 // Target of a scattered relocation is an address. In the interest of
971 // generating pretty output, scan through the symbol table looking for a
972 // symbol that aligns with that address. If we find one, print it.
973 // Otherwise, we just print the hex address of the target.
974 if (isScattered) {
975 uint32_t Val = RE->Word1;
977 error_code ec;
978 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
979 SI.increment(ec)) {
980 if (ec) report_fatal_error(ec.message());
982 uint64_t Addr;
983 StringRef Name;
985 if ((ec = SI->getAddress(Addr)))
986 report_fatal_error(ec.message());
987 if (Addr != Val) continue;
988 if ((ec = SI->getName(Name)))
989 report_fatal_error(ec.message());
990 fmt << Name;
991 return;
992 }
994 // If we couldn't find a symbol that this relocation refers to, try
995 // to find a section beginning instead.
996 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
997 SI.increment(ec)) {
998 if (ec) report_fatal_error(ec.message());
1000 uint64_t Addr;
1001 StringRef Name;
1003 if ((ec = SI->getAddress(Addr)))
1004 report_fatal_error(ec.message());
1005 if (Addr != Val) continue;
1006 if ((ec = SI->getName(Name)))
1007 report_fatal_error(ec.message());
1008 fmt << Name;
1009 return;
1010 }
1012 fmt << format("0x%x", Val);
1013 return;
1014 }
1016 StringRef S;
1017 bool isExtern = (RE->Word1 >> 27) & 1;
1018 uint32_t Val = RE->Word1 & 0xFFFFFF;
1020 if (isExtern) {
1021 symbol_iterator SI = begin_symbols();
1022 advanceTo(SI, Val);
1023 SI->getName(S);
1024 } else {
1025 section_iterator SI = begin_sections();
1026 advanceTo(SI, Val);
1027 SI->getName(S);
1028 }
1030 fmt << S;
1031 }
1033 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1034 SmallVectorImpl<char> &Result) const {
1035 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1037 unsigned Arch = getArch();
1038 bool isScattered = (Arch != Triple::x86_64) &&
1039 (RE->Word0 & macho::RF_Scattered);
1041 std::string fmtbuf;
1042 raw_string_ostream fmt(fmtbuf);
1044 unsigned Type;
1045 if (isScattered)
1046 Type = (RE->Word0 >> 24) & 0xF;
1047 else
1048 Type = (RE->Word1 >> 28) & 0xF;
1050 bool isPCRel;
1051 if (isScattered)
1052 isPCRel = ((RE->Word0 >> 30) & 1);
1053 else
1054 isPCRel = ((RE->Word1 >> 24) & 1);
1056 // Determine any addends that should be displayed with the relocation.
1057 // These require decoding the relocation type, which is triple-specific.
1059 // X86_64 has entirely custom relocation types.
1060 if (Arch == Triple::x86_64) {
1061 bool isPCRel = ((RE->Word1 >> 24) & 1);
1063 switch (Type) {
1064 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1065 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1066 printRelocationTargetName(RE, fmt);
1067 fmt << "@GOT";
1068 if (isPCRel) fmt << "PCREL";
1069 break;
1070 }
1071 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1072 DataRefImpl RelNext = Rel;
1073 RelNext.d.a++;
1074 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1076 // X86_64_SUBTRACTOR must be followed by a relocation of type
1077 // X86_64_RELOC_UNSIGNED.
1078 // NOTE: Scattered relocations don't exist on x86_64.
1079 unsigned RType = (RENext->Word1 >> 28) & 0xF;
1080 if (RType != 0)
1081 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1082 "X86_64_RELOC_SUBTRACTOR.");
1084 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1085 // X86_64_SUBTRACTOR contains to the subtrahend.
1086 printRelocationTargetName(RENext, fmt);
1087 fmt << "-";
1088 printRelocationTargetName(RE, fmt);
1089 break;
1090 }
1091 case macho::RIT_X86_64_TLV:
1092 printRelocationTargetName(RE, fmt);
1093 fmt << "@TLV";
1094 if (isPCRel) fmt << "P";
1095 break;
1096 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1097 printRelocationTargetName(RE, fmt);
1098 fmt << "-1";
1099 break;
1100 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1101 printRelocationTargetName(RE, fmt);
1102 fmt << "-2";
1103 break;
1104 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1105 printRelocationTargetName(RE, fmt);
1106 fmt << "-4";
1107 break;
1108 default:
1109 printRelocationTargetName(RE, fmt);
1110 break;
1111 }
1112 // X86 and ARM share some relocation types in common.
1113 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1114 // Generic relocation types...
1115 switch (Type) {
1116 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1117 return object_error::success;
1118 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1119 DataRefImpl RelNext = Rel;
1120 RelNext.d.a++;
1121 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1123 // X86 sect diff's must be followed by a relocation of type
1124 // GENERIC_RELOC_PAIR.
1125 bool isNextScattered = (Arch != Triple::x86_64) &&
1126 (RENext->Word0 & macho::RF_Scattered);
1127 unsigned RType;
1128 if (isNextScattered)
1129 RType = (RENext->Word0 >> 24) & 0xF;
1130 else
1131 RType = (RENext->Word1 >> 28) & 0xF;
1132 if (RType != 1)
1133 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1134 "GENERIC_RELOC_SECTDIFF.");
1136 printRelocationTargetName(RE, fmt);
1137 fmt << "-";
1138 printRelocationTargetName(RENext, fmt);
1139 break;
1140 }
1141 }
1143 if (Arch == Triple::x86) {
1144 // All X86 relocations that need special printing were already
1145 // handled in the generic code.
1146 switch (Type) {
1147 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1148 DataRefImpl RelNext = Rel;
1149 RelNext.d.a++;
1150 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1152 // X86 sect diff's must be followed by a relocation of type
1153 // GENERIC_RELOC_PAIR.
1154 bool isNextScattered = (Arch != Triple::x86_64) &&
1155 (RENext->Word0 & macho::RF_Scattered);
1156 unsigned RType;
1157 if (isNextScattered)
1158 RType = (RENext->Word0 >> 24) & 0xF;
1159 else
1160 RType = (RENext->Word1 >> 28) & 0xF;
1161 if (RType != 1)
1162 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1163 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1165 printRelocationTargetName(RE, fmt);
1166 fmt << "-";
1167 printRelocationTargetName(RENext, fmt);
1168 break;
1169 }
1170 case macho::RIT_Generic_TLV: {
1171 printRelocationTargetName(RE, fmt);
1172 fmt << "@TLV";
1173 if (isPCRel) fmt << "P";
1174 break;
1175 }
1176 default:
1177 printRelocationTargetName(RE, fmt);
1178 }
1179 } else { // ARM-specific relocations
1180 switch (Type) {
1181 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1182 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1183 // Half relocations steal a bit from the length field to encode
1184 // whether this is an upper16 or a lower16 relocation.
1185 bool isUpper;
1186 if (isScattered)
1187 isUpper = (RE->Word0 >> 28) & 1;
1188 else
1189 isUpper = (RE->Word1 >> 25) & 1;
1191 if (isUpper)
1192 fmt << ":upper16:(";
1193 else
1194 fmt << ":lower16:(";
1195 printRelocationTargetName(RE, fmt);
1197 DataRefImpl RelNext = Rel;
1198 RelNext.d.a++;
1199 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1201 // ARM half relocs must be followed by a relocation of type
1202 // ARM_RELOC_PAIR.
1203 bool isNextScattered = (Arch != Triple::x86_64) &&
1204 (RENext->Word0 & macho::RF_Scattered);
1205 unsigned RType;
1206 if (isNextScattered)
1207 RType = (RENext->Word0 >> 24) & 0xF;
1208 else
1209 RType = (RENext->Word1 >> 28) & 0xF;
1211 if (RType != 1)
1212 report_fatal_error("Expected ARM_RELOC_PAIR after "
1213 "GENERIC_RELOC_HALF");
1215 // NOTE: The half of the target virtual address is stashed in the
1216 // address field of the secondary relocation, but we can't reverse
1217 // engineer the constant offset from it without decoding the movw/movt
1218 // instruction to find the other half in its immediate field.
1220 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1221 // symbol/section pointer of the follow-on relocation.
1222 if (Type == macho::RIT_ARM_HalfDifference) {
1223 fmt << "-";
1224 printRelocationTargetName(RENext, fmt);
1225 }
1227 fmt << ")";
1228 break;
1229 }
1230 default: {
1231 printRelocationTargetName(RE, fmt);
1232 }
1233 }
1234 }
1235 } else
1236 printRelocationTargetName(RE, fmt);
1238 fmt.flush();
1239 Result.append(fmtbuf.begin(), fmtbuf.end());
1240 return object_error::success;
1241 }
1243 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1244 bool &Result) const {
1245 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1247 unsigned Arch = getArch();
1248 bool isScattered = (Arch != Triple::x86_64) &&
1249 (RE->Word0 & macho::RF_Scattered);
1250 unsigned Type;
1251 if (isScattered)
1252 Type = (RE->Word0 >> 24) & 0xF;
1253 else
1254 Type = (RE->Word1 >> 28) & 0xF;
1256 Result = false;
1258 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1259 // is always hidden.
1260 if (Arch == Triple::x86 || Arch == Triple::arm) {
1261 if (Type == macho::RIT_Pair) Result = true;
1262 } else if (Arch == Triple::x86_64) {
1263 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1264 // an X864_64_RELOC_SUBTRACTOR.
1265 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1266 DataRefImpl RelPrev = Rel;
1267 RelPrev.d.a--;
1268 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
1270 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1272 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1273 }
1274 }
1276 return object_error::success;
1277 }
1279 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1280 LibraryRef &Res) const {
1281 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1282 }
1284 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1285 StringRef &Res) const {
1286 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1287 }
1290 /*===-- Miscellaneous -----------------------------------------------------===*/
1292 uint8_t MachOObjectFile::getBytesInAddress() const {
1293 return is64Bit() ? 8 : 4;
1294 }
1296 StringRef MachOObjectFile::getFileFormatName() const {
1297 if (!is64Bit()) {
1298 switch (getHeader()->CPUType) {
1299 case llvm::MachO::CPUTypeI386:
1300 return "Mach-O 32-bit i386";
1301 case llvm::MachO::CPUTypeARM:
1302 return "Mach-O arm";
1303 case llvm::MachO::CPUTypePowerPC:
1304 return "Mach-O 32-bit ppc";
1305 default:
1306 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1307 "64-bit object file when we're not 64-bit?");
1308 return "Mach-O 32-bit unknown";
1309 }
1310 }
1312 // Make sure the cpu type has the correct mask.
1313 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
1314 == llvm::MachO::CPUArchABI64 &&
1315 "32-bit object file when we're 64-bit?");
1317 switch (getHeader()->CPUType) {
1318 case llvm::MachO::CPUTypeX86_64:
1319 return "Mach-O 64-bit x86-64";
1320 case llvm::MachO::CPUTypePowerPC64:
1321 return "Mach-O 64-bit ppc64";
1322 default:
1323 return "Mach-O 64-bit unknown";
1324 }
1325 }
1327 unsigned MachOObjectFile::getArch() const {
1328 switch (getHeader()->CPUType) {
1329 case llvm::MachO::CPUTypeI386:
1330 return Triple::x86;
1331 case llvm::MachO::CPUTypeX86_64:
1332 return Triple::x86_64;
1333 case llvm::MachO::CPUTypeARM:
1334 return Triple::arm;
1335 case llvm::MachO::CPUTypePowerPC:
1336 return Triple::ppc;
1337 case llvm::MachO::CPUTypePowerPC64:
1338 return Triple::ppc64;
1339 default:
1340 return Triple::UnknownArch;
1341 }
1342 }
1344 } // end namespace object
1345 } // end namespace llvm