MachOObjectFile.cpp revision 5f4e02cbf1d0fa0d8048369264201c258f2ad717
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  uint64_t SectionOffset;
130  uint8_t SectionIndex;
131  if (MachOObj->is64Bit()) {
132    InMemoryStruct<macho::Symbol64TableEntry> Entry;
133    getSymbol64TableEntry(DRI, Entry);
134    Result = Entry->Value;
135    SectionIndex = Entry->SectionIndex;
136  } else {
137    InMemoryStruct<macho::SymbolTableEntry> Entry;
138    getSymbolTableEntry(DRI, Entry);
139    Result = Entry->Value;
140    SectionIndex = Entry->SectionIndex;
141  }
142  getSectionAddress(Sections[SectionIndex-1], SectionOffset);
143  Result -= SectionOffset;
144
145  return object_error::success;
146}
147
148error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
149                                             uint64_t &Result) const {
150  if (MachOObj->is64Bit()) {
151    InMemoryStruct<macho::Symbol64TableEntry> Entry;
152    getSymbol64TableEntry(DRI, Entry);
153    Result = Entry->Value;
154  } else {
155    InMemoryStruct<macho::SymbolTableEntry> Entry;
156    getSymbolTableEntry(DRI, Entry);
157    Result = Entry->Value;
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::isSymbolWeak(DataRefImpl Symb, bool &Res) const {
232
233  if (MachOObj->is64Bit()) {
234    InMemoryStruct<macho::Symbol64TableEntry> Entry;
235    getSymbol64TableEntry(Symb, Entry);
236    Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
237  } else {
238    InMemoryStruct<macho::SymbolTableEntry> Entry;
239    getSymbolTableEntry(Symb, Entry);
240    Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
241  }
242  return object_error::success;
243}
244
245error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{
246  uint8_t n_type;
247  if (MachOObj->is64Bit()) {
248    InMemoryStruct<macho::Symbol64TableEntry> Entry;
249    getSymbol64TableEntry(Symb, Entry);
250    n_type = Entry->Type;
251  } else {
252    InMemoryStruct<macho::SymbolTableEntry> Entry;
253    getSymbolTableEntry(Symb, Entry);
254    n_type = Entry->Type;
255  }
256
257  Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute;
258  return object_error::success;
259}
260
261error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
262                                             section_iterator &Res) const {
263  uint8_t index;
264  if (MachOObj->is64Bit()) {
265    InMemoryStruct<macho::Symbol64TableEntry> Entry;
266    getSymbol64TableEntry(Symb, Entry);
267    index = Entry->SectionIndex;
268  } else {
269    InMemoryStruct<macho::SymbolTableEntry> Entry;
270    getSymbolTableEntry(Symb, Entry);
271    index = Entry->SectionIndex;
272  }
273
274  if (index == 0)
275    Res = end_sections();
276  else
277    Res = section_iterator(SectionRef(Sections[index], this));
278
279  return object_error::success;
280}
281
282error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
283                                          SymbolRef::Type &Res) const {
284  uint8_t n_type;
285  if (MachOObj->is64Bit()) {
286    InMemoryStruct<macho::Symbol64TableEntry> Entry;
287    getSymbol64TableEntry(Symb, Entry);
288    n_type = Entry->Type;
289  } else {
290    InMemoryStruct<macho::SymbolTableEntry> Entry;
291    getSymbolTableEntry(Symb, Entry);
292    n_type = Entry->Type;
293  }
294  Res = SymbolRef::ST_Other;
295
296  // If this is a STAB debugging symbol, we can do nothing more.
297  if (n_type & MachO::NlistMaskStab) {
298    Res = SymbolRef::ST_Debug;
299    return object_error::success;
300  }
301
302  switch (n_type & MachO::NlistMaskType) {
303    case MachO::NListTypeUndefined :
304      Res = SymbolRef::ST_External;
305      break;
306    case MachO::NListTypeSection :
307      Res = SymbolRef::ST_Function;
308      break;
309  }
310  return object_error::success;
311}
312
313
314symbol_iterator MachOObjectFile::begin_symbols() const {
315  // DRI.d.a = segment number; DRI.d.b = symbol index.
316  DataRefImpl DRI;
317  DRI.d.a = DRI.d.b = 0;
318  moveToNextSymbol(DRI);
319  return symbol_iterator(SymbolRef(DRI, this));
320}
321
322symbol_iterator MachOObjectFile::end_symbols() const {
323  DataRefImpl DRI;
324  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
325  DRI.d.b = 0;
326  return symbol_iterator(SymbolRef(DRI, this));
327}
328
329
330/*===-- Sections ----------------------------------------------------------===*/
331
332void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
333  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
334  while (DRI.d.a < LoadCommandCount) {
335    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
336    if (LCI.Command.Type == macho::LCT_Segment) {
337      InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
338      MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
339      if (DRI.d.b < SegmentLoadCmd->NumSections)
340        return;
341    } else if (LCI.Command.Type == macho::LCT_Segment64) {
342      InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
343      MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
344      if (DRI.d.b < Segment64LoadCmd->NumSections)
345        return;
346    }
347
348    DRI.d.a++;
349    DRI.d.b = 0;
350  }
351}
352
353error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
354                                           SectionRef &Result) const {
355  DRI.d.b++;
356  moveToNextSection(DRI);
357  Result = SectionRef(DRI, this);
358  return object_error::success;
359}
360
361void
362MachOObjectFile::getSection(DataRefImpl DRI,
363                            InMemoryStruct<macho::Section> &Res) const {
364  InMemoryStruct<macho::SegmentLoadCommand> SLC;
365  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
366  MachOObj->ReadSegmentLoadCommand(LCI, SLC);
367  MachOObj->ReadSection(LCI, DRI.d.b, Res);
368}
369
370std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
371  SectionList::const_iterator loc =
372    std::find(Sections.begin(), Sections.end(), Sec);
373  assert(loc != Sections.end() && "Sec is not a valid section!");
374  return std::distance(Sections.begin(), loc);
375}
376
377void
378MachOObjectFile::getSection64(DataRefImpl DRI,
379                            InMemoryStruct<macho::Section64> &Res) const {
380  InMemoryStruct<macho::Segment64LoadCommand> SLC;
381  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
382  MachOObj->ReadSegment64LoadCommand(LCI, SLC);
383  MachOObj->ReadSection64(LCI, DRI.d.b, Res);
384}
385
386static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
387  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
388  if (LCI.Command.Type == macho::LCT_Segment64)
389    return true;
390  assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
391  return false;
392}
393
394error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
395                                           StringRef &Result) const {
396  // FIXME: thread safety.
397  static char result[34];
398  if (is64BitLoadCommand(MachOObj, DRI)) {
399    InMemoryStruct<macho::Segment64LoadCommand> SLC;
400    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
401    MachOObj->ReadSegment64LoadCommand(LCI, SLC);
402    InMemoryStruct<macho::Section64> Sect;
403    MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
404
405    strcpy(result, Sect->SegmentName);
406    strcat(result, ",");
407    strcat(result, Sect->Name);
408  } else {
409    InMemoryStruct<macho::SegmentLoadCommand> SLC;
410    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
411    MachOObj->ReadSegmentLoadCommand(LCI, SLC);
412    InMemoryStruct<macho::Section> Sect;
413    MachOObj->ReadSection(LCI, DRI.d.b, Sect);
414
415    strcpy(result, Sect->SegmentName);
416    strcat(result, ",");
417    strcat(result, Sect->Name);
418  }
419  Result = StringRef(result);
420  return object_error::success;
421}
422
423error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
424                                              uint64_t &Result) const {
425  if (is64BitLoadCommand(MachOObj, DRI)) {
426    InMemoryStruct<macho::Section64> Sect;
427    getSection64(DRI, Sect);
428    Result = Sect->Address;
429  } else {
430    InMemoryStruct<macho::Section> Sect;
431    getSection(DRI, Sect);
432    Result = Sect->Address;
433  }
434  return object_error::success;
435}
436
437error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
438                                           uint64_t &Result) const {
439  if (is64BitLoadCommand(MachOObj, DRI)) {
440    InMemoryStruct<macho::Section64> Sect;
441    getSection64(DRI, Sect);
442    Result = Sect->Size;
443  } else {
444    InMemoryStruct<macho::Section> Sect;
445    getSection(DRI, Sect);
446    Result = Sect->Size;
447  }
448  return object_error::success;
449}
450
451error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
452                                               StringRef &Result) const {
453  if (is64BitLoadCommand(MachOObj, DRI)) {
454    InMemoryStruct<macho::Section64> Sect;
455    getSection64(DRI, Sect);
456    Result = MachOObj->getData(Sect->Offset, Sect->Size);
457  } else {
458    InMemoryStruct<macho::Section> Sect;
459    getSection(DRI, Sect);
460    Result = MachOObj->getData(Sect->Offset, Sect->Size);
461  }
462  return object_error::success;
463}
464
465error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
466                                                uint64_t &Result) const {
467  if (is64BitLoadCommand(MachOObj, DRI)) {
468    InMemoryStruct<macho::Section64> Sect;
469    getSection64(DRI, Sect);
470    Result = uint64_t(1) << Sect->Align;
471  } else {
472    InMemoryStruct<macho::Section> Sect;
473    getSection(DRI, Sect);
474    Result = uint64_t(1) << Sect->Align;
475  }
476  return object_error::success;
477}
478
479error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
480                                          bool &Result) const {
481  if (is64BitLoadCommand(MachOObj, DRI)) {
482    InMemoryStruct<macho::Section64> Sect;
483    getSection64(DRI, Sect);
484    Result = !strcmp(Sect->Name, "__text");
485  } else {
486    InMemoryStruct<macho::Section> Sect;
487    getSection(DRI, Sect);
488    Result = !strcmp(Sect->Name, "__text");
489  }
490  return object_error::success;
491}
492
493error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
494                                          bool &Result) const {
495  // FIXME: Unimplemented.
496  Result = false;
497  return object_error::success;
498}
499
500error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
501                                         bool &Result) const {
502  // FIXME: Unimplemented.
503  Result = false;
504  return object_error::success;
505}
506
507error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
508                                                  DataRefImpl Symb,
509                                                  bool &Result) const {
510  SymbolRef::Type ST;
511  getSymbolType(Symb, ST);
512  if (ST == SymbolRef::ST_External) {
513    Result = false;
514    return object_error::success;
515  }
516
517  uint64_t SectBegin, SectEnd;
518  getSectionAddress(Sec, SectBegin);
519  getSectionSize(Sec, SectEnd);
520  SectEnd += SectBegin;
521
522  if (MachOObj->is64Bit()) {
523    InMemoryStruct<macho::Symbol64TableEntry> Entry;
524    getSymbol64TableEntry(Symb, Entry);
525    uint64_t SymAddr= Entry->Value;
526    Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
527  } else {
528    InMemoryStruct<macho::SymbolTableEntry> Entry;
529    getSymbolTableEntry(Symb, Entry);
530    uint64_t SymAddr= Entry->Value;
531    Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
532  }
533
534  return object_error::success;
535}
536
537relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
538  DataRefImpl ret;
539  ret.d.a = 0;
540  ret.d.b = getSectionIndex(Sec);
541  return relocation_iterator(RelocationRef(ret, this));
542}
543relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
544  uint32_t last_reloc;
545  if (is64BitLoadCommand(MachOObj, Sec)) {
546    InMemoryStruct<macho::Section64> Sect;
547    getSection64(Sec, Sect);
548    last_reloc = Sect->NumRelocationTableEntries;
549  } else {
550    InMemoryStruct<macho::Section> Sect;
551    getSection(Sec, Sect);
552    last_reloc = Sect->NumRelocationTableEntries;
553  }
554  DataRefImpl ret;
555  ret.d.a = last_reloc;
556  ret.d.b = getSectionIndex(Sec);
557  return relocation_iterator(RelocationRef(ret, this));
558}
559
560section_iterator MachOObjectFile::begin_sections() const {
561  DataRefImpl DRI;
562  DRI.d.a = DRI.d.b = 0;
563  moveToNextSection(DRI);
564  return section_iterator(SectionRef(DRI, this));
565}
566
567section_iterator MachOObjectFile::end_sections() const {
568  DataRefImpl DRI;
569  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
570  DRI.d.b = 0;
571  return section_iterator(SectionRef(DRI, this));
572}
573
574/*===-- Relocations -------------------------------------------------------===*/
575
576void MachOObjectFile::
577getRelocation(DataRefImpl Rel,
578              InMemoryStruct<macho::RelocationEntry> &Res) const {
579  uint32_t relOffset;
580  if (MachOObj->is64Bit()) {
581    InMemoryStruct<macho::Section64> Sect;
582    getSection64(Sections[Rel.d.b], Sect);
583    relOffset = Sect->RelocationTableOffset;
584  } else {
585    InMemoryStruct<macho::Section> Sect;
586    getSection(Sections[Rel.d.b], Sect);
587    relOffset = Sect->RelocationTableOffset;
588  }
589  MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
590}
591error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
592                                              RelocationRef &Res) const {
593  ++Rel.d.a;
594  Res = RelocationRef(Rel, this);
595  return object_error::success;
596}
597error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
598                                                 uint64_t &Res) const {
599  const uint8_t* sectAddress = base();
600  if (MachOObj->is64Bit()) {
601    InMemoryStruct<macho::Section64> Sect;
602    getSection64(Sections[Rel.d.b], Sect);
603    sectAddress += Sect->Offset;
604  } else {
605    InMemoryStruct<macho::Section> Sect;
606    getSection(Sections[Rel.d.b], Sect);
607    sectAddress += Sect->Offset;
608  }
609  InMemoryStruct<macho::RelocationEntry> RE;
610  getRelocation(Rel, RE);
611  Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
612  return object_error::success;
613}
614error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
615                                                SymbolRef &Res) const {
616  InMemoryStruct<macho::RelocationEntry> RE;
617  getRelocation(Rel, RE);
618  uint32_t SymbolIdx = RE->Word1 & 0xffffff;
619  bool isExtern = (RE->Word1 >> 27) & 1;
620
621  DataRefImpl Sym;
622  Sym.d.a = Sym.d.b = 0;
623  moveToNextSymbol(Sym);
624  if (isExtern) {
625    for (unsigned i = 0; i < SymbolIdx; i++) {
626      Sym.d.b++;
627      moveToNextSymbol(Sym);
628      assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
629             "Relocation symbol index out of range!");
630    }
631  }
632  Res = SymbolRef(Sym, this);
633  return object_error::success;
634}
635error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
636                                              uint32_t &Res) const {
637  InMemoryStruct<macho::RelocationEntry> RE;
638  getRelocation(Rel, RE);
639  Res = RE->Word1;
640  return object_error::success;
641}
642error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
643                                          SmallVectorImpl<char> &Result) const {
644  StringRef res = "Unknown";
645  Result.append(res.begin(), res.end());
646  return object_error::success;
647}
648error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
649                                                        int64_t &Res) const {
650  InMemoryStruct<macho::RelocationEntry> RE;
651  getRelocation(Rel, RE);
652  bool isExtern = (RE->Word1 >> 27) & 1;
653  Res = 0;
654  if (!isExtern) {
655    const uint8_t* sectAddress = base();
656    if (MachOObj->is64Bit()) {
657      InMemoryStruct<macho::Section64> Sect;
658      getSection64(Sections[Rel.d.b], Sect);
659      sectAddress += Sect->Offset;
660    } else {
661      InMemoryStruct<macho::Section> Sect;
662      getSection(Sections[Rel.d.b], Sect);
663      sectAddress += Sect->Offset;
664    }
665    Res = reinterpret_cast<uintptr_t>(sectAddress);
666  }
667  return object_error::success;
668}
669error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
670                                          SmallVectorImpl<char> &Result) const {
671  StringRef res = "Unknown";
672  Result.append(res.begin(), res.end());
673  return object_error::success;
674}
675
676/*===-- Miscellaneous -----------------------------------------------------===*/
677
678uint8_t MachOObjectFile::getBytesInAddress() const {
679  return MachOObj->is64Bit() ? 8 : 4;
680}
681
682StringRef MachOObjectFile::getFileFormatName() const {
683  if (!MachOObj->is64Bit()) {
684    switch (MachOObj->getHeader().CPUType) {
685    case llvm::MachO::CPUTypeI386:
686      return "Mach-O 32-bit i386";
687    case llvm::MachO::CPUTypeARM:
688      return "Mach-O arm";
689    case llvm::MachO::CPUTypePowerPC:
690      return "Mach-O 32-bit ppc";
691    default:
692      assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
693             "64-bit object file when we're not 64-bit?");
694      return "Mach-O 32-bit unknown";
695    }
696  }
697
698  switch (MachOObj->getHeader().CPUType) {
699  case llvm::MachO::CPUTypeX86_64:
700    return "Mach-O 64-bit x86-64";
701  case llvm::MachO::CPUTypePowerPC64:
702    return "Mach-O 64-bit ppc64";
703  default:
704    assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
705           "32-bit object file when we're 64-bit?");
706    return "Mach-O 64-bit unknown";
707  }
708}
709
710unsigned MachOObjectFile::getArch() const {
711  switch (MachOObj->getHeader().CPUType) {
712  case llvm::MachO::CPUTypeI386:
713    return Triple::x86;
714  case llvm::MachO::CPUTypeX86_64:
715    return Triple::x86_64;
716  case llvm::MachO::CPUTypeARM:
717    return Triple::arm;
718  case llvm::MachO::CPUTypePowerPC:
719    return Triple::ppc;
720  case llvm::MachO::CPUTypePowerPC64:
721    return Triple::ppc64;
722  default:
723    return Triple::UnknownArch;
724  }
725}
726
727} // end namespace object
728} // end namespace llvm
729