//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the MachOObjectFile class, which binds the MachOObject
// class to the generic ObjectFile wrapper.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/MachO.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/MachOFormat.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cctype>
#include <cstring>
#include <limits>

using namespace llvm;
using namespace object;

namespace llvm {
namespace object {

struct SymbolTableEntryBase {
  uint32_t StringIndex;
  uint8_t Type;
  uint8_t SectionIndex;
  uint16_t Flags;
};

struct SectionBase {
  char Name[16];
  char SegmentName[16];
};

template<typename T>
static void SwapValue(T &Value) {
  Value = sys::SwapByteOrder(Value);
}

template<typename T>
static void SwapStruct(T &Value);

template<>
void SwapStruct(macho::RelocationEntry &H) {
  SwapValue(H.Word0);
  SwapValue(H.Word1);
}

template<>
void SwapStruct(macho::LoadCommand &L) {
  SwapValue(L.Type);
  SwapValue(L.Size);
}

template<>
void SwapStruct(SymbolTableEntryBase &S) {
  SwapValue(S.StringIndex);
  SwapValue(S.Flags);
}

template<>
void SwapStruct(macho::Section &S) {
  SwapValue(S.Address);
  SwapValue(S.Size);
  SwapValue(S.Offset);
  SwapValue(S.Align);
  SwapValue(S.RelocationTableOffset);
  SwapValue(S.NumRelocationTableEntries);
  SwapValue(S.Flags);
  SwapValue(S.Reserved1);
  SwapValue(S.Reserved2);
}

template<>
void SwapStruct(macho::Section64 &S) {
  SwapValue(S.Address);
  SwapValue(S.Size);
  SwapValue(S.Offset);
  SwapValue(S.Align);
  SwapValue(S.RelocationTableOffset);
  SwapValue(S.NumRelocationTableEntries);
  SwapValue(S.Flags);
  SwapValue(S.Reserved1);
  SwapValue(S.Reserved2);
  SwapValue(S.Reserved3);
}

template<>
void SwapStruct(macho::SymbolTableEntry &S) {
  SwapValue(S.StringIndex);
  SwapValue(S.Flags);
  SwapValue(S.Value);
}

template<>
void SwapStruct(macho::Symbol64TableEntry &S) {
  SwapValue(S.StringIndex);
  SwapValue(S.Flags);
  SwapValue(S.Value);
}

template<>
void SwapStruct(macho::Header &H) {
  SwapValue(H.Magic);
  SwapValue(H.CPUType);
  SwapValue(H.CPUSubtype);
  SwapValue(H.FileType);
  SwapValue(H.NumLoadCommands);
  SwapValue(H.SizeOfLoadCommands);
  SwapValue(H.Flags);
}

template<>
void SwapStruct(macho::Header64Ext &E) {
  SwapValue(E.Reserved);
}

template<>
void SwapStruct(macho::SymtabLoadCommand &C) {
  SwapValue(C.Type);
  SwapValue(C.Size);
  SwapValue(C.SymbolTableOffset);
  SwapValue(C.NumSymbolTableEntries);
  SwapValue(C.StringTableOffset);
  SwapValue(C.StringTableSize);
}

template<>
void SwapStruct(macho::DysymtabLoadCommand &C) {
  SwapValue(C.Type);
  SwapValue(C.Size);
  SwapValue(C.LocalSymbolsIndex);
  SwapValue(C.NumLocalSymbols);
  SwapValue(C.ExternalSymbolsIndex);
  SwapValue(C.NumExternalSymbols);
  SwapValue(C.UndefinedSymbolsIndex);
  SwapValue(C.NumUndefinedSymbols);
  SwapValue(C.TOCOffset);
  SwapValue(C.NumTOCEntries);
  SwapValue(C.ModuleTableOffset);
  SwapValue(C.NumModuleTableEntries);
  SwapValue(C.ReferenceSymbolTableOffset);
  SwapValue(C.NumReferencedSymbolTableEntries);
  SwapValue(C.IndirectSymbolTableOffset);
  SwapValue(C.NumIndirectSymbolTableEntries);
  SwapValue(C.ExternalRelocationTableOffset);
  SwapValue(C.NumExternalRelocationTableEntries);
  SwapValue(C.LocalRelocationTableOffset);
  SwapValue(C.NumLocalRelocationTableEntries);
}

template<>
void SwapStruct(macho::LinkeditDataLoadCommand &C) {
  SwapValue(C.Type);
  SwapValue(C.Size);
  SwapValue(C.DataOffset);
  SwapValue(C.DataSize);
}

template<>
void SwapStruct(macho::SegmentLoadCommand &C) {
  SwapValue(C.Type);
  SwapValue(C.Size);
  SwapValue(C.VMAddress);
  SwapValue(C.VMSize);
  SwapValue(C.FileOffset);
  SwapValue(C.FileSize);
  SwapValue(C.MaxVMProtection);
  SwapValue(C.InitialVMProtection);
  SwapValue(C.NumSections);
  SwapValue(C.Flags);
}

template<>
void SwapStruct(macho::Segment64LoadCommand &C) {
  SwapValue(C.Type);
  SwapValue(C.Size);
  SwapValue(C.VMAddress);
  SwapValue(C.VMSize);
  SwapValue(C.FileOffset);
  SwapValue(C.FileSize);
  SwapValue(C.MaxVMProtection);
  SwapValue(C.InitialVMProtection);
  SwapValue(C.NumSections);
  SwapValue(C.Flags);
}

template<>
void SwapStruct(macho::IndirectSymbolTableEntry &C) {
  SwapValue(C.Index);
}

template<>
void SwapStruct(macho::LinkerOptionsLoadCommand &C) {
  SwapValue(C.Type);
  SwapValue(C.Size);
  SwapValue(C.Count);
}

template<>
void SwapStruct(macho::DataInCodeTableEntry &C) {
  SwapValue(C.Offset);
  SwapValue(C.Length);
  SwapValue(C.Kind);
}

template<typename T>
T getStruct(const MachOObjectFile *O, const char *P) {
  T Cmd;
  memcpy(&Cmd, P, sizeof(T));
  if (O->isLittleEndian() != sys::IsLittleEndianHost)
    SwapStruct(Cmd);
  return Cmd;
}

static uint32_t
getSegmentLoadCommandNumSections(const MachOObjectFile *O,
                                 const MachOObjectFile::LoadCommandInfo &L) {
  if (O->is64Bit()) {
    macho::Segment64LoadCommand S = O->getSegment64LoadCommand(L);
    return S.NumSections;
  }
  macho::SegmentLoadCommand S = O->getSegmentLoadCommand(L);
  return S.NumSections;
}

static const char *
getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
              unsigned Sec) {
  uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);

