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