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