]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - opencl/llvm.git/blob - lib/Object/MachOObjectFile.cpp
Make MachOObjectFile independent from MachOObject.
[opencl/llvm.git] / lib / Object / MachOObjectFile.cpp
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   }
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);
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());
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);
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());
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;
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;
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;
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;
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;
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;
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;
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;
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;
415 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
416                                            uint64_t &Val) const {
417   report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
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));
427 symbol_iterator MachOObjectFile::end_symbols() const {
428   DataRefImpl DRI;
429   DRI.d.a = getHeader()->NumLoadCommands;
430   return symbol_iterator(SymbolRef(DRI, this));
433 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
434   // TODO: implement
435   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
438 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
439   // TODO: implement
440   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
443 library_iterator MachOObjectFile::begin_libraries_needed() const {
444   // TODO: implement
445   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
448 library_iterator MachOObjectFile::end_libraries_needed() const {
449   // TODO: implement
450   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
453 StringRef MachOObjectFile::getLoadName() const {
454   // TODO: Implement
455   report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
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   }
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;
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;
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);
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);
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);
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);
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   }
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;
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   }
561 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
562   ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
563   return parseSegmentOrSectionName(Raw.data());
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;
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;
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;
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;
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;
626 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
627                                           bool &Result) const {
628   // FIXME: Unimplemented.
629   Result = false;
630   return object_error::success;
633 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
634                                          bool &Result) const {
635   // FIXME: Unimplemented.
636   Result = false;
637   return object_error::success;
640 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
641                                                           bool &Result) const {
642   // FIXME: Unimplemented.
643   Result = true;
644   return object_error::success;
647 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
648                                              bool &Result) const {
649   // FIXME: Unimplemented.
650   Result = false;
651   return object_error::success;
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;
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;
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;
710 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
711   DataRefImpl ret;
712   ret.d.b = getSectionIndex(Sec);
713   return relocation_iterator(RelocationRef(ret, this));
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));
730 section_iterator MachOObjectFile::begin_sections() const {
731   DataRefImpl DRI;
732   moveToNextSection(DRI);
733   return section_iterator(SectionRef(DRI, this));
736 section_iterator MachOObjectFile::end_sections() const {
737   DataRefImpl DRI;
738   DRI.d.a = getHeader()->NumLoadCommands;
739   return section_iterator(SectionRef(DRI, this));
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());
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;
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;
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;
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;
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;
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;
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;
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;
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());
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;
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;
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;
1279 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1280                                            LibraryRef &Res) const {
1281   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1284 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1285                                            StringRef &Res) const {
1286   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1290 /*===-- Miscellaneous -----------------------------------------------------===*/
1292 uint8_t MachOObjectFile::getBytesInAddress() const {
1293   return is64Bit() ? 8 : 4;
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   }
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   }
1344 } // end namespace object
1345 } // end namespace llvm