  bool Is64 = O->is64Bit();
  unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
                                    sizeof(macho::SegmentLoadCommand);
  unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
                                sizeof(macho::Section);

  uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
  return reinterpret_cast<const char*>(SectionAddr);
}

static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
  return O->getData().substr(Offset, 1).data();
}

static SymbolTableEntryBase
getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
  const char *P = reinterpret_cast<const char *>(DRI.p);
  return getStruct<SymbolTableEntryBase>(O, P);
}

static StringRef parseSegmentOrSectionName(const char *P) {
  if (P[15] == 0)
    // Null terminated.
    return P;
  // Not null terminated, so this is a 16 char string.
  return StringRef(P, 16);
}

// Helper to advance a section or symbol iterator multiple increments at a time.
template<class T>
static error_code advance(T &it, size_t Val) {
  error_code ec;
  while (Val--) {
    it.increment(ec);
  }
  return ec;
}

template<class T>
static void advanceTo(T &it, size_t Val) {
  if (error_code ec = advance(it, Val))
    report_fatal_error(ec.message());
}

static unsigned getCPUType(const MachOObjectFile *O) {
  return O->getHeader().CPUType;
}

static void printRelocationTargetName(const MachOObjectFile *O,
                                      const macho::RelocationEntry &RE,
                                      raw_string_ostream &fmt) {
  bool IsScattered = O->isRelocationScattered(RE);

  // Target of a scattered relocation is an address.  In the interest of
  // generating pretty output, scan through the symbol table looking for a
  // symbol that aligns with that address.  If we find one, print it.
  // Otherwise, we just print the hex address of the target.
  if (IsScattered) {
    uint32_t Val = O->getPlainRelocationSymbolNum(RE);

    error_code ec;
    for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
         SI != SE; SI.increment(ec)) {
      if (ec) report_fatal_error(ec.message());

      uint64_t Addr;
      StringRef Name;

      if ((ec = SI->getAddress(Addr)))
        report_fatal_error(ec.message());
      if (Addr != Val) continue;
      if ((ec = SI->getName(Name)))
        report_fatal_error(ec.message());
      fmt << Name;
      return;
    }

    // If we couldn't find a symbol that this relocation refers to, try
    // to find a section beginning instead.
    for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
         SI != SE; SI.increment(ec)) {
      if (ec) report_fatal_error(ec.message());

      uint64_t Addr;
      StringRef Name;

      if ((ec = SI->getAddress(Addr)))
        report_fatal_error(ec.message());
      if (Addr != Val) continue;
      if ((ec = SI->getName(Name)))
        report_fatal_error(ec.message());
      fmt << Name;
      return;
    }

    fmt << format("0x%x", Val);
    return;
  }

  StringRef S;
  bool isExtern = O->getPlainRelocationExternal(RE);
  uint64_t Val = O->getPlainRelocationSymbolNum(RE);

  if (isExtern) {
    symbol_iterator SI = O->begin_symbols();
    advanceTo(SI, Val);
    SI->getName(S);
  } else {
    section_iterator SI = O->begin_sections();
    // Adjust for the fact that sections are 1-indexed.
    advanceTo(SI, Val - 1);
    SI->getName(S);
  }

  fmt << S;
}

static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
  return RE.Word0;
}

static unsigned
getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
  return RE.Word0 & 0xffffff;
}

static bool getPlainRelocationPCRel(const MachOObjectFile *O,
                                    const macho::RelocationEntry &RE) {
  if (O->isLittleEndian())
    return (RE.Word1 >> 24) & 1;
  return (RE.Word1 >> 7) & 1;
}

static bool
getScatteredRelocationPCRel(const MachOObjectFile *O,
                            const macho::RelocationEntry &RE) {
  return (RE.Word0 >> 30) & 1;
}

static unsigned getPlainRelocationLength(const MachOObjectFile *O,
                                         const macho::RelocationEntry &RE) {
  if (O->isLittleEndian())
    return (RE.Word1 >> 25) & 3;
  return (RE.Word1 >> 5) & 3;
}

static unsigned
getScatteredRelocationLength(const macho::RelocationEntry &RE) {
  return (RE.Word0 >> 28) & 3;
}

static unsigned getPlainRelocationType(const MachOObjectFile *O,
                                       const macho::RelocationEntry &RE) {
  if (O->isLittleEndian())
    return RE.Word1 >> 28;
  return RE.Word1 & 0xf;
}

static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
  return (RE.Word0 >> 24) & 0xf;
}

static uint32_t getSectionFlags(const MachOObjectFile *O,
                                DataRefImpl Sec) {
  if (O->is64Bit()) {
    macho::Section64 Sect = O->getSection64(Sec);
    return Sect.Flags;
  }
  macho::Section Sect = O->getSection(Sec);
  return Sect.Flags;
}

MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
                                 bool IsLittleEndian, bool Is64bits,
                                 error_code &ec)
    : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
      SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) {
  uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
  macho::LoadCommandType SegmentLoadType = is64Bit() ?
    macho::LCT_Segment64 : macho::LCT_Segment;

  MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
  for (unsigned I = 0; ; ++I) {
    if (Load.C.Type == macho::LCT_Symtab) {
      assert(!SymtabLoadCmd && "Multiple symbol tables");
      SymtabLoadCmd = Load.Ptr;
    } else if (Load.C.Type == macho::LCT_Dysymtab) {
      assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
      DysymtabLoadCmd = Load.Ptr;
    } else if (Load.C.Type == macho::LCT_DataInCode) {
      assert(!DataInCodeLoadCmd && "Multiple data in code tables");
      DataInCodeLoadCmd = Load.Ptr;
    } else if (Load.C.Type == SegmentLoadType) {
      uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
      for (unsigned J = 0; J < NumSections; ++J) {
        const char *Sec = getSectionPtr(this, Load, J);
        Sections.push_back(Sec);
      }
    }

    if (I == LoadCommandCount - 1)
      break;
    else
      Load = getNextLoadCommandInfo(Load);
  }
}

error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
                                          SymbolRef &Res) const {
  unsigned SymbolTableEntrySize = is64Bit() ?
    sizeof(macho::Symbol64TableEntry) :
    sizeof(macho::SymbolTableEntry);
  Symb.p += SymbolTableEntrySize;
  Res = SymbolRef(Symb, this);
  return object_error::success;
}

error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
                                          StringRef &Res) const {
  StringRef StringTable = getStringTableData();
  SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
  const char *Start = &StringTable.data()[Entry.StringIndex];
  Res = StringRef(Start);
  return object_error::success;
}

error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
                                             uint64_t &Res) const {
  if (is64Bit()) {
    macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
    Res = Entry.Value;
  } else {
    macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
    Res = Entry.Value;
  }
  return object_error::success;
}

error_code
MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
                                     uint64_t &Res) const {
  SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
  getSymbolAddress(Symb, Res);
  if (Entry.SectionIndex) {
    uint64_t Delta;
    DataRefImpl SecRel;
    SecRel.d.a = Entry.SectionIndex-1;
    if (is64Bit()) {
      macho::Section64 Sec = getSection64(SecRel);
      Delta = Sec.Offset - Sec.Address;
    } else {
      macho::Section Sec = getSection(SecRel);
      Delta = Sec.Offset - Sec.Address;
    }

    Res += Delta;
  }

  return object_error::success;
}

error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
                                               uint32_t &Result) const {
  uint32_t flags;
  this->getSymbolFlags(DRI, flags);
  if (flags & SymbolRef::SF_Common) {
    SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
    Result = 1 << MachO::GET_COMM_ALIGN(Entry.Flags);
  } else {
    Result = 0;
  }
  return object_error::success;
}

error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
                                          uint64_t &Result) const {
  uint64_t BeginOffset;
  uint64_t EndOffset = 0;
  uint8_t SectionIndex;

  SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
  uint64_t Value;
  getSymbolAddress(DRI, Value);

  BeginOffset = Value;

  SectionIndex = Entry.SectionIndex;
  if (!SectionIndex) {
    uint32_t flags = SymbolRef::SF_None;
    this->getSymbolFlags(DRI, flags);
    if (flags & SymbolRef::SF_Common)
      Result = Value;
    else
      Result = UnknownAddressOrSize;
    return object_error::success;
  }
  // Unfortunately symbols are unsorted so we need to touch all
  // symbols from load command
  error_code ec;
  for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E;
       I.increment(ec)) {
    DataRefImpl DRI = I->getRawDataRefImpl();
    Entry = getSymbolTableEntryBase(this, DRI);
    getSymbolAddress(DRI, Value);
    if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
      if (!EndOffset || Value < EndOffset)
        EndOffset = Value;
  }
  if (!EndOffset) {
    uint64_t Size;
    DataRefImpl Sec;
    Sec.d.a = SectionIndex-1;
    getSectionSize(Sec, Size);
    getSectionAddress(Sec, EndOffset);
    EndOffset += Size;
  }
  Result = EndOffset - BeginOffset;
  return object_error::success;
}

error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
                                          SymbolRef::Type &Res) const {
  SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
  uint8_t n_type = Entry.Type;

  Res = SymbolRef::ST_Other;

  // If this is a STAB debugging symbol, we can do nothing more.
  if (n_type & MachO::NlistMaskStab) {
    Res = SymbolRef::ST_Debug;
    return object_error::success;
  }

  switch (n_type & MachO::NlistMaskType) {
    case MachO::NListTypeUndefined :
      Res = SymbolRef::ST_Unknown;
      break;
    case MachO::NListTypeSection :
      Res = SymbolRef::ST_Function;
      break;
  }
  return object_error::success;
}

error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
                                                char &Res) const {
  SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
  uint8_t Type = Entry.Type;
  uint16_t Flags = Entry.Flags;

  char Char;
  switch (Type & macho::STF_TypeMask) {
    case macho::STT_Undefined:
      Char = 'u';
      break;
    case macho::STT_Absolute:
    case macho::STT_Section:
      Char = 's';
      break;
    default:
      Char = '?';
      break;
  }

  if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
    Char = toupper(static_cast<unsigned char>(Char));
  Res = Char;
  return object_error::success;
}

error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
                                           uint32_t &Result) const {
  SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);

  uint8_t MachOType = Entry.Type;
  uint16_t MachOFlags = Entry.Flags;

  // TODO: Correctly set SF_ThreadLocal
  Result = SymbolRef::SF_None;

  if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
    Result |= SymbolRef::SF_Undefined;

  if (MachOFlags & macho::STF_StabsEntryMask)
    Result |= SymbolRef::SF_FormatSpecific;

  if (MachOType & MachO::NlistMaskExternal) {
    Result |= SymbolRef::SF_Global;
    if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) {
      uint64_t Value;
      getSymbolAddress(DRI, Value);
      if (Value)
        Result |= SymbolRef::SF_Common;
    }
  }

  if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
    Result |= SymbolRef::SF_Weak;

  if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
    Result |= SymbolRef::SF_Absolute;

  return object_error::success;
}

