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