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