error_code
MachOObjectFile::getSymbolSection(DataRefImpl Symb,
                                  section_iterator &Res) const {
  SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
  uint8_t index = Entry.SectionIndex;

  if (index == 0) {
    Res = end_sections();
  } else {
    DataRefImpl DRI;
    DRI.d.a = index - 1;
    Res = section_iterator(SectionRef(DRI, this));
  }

  return object_error::success;
}

error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
                                           uint64_t &Val) const {
  report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
}

error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
                                           SectionRef &Res) const {
  Sec.d.a++;
  Res = SectionRef(Sec, this);
  return object_error::success;
}

error_code
MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const {
  ArrayRef<char> Raw = getSectionRawName(Sec);
  Result = parseSegmentOrSectionName(Raw.data());
  return object_error::success;
}

error_code
MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {
  if (is64Bit()) {
    macho::Section64 Sect = getSection64(Sec);
    Res = Sect.Address;
  } else {
    macho::Section Sect = getSection(Sec);
    Res = Sect.Address;
  }
  return object_error::success;
}

error_code
MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {
  if (is64Bit()) {
    macho::Section64 Sect = getSection64(Sec);
    Res = Sect.Size;
  } else {
    macho::Section Sect = getSection(Sec);
    Res = Sect.Size;
  }

  return object_error::success;
}

error_code
MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {
  uint32_t Offset;
  uint64_t Size;

  if (is64Bit()) {
    macho::Section64 Sect = getSection64(Sec);
    Offset = Sect.Offset;
    Size = Sect.Size;
  } else {
    macho::Section Sect =getSection(Sec);
    Offset = Sect.Offset;
    Size = Sect.Size;
  }

  Res = this->getData().substr(Offset, Size);
  return object_error::success;
}

error_code
MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {
  uint32_t Align;
  if (is64Bit()) {
    macho::Section64 Sect = getSection64(Sec);
    Align = Sect.Align;
  } else {
    macho::Section Sect = getSection(Sec);
    Align = Sect.Align;
  }

  Res = uint64_t(1) << Align;
  return object_error::success;
}

error_code
MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
  uint32_t Flags = getSectionFlags(this, Sec);
  Res = Flags & macho::SF_PureInstructions;
  return object_error::success;
}

error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const {
  // FIXME: Unimplemented.
  Result = false;
  return object_error::success;
}

error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const {
  // FIXME: Unimplemented.
  Result = false;
  return object_error::success;
}

error_code
MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
                                               bool &Result) const {
  // FIXME: Unimplemented.
  Result = true;
  return object_error::success;
}

error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
                                             bool &Result) const {
  // FIXME: Unimplemented.
  Result = false;
  return object_error::success;
}

error_code
MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
  uint32_t Flags = getSectionFlags(this, Sec);
  unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
  Res = SectionType == MachO::SectionTypeZeroFill ||
    SectionType == MachO::SectionTypeZeroFillLarge;
  return object_error::success;
}

error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
                                                  bool &Result) const {
  // Consider using the code from isSectionText to look for __const sections.
  // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
  // to use section attributes to distinguish code from data.

  // FIXME: Unimplemented.
  Result = false;
  return object_error::success;
}

error_code
MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
                                       bool &Result) const {
  SymbolRef::Type ST;
  this->getSymbolType(Symb, ST);
  if (ST == SymbolRef::ST_Unknown) {
    Result = false;
    return object_error::success;
  }

  uint64_t SectBegin, SectEnd;
  getSectionAddress(Sec, SectBegin);
  getSectionSize(Sec, SectEnd);
  SectEnd += SectBegin;

  uint64_t SymAddr;
  getSymbolAddress(Symb, SymAddr);
  Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);

  return object_error::success;
}

relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
  uint32_t Offset;
  if (is64Bit()) {
    macho::Section64 Sect = getSection64(Sec);
    Offset = Sect.RelocationTableOffset;
  } else {
    macho::Section Sect = getSection(Sec);
    Offset = Sect.RelocationTableOffset;
  }

  DataRefImpl Ret;
  Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
  return relocation_iterator(RelocationRef(Ret, this));
}

relocation_iterator
MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
  uint32_t Offset;
  uint32_t Num;
  if (is64Bit()) {
    macho::Section64 Sect = getSection64(Sec);
    Offset = Sect.RelocationTableOffset;
    Num = Sect.NumRelocationTableEntries;
  } else {
    macho::Section Sect = getSection(Sec);
    Offset = Sect.RelocationTableOffset;
    Num = Sect.NumRelocationTableEntries;
  }

  const macho::RelocationEntry *P =
    reinterpret_cast<const macho::RelocationEntry*>(getPtr(this, Offset));

  DataRefImpl Ret;
  Ret.p = reinterpret_cast<uintptr_t>(P + Num);
  return relocation_iterator(RelocationRef(Ret, this));
}

error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
                                              RelocationRef &Res) const {
  const macho::RelocationEntry *P =
    reinterpret_cast<const macho::RelocationEntry *>(Rel.p);
  Rel.p = reinterpret_cast<uintptr_t>(P + 1);
  Res = RelocationRef(Rel, this);
  return object_error::success;
}

error_code
MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const {
  report_fatal_error("getRelocationAddress not implemented in MachOObjectFile");
}

error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
                                                uint64_t &Res) const {
  macho::RelocationEntry RE = getRelocation(Rel);
  Res = getAnyRelocationAddress(RE);
  return object_error::success;
}

