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