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