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