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