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