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