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