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