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