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