symbol_iterator
MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
  macho::RelocationEntry RE = getRelocation(Rel);
  uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
  bool isExtern = getPlainRelocationExternal(RE);
  if (!isExtern)
    return end_symbols();

  macho::SymtabLoadCommand S = getSymtabLoadCommand();
  unsigned SymbolTableEntrySize = is64Bit() ?
    sizeof(macho::Symbol64TableEntry) :
    sizeof(macho::SymbolTableEntry);
  uint64_t Offset = S.SymbolTableOffset + SymbolIdx * SymbolTableEntrySize;
  DataRefImpl Sym;
  Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
  return symbol_iterator(SymbolRef(Sym, this));
}

error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
                                              uint64_t &Res) const {
  macho::RelocationEntry RE = getRelocation(Rel);
  Res = getAnyRelocationType(RE);
  return object_error::success;
}

error_code
MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
                                       SmallVectorImpl<char> &Result) const {
  StringRef res;
  uint64_t RType;
  getRelocationType(Rel, RType);

  unsigned Arch = this->getArch();

  switch (Arch) {
    case Triple::x86: {
      static const char *const Table[] =  {
        "GENERIC_RELOC_VANILLA",
        "GENERIC_RELOC_PAIR",
        "GENERIC_RELOC_SECTDIFF",
        "GENERIC_RELOC_PB_LA_PTR",
        "GENERIC_RELOC_LOCAL_SECTDIFF",
        "GENERIC_RELOC_TLV" };

      if (RType > 6)
        res = "Unknown";
      else
        res = Table[RType];
      break;
    }
    case Triple::x86_64: {
      static const char *const Table[] =  {
        "X86_64_RELOC_UNSIGNED",
        "X86_64_RELOC_SIGNED",
        "X86_64_RELOC_BRANCH",
        "X86_64_RELOC_GOT_LOAD",
        "X86_64_RELOC_GOT",
        "X86_64_RELOC_SUBTRACTOR",
        "X86_64_RELOC_SIGNED_1",
        "X86_64_RELOC_SIGNED_2",
        "X86_64_RELOC_SIGNED_4",
        "X86_64_RELOC_TLV" };

      if (RType > 9)
        res = "Unknown";
      else
        res = Table[RType];
      break;
    }
    case Triple::arm: {
      static const char *const Table[] =  {
        "ARM_RELOC_VANILLA",
        "ARM_RELOC_PAIR",
        "ARM_RELOC_SECTDIFF",
        "ARM_RELOC_LOCAL_SECTDIFF",
        "ARM_RELOC_PB_LA_PTR",
        "ARM_RELOC_BR24",
        "ARM_THUMB_RELOC_BR22",
        "ARM_THUMB_32BIT_BRANCH",
        "ARM_RELOC_HALF",
        "ARM_RELOC_HALF_SECTDIFF" };

      if (RType > 9)
        res = "Unknown";
      else
        res = Table[RType];
      break;
    }
    case Triple::ppc: {
      static const char *const Table[] =  {
        "PPC_RELOC_VANILLA",
        "PPC_RELOC_PAIR",
        "PPC_RELOC_BR14",
        "PPC_RELOC_BR24",
        "PPC_RELOC_HI16",
        "PPC_RELOC_LO16",
        "PPC_RELOC_HA16",
        "PPC_RELOC_LO14",
        "PPC_RELOC_SECTDIFF",
        "PPC_RELOC_PB_LA_PTR",
        "PPC_RELOC_HI16_SECTDIFF",
        "PPC_RELOC_LO16_SECTDIFF",
        "PPC_RELOC_HA16_SECTDIFF",
        "PPC_RELOC_JBSR",
        "PPC_RELOC_LO14_SECTDIFF",
        "PPC_RELOC_LOCAL_SECTDIFF" };

      res = Table[RType];
      break;
    }
    case Triple::UnknownArch:
      res = "Unknown";
      break;
  }
  Result.append(res.begin(), res.end());
  return object_error::success;
}

