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