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