Cosmetic changes
[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
367 symbol_iterator MachOObjectFile::begin_symbols() const {
368   // DRI.d.a = segment number; DRI.d.b = symbol index.
369   DataRefImpl DRI;
370   moveToNextSymbol(DRI);
371   return symbol_iterator(SymbolRef(DRI, this));
372 }
373
374 symbol_iterator MachOObjectFile::end_symbols() const {
375   DataRefImpl DRI;
376   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
377   return symbol_iterator(SymbolRef(DRI, this));
378 }
379
380 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
381   // TODO: implement
382   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
383 }
384
385 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
386   // TODO: implement
387   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
388 }
389
390 library_iterator MachOObjectFile::begin_libraries_needed() const {
391   // TODO: implement
392   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
393 }
394
395 library_iterator MachOObjectFile::end_libraries_needed() const {
396   // TODO: implement
397   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
398 }
399
400 StringRef MachOObjectFile::getLoadName() const {
401   // TODO: Implement
402   report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
403 }
404
405 /*===-- Sections ----------------------------------------------------------===*/
406
407 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
408   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
409   while (DRI.d.a < LoadCommandCount) {
410     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
411     if (LCI.Command.Type == macho::LCT_Segment) {
412       InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
413       MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
414       if (DRI.d.b < SegmentLoadCmd->NumSections)
415         return;
416     } else if (LCI.Command.Type == macho::LCT_Segment64) {
417       InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
418       MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
419       if (DRI.d.b < Segment64LoadCmd->NumSections)
420         return;
421     }
422
423     DRI.d.a++;
424     DRI.d.b = 0;
425   }
426 }
427
428 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
429                                            SectionRef &Result) const {
430   DRI.d.b++;
431   moveToNextSection(DRI);
432   Result = SectionRef(DRI, this);
433   return object_error::success;
434 }
435
436 void
437 MachOObjectFile::getSection(DataRefImpl DRI,
438                             InMemoryStruct<macho::Section> &Res) const {
439   InMemoryStruct<macho::SegmentLoadCommand> SLC;
440   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
441   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
442   MachOObj->ReadSection(LCI, DRI.d.b, Res);
443 }
444
445 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
446   SectionList::const_iterator loc =
447     std::find(Sections.begin(), Sections.end(), Sec);
448   assert(loc != Sections.end() && "Sec is not a valid section!");
449   return std::distance(Sections.begin(), loc);
450 }
451
452 void
453 MachOObjectFile::getSection64(DataRefImpl DRI,
454                             InMemoryStruct<macho::Section64> &Res) const {
455   InMemoryStruct<macho::Segment64LoadCommand> SLC;
456   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
457   MachOObj->ReadSegment64LoadCommand(LCI, SLC);
458   MachOObj->ReadSection64(LCI, DRI.d.b, Res);
459 }
460
461 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
462   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
463   if (LCI.Command.Type == macho::LCT_Segment64)
464     return true;
465   assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
466   return false;
467 }
468
469 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
470                                            StringRef &Result) const {
471   // FIXME: thread safety.
472   static char result[34];
473   if (is64BitLoadCommand(MachOObj, DRI)) {
474     InMemoryStruct<macho::Segment64LoadCommand> SLC;
475     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
476     MachOObj->ReadSegment64LoadCommand(LCI, SLC);
477     InMemoryStruct<macho::Section64> Sect;
478     MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
479
480     strcpy(result, Sect->SegmentName);
481     strcat(result, ",");
482     strcat(result, Sect->Name);
483   } else {
484     InMemoryStruct<macho::SegmentLoadCommand> SLC;
485     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
486     MachOObj->ReadSegmentLoadCommand(LCI, SLC);
487     InMemoryStruct<macho::Section> Sect;
488     MachOObj->ReadSection(LCI, DRI.d.b, Sect);
489
490     strcpy(result, Sect->SegmentName);
491     strcat(result, ",");
492     strcat(result, Sect->Name);
493   }
494   Result = StringRef(result);
495   return object_error::success;
496 }
497
498 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
499                                               uint64_t &Result) const {
500   if (is64BitLoadCommand(MachOObj, DRI)) {
501     InMemoryStruct<macho::Section64> Sect;
502     getSection64(DRI, Sect);
503     Result = Sect->Address;
504   } else {
505     InMemoryStruct<macho::Section> Sect;
506     getSection(DRI, Sect);
507     Result = Sect->Address;
508   }
509   return object_error::success;
510 }
511
512 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
513                                            uint64_t &Result) const {
514   if (is64BitLoadCommand(MachOObj, DRI)) {
515     InMemoryStruct<macho::Section64> Sect;
516     getSection64(DRI, Sect);
517     Result = Sect->Size;
518   } else {
519     InMemoryStruct<macho::Section> Sect;
520     getSection(DRI, Sect);
521     Result = Sect->Size;
522   }
523   return object_error::success;
524 }
525
526 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
527                                                StringRef &Result) const {
528   if (is64BitLoadCommand(MachOObj, DRI)) {
529     InMemoryStruct<macho::Section64> Sect;
530     getSection64(DRI, Sect);
531     Result = MachOObj->getData(Sect->Offset, Sect->Size);
532   } else {
533     InMemoryStruct<macho::Section> Sect;
534     getSection(DRI, Sect);
535     Result = MachOObj->getData(Sect->Offset, Sect->Size);
536   }
537   return object_error::success;
538 }
539
540 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
541                                                 uint64_t &Result) const {
542   if (is64BitLoadCommand(MachOObj, DRI)) {
543     InMemoryStruct<macho::Section64> Sect;
544     getSection64(DRI, Sect);
545     Result = uint64_t(1) << Sect->Align;
546   } else {
547     InMemoryStruct<macho::Section> Sect;
548     getSection(DRI, Sect);
549     Result = uint64_t(1) << Sect->Align;
550   }
551   return object_error::success;
552 }
553
554 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
555                                           bool &Result) const {
556   if (is64BitLoadCommand(MachOObj, DRI)) {
557     InMemoryStruct<macho::Section64> Sect;
558     getSection64(DRI, Sect);
559     Result = !strcmp(Sect->Name, "__text");
560   } else {
561     InMemoryStruct<macho::Section> Sect;
562     getSection(DRI, Sect);
563     Result = !strcmp(Sect->Name, "__text");
564   }
565   return object_error::success;
566 }
567
568 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
569                                           bool &Result) const {
570   // FIXME: Unimplemented.
571   Result = false;
572   return object_error::success;
573 }
574
575 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
576                                          bool &Result) const {
577   // FIXME: Unimplemented.
578   Result = false;
579   return object_error::success;
580 }
581
582 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
583                                                           bool &Result) const {
584   // FIXME: Unimplemented.
585   Result = true;
586   return object_error::success;
587 }
588
589 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
590                                              bool &Result) const {
591   // FIXME: Unimplemented.
592   Result = false;
593   return object_error::success;
594 }
595
596 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
597                                               bool &Result) const {
598   if (MachOObj->is64Bit()) {
599     InMemoryStruct<macho::Section64> Sect;
600     getSection64(DRI, Sect);
601     unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
602     Result = (SectionType == MachO::SectionTypeZeroFill ||
603               SectionType == MachO::SectionTypeZeroFillLarge);
604   } else {
605     InMemoryStruct<macho::Section> Sect;
606     getSection(DRI, Sect);
607     unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
608     Result = (SectionType == MachO::SectionTypeZeroFill ||
609               SectionType == MachO::SectionTypeZeroFillLarge);
610   }
611
612   return object_error::success;
613 }
614
615 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
616                                                   bool &Result) const {
617   // Consider using the code from isSectionText to look for __const sections.
618   // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
619   // to use section attributes to distinguish code from data.
620
621   // FIXME: Unimplemented.
622   Result = false;
623   return object_error::success;
624 }
625
626 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
627                                                   DataRefImpl Symb,
628                                                   bool &Result) const {
629   SymbolRef::Type ST;
630   getSymbolType(Symb, ST);
631   if (ST == SymbolRef::ST_Unknown) {
632     Result = false;
633     return object_error::success;
634   }
635
636   uint64_t SectBegin, SectEnd;
637   getSectionAddress(Sec, SectBegin);
638   getSectionSize(Sec, SectEnd);
639   SectEnd += SectBegin;
640
641   if (MachOObj->is64Bit()) {
642     InMemoryStruct<macho::Symbol64TableEntry> Entry;
643     getSymbol64TableEntry(Symb, Entry);
644     uint64_t SymAddr= Entry->Value;
645     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
646   } else {
647     InMemoryStruct<macho::SymbolTableEntry> Entry;
648     getSymbolTableEntry(Symb, Entry);
649     uint64_t SymAddr= Entry->Value;
650     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
651   }
652
653   return object_error::success;
654 }
655
656 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
657   DataRefImpl ret;
658   ret.d.b = getSectionIndex(Sec);
659   return relocation_iterator(RelocationRef(ret, this));
660 }
661 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
662   uint32_t last_reloc;
663   if (is64BitLoadCommand(MachOObj, Sec)) {
664     InMemoryStruct<macho::Section64> Sect;
665     getSection64(Sec, Sect);
666     last_reloc = Sect->NumRelocationTableEntries;
667   } else {
668     InMemoryStruct<macho::Section> Sect;
669     getSection(Sec, Sect);
670     last_reloc = Sect->NumRelocationTableEntries;
671   }
672   DataRefImpl ret;
673   ret.d.a = last_reloc;
674   ret.d.b = getSectionIndex(Sec);
675   return relocation_iterator(RelocationRef(ret, this));
676 }
677
678 section_iterator MachOObjectFile::begin_sections() const {
679   DataRefImpl DRI;
680   moveToNextSection(DRI);
681   return section_iterator(SectionRef(DRI, this));
682 }
683
684 section_iterator MachOObjectFile::end_sections() const {
685   DataRefImpl DRI;
686   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
687   return section_iterator(SectionRef(DRI, this));
688 }
689
690 /*===-- Relocations -------------------------------------------------------===*/
691
692 void MachOObjectFile::
693 getRelocation(DataRefImpl Rel,
694               InMemoryStruct<macho::RelocationEntry> &Res) const {
695   uint32_t relOffset;
696   if (MachOObj->is64Bit()) {
697     InMemoryStruct<macho::Section64> Sect;
698     getSection64(Sections[Rel.d.b], Sect);
699     relOffset = Sect->RelocationTableOffset;
700   } else {
701     InMemoryStruct<macho::Section> Sect;
702     getSection(Sections[Rel.d.b], Sect);
703     relOffset = Sect->RelocationTableOffset;
704   }
705   MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
706 }
707 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
708                                               RelocationRef &Res) const {
709   ++Rel.d.a;
710   Res = RelocationRef(Rel, this);
711   return object_error::success;
712 }
713 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
714                                                  uint64_t &Res) const {
715   const uint8_t* sectAddress = 0;
716   if (MachOObj->is64Bit()) {
717     InMemoryStruct<macho::Section64> Sect;
718     getSection64(Sections[Rel.d.b], Sect);
719     sectAddress += Sect->Address;
720   } else {
721     InMemoryStruct<macho::Section> Sect;
722     getSection(Sections[Rel.d.b], Sect);
723     sectAddress += Sect->Address;
724   }
725   InMemoryStruct<macho::RelocationEntry> RE;
726   getRelocation(Rel, RE);
727
728   unsigned Arch = getArch();
729   bool isScattered = (Arch != Triple::x86_64) &&
730                      (RE->Word0 & macho::RF_Scattered);
731   uint64_t RelAddr = 0;
732   if (isScattered)
733     RelAddr = RE->Word0 & 0xFFFFFF;
734   else
735     RelAddr = RE->Word0;
736
737   Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
738   return object_error::success;
739 }
740 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
741                                                 uint64_t &Res) const {
742   InMemoryStruct<macho::RelocationEntry> RE;
743   getRelocation(Rel, RE);
744
745   unsigned Arch = getArch();
746   bool isScattered = (Arch != Triple::x86_64) &&
747                      (RE->Word0 & macho::RF_Scattered);
748   if (isScattered)
749     Res = RE->Word0 & 0xFFFFFF;
750   else
751     Res = RE->Word0;
752   return object_error::success;
753 }
754 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
755                                                 SymbolRef &Res) const {
756   InMemoryStruct<macho::RelocationEntry> RE;
757   getRelocation(Rel, RE);
758   uint32_t SymbolIdx = RE->Word1 & 0xffffff;
759   bool isExtern = (RE->Word1 >> 27) & 1;
760
761   DataRefImpl Sym;
762   moveToNextSymbol(Sym);
763   if (isExtern) {
764     for (unsigned i = 0; i < SymbolIdx; i++) {
765       Sym.d.b++;
766       moveToNextSymbol(Sym);
767       assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
768              "Relocation symbol index out of range!");
769     }
770   }
771   Res = SymbolRef(Sym, this);
772   return object_error::success;
773 }
774 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
775                                               uint64_t &Res) const {
776   InMemoryStruct<macho::RelocationEntry> RE;
777   getRelocation(Rel, RE);
778   Res = RE->Word0;
779   Res <<= 32;
780   Res |= RE->Word1;
781   return object_error::success;
782 }
783 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
784                                           SmallVectorImpl<char> &Result) const {
785   // TODO: Support scattered relocations.
786   StringRef res;
787   InMemoryStruct<macho::RelocationEntry> RE;
788   getRelocation(Rel, RE);
789
790   unsigned Arch = getArch();
791   bool isScattered = (Arch != Triple::x86_64) &&
792                      (RE->Word0 & macho::RF_Scattered);
793
794   unsigned r_type;
795   if (isScattered)
796     r_type = (RE->Word0 >> 24) & 0xF;
797   else
798     r_type = (RE->Word1 >> 28) & 0xF;
799
800   switch (Arch) {
801     case Triple::x86: {
802       static const char *const Table[] =  {
803         "GENERIC_RELOC_VANILLA",
804         "GENERIC_RELOC_PAIR",
805         "GENERIC_RELOC_SECTDIFF",
806         "GENERIC_RELOC_PB_LA_PTR",
807         "GENERIC_RELOC_LOCAL_SECTDIFF",
808         "GENERIC_RELOC_TLV" };
809
810       if (r_type > 6)
811         res = "Unknown";
812       else
813         res = Table[r_type];
814       break;
815     }
816     case Triple::x86_64: {
817       static const char *const Table[] =  {
818         "X86_64_RELOC_UNSIGNED",
819         "X86_64_RELOC_SIGNED",
820         "X86_64_RELOC_BRANCH",
821         "X86_64_RELOC_GOT_LOAD",
822         "X86_64_RELOC_GOT",
823         "X86_64_RELOC_SUBTRACTOR",
824         "X86_64_RELOC_SIGNED_1",
825         "X86_64_RELOC_SIGNED_2",
826         "X86_64_RELOC_SIGNED_4",
827         "X86_64_RELOC_TLV" };
828
829       if (r_type > 9)
830         res = "Unknown";
831       else
832         res = Table[r_type];
833       break;
834     }
835     case Triple::arm: {
836       static const char *const Table[] =  {
837         "ARM_RELOC_VANILLA",
838         "ARM_RELOC_PAIR",
839         "ARM_RELOC_SECTDIFF",
840         "ARM_RELOC_LOCAL_SECTDIFF",
841         "ARM_RELOC_PB_LA_PTR",
842         "ARM_RELOC_BR24",
843         "ARM_THUMB_RELOC_BR22",
844         "ARM_THUMB_32BIT_BRANCH",
845         "ARM_RELOC_HALF",
846         "ARM_RELOC_HALF_SECTDIFF" };
847
848       if (r_type > 9)
849         res = "Unknown";
850       else
851         res = Table[r_type];
852       break;
853     }
854     case Triple::ppc: {
855       static const char *const Table[] =  {
856         "PPC_RELOC_VANILLA",
857         "PPC_RELOC_PAIR",
858         "PPC_RELOC_BR14",
859         "PPC_RELOC_BR24",
860         "PPC_RELOC_HI16",
861         "PPC_RELOC_LO16",
862         "PPC_RELOC_HA16",
863         "PPC_RELOC_LO14",
864         "PPC_RELOC_SECTDIFF",
865         "PPC_RELOC_PB_LA_PTR",
866         "PPC_RELOC_HI16_SECTDIFF",
867         "PPC_RELOC_LO16_SECTDIFF",
868         "PPC_RELOC_HA16_SECTDIFF",
869         "PPC_RELOC_JBSR",
870         "PPC_RELOC_LO14_SECTDIFF",
871         "PPC_RELOC_LOCAL_SECTDIFF" };
872
873       res = Table[r_type];
874       break;
875     }
876     case Triple::UnknownArch:
877       res = "Unknown";
878       break;
879   }
880   Result.append(res.begin(), res.end());
881   return object_error::success;
882 }
883 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
884                                                         int64_t &Res) const {
885   InMemoryStruct<macho::RelocationEntry> RE;
886   getRelocation(Rel, RE);
887   bool isExtern = (RE->Word1 >> 27) & 1;
888   Res = 0;
889   if (!isExtern) {
890     const uint8_t* sectAddress = base();
891     if (MachOObj->is64Bit()) {
892       InMemoryStruct<macho::Section64> Sect;
893       getSection64(Sections[Rel.d.b], Sect);
894       sectAddress += Sect->Offset;
895     } else {
896       InMemoryStruct<macho::Section> Sect;
897       getSection(Sections[Rel.d.b], Sect);
898       sectAddress += Sect->Offset;
899     }
900     Res = reinterpret_cast<uintptr_t>(sectAddress);
901   }
902   return object_error::success;
903 }
904
905 // Helper to advance a section or symbol iterator multiple increments at a time.
906 template<class T>
907 error_code advance(T &it, size_t Val) {
908   error_code ec;
909   while (Val--) {
910     it.increment(ec);
911   }
912   return ec;
913 }
914
915 template<class T>
916 void advanceTo(T &it, size_t Val) {
917   if (error_code ec = advance(it, Val))
918     report_fatal_error(ec.message());
919 }
920
921 void MachOObjectFile::printRelocationTargetName(
922                                      InMemoryStruct<macho::RelocationEntry>& RE,
923                                      raw_string_ostream &fmt) const {
924   unsigned Arch = getArch();
925   bool isScattered = (Arch != Triple::x86_64) &&
926                      (RE->Word0 & macho::RF_Scattered);
927
928   // Target of a scattered relocation is an address.  In the interest of
929   // generating pretty output, scan through the symbol table looking for a
930   // symbol that aligns with that address.  If we find one, print it.
931   // Otherwise, we just print the hex address of the target.
932   if (isScattered) {
933     uint32_t Val = RE->Word1;
934
935     error_code ec;
936     for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
937         SI.increment(ec)) {
938       if (ec) report_fatal_error(ec.message());
939
940       uint64_t Addr;
941       StringRef Name;
942
943       if ((ec = SI->getAddress(Addr)))
944         report_fatal_error(ec.message());
945       if (Addr != Val) continue;
946       if ((ec = SI->getName(Name)))
947         report_fatal_error(ec.message());
948       fmt << Name;
949       return;
950     }
951
952     // If we couldn't find a symbol that this relocation refers to, try
953     // to find a section beginning instead.
954     for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
955          SI.increment(ec)) {
956       if (ec) report_fatal_error(ec.message());
957
958       uint64_t Addr;
959       StringRef Name;
960
961       if ((ec = SI->getAddress(Addr)))
962         report_fatal_error(ec.message());
963       if (Addr != Val) continue;
964       if ((ec = SI->getName(Name)))
965         report_fatal_error(ec.message());
966       fmt << Name;
967       return;
968     }
969
970     fmt << format("0x%x", Val);
971     return;
972   }
973
974   StringRef S;
975   bool isExtern = (RE->Word1 >> 27) & 1;
976   uint32_t Val = RE->Word1 & 0xFFFFFF;
977
978   if (isExtern) {
979     symbol_iterator SI = begin_symbols();
980     advanceTo(SI, Val);
981     SI->getName(S);
982   } else {
983     section_iterator SI = begin_sections();
984     advanceTo(SI, Val);
985     SI->getName(S);
986   }
987
988   fmt << S;
989 }
990
991 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
992                                           SmallVectorImpl<char> &Result) const {
993   InMemoryStruct<macho::RelocationEntry> RE;
994   getRelocation(Rel, RE);
995
996   unsigned Arch = getArch();
997   bool isScattered = (Arch != Triple::x86_64) &&
998                      (RE->Word0 & macho::RF_Scattered);
999
1000   std::string fmtbuf;
1001   raw_string_ostream fmt(fmtbuf);
1002
1003   unsigned Type;
1004   if (isScattered)
1005     Type = (RE->Word0 >> 24) & 0xF;
1006   else
1007     Type = (RE->Word1 >> 28) & 0xF;
1008
1009   bool isPCRel;
1010   if (isScattered)
1011     isPCRel = ((RE->Word0 >> 30) & 1);
1012   else
1013     isPCRel = ((RE->Word1 >> 24) & 1);
1014
1015   // Determine any addends that should be displayed with the relocation.
1016   // These require decoding the relocation type, which is triple-specific.
1017
1018   // X86_64 has entirely custom relocation types.
1019   if (Arch == Triple::x86_64) {
1020     bool isPCRel = ((RE->Word1 >> 24) & 1);
1021
1022     switch (Type) {
1023       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
1024       case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
1025         printRelocationTargetName(RE, fmt);
1026         fmt << "@GOT";
1027         if (isPCRel) fmt << "PCREL";
1028         break;
1029       }
1030       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1031         InMemoryStruct<macho::RelocationEntry> RENext;
1032         DataRefImpl RelNext = Rel;
1033         RelNext.d.a++;
1034         getRelocation(RelNext, RENext);
1035
1036         // X86_64_SUBTRACTOR must be followed by a relocation of type
1037         // X86_64_RELOC_UNSIGNED.
1038         // NOTE: Scattered relocations don't exist on x86_64.
1039         unsigned RType = (RENext->Word1 >> 28) & 0xF;
1040         if (RType != 0)
1041           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1042                              "X86_64_RELOC_SUBTRACTOR.");
1043
1044         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1045         // X86_64_SUBTRACTOR contains to the subtrahend.
1046         printRelocationTargetName(RENext, fmt);
1047         fmt << "-";
1048         printRelocationTargetName(RE, fmt);
1049       }
1050       case macho::RIT_X86_64_TLV:
1051         printRelocationTargetName(RE, fmt);
1052         fmt << "@TLV";
1053         if (isPCRel) fmt << "P";
1054         break;
1055       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1056         printRelocationTargetName(RE, fmt);
1057         fmt << "-1";
1058         break;
1059       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1060         printRelocationTargetName(RE, fmt);
1061         fmt << "-2";
1062         break;
1063       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1064         printRelocationTargetName(RE, fmt);
1065         fmt << "-4";
1066         break;
1067       default:
1068         printRelocationTargetName(RE, fmt);
1069         break;
1070     }
1071   // X86 and ARM share some relocation types in common.
1072   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1073     // Generic relocation types...
1074     switch (Type) {
1075       case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1076         return object_error::success;
1077       case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1078         InMemoryStruct<macho::RelocationEntry> RENext;
1079         DataRefImpl RelNext = Rel;
1080         RelNext.d.a++;
1081         getRelocation(RelNext, RENext);
1082
1083         // X86 sect diff's must be followed by a relocation of type
1084         // GENERIC_RELOC_PAIR.
1085         bool isNextScattered = (Arch != Triple::x86_64) &&
1086                                (RENext->Word0 & macho::RF_Scattered);
1087         unsigned RType;
1088         if (isNextScattered)
1089           RType = (RENext->Word0 >> 24) & 0xF;
1090         else
1091           RType = (RENext->Word1 >> 28) & 0xF;
1092         if (RType != 1)
1093           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1094                              "GENERIC_RELOC_SECTDIFF.");
1095
1096         printRelocationTargetName(RE, fmt);
1097         fmt << "-";
1098         printRelocationTargetName(RENext, fmt);
1099         break;
1100       }
1101     }
1102
1103     if (Arch == Triple::x86) {
1104       // All X86 relocations that need special printing were already
1105       // handled in the generic code.
1106       switch (Type) {
1107         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1108           InMemoryStruct<macho::RelocationEntry> RENext;
1109           DataRefImpl RelNext = Rel;
1110           RelNext.d.a++;
1111           getRelocation(RelNext, RENext);
1112
1113           // X86 sect diff's must be followed by a relocation of type
1114           // GENERIC_RELOC_PAIR.
1115           bool isNextScattered = (Arch != Triple::x86_64) &&
1116                                (RENext->Word0 & macho::RF_Scattered);
1117           unsigned RType;
1118           if (isNextScattered)
1119             RType = (RENext->Word0 >> 24) & 0xF;
1120           else
1121             RType = (RENext->Word1 >> 28) & 0xF;
1122           if (RType != 1)
1123             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1124                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
1125
1126           printRelocationTargetName(RE, fmt);
1127           fmt << "-";
1128           printRelocationTargetName(RENext, fmt);
1129           break;
1130         }
1131         case macho::RIT_Generic_TLV: {
1132           printRelocationTargetName(RE, fmt);
1133           fmt << "@TLV";
1134           if (isPCRel) fmt << "P";
1135           break;
1136         }
1137         default:
1138           printRelocationTargetName(RE, fmt);
1139       }
1140     } else { // ARM-specific relocations
1141       switch (Type) {
1142         case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
1143         case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1144           // Half relocations steal a bit from the length field to encode
1145           // whether this is an upper16 or a lower16 relocation.
1146           bool isUpper;
1147           if (isScattered)
1148             isUpper = (RE->Word0 >> 28) & 1;
1149           else
1150             isUpper = (RE->Word1 >> 25) & 1;
1151
1152           if (isUpper)
1153             fmt << ":upper16:(";
1154           else
1155             fmt << ":lower16:(";
1156           printRelocationTargetName(RE, fmt);
1157
1158           InMemoryStruct<macho::RelocationEntry> RENext;
1159           DataRefImpl RelNext = Rel;
1160           RelNext.d.a++;
1161           getRelocation(RelNext, RENext);
1162
1163           // ARM half relocs must be followed by a relocation of type
1164           // ARM_RELOC_PAIR.
1165           bool isNextScattered = (Arch != Triple::x86_64) &&
1166                                  (RENext->Word0 & macho::RF_Scattered);
1167           unsigned RType;
1168           if (isNextScattered)
1169             RType = (RENext->Word0 >> 24) & 0xF;
1170           else
1171             RType = (RENext->Word1 >> 28) & 0xF;
1172
1173           if (RType != 1)
1174             report_fatal_error("Expected ARM_RELOC_PAIR after "
1175                                "GENERIC_RELOC_HALF");
1176
1177           // NOTE: The half of the target virtual address is stashed in the
1178           // address field of the secondary relocation, but we can't reverse
1179           // engineer the constant offset from it without decoding the movw/movt
1180           // instruction to find the other half in its immediate field.
1181
1182           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1183           // symbol/section pointer of the follow-on relocation.
1184           if (Type == macho::RIT_ARM_HalfDifference) {
1185             fmt << "-";
1186             printRelocationTargetName(RENext, fmt);
1187           }
1188
1189           fmt << ")";
1190           break;
1191         }
1192         default: {
1193           printRelocationTargetName(RE, fmt);
1194         }
1195       }
1196     }
1197   } else
1198     printRelocationTargetName(RE, fmt);
1199
1200   fmt.flush();
1201   Result.append(fmtbuf.begin(), fmtbuf.end());
1202   return object_error::success;
1203 }
1204
1205 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1206                                                 bool &Result) const {
1207   InMemoryStruct<macho::RelocationEntry> RE;
1208   getRelocation(Rel, RE);
1209
1210   unsigned Arch = getArch();
1211   bool isScattered = (Arch != Triple::x86_64) &&
1212                      (RE->Word0 & macho::RF_Scattered);
1213   unsigned Type;
1214   if (isScattered)
1215     Type = (RE->Word0 >> 24) & 0xF;
1216   else
1217     Type = (RE->Word1 >> 28) & 0xF;
1218
1219   Result = false;
1220
1221   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1222   // is always hidden.
1223   if (Arch == Triple::x86 || Arch == Triple::arm) {
1224     if (Type == macho::RIT_Pair) Result = true;
1225   } else if (Arch == Triple::x86_64) {
1226     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1227     // an X864_64_RELOC_SUBTRACTOR.
1228     if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1229       DataRefImpl RelPrev = Rel;
1230       RelPrev.d.a--;
1231       InMemoryStruct<macho::RelocationEntry> REPrev;
1232       getRelocation(RelPrev, REPrev);
1233
1234       unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1235
1236       if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1237     }
1238   }
1239
1240   return object_error::success;
1241 }
1242
1243 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1244                                            LibraryRef &Res) const {
1245   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1246 }
1247
1248 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1249                                            StringRef &Res) const {
1250   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1251 }
1252
1253
1254 /*===-- Miscellaneous -----------------------------------------------------===*/
1255
1256 uint8_t MachOObjectFile::getBytesInAddress() const {
1257   return MachOObj->is64Bit() ? 8 : 4;
1258 }
1259
1260 StringRef MachOObjectFile::getFileFormatName() const {
1261   if (!MachOObj->is64Bit()) {
1262     switch (MachOObj->getHeader().CPUType) {
1263     case llvm::MachO::CPUTypeI386:
1264       return "Mach-O 32-bit i386";
1265     case llvm::MachO::CPUTypeARM:
1266       return "Mach-O arm";
1267     case llvm::MachO::CPUTypePowerPC:
1268       return "Mach-O 32-bit ppc";
1269     default:
1270       assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1271              "64-bit object file when we're not 64-bit?");
1272       return "Mach-O 32-bit unknown";
1273     }
1274   }
1275
1276   switch (MachOObj->getHeader().CPUType) {
1277   case llvm::MachO::CPUTypeX86_64:
1278     return "Mach-O 64-bit x86-64";
1279   case llvm::MachO::CPUTypePowerPC64:
1280     return "Mach-O 64-bit ppc64";
1281   default:
1282     assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
1283            "32-bit object file when we're 64-bit?");
1284     return "Mach-O 64-bit unknown";
1285   }
1286 }
1287
1288 unsigned MachOObjectFile::getArch() const {
1289   switch (MachOObj->getHeader().CPUType) {
1290   case llvm::MachO::CPUTypeI386:
1291     return Triple::x86;
1292   case llvm::MachO::CPUTypeX86_64:
1293     return Triple::x86_64;
1294   case llvm::MachO::CPUTypeARM:
1295     return Triple::arm;
1296   case llvm::MachO::CPUTypePowerPC:
1297     return Triple::ppc;
1298   case llvm::MachO::CPUTypePowerPC64:
1299     return Triple::ppc64;
1300   default:
1301     return Triple::UnknownArch;
1302   }
1303 }
1304
1305 } // end namespace object
1306 } // end namespace llvm