error_code
MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
                                          SmallVectorImpl<char> &Result) const {
  macho::RelocationEntry RE = getRelocation(Rel);

  unsigned Arch = this->getArch();

  std::string fmtbuf;
  raw_string_ostream fmt(fmtbuf);
  unsigned Type = this->getAnyRelocationType(RE);
  bool IsPCRel = this->getAnyRelocationPCRel(RE);

  // Determine any addends that should be displayed with the relocation.
  // These require decoding the relocation type, which is triple-specific.

  // X86_64 has entirely custom relocation types.
  if (Arch == Triple::x86_64) {
    bool isPCRel = getAnyRelocationPCRel(RE);

    switch (Type) {
      case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
      case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
        printRelocationTargetName(this, RE, fmt);
        fmt << "@GOT";
        if (isPCRel) fmt << "PCREL";
        break;
      }
      case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
        DataRefImpl RelNext = Rel;
        RelNext.d.a++;
        macho::RelocationEntry RENext = getRelocation(RelNext);

        // X86_64_SUBTRACTOR must be followed by a relocation of type
        // X86_64_RELOC_UNSIGNED.
        // NOTE: Scattered relocations don't exist on x86_64.
        unsigned RType = getAnyRelocationType(RENext);
        if (RType != 0)
          report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
                             "X86_64_RELOC_SUBTRACTOR.");

        // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
        // X86_64_SUBTRACTOR contains to the subtrahend.
        printRelocationTargetName(this, RENext, fmt);
        fmt << "-";
        printRelocationTargetName(this, RE, fmt);
        break;
      }
      case macho::RIT_X86_64_TLV:
        printRelocationTargetName(this, RE, fmt);
        fmt << "@TLV";
        if (isPCRel) fmt << "P";
        break;
      case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
        printRelocationTargetName(this, RE, fmt);
        fmt << "-1";
        break;
      case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
        printRelocationTargetName(this, RE, fmt);
        fmt << "-2";
        break;
      case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
        printRelocationTargetName(this, RE, fmt);
        fmt << "-4";
        break;
      default:
        printRelocationTargetName(this, RE, fmt);
        break;
    }
  // X86 and ARM share some relocation types in common.
  } else if (Arch == Triple::x86 || Arch == Triple::arm) {
    // Generic relocation types...
    switch (Type) {
      case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
        return object_error::success;
      case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
        DataRefImpl RelNext = Rel;
        RelNext.d.a++;
        macho::RelocationEntry RENext = getRelocation(RelNext);

        // X86 sect diff's must be followed by a relocation of type
        // GENERIC_RELOC_PAIR.
        unsigned RType = getAnyRelocationType(RENext);

        if (RType != 1)
          report_fatal_error("Expected GENERIC_RELOC_PAIR after "
                             "GENERIC_RELOC_SECTDIFF.");

        printRelocationTargetName(this, RE, fmt);
        fmt << "-";
        printRelocationTargetName(this, RENext, fmt);
        break;
      }
    }

    if (Arch == Triple::x86) {
      // All X86 relocations that need special printing were already
      // handled in the generic code.
      switch (Type) {
        case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
          DataRefImpl RelNext = Rel;
          RelNext.d.a++;
          macho::RelocationEntry RENext = getRelocation(RelNext);

          // X86 sect diff's must be followed by a relocation of type
          // GENERIC_RELOC_PAIR.
          unsigned RType = getAnyRelocationType(RENext);
          if (RType != 1)
            report_fatal_error("Expected GENERIC_RELOC_PAIR after "
                               "GENERIC_RELOC_LOCAL_SECTDIFF.");

          printRelocationTargetName(this, RE, fmt);
          fmt << "-";
          printRelocationTargetName(this, RENext, fmt);
          break;
        }
        case macho::RIT_Generic_TLV: {
          printRelocationTargetName(this, RE, fmt);
          fmt << "@TLV";
          if (IsPCRel) fmt << "P";
          break;
        }
        default:
          printRelocationTargetName(this, RE, fmt);
      }
    } else { // ARM-specific relocations
      switch (Type) {
        case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
        case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
          // Half relocations steal a bit from the length field to encode
          // whether this is an upper16 or a lower16 relocation.
          bool isUpper = getAnyRelocationLength(RE) >> 1;

          if (isUpper)
            fmt << ":upper16:(";
          else
            fmt << ":lower16:(";
          printRelocationTargetName(this, RE, fmt);

          DataRefImpl RelNext = Rel;
          RelNext.d.a++;
          macho::RelocationEntry RENext = getRelocation(RelNext);

          // ARM half relocs must be followed by a relocation of type
          // ARM_RELOC_PAIR.
          unsigned RType = getAnyRelocationType(RENext);
          if (RType != 1)
            report_fatal_error("Expected ARM_RELOC_PAIR after "
                               "GENERIC_RELOC_HALF");

          // NOTE: The half of the target virtual address is stashed in the
          // address field of the secondary relocation, but we can't reverse
          // engineer the constant offset from it without decoding the movw/movt
          // instruction to find the other half in its immediate field.

          // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
          // symbol/section pointer of the follow-on relocation.
          if (Type == macho::RIT_ARM_HalfDifference) {
            fmt << "-";
            printRelocationTargetName(this, RENext, fmt);
          }

          fmt << ")";
          break;
        }
        default: {
          printRelocationTargetName(this, RE, fmt);
        }
      }
    }
  } else
    printRelocationTargetName(this, RE, fmt);

  fmt.flush();
  Result.append(fmtbuf.begin(), fmtbuf.end());
  return object_error::success;
}

error_code
MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
  unsigned Arch = getArch();
  uint64_t Type;
  getRelocationType(Rel, Type);

  Result = false;

  // On arches that use the generic relocations, GENERIC_RELOC_PAIR
  // is always hidden.
  if (Arch == Triple::x86 || Arch == Triple::arm) {
    if (Type == macho::RIT_Pair) Result = true;
  } else if (Arch == Triple::x86_64) {
    // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
    // an X86_64_RELOC_SUBTRACTOR.
    if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
      DataRefImpl RelPrev = Rel;
      RelPrev.d.a--;
      uint64_t PrevType;
      getRelocationType(RelPrev, PrevType);
      if (PrevType == macho::RIT_X86_64_Subtractor)
        Result = true;
    }
  }

  return object_error::success;
}

error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
                                           LibraryRef &Res) const {
  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}

error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
                                           StringRef &Res) const {
  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}

symbol_iterator MachOObjectFile::begin_symbols() const {
  DataRefImpl DRI;
  if (!SymtabLoadCmd)
    return symbol_iterator(SymbolRef(DRI, this));

  macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.SymbolTableOffset));
  return symbol_iterator(SymbolRef(DRI, this));
}

symbol_iterator MachOObjectFile::end_symbols() const {
  DataRefImpl DRI;
  if (!SymtabLoadCmd)
    return symbol_iterator(SymbolRef(DRI, this));

  macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
  unsigned SymbolTableEntrySize = is64Bit() ?
    sizeof(macho::Symbol64TableEntry) :
    sizeof(macho::SymbolTableEntry);
  unsigned Offset = Symtab.SymbolTableOffset +
    Symtab.NumSymbolTableEntries * SymbolTableEntrySize;
  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
  return symbol_iterator(SymbolRef(DRI, this));
}

symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
  // TODO: implement
  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
}

symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
  // TODO: implement
  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
}

section_iterator MachOObjectFile::begin_sections() const {
  DataRefImpl DRI;
  return section_iterator(SectionRef(DRI, this));
}

section_iterator MachOObjectFile::end_sections() const {
  DataRefImpl DRI;
  DRI.d.a = Sections.size();
  return section_iterator(SectionRef(DRI, this));
}

