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