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