library_iterator MachOObjectFile::begin_libraries_needed() const {
  // TODO: implement
  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}

library_iterator MachOObjectFile::end_libraries_needed() const {
  // TODO: implement
  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}

uint8_t MachOObjectFile::getBytesInAddress() const {
  return is64Bit() ? 8 : 4;
}

StringRef MachOObjectFile::getFileFormatName() const {
  unsigned CPUType = getCPUType(this);
  if (!is64Bit()) {
    switch (CPUType) {
    case llvm::MachO::CPUTypeI386:
      return "Mach-O 32-bit i386";
    case llvm::MachO::CPUTypeARM:
      return "Mach-O arm";
    case llvm::MachO::CPUTypePowerPC:
      return "Mach-O 32-bit ppc";
    default:
      assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
             "64-bit object file when we're not 64-bit?");
      return "Mach-O 32-bit unknown";
    }
  }

  // Make sure the cpu type has the correct mask.
  assert((CPUType & llvm::MachO::CPUArchABI64)
         == llvm::MachO::CPUArchABI64 &&
         "32-bit object file when we're 64-bit?");

  switch (CPUType) {
  case llvm::MachO::CPUTypeX86_64:
    return "Mach-O 64-bit x86-64";
  case llvm::MachO::CPUTypePowerPC64:
    return "Mach-O 64-bit ppc64";
  default:
    return "Mach-O 64-bit unknown";
  }
}

Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
  switch (CPUType) {
  case llvm::MachO::CPUTypeI386:
    return Triple::x86;
  case llvm::MachO::CPUTypeX86_64:
    return Triple::x86_64;
  case llvm::MachO::CPUTypeARM:
    return Triple::arm;
  case llvm::MachO::CPUTypePowerPC:
    return Triple::ppc;
  case llvm::MachO::CPUTypePowerPC64:
    return Triple::ppc64;
  default:
    return Triple::UnknownArch;
  }
}

unsigned MachOObjectFile::getArch() const {
  return getArch(getCPUType(this));
}

StringRef MachOObjectFile::getLoadName() const {
  // TODO: Implement
  report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
}

relocation_iterator MachOObjectFile::getSectionRelBegin(unsigned Index) const {
  DataRefImpl DRI;
  DRI.d.a = Index;
  return getSectionRelBegin(DRI);
}

relocation_iterator MachOObjectFile::getSectionRelEnd(unsigned Index) const {
  DataRefImpl DRI;
  DRI.d.a = Index;
  return getSectionRelEnd(DRI);
}

dice_iterator MachOObjectFile::begin_dices() const {
  DataRefImpl DRI;
  if (!DataInCodeLoadCmd)
    return dice_iterator(DiceRef(DRI, this));

  macho::LinkeditDataLoadCommand DicLC = getDataInCodeLoadCommand();
  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.DataOffset));
  return dice_iterator(DiceRef(DRI, this));
}

dice_iterator MachOObjectFile::end_dices() const {
  DataRefImpl DRI;
  if (!DataInCodeLoadCmd)
    return dice_iterator(DiceRef(DRI, this));

  macho::LinkeditDataLoadCommand DicLC = getDataInCodeLoadCommand();
  unsigned Offset = DicLC.DataOffset + DicLC.DataSize;
  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
  return dice_iterator(DiceRef(DRI, this));
}

StringRef
MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
  ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
  return parseSegmentOrSectionName(Raw.data());
}

ArrayRef<char>
MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
  const SectionBase *Base =
    reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
  return ArrayRef<char>(Base->Name);
}

ArrayRef<char>
MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
  const SectionBase *Base =
    reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
  return ArrayRef<char>(Base->SegmentName);
}

bool
MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
  const {
  if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
    return false;
  return getPlainRelocationAddress(RE) & macho::RF_Scattered;
}

unsigned MachOObjectFile::getPlainRelocationSymbolNum(
    const macho::RelocationEntry &RE) const {
  if (isLittleEndian())
    return RE.Word1 & 0xffffff;
  return RE.Word1 >> 8;
}

bool MachOObjectFile::getPlainRelocationExternal(
    const macho::RelocationEntry &RE) const {
  if (isLittleEndian())
    return (RE.Word1 >> 27) & 1;
  return (RE.Word1 >> 4) & 1;
}

bool MachOObjectFile::getScatteredRelocationScattered(
    const macho::RelocationEntry &RE) const {
  return RE.Word0 >> 31;
}

uint32_t MachOObjectFile::getScatteredRelocationValue(
    const macho::RelocationEntry &RE) const {
  return RE.Word1;
}

unsigned MachOObjectFile::getAnyRelocationAddress(
    const macho::RelocationEntry &RE) const {
  if (isRelocationScattered(RE))
    return getScatteredRelocationAddress(RE);
  return getPlainRelocationAddress(RE);
}

unsigned
MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
  if (isRelocationScattered(RE))
    return getScatteredRelocationPCRel(this, RE);
  return getPlainRelocationPCRel(this, RE);
}

unsigned MachOObjectFile::getAnyRelocationLength(
    const macho::RelocationEntry &RE) const {
  if (isRelocationScattered(RE))
    return getScatteredRelocationLength(RE);
  return getPlainRelocationLength(this, RE);
}

unsigned
MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
  if (isRelocationScattered(RE))
    return getScatteredRelocationType(RE);
  return getPlainRelocationType(this, RE);
}

SectionRef
MachOObjectFile::getRelocationSection(const macho::RelocationEntry &RE) const {
  if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
    return *end_sections();
  unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
  DataRefImpl DRI;
  DRI.d.a = SecNum;
  return SectionRef(DRI, this);
}

MachOObjectFile::LoadCommandInfo
MachOObjectFile::getFirstLoadCommandInfo() const {
  MachOObjectFile::LoadCommandInfo Load;

  unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
  Load.Ptr = getPtr(this, HeaderSize);
  Load.C = getStruct<macho::LoadCommand>(this, Load.Ptr);
  return Load;
}

