Fix the implementation of MachOObjectFile::isSectionZeroInit so it follows the MachO...
[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::sectionContainsSymbol(DataRefImpl Sec,
616                                                   DataRefImpl Symb,
617                                                   bool &Result) const {
618   SymbolRef::Type ST;
619   getSymbolType(Symb, ST);
620   if (ST == SymbolRef::ST_Unknown) {
621     Result = false;
622     return object_error::success;
623   }
624
625   uint64_t SectBegin, SectEnd;
626   getSectionAddress(Sec, SectBegin);
627   getSectionSize(Sec, SectEnd);
628   SectEnd += SectBegin;
629
630   if (MachOObj->is64Bit()) {
631     InMemoryStruct<macho::Symbol64TableEntry> Entry;
632     getSymbol64TableEntry(Symb, Entry);
633     uint64_t SymAddr= Entry->Value;
634     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
635   } else {
636     InMemoryStruct<macho::SymbolTableEntry> Entry;
637     getSymbolTableEntry(Symb, Entry);
638     uint64_t SymAddr= Entry->Value;
639     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
640   }
641
642   return object_error::success;
643 }
644
645 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
646   DataRefImpl ret;
647   ret.d.b = getSectionIndex(Sec);
648   return relocation_iterator(RelocationRef(ret, this));
649 }
650 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
651   uint32_t last_reloc;
652   if (is64BitLoadCommand(MachOObj, Sec)) {
653     InMemoryStruct<macho::Section64> Sect;
654     getSection64(Sec, Sect);
655     last_reloc = Sect->NumRelocationTableEntries;
656   } else {
657     InMemoryStruct<macho::Section> Sect;
658     getSection(Sec, Sect);
659     last_reloc = Sect->NumRelocationTableEntries;
660   }
661   DataRefImpl ret;
662   ret.d.a = last_reloc;
663   ret.d.b = getSectionIndex(Sec);
664   return relocation_iterator(RelocationRef(ret, this));
665 }
666
667 section_iterator MachOObjectFile::begin_sections() const {
668   DataRefImpl DRI;
669   moveToNextSection(DRI);
670   return section_iterator(SectionRef(DRI, this));
671 }
672
673 section_iterator MachOObjectFile::end_sections() const {
674   DataRefImpl DRI;
675   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
676   return section_iterator(SectionRef(DRI, this));
677 }
678
679 /*===-- Relocations -------------------------------------------------------===*/
680
681 void MachOObjectFile::
682 getRelocation(DataRefImpl Rel,
683               InMemoryStruct<macho::RelocationEntry> &Res) const {
684   uint32_t relOffset;
685   if (MachOObj->is64Bit()) {
686     InMemoryStruct<macho::Section64> Sect;
687     getSection64(Sections[Rel.d.b], Sect);
688     relOffset = Sect->RelocationTableOffset;
689   } else {
690     InMemoryStruct<macho::Section> Sect;
691     getSection(Sections[Rel.d.b], Sect);
692     relOffset = Sect->RelocationTableOffset;
693   }
694   MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
695 }
696 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
697                                               RelocationRef &Res) const {
698   ++Rel.d.a;
699   Res = RelocationRef(Rel, this);
700   return object_error::success;
701 }
702 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
703                                                  uint64_t &Res) const {
704   const uint8_t* sectAddress = 0;
705   if (MachOObj->is64Bit()) {
706     InMemoryStruct<macho::Section64> Sect;
707     getSection64(Sections[Rel.d.b], Sect);
708     sectAddress += Sect->Address;
709   } else {
710     InMemoryStruct<macho::Section> Sect;
711     getSection(Sections[Rel.d.b], Sect);
712     sectAddress += Sect->Address;
713   }
714   InMemoryStruct<macho::RelocationEntry> RE;
715   getRelocation(Rel, RE);
716
717   unsigned Arch = getArch();
718   bool isScattered = (Arch != Triple::x86_64) &&
719                      (RE->Word0 & macho::RF_Scattered);
720   uint64_t RelAddr = 0;
721   if (isScattered)
722     RelAddr = RE->Word0 & 0xFFFFFF;
723   else
724     RelAddr = RE->Word0;
725
726   Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
727   return object_error::success;
728 }
729 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
730                                                 uint64_t &Res) const {
731   InMemoryStruct<macho::RelocationEntry> RE;
732   getRelocation(Rel, RE);
733
734   unsigned Arch = getArch();
735   bool isScattered = (Arch != Triple::x86_64) &&
736                      (RE->Word0 & macho::RF_Scattered);
737   if (isScattered)
738     Res = RE->Word0 & 0xFFFFFF;
739   else
740     Res = RE->Word0;
741   return object_error::success;
742 }
743 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
744                                                 SymbolRef &Res) const {
745   InMemoryStruct<macho::RelocationEntry> RE;
746   getRelocation(Rel, RE);
747   uint32_t SymbolIdx = RE->Word1 & 0xffffff;
748   bool isExtern = (RE->Word1 >> 27) & 1;
749
750   DataRefImpl Sym;
751   moveToNextSymbol(Sym);
752   if (isExtern) {
753     for (unsigned i = 0; i < SymbolIdx; i++) {
754       Sym.d.b++;
755       moveToNextSymbol(Sym);
756       assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
757              "Relocation symbol index out of range!");
758     }
759   }
760   Res = SymbolRef(Sym, this);
761   return object_error::success;
762 }
763 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
764                                               uint64_t &Res) const {
765   InMemoryStruct<macho::RelocationEntry> RE;
766   getRelocation(Rel, RE);
767   Res = RE->Word0;
768   Res <<= 32;
769   Res |= RE->Word1;
770   return object_error::success;
771 }
772 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
773                                           SmallVectorImpl<char> &Result) const {
774   // TODO: Support scattered relocations.
775   StringRef res;
776   InMemoryStruct<macho::RelocationEntry> RE;
777   getRelocation(Rel, RE);
778
779   unsigned Arch = getArch();
780   bool isScattered = (Arch != Triple::x86_64) &&
781                      (RE->Word0 & macho::RF_Scattered);
782
783   unsigned r_type;
784   if (isScattered)
785     r_type = (RE->Word0 >> 24) & 0xF;
786   else
787     r_type = (RE->Word1 >> 28) & 0xF;
788
789   switch (Arch) {
790     case Triple::x86: {
791       const char* Table[] =  {
792         "GENERIC_RELOC_VANILLA",
793         "GENERIC_RELOC_PAIR",
794         "GENERIC_RELOC_SECTDIFF",
795         "GENERIC_RELOC_PB_LA_PTR",
796         "GENERIC_RELOC_LOCAL_SECTDIFF",
797         "GENERIC_RELOC_TLV" };
798
799       if (r_type > 6)
800         res = "Unknown";
801       else
802         res = Table[r_type];
803       break;
804     }
805     case Triple::x86_64: {
806       const char* Table[] =  {
807         "X86_64_RELOC_UNSIGNED",
808         "X86_64_RELOC_SIGNED",
809         "X86_64_RELOC_BRANCH",
810         "X86_64_RELOC_GOT_LOAD",
811         "X86_64_RELOC_GOT",
812         "X86_64_RELOC_SUBTRACTOR",
813         "X86_64_RELOC_SIGNED_1",
814         "X86_64_RELOC_SIGNED_2",
815         "X86_64_RELOC_SIGNED_4",
816         "X86_64_RELOC_TLV" };
817
818       if (r_type > 9)
819         res = "Unknown";
820       else
821         res = Table[r_type];
822       break;
823     }
824     case Triple::arm: {
825       const char* Table[] =  {
826         "ARM_RELOC_VANILLA",
827         "ARM_RELOC_PAIR",
828         "ARM_RELOC_SECTDIFF",
829         "ARM_RELOC_LOCAL_SECTDIFF",
830         "ARM_RELOC_PB_LA_PTR",
831         "ARM_RELOC_BR24",
832         "ARM_THUMB_RELOC_BR22",
833         "ARM_THUMB_32BIT_BRANCH",
834         "ARM_RELOC_HALF",
835         "ARM_RELOC_HALF_SECTDIFF" };
836
837       if (r_type > 9)
838         res = "Unknown";
839       else
840         res = Table[r_type];
841       break;
842     }
843     case Triple::ppc: {
844       const char* Table[] =  {
845         "PPC_RELOC_VANILLA",
846         "PPC_RELOC_PAIR",
847         "PPC_RELOC_BR14",
848         "PPC_RELOC_BR24",
849         "PPC_RELOC_HI16",
850         "PPC_RELOC_LO16",
851         "PPC_RELOC_HA16",
852         "PPC_RELOC_LO14",
853         "PPC_RELOC_SECTDIFF",
854         "PPC_RELOC_PB_LA_PTR",
855         "PPC_RELOC_HI16_SECTDIFF",
856         "PPC_RELOC_LO16_SECTDIFF",
857         "PPC_RELOC_HA16_SECTDIFF",
858         "PPC_RELOC_JBSR",
859         "PPC_RELOC_LO14_SECTDIFF",
860         "PPC_RELOC_LOCAL_SECTDIFF" };
861
862       res = Table[r_type];
863       break;
864     }
865     case Triple::UnknownArch:
866       res = "Unknown";
867       break;
868   }
869   Result.append(res.begin(), res.end());
870   return object_error::success;
871 }
872 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
873                                                         int64_t &Res) const {
874   InMemoryStruct<macho::RelocationEntry> RE;
875   getRelocation(Rel, RE);
876   bool isExtern = (RE->Word1 >> 27) & 1;
877   Res = 0;
878   if (!isExtern) {
879     const uint8_t* sectAddress = base();
880     if (MachOObj->is64Bit()) {
881       InMemoryStruct<macho::Section64> Sect;
882       getSection64(Sections[Rel.d.b], Sect);
883       sectAddress += Sect->Offset;
884     } else {
885       InMemoryStruct<macho::Section> Sect;
886       getSection(Sections[Rel.d.b], Sect);
887       sectAddress += Sect->Offset;
888     }
889     Res = reinterpret_cast<uintptr_t>(sectAddress);
890   }
891   return object_error::success;
892 }
893
894 // Helper to advance a section or symbol iterator multiple increments at a time.
895 template<class T>
896 error_code advance(T &it, size_t Val) {
897   error_code ec;
898   while (Val--) {
899     it.increment(ec);
900   }
901   return ec;
902 }
903
904 template<class T>
905 void advanceTo(T &it, size_t Val) {
906   if (error_code ec = advance(it, Val))
907     report_fatal_error(ec.message());
908 }
909
910 void MachOObjectFile::printRelocationTargetName(
911                                      InMemoryStruct<macho::RelocationEntry>& RE,
912                                      raw_string_ostream &fmt) const {
913   unsigned Arch = getArch();
914   bool isScattered = (Arch != Triple::x86_64) &&
915                      (RE->Word0 & macho::RF_Scattered);
916
917   // Target of a scattered relocation is an address.  In the interest of
918   // generating pretty output, scan through the symbol table looking for a
919   // symbol that aligns with that address.  If we find one, print it.
920   // Otherwise, we just print the hex address of the target.
921   if (isScattered) {
922     uint32_t Val = RE->Word1;
923
924     error_code ec;
925     for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
926         SI.increment(ec)) {
927       if (ec) report_fatal_error(ec.message());
928
929       uint64_t Addr;
930       StringRef Name;
931
932       if ((ec = SI->getAddress(Addr)))
933         report_fatal_error(ec.message());
934       if (Addr != Val) continue;
935       if ((ec = SI->getName(Name)))
936         report_fatal_error(ec.message());
937       fmt << Name;
938       return;
939     }
940
941     // If we couldn't find a symbol that this relocation refers to, try
942     // to find a section beginning instead.
943     for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
944          SI.increment(ec)) {
945       if (ec) report_fatal_error(ec.message());
946
947       uint64_t Addr;
948       StringRef Name;
949
950       if ((ec = SI->getAddress(Addr)))
951         report_fatal_error(ec.message());
952       if (Addr != Val) continue;
953       if ((ec = SI->getName(Name)))
954         report_fatal_error(ec.message());
955       fmt << Name;
956       return;
957     }
958
959     fmt << format("0x%x", Val);
960     return;
961   }
962
963   StringRef S;
964   bool isExtern = (RE->Word1 >> 27) & 1;
965   uint32_t Val = RE->Word1 & 0xFFFFFF;
966
967   if (isExtern) {
968     symbol_iterator SI = begin_symbols();
969     advanceTo(SI, Val);
970     SI->getName(S);
971   } else {
972     section_iterator SI = begin_sections();
973     advanceTo(SI, Val);
974     SI->getName(S);
975   }
976
977   fmt << S;
978 }
979
980 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
981                                           SmallVectorImpl<char> &Result) const {
982   InMemoryStruct<macho::RelocationEntry> RE;
983   getRelocation(Rel, RE);
984
985   unsigned Arch = getArch();
986   bool isScattered = (Arch != Triple::x86_64) &&
987                      (RE->Word0 & macho::RF_Scattered);
988
989   std::string fmtbuf;
990   raw_string_ostream fmt(fmtbuf);
991
992   unsigned Type;
993   if (isScattered)
994     Type = (RE->Word0 >> 24) & 0xF;
995   else
996     Type = (RE->Word1 >> 28) & 0xF;
997
998   bool isPCRel;
999   if (isScattered)
1000     isPCRel = ((RE->Word0 >> 30) & 1);
1001   else
1002     isPCRel = ((RE->Word1 >> 24) & 1);
1003
1004   // Determine any addends that should be displayed with the relocation.
1005   // These require decoding the relocation type, which is triple-specific.
1006
1007   // X86_64 has entirely custom relocation types.
1008   if (Arch == Triple::x86_64) {
1009     bool isPCRel = ((RE->Word1 >> 24) & 1);
1010
1011     switch (Type) {
1012       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
1013       case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
1014         printRelocationTargetName(RE, fmt);
1015         fmt << "@GOT";
1016         if (isPCRel) fmt << "PCREL";
1017         break;
1018       }
1019       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1020         InMemoryStruct<macho::RelocationEntry> RENext;
1021         DataRefImpl RelNext = Rel;
1022         RelNext.d.a++;
1023         getRelocation(RelNext, RENext);
1024
1025         // X86_64_SUBTRACTOR must be followed by a relocation of type
1026         // X86_64_RELOC_UNSIGNED.
1027         // NOTE: Scattered relocations don't exist on x86_64.
1028         unsigned RType = (RENext->Word1 >> 28) & 0xF;
1029         if (RType != 0)
1030           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1031                              "X86_64_RELOC_SUBTRACTOR.");
1032
1033         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1034         // X86_64_SUBTRACTOR contains to the subtrahend.
1035         printRelocationTargetName(RENext, fmt);
1036         fmt << "-";
1037         printRelocationTargetName(RE, fmt);
1038       }
1039       case macho::RIT_X86_64_TLV:
1040         printRelocationTargetName(RE, fmt);
1041         fmt << "@TLV";
1042         if (isPCRel) fmt << "P";
1043         break;
1044       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1045         printRelocationTargetName(RE, fmt);
1046         fmt << "-1";
1047         break;
1048       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1049         printRelocationTargetName(RE, fmt);
1050         fmt << "-2";
1051         break;
1052       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1053         printRelocationTargetName(RE, fmt);
1054         fmt << "-4";
1055         break;
1056       default:
1057         printRelocationTargetName(RE, fmt);
1058         break;
1059     }
1060   // X86 and ARM share some relocation types in common.
1061   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1062     // Generic relocation types...
1063     switch (Type) {
1064       case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1065         return object_error::success;
1066       case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1067         InMemoryStruct<macho::RelocationEntry> RENext;
1068         DataRefImpl RelNext = Rel;
1069         RelNext.d.a++;
1070         getRelocation(RelNext, RENext);
1071
1072         // X86 sect diff's must be followed by a relocation of type
1073         // GENERIC_RELOC_PAIR.
1074         bool isNextScattered = (Arch != Triple::x86_64) &&
1075                                (RENext->Word0 & macho::RF_Scattered);
1076         unsigned RType;
1077         if (isNextScattered)
1078           RType = (RENext->Word0 >> 24) & 0xF;
1079         else
1080           RType = (RENext->Word1 >> 28) & 0xF;
1081         if (RType != 1)
1082           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1083                              "GENERIC_RELOC_SECTDIFF.");
1084
1085         printRelocationTargetName(RE, fmt);
1086         fmt << "-";
1087         printRelocationTargetName(RENext, fmt);
1088         break;
1089       }
1090     }
1091
1092     if (Arch == Triple::x86) {
1093       // All X86 relocations that need special printing were already
1094       // handled in the generic code.
1095       switch (Type) {
1096         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1097           InMemoryStruct<macho::RelocationEntry> RENext;
1098           DataRefImpl RelNext = Rel;
1099           RelNext.d.a++;
1100           getRelocation(RelNext, RENext);
1101
1102           // X86 sect diff's must be followed by a relocation of type
1103           // GENERIC_RELOC_PAIR.
1104           bool isNextScattered = (Arch != Triple::x86_64) &&
1105                                (RENext->Word0 & macho::RF_Scattered);
1106           unsigned RType;
1107           if (isNextScattered)
1108             RType = (RENext->Word0 >> 24) & 0xF;
1109           else
1110             RType = (RENext->Word1 >> 28) & 0xF;
1111           if (RType != 1)
1112             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1113                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
1114
1115           printRelocationTargetName(RE, fmt);
1116           fmt << "-";
1117           printRelocationTargetName(RENext, fmt);
1118           break;
1119         }
1120         case macho::RIT_Generic_TLV: {
1121           printRelocationTargetName(RE, fmt);
1122           fmt << "@TLV";
1123           if (isPCRel) fmt << "P";
1124           break;
1125         }
1126         default:
1127           printRelocationTargetName(RE, fmt);
1128       }
1129     } else { // ARM-specific relocations
1130       switch (Type) {
1131         case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
1132         case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1133           // Half relocations steal a bit from the length field to encode
1134           // whether this is an upper16 or a lower16 relocation.
1135           bool isUpper;
1136           if (isScattered)
1137             isUpper = (RE->Word0 >> 28) & 1;
1138           else
1139             isUpper = (RE->Word1 >> 25) & 1;
1140
1141           if (isUpper)
1142             fmt << ":upper16:(";
1143           else
1144             fmt << ":lower16:(";
1145           printRelocationTargetName(RE, fmt);
1146
1147           InMemoryStruct<macho::RelocationEntry> RENext;
1148           DataRefImpl RelNext = Rel;
1149           RelNext.d.a++;
1150           getRelocation(RelNext, RENext);
1151
1152           // ARM half relocs must be followed by a relocation of type
1153           // ARM_RELOC_PAIR.
1154           bool isNextScattered = (Arch != Triple::x86_64) &&
1155                                  (RENext->Word0 & macho::RF_Scattered);
1156           unsigned RType;
1157           if (isNextScattered)
1158             RType = (RENext->Word0 >> 24) & 0xF;
1159           else
1160             RType = (RENext->Word1 >> 28) & 0xF;
1161
1162           if (RType != 1)
1163             report_fatal_error("Expected ARM_RELOC_PAIR after "
1164                                "GENERIC_RELOC_HALF");
1165
1166           // NOTE: The half of the target virtual address is stashed in the
1167           // address field of the secondary relocation, but we can't reverse
1168           // engineer the constant offset from it without decoding the movw/movt
1169           // instruction to find the other half in its immediate field.
1170
1171           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1172           // symbol/section pointer of the follow-on relocation.
1173           if (Type == macho::RIT_ARM_HalfDifference) {
1174             fmt << "-";
1175             printRelocationTargetName(RENext, fmt);
1176           }
1177
1178           fmt << ")";
1179           break;
1180         }
1181         default: {
1182           printRelocationTargetName(RE, fmt);
1183         }
1184       }
1185     }
1186   } else
1187     printRelocationTargetName(RE, fmt);
1188
1189   fmt.flush();
1190   Result.append(fmtbuf.begin(), fmtbuf.end());
1191   return object_error::success;
1192 }
1193
1194 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1195                                                 bool &Result) const {
1196   InMemoryStruct<macho::RelocationEntry> RE;
1197   getRelocation(Rel, RE);
1198
1199   unsigned Arch = getArch();
1200   bool isScattered = (Arch != Triple::x86_64) &&
1201                      (RE->Word0 & macho::RF_Scattered);
1202   unsigned Type;
1203   if (isScattered)
1204     Type = (RE->Word0 >> 24) & 0xF;
1205   else
1206     Type = (RE->Word1 >> 28) & 0xF;
1207
1208   Result = false;
1209
1210   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1211   // is always hidden.
1212   if (Arch == Triple::x86 || Arch == Triple::arm) {
1213     if (Type == macho::RIT_Pair) Result = true;
1214   } else if (Arch == Triple::x86_64) {
1215     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1216     // an X864_64_RELOC_SUBTRACTOR.
1217     if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1218       DataRefImpl RelPrev = Rel;
1219       RelPrev.d.a--;
1220       InMemoryStruct<macho::RelocationEntry> REPrev;
1221       getRelocation(RelPrev, REPrev);
1222
1223       unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1224
1225       if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1226     }
1227   }
1228
1229   return object_error::success;
1230 }
1231
1232 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1233                                            LibraryRef &Res) const {
1234   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1235 }
1236
1237 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1238                                            StringRef &Res) const {
1239   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1240 }
1241
1242
1243 /*===-- Miscellaneous -----------------------------------------------------===*/
1244
1245 uint8_t MachOObjectFile::getBytesInAddress() const {
1246   return MachOObj->is64Bit() ? 8 : 4;
1247 }
1248
1249 StringRef MachOObjectFile::getFileFormatName() const {
1250   if (!MachOObj->is64Bit()) {
1251     switch (MachOObj->getHeader().CPUType) {
1252     case llvm::MachO::CPUTypeI386:
1253       return "Mach-O 32-bit i386";
1254     case llvm::MachO::CPUTypeARM:
1255       return "Mach-O arm";
1256     case llvm::MachO::CPUTypePowerPC:
1257       return "Mach-O 32-bit ppc";
1258     default:
1259       assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1260              "64-bit object file when we're not 64-bit?");
1261       return "Mach-O 32-bit unknown";
1262     }
1263   }
1264
1265   switch (MachOObj->getHeader().CPUType) {
1266   case llvm::MachO::CPUTypeX86_64:
1267     return "Mach-O 64-bit x86-64";
1268   case llvm::MachO::CPUTypePowerPC64:
1269     return "Mach-O 64-bit ppc64";
1270   default:
1271     assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
1272            "32-bit object file when we're 64-bit?");
1273     return "Mach-O 64-bit unknown";
1274   }
1275 }
1276
1277 unsigned MachOObjectFile::getArch() const {
1278   switch (MachOObj->getHeader().CPUType) {
1279   case llvm::MachO::CPUTypeI386:
1280     return Triple::x86;
1281   case llvm::MachO::CPUTypeX86_64:
1282     return Triple::x86_64;
1283   case llvm::MachO::CPUTypeARM:
1284     return Triple::arm;
1285   case llvm::MachO::CPUTypePowerPC:
1286     return Triple::ppc;
1287   case llvm::MachO::CPUTypePowerPC64:
1288     return Triple::ppc64;
1289   default:
1290     return Triple::UnknownArch;
1291   }
1292 }
1293
1294 } // end namespace object
1295 } // end namespace llvm