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