MachOObjectFile.cpp revision 41242942fcbb2e6bc4e5bed3e8041f7b20ece8af
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/MemoryBuffer.h"
19
20#include <cctype>
21#include <cstring>
22#include <limits>
23
24using namespace llvm;
25using namespace object;
26
27namespace llvm {
28namespace object {
29
30MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
31                                 error_code &ec)
32    : ObjectFile(Binary::isMachO, Object, ec),
33      MachOObj(MOO),
34      RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
35  DataRefImpl DRI;
36  DRI.d.a = DRI.d.b = 0;
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::getSymbolOffset(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  } else {
134    InMemoryStruct<macho::SymbolTableEntry> Entry;
135    getSymbolTableEntry(DRI, Entry);
136    Result = Entry->Value;
137  }
138  return object_error::success;
139}
140
141error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
142                                             uint64_t &Result) const {
143  uint64_t SymbolOffset;
144  uint8_t SectionIndex;
145  if (MachOObj->is64Bit()) {
146    InMemoryStruct<macho::Symbol64TableEntry> Entry;
147    getSymbol64TableEntry(DRI, Entry);
148    SymbolOffset = Entry->Value;
149    SectionIndex = Entry->SectionIndex;
150  } else {
151    InMemoryStruct<macho::SymbolTableEntry> Entry;
152    getSymbolTableEntry(DRI, Entry);
153    SymbolOffset = Entry->Value;
154    SectionIndex = Entry->SectionIndex;
155  }
156  getSectionAddress(Sections[SectionIndex-1], Result);
157  Result += SymbolOffset;
158
159  return object_error::success;
160}
161
162error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
163                                          uint64_t &Result) const {
164  Result = UnknownAddressOrSize;
165  return object_error::success;
166}
167
168error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
169                                                char &Result) const {
170  uint8_t Type, Flags;
171  if (MachOObj->is64Bit()) {
172    InMemoryStruct<macho::Symbol64TableEntry> Entry;
173    getSymbol64TableEntry(DRI, Entry);
174    Type = Entry->Type;
175    Flags = Entry->Flags;
176  } else {
177    InMemoryStruct<macho::SymbolTableEntry> Entry;
178    getSymbolTableEntry(DRI, Entry);
179    Type = Entry->Type;
180    Flags = Entry->Flags;
181  }
182
183  char Char;
184  switch (Type & macho::STF_TypeMask) {
185    case macho::STT_Undefined:
186      Char = 'u';
187      break;
188    case macho::STT_Absolute:
189    case macho::STT_Section:
190      Char = 's';
191      break;
192    default:
193      Char = '?';
194      break;
195  }
196
197  if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
198    Char = toupper(Char);
199  Result = Char;
200  return object_error::success;
201}
202
203error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
204                                             bool &Result) const {
205  if (MachOObj->is64Bit()) {
206    InMemoryStruct<macho::Symbol64TableEntry> Entry;
207    getSymbol64TableEntry(DRI, Entry);
208    Result = Entry->Flags & macho::STF_StabsEntryMask;
209  } else {
210    InMemoryStruct<macho::SymbolTableEntry> Entry;
211    getSymbolTableEntry(DRI, Entry);
212    Result = Entry->Flags & macho::STF_StabsEntryMask;
213  }
214  return object_error::success;
215}
216
217error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
218
219  if (MachOObj->is64Bit()) {
220    InMemoryStruct<macho::Symbol64TableEntry> Entry;
221    getSymbol64TableEntry(Symb, Entry);
222    Res = Entry->Type & MachO::NlistMaskExternal;
223  } else {
224    InMemoryStruct<macho::SymbolTableEntry> Entry;
225    getSymbolTableEntry(Symb, Entry);
226    Res = Entry->Type & MachO::NlistMaskExternal;
227  }
228  return object_error::success;
229}
230
231error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
232                                          SymbolRef::SymbolType &Res) const {
233  uint8_t n_type;
234  if (MachOObj->is64Bit()) {
235    InMemoryStruct<macho::Symbol64TableEntry> Entry;
236    getSymbol64TableEntry(Symb, Entry);
237    n_type = Entry->Type;
238  } else {
239    InMemoryStruct<macho::SymbolTableEntry> Entry;
240    getSymbolTableEntry(Symb, Entry);
241    n_type = Entry->Type;
242  }
243  Res = SymbolRef::ST_Other;
244  switch (n_type & MachO::NlistMaskType) {
245    case MachO::NListTypeUndefined :
246      Res = SymbolRef::ST_External;
247      break;
248    case MachO::NListTypeSection :
249      Res = SymbolRef::ST_Function;
250      break;
251  }
252  return object_error::success;
253}
254
255
256symbol_iterator MachOObjectFile::begin_symbols() const {
257  // DRI.d.a = segment number; DRI.d.b = symbol index.
258  DataRefImpl DRI;
259  DRI.d.a = DRI.d.b = 0;
260  moveToNextSymbol(DRI);
261  return symbol_iterator(SymbolRef(DRI, this));
262}
263
264symbol_iterator MachOObjectFile::end_symbols() const {
265  DataRefImpl DRI;
266  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
267  DRI.d.b = 0;
268  return symbol_iterator(SymbolRef(DRI, this));
269}
270
271
272/*===-- Sections ----------------------------------------------------------===*/
273
274void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
275  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
276  while (DRI.d.a < LoadCommandCount) {
277    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
278    if (LCI.Command.Type == macho::LCT_Segment) {
279      InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
280      MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
281      if (DRI.d.b < SegmentLoadCmd->NumSections)
282        return;
283    } else if (LCI.Command.Type == macho::LCT_Segment64) {
284      InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
285      MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
286      if (DRI.d.b < Segment64LoadCmd->NumSections)
287        return;
288    }
289
290    DRI.d.a++;
291    DRI.d.b = 0;
292  }
293}
294
295error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
296                                           SectionRef &Result) const {
297  DRI.d.b++;
298  moveToNextSection(DRI);
299  Result = SectionRef(DRI, this);
300  return object_error::success;
301}
302
303void
304MachOObjectFile::getSection(DataRefImpl DRI,
305                            InMemoryStruct<macho::Section> &Res) const {
306  InMemoryStruct<macho::SegmentLoadCommand> SLC;
307  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
308  MachOObj->ReadSegmentLoadCommand(LCI, SLC);
309  MachOObj->ReadSection(LCI, DRI.d.b, Res);
310}
311
312std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
313  SectionList::const_iterator loc =
314    std::find(Sections.begin(), Sections.end(), Sec);
315  assert(loc != Sections.end() && "Sec is not a valid section!");
316  return std::distance(Sections.begin(), loc);
317}
318
319void
320MachOObjectFile::getSection64(DataRefImpl DRI,
321                            InMemoryStruct<macho::Section64> &Res) const {
322  InMemoryStruct<macho::Segment64LoadCommand> SLC;
323  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
324  MachOObj->ReadSegment64LoadCommand(LCI, SLC);
325  MachOObj->ReadSection64(LCI, DRI.d.b, Res);
326}
327
328static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
329  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
330  if (LCI.Command.Type == macho::LCT_Segment64)
331    return true;
332  assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
333  return false;
334}
335
336error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
337                                           StringRef &Result) const {
338  // FIXME: thread safety.
339  static char result[34];
340  if (is64BitLoadCommand(MachOObj, DRI)) {
341    InMemoryStruct<macho::Segment64LoadCommand> SLC;
342    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
343    MachOObj->ReadSegment64LoadCommand(LCI, SLC);
344    InMemoryStruct<macho::Section64> Sect;
345    MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
346
347    strcpy(result, Sect->SegmentName);
348    strcat(result, ",");
349    strcat(result, Sect->Name);
350  } else {
351    InMemoryStruct<macho::SegmentLoadCommand> SLC;
352    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
353    MachOObj->ReadSegmentLoadCommand(LCI, SLC);
354    InMemoryStruct<macho::Section> Sect;
355    MachOObj->ReadSection(LCI, DRI.d.b, Sect);
356
357    strcpy(result, Sect->SegmentName);
358    strcat(result, ",");
359    strcat(result, Sect->Name);
360  }
361  Result = StringRef(result);
362  return object_error::success;
363}
364
365error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
366                                              uint64_t &Result) const {
367  if (is64BitLoadCommand(MachOObj, DRI)) {
368    InMemoryStruct<macho::Section64> Sect;
369    getSection64(DRI, Sect);
370    Result = Sect->Address;
371  } else {
372    InMemoryStruct<macho::Section> Sect;
373    getSection(DRI, Sect);
374    Result = Sect->Address;
375  }
376  return object_error::success;
377}
378
379error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
380                                           uint64_t &Result) const {
381  if (is64BitLoadCommand(MachOObj, DRI)) {
382    InMemoryStruct<macho::Section64> Sect;
383    getSection64(DRI, Sect);
384    Result = Sect->Size;
385  } else {
386    InMemoryStruct<macho::Section> Sect;
387    getSection(DRI, Sect);
388    Result = Sect->Size;
389  }
390  return object_error::success;
391}
392
393error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
394                                               StringRef &Result) const {
395  if (is64BitLoadCommand(MachOObj, DRI)) {
396    InMemoryStruct<macho::Section64> Sect;
397    getSection64(DRI, Sect);
398    Result = MachOObj->getData(Sect->Offset, Sect->Size);
399  } else {
400    InMemoryStruct<macho::Section> Sect;
401    getSection(DRI, Sect);
402    Result = MachOObj->getData(Sect->Offset, Sect->Size);
403  }
404  return object_error::success;
405}
406
407error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
408                                                uint64_t &Result) const {
409  if (is64BitLoadCommand(MachOObj, DRI)) {
410    InMemoryStruct<macho::Section64> Sect;
411    getSection64(DRI, Sect);
412    Result = uint64_t(1) << Sect->Align;
413  } else {
414    InMemoryStruct<macho::Section> Sect;
415    getSection(DRI, Sect);
416    Result = uint64_t(1) << Sect->Align;
417  }
418  return object_error::success;
419}
420
421error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
422                                          bool &Result) const {
423  if (is64BitLoadCommand(MachOObj, DRI)) {
424    InMemoryStruct<macho::Section64> Sect;
425    getSection64(DRI, Sect);
426    Result = !strcmp(Sect->Name, "__text");
427  } else {
428    InMemoryStruct<macho::Section> Sect;
429    getSection(DRI, Sect);
430    Result = !strcmp(Sect->Name, "__text");
431  }
432  return object_error::success;
433}
434
435error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
436                                          bool &Result) const {
437  // FIXME: Unimplemented.
438  Result = false;
439  return object_error::success;
440}
441
442error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
443                                         bool &Result) const {
444  // FIXME: Unimplemented.
445  Result = false;
446  return object_error::success;
447}
448
449error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
450                                                  DataRefImpl Symb,
451                                                  bool &Result) const {
452  if (MachOObj->is64Bit()) {
453    InMemoryStruct<macho::Symbol64TableEntry> Entry;
454    getSymbol64TableEntry(Symb, Entry);
455    Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
456  } else {
457    InMemoryStruct<macho::SymbolTableEntry> Entry;
458    getSymbolTableEntry(Symb, Entry);
459    Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
460  }
461  return object_error::success;
462}
463
464relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
465  DataRefImpl ret;
466  ret.d.a = 0;
467  ret.d.b = getSectionIndex(Sec);
468  return relocation_iterator(RelocationRef(ret, this));
469}
470relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
471  uint32_t last_reloc;
472  if (is64BitLoadCommand(MachOObj, Sec)) {
473    InMemoryStruct<macho::Section64> Sect;
474    getSection64(Sec, Sect);
475    last_reloc = Sect->NumRelocationTableEntries;
476  } else {
477    InMemoryStruct<macho::Section> Sect;
478    getSection(Sec, Sect);
479    last_reloc = Sect->NumRelocationTableEntries;
480  }
481  DataRefImpl ret;
482  ret.d.a = last_reloc;
483  ret.d.b = getSectionIndex(Sec);
484  return relocation_iterator(RelocationRef(ret, this));
485}
486
487section_iterator MachOObjectFile::begin_sections() const {
488  DataRefImpl DRI;
489  DRI.d.a = DRI.d.b = 0;
490  moveToNextSection(DRI);
491  return section_iterator(SectionRef(DRI, this));
492}
493
494section_iterator MachOObjectFile::end_sections() const {
495  DataRefImpl DRI;
496  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
497  DRI.d.b = 0;
498  return section_iterator(SectionRef(DRI, this));
499}
500
501/*===-- Relocations -------------------------------------------------------===*/
502
503void MachOObjectFile::
504getRelocation(DataRefImpl Rel,
505              InMemoryStruct<macho::RelocationEntry> &Res) const {
506  uint32_t relOffset;
507  if (MachOObj->is64Bit()) {
508    InMemoryStruct<macho::Section64> Sect;
509    getSection64(Sections[Rel.d.b], Sect);
510    relOffset = Sect->RelocationTableOffset;
511  } else {
512    InMemoryStruct<macho::Section> Sect;
513    getSection(Sections[Rel.d.b], Sect);
514    relOffset = Sect->RelocationTableOffset;
515  }
516  MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
517}
518error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
519                                              RelocationRef &Res) const {
520  ++Rel.d.a;
521  Res = RelocationRef(Rel, this);
522  return object_error::success;
523}
524error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
525                                                 uint64_t &Res) const {
526  const uint8_t* sectAddress = base();
527  if (MachOObj->is64Bit()) {
528    InMemoryStruct<macho::Section64> Sect;
529    getSection64(Sections[Rel.d.b], Sect);
530    sectAddress += Sect->Offset;
531  } else {
532    InMemoryStruct<macho::Section> Sect;
533    getSection(Sections[Rel.d.b], Sect);
534    sectAddress += Sect->Offset;
535  }
536  InMemoryStruct<macho::RelocationEntry> RE;
537  getRelocation(Rel, RE);
538  Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
539  return object_error::success;
540}
541error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
542                                                SymbolRef &Res) const {
543  InMemoryStruct<macho::RelocationEntry> RE;
544  getRelocation(Rel, RE);
545  uint32_t SymbolIdx = RE->Word1 & 0xffffff;
546  bool isExtern = (RE->Word1 >> 27) & 1;
547
548  DataRefImpl Sym;
549  Sym.d.a = Sym.d.b = 0;
550  moveToNextSymbol(Sym);
551  if (isExtern) {
552    for (unsigned i = 0; i < SymbolIdx; i++) {
553      Sym.d.b++;
554      moveToNextSymbol(Sym);
555      assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
556             "Relocation symbol index out of range!");
557    }
558  }
559  Res = SymbolRef(Sym, this);
560  return object_error::success;
561}
562error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
563                                              uint32_t &Res) const {
564  InMemoryStruct<macho::RelocationEntry> RE;
565  getRelocation(Rel, RE);
566  Res = RE->Word1;
567  return object_error::success;
568}
569error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
570                                          SmallVectorImpl<char> &Result) const {
571  return object_error::success;
572}
573error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
574                                                        int64_t &Res) const {
575  InMemoryStruct<macho::RelocationEntry> RE;
576  getRelocation(Rel, RE);
577  bool isExtern = (RE->Word1 >> 27) & 1;
578  Res = 0;
579  if (!isExtern) {
580    const uint8_t* sectAddress = base();
581    if (MachOObj->is64Bit()) {
582      InMemoryStruct<macho::Section64> Sect;
583      getSection64(Sections[Rel.d.b], Sect);
584      sectAddress += Sect->Offset;
585    } else {
586      InMemoryStruct<macho::Section> Sect;
587      getSection(Sections[Rel.d.b], Sect);
588      sectAddress += Sect->Offset;
589    }
590    Res = reinterpret_cast<uintptr_t>(sectAddress);
591  }
592  return object_error::success;
593}
594error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
595                                          SmallVectorImpl<char> &Result) const {
596  return object_error::success;
597}
598
599/*===-- Miscellaneous -----------------------------------------------------===*/
600
601uint8_t MachOObjectFile::getBytesInAddress() const {
602  return MachOObj->is64Bit() ? 8 : 4;
603}
604
605StringRef MachOObjectFile::getFileFormatName() const {
606  if (!MachOObj->is64Bit()) {
607    switch (MachOObj->getHeader().CPUType) {
608    case llvm::MachO::CPUTypeI386:
609      return "Mach-O 32-bit i386";
610    case llvm::MachO::CPUTypeARM:
611      return "Mach-O arm";
612    case llvm::MachO::CPUTypePowerPC:
613      return "Mach-O 32-bit ppc";
614    default:
615      assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
616             "64-bit object file when we're not 64-bit?");
617      return "Mach-O 32-bit unknown";
618    }
619  }
620
621  switch (MachOObj->getHeader().CPUType) {
622  case llvm::MachO::CPUTypeX86_64:
623    return "Mach-O 64-bit x86-64";
624  case llvm::MachO::CPUTypePowerPC64:
625    return "Mach-O 64-bit ppc64";
626  default:
627    assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
628           "32-bit object file when we're 64-bit?");
629    return "Mach-O 64-bit unknown";
630  }
631}
632
633unsigned MachOObjectFile::getArch() const {
634  switch (MachOObj->getHeader().CPUType) {
635  case llvm::MachO::CPUTypeI386:
636    return Triple::x86;
637  case llvm::MachO::CPUTypeX86_64:
638    return Triple::x86_64;
639  case llvm::MachO::CPUTypeARM:
640    return Triple::arm;
641  case llvm::MachO::CPUTypePowerPC:
642    return Triple::ppc;
643  case llvm::MachO::CPUTypePowerPC64:
644    return Triple::ppc64;
645  default:
646    return Triple::UnknownArch;
647  }
648}
649
650} // end namespace object
651} // end namespace llvm
652