MachOObjectFile::LoadCommandInfo
MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
  MachOObjectFile::LoadCommandInfo Next;
  Next.Ptr = L.Ptr + L.C.Size;
  Next.C = getStruct<macho::LoadCommand>(this, Next.Ptr);
  return Next;
}

macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
  return getStruct<macho::Section>(this, Sections[DRI.d.a]);
}

macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
  return getStruct<macho::Section64>(this, Sections[DRI.d.a]);
}

macho::Section MachOObjectFile::getSection(const LoadCommandInfo &L,
                                           unsigned Index) const {
  const char *Sec = getSectionPtr(this, L, Index);
  return getStruct<macho::Section>(this, Sec);
}

macho::Section64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
                                               unsigned Index) const {
  const char *Sec = getSectionPtr(this, L, Index);
  return getStruct<macho::Section64>(this, Sec);
}

macho::SymbolTableEntry
MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
  const char *P = reinterpret_cast<const char *>(DRI.p);
  return getStruct<macho::SymbolTableEntry>(this, P);
}

macho::Symbol64TableEntry
MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
  const char *P = reinterpret_cast<const char *>(DRI.p);
  return getStruct<macho::Symbol64TableEntry>(this, P);
}

macho::LinkeditDataLoadCommand MachOObjectFile::getLinkeditDataLoadCommand(
    const MachOObjectFile::LoadCommandInfo &L) const {
  return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr);
}

macho::SegmentLoadCommand
MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
  return getStruct<macho::SegmentLoadCommand>(this, L.Ptr);
}

macho::Segment64LoadCommand
MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
  return getStruct<macho::Segment64LoadCommand>(this, L.Ptr);
}

macho::LinkerOptionsLoadCommand
MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
  return getStruct<macho::LinkerOptionsLoadCommand>(this, L.Ptr);
}

macho::RelocationEntry
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
  const char *P = reinterpret_cast<const char *>(Rel.p);
  return getStruct<macho::RelocationEntry>(this, P);
}

macho::DataInCodeTableEntry
MachOObjectFile::getDice(DataRefImpl Rel) const {
  const char *P = reinterpret_cast<const char *>(Rel.p);
  return getStruct<macho::DataInCodeTableEntry>(this, P);
}

macho::Header MachOObjectFile::getHeader() const {
  return getStruct<macho::Header>(this, getPtr(this, 0));
}

macho::Header64Ext MachOObjectFile::getHeader64Ext() const {
  return
    getStruct<macho::Header64Ext>(this, getPtr(this, sizeof(macho::Header)));
}

macho::IndirectSymbolTableEntry MachOObjectFile::getIndirectSymbolTableEntry(
                                          const macho::DysymtabLoadCommand &DLC,
                                          unsigned Index) const {
  uint64_t Offset = DLC.IndirectSymbolTableOffset +
    Index * sizeof(macho::IndirectSymbolTableEntry);
  return getStruct<macho::IndirectSymbolTableEntry>(this, getPtr(this, Offset));
}

macho::DataInCodeTableEntry
MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
                                         unsigned Index) const {
  uint64_t Offset = DataOffset + Index * sizeof(macho::DataInCodeTableEntry);
  return getStruct<macho::DataInCodeTableEntry>(this, getPtr(this, Offset));
}

macho::SymtabLoadCommand MachOObjectFile::getSymtabLoadCommand() const {
  return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd);
}

macho::DysymtabLoadCommand MachOObjectFile::getDysymtabLoadCommand() const {
  return getStruct<macho::DysymtabLoadCommand>(this, DysymtabLoadCmd);
}

macho::LinkeditDataLoadCommand
MachOObjectFile::getDataInCodeLoadCommand() const {
  if (DataInCodeLoadCmd)
    return getStruct<macho::LinkeditDataLoadCommand>(this, DataInCodeLoadCmd);

  // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
  macho::LinkeditDataLoadCommand Cmd;
  Cmd.Type = macho::LCT_DataInCode;
  Cmd.Size = macho::LinkeditLoadCommandSize;
  Cmd.DataOffset = 0;
  Cmd.DataSize = 0;
  return Cmd;
}

StringRef MachOObjectFile::getStringTableData() const {
  macho::SymtabLoadCommand S = getSymtabLoadCommand();
  return getData().substr(S.StringTableOffset, S.StringTableSize);
}

bool MachOObjectFile::is64Bit() const {
  return getType() == getMachOType(false, true) ||
    getType() == getMachOType(true, true);
}

void MachOObjectFile::ReadULEB128s(uint64_t Index,
                                   SmallVectorImpl<uint64_t> &Out) const {
  DataExtractor extractor(ObjectFile::getData(), true, 0);

  uint32_t offset = Index;
  uint64_t data = 0;
  while (uint64_t delta = extractor.getULEB128(&offset)) {
    data += delta;
    Out.push_back(data);
  }
}

ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
  StringRef Magic = Buffer->getBuffer().slice(0, 4);
  error_code ec;
  OwningPtr<ObjectFile> Ret;
  if (Magic == "\xFE\xED\xFA\xCE")
    Ret.reset(new MachOObjectFile(Buffer, false, false, ec));
  else if (Magic == "\xCE\xFA\xED\xFE")
    Ret.reset(new MachOObjectFile(Buffer, true, false, ec));
  else if (Magic == "\xFE\xED\xFA\xCF")
    Ret.reset(new MachOObjectFile(Buffer, false, true, ec));
  else if (Magic == "\xCF\xFA\xED\xFE")
    Ret.reset(new MachOObjectFile(Buffer, true, true, ec));
  else {
    delete Buffer;
    return NULL;
  }

  if (ec)
    return NULL;
  return Ret.take();
}

} // end namespace object
} // end namespace llvm
