Convert MachOObjectFile to a template.
[oota-llvm.git] / lib / Object / MachOObjectFile.cpp
index 26a6e136d753ff0ccb08f87f2f43abc23cb40f93..20b66d94e8c6e0784c733cbf01257a2c7148a9f1 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/Object/MachO.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Object/MachOFormat.h"
-#include "llvm/Object/MachOObject.h"
-#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/MachO.h"
-
 #include <cctype>
 #include <cstring>
 #include <limits>
@@ -27,75 +27,82 @@ using namespace llvm;
 using namespace object;
 
 namespace llvm {
+namespace object {
 
-typedef MachOObject::LoadCommandInfo LoadCommandInfo;
-
-class MachOObjectFile : public ObjectFile {
-public:
-  MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec)
-    : ObjectFile(Binary::isMachO, Object, ec),
-      MachOObj(MOO),
-      RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {}
-
-  virtual symbol_iterator begin_symbols() const;
-  virtual symbol_iterator end_symbols() const;
-  virtual section_iterator begin_sections() const;
-  virtual section_iterator end_sections() const;
-
-  virtual uint8_t getBytesInAddress() const;
-  virtual StringRef getFileFormatName() const;
-  virtual unsigned getArch() const;
-
-protected:
-  virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
-  virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
-  virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
-  virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
-  virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
-  virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const;
-
-  virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
-  virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
-  virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
-  virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
-  virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
-  virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
-  virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S,
-                                           bool &Result) const;
-
-private:
-  MachOObject *MachOObj;
-  mutable uint32_t RegisteredStringTable;
-
-  void moveToNextSection(DataRefImpl &DRI) const;
-  void getSymbolTableEntry(DataRefImpl DRI,
-                           InMemoryStruct<macho::SymbolTableEntry> &Res) const;
-  void getSymbol64TableEntry(DataRefImpl DRI,
-                          InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
-  void moveToNextSymbol(DataRefImpl &DRI) const;
-  void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
-  void getSection64(DataRefImpl DRI,
-                    InMemoryStruct<macho::Section64> &Res) const;
-};
+MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits,
+                                         error_code &ec)
+    : ObjectFile(getMachOType(true, Is64bits), Object) {
+}
+
+bool MachOObjectFileBase::is64Bit() const {
+  return isa<MachOObjectFile<true> >(this);
+}
+
+const MachOObjectFileBase::LoadCommand *
+MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const {
+  uint64_t Offset;
+  uint64_t NewOffset = getHeaderSize();
+  const LoadCommand *Load;
+  unsigned I = 0;
+  do {
+    Offset = NewOffset;
+    StringRef Data = getData(Offset, sizeof(LoadCommand));
+    Load = reinterpret_cast<const LoadCommand*>(Data.data());
+    NewOffset = Offset + Load->Size;
+    ++I;
+  } while (I != Index + 1);
+
+  return Load;
+}
+
+void MachOObjectFileBase::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);
+  }
+}
+
+const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const {
+  StringRef Data = getData(0, sizeof(Header));
+  return reinterpret_cast<const Header*>(Data.data());
+}
+
+unsigned MachOObjectFileBase::getHeaderSize() const {
+  return is64Bit() ? macho::Header64Size : macho::Header32Size;
+}
+
+StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
+  return ObjectFile::getData().substr(Offset, Size);
+}
 
 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
+  StringRef Magic = Buffer->getBuffer().slice(0, 4);
   error_code ec;
-  std::string Err;
-  MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
-  if (!MachOObj)
+  bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
+  ObjectFile *Ret;
+  if (Is64Bits)
+    Ret = new MachOObjectFile<true>(Buffer, ec);
+  else
+    Ret = new MachOObjectFile<false>(Buffer, ec);
+  if (ec)
     return NULL;
-  return new MachOObjectFile(Buffer, MachOObj, ec);
+  return Ret;
 }
 
 /*===-- Symbols -----------------------------------------------------------===*/
 
-void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
-  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
+void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const {
+  uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
   while (DRI.d.a < LoadCommandCount) {
-    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-    if (LCI.Command.Type == macho::LCT_Symtab) {
-      InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
-      MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
+    const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
+    if (Command->Type == macho::LCT_Symtab) {
+      const SymtabLoadCommand *SymtabLoadCmd =
+        reinterpret_cast<const SymtabLoadCommand*>(Command);
       if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
         return;
     }
@@ -105,93 +112,61 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
   }
 }
 
-void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
-    InMemoryStruct<macho::SymbolTableEntry> &Res) const {
-  InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
-  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-  MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
-
-  if (RegisteredStringTable != DRI.d.a) {
-    MachOObj->RegisterStringTable(*SymtabLoadCmd);
-    RegisteredStringTable = DRI.d.a;
-  }
-
-  MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
-                                 Res);
+const MachOObjectFileBase::SymbolTableEntryBase *
+MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const {
+  const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
+  const SymtabLoadCommand *SymtabLoadCmd =
+    reinterpret_cast<const SymtabLoadCommand*>(Command);
+  return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
 }
 
-void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
-    InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
-  InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
-  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-  MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
+const MachOObjectFileBase::SymbolTableEntryBase *
+MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI,
+                                 const SymtabLoadCommand *SymtabLoadCmd) const {
+  uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
+  unsigned Index = DRI.d.b;
 
-  if (RegisteredStringTable != DRI.d.a) {
-    MachOObj->RegisterStringTable(*SymtabLoadCmd);
-    RegisteredStringTable = DRI.d.a;
-  }
+  unsigned SymbolTableEntrySize = is64Bit() ?
+    sizeof(MachOFormat::SymbolTableEntry<true>) :
+    sizeof(MachOFormat::SymbolTableEntry<false>);
 
-  MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
-                                   Res);
+  uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
+  StringRef Data = getData(Offset, SymbolTableEntrySize);
+  return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
 }
 
-
-error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
-                                          SymbolRef &Result) const {
+error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI,
+                                              SymbolRef &Result) const {
   DRI.d.b++;
   moveToNextSymbol(DRI);
   Result = SymbolRef(DRI, this);
   return object_error::success;
 }
 
-error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
-                                          StringRef &Result) const {
-  if (MachOObj->is64Bit()) {
-    InMemoryStruct<macho::Symbol64TableEntry> Entry;
-    getSymbol64TableEntry(DRI, Entry);
-    Result = MachOObj->getStringAtIndex(Entry->StringIndex);
-  } else {
-    InMemoryStruct<macho::SymbolTableEntry> Entry;
-    getSymbolTableEntry(DRI, Entry);
-    Result = MachOObj->getStringAtIndex(Entry->StringIndex);
-  }
-  return object_error::success;
-}
+error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI,
+                                              StringRef &Result) const {
+  const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
+  const SymtabLoadCommand *SymtabLoadCmd =
+    reinterpret_cast<const SymtabLoadCommand*>(Command);
 
-error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
-                                             uint64_t &Result) const {
-  if (MachOObj->is64Bit()) {
-    InMemoryStruct<macho::Symbol64TableEntry> Entry;
-    getSymbol64TableEntry(DRI, Entry);
-    Result = Entry->Value;
-  } else {
-    InMemoryStruct<macho::SymbolTableEntry> Entry;
-    getSymbolTableEntry(DRI, Entry);
-    Result = Entry->Value;
-  }
-  return object_error::success;
-}
+  StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
+                                  SymtabLoadCmd->StringTableSize);
+
+  const SymbolTableEntryBase *Entry =
+    getSymbolTableEntryBase(DRI, SymtabLoadCmd);
+  uint32_t StringIndex = Entry->StringIndex;
+
+  const char *Start = &StringTable.data()[StringIndex];
+  Result = StringRef(Start);
 
-error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
-                                          uint64_t &Result) const {
-  Result = UnknownAddressOrSize;
   return object_error::success;
 }
 
-error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
-                                                char &Result) const {
-  uint8_t Type, Flags;
-  if (MachOObj->is64Bit()) {
-    InMemoryStruct<macho::Symbol64TableEntry> Entry;
-    getSymbol64TableEntry(DRI, Entry);
-    Type = Entry->Type;
-    Flags = Entry->Flags;
-  } else {
-    InMemoryStruct<macho::SymbolTableEntry> Entry;
-    getSymbolTableEntry(DRI, Entry);
-    Type = Entry->Type;
-    Flags = Entry->Flags;
-  }
+error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI,
+                                                    char &Result) const {
+  const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
+  uint8_t Type = Entry->Type;
+  uint16_t Flags = Entry->Flags;
 
   char Char;
   switch (Type & macho::STF_TypeMask) {
@@ -208,221 +183,345 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
   }
 
   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
-    Char = toupper(Char);
+    Char = toupper(static_cast<unsigned char>(Char));
   Result = Char;
   return object_error::success;
 }
 
-error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
-                                             bool &Result) const {
-  if (MachOObj->is64Bit()) {
-    InMemoryStruct<macho::Symbol64TableEntry> Entry;
-    getSymbol64TableEntry(DRI, Entry);
-    Result = Entry->Flags & macho::STF_StabsEntryMask;
-  } else {
-    InMemoryStruct<macho::SymbolTableEntry> Entry;
-    getSymbolTableEntry(DRI, Entry);
-    Result = Entry->Flags & macho::STF_StabsEntryMask;
+error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI,
+                                               uint32_t &Result) const {
+  const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(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)
+      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;
 }
 
-ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const {
+error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb,
+                                                 section_iterator &Res) const {
+  const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
+  uint8_t index = Entry->SectionIndex;
+
+  if (index == 0)
+    Res = end_sections();
+  else
+    Res = section_iterator(SectionRef(Sections[index-1], this));
+
+  return object_error::success;
+}
+
+error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb,
+                                              SymbolRef::Type &Res) const {
+  const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(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 MachOObjectFileBase::getSymbolValue(DataRefImpl Symb,
+                                               uint64_t &Val) const {
+  report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase");
+}
+
+symbol_iterator MachOObjectFileBase::begin_symbols() const {
   // DRI.d.a = segment number; DRI.d.b = symbol index.
   DataRefImpl DRI;
-  DRI.d.a = DRI.d.b = 0;
   moveToNextSymbol(DRI);
   return symbol_iterator(SymbolRef(DRI, this));
 }
 
-ObjectFile::symbol_iterator MachOObjectFile::end_symbols() const {
+symbol_iterator MachOObjectFileBase::end_symbols() const {
   DataRefImpl DRI;
-  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
-  DRI.d.b = 0;
+  DRI.d.a = getHeader()->NumLoadCommands;
   return symbol_iterator(SymbolRef(DRI, this));
 }
 
+symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const {
+  // TODO: implement
+  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
+}
+
+symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const {
+  // TODO: implement
+  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
+}
+
+library_iterator MachOObjectFileBase::begin_libraries_needed() const {
+  // TODO: implement
+  report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
+}
+
+library_iterator MachOObjectFileBase::end_libraries_needed() const {
+  // TODO: implement
+  report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
+}
+
+StringRef MachOObjectFileBase::getLoadName() const {
+  // TODO: Implement
+  report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase");
+}
 
 /*===-- Sections ----------------------------------------------------------===*/
 
-void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
-  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
-  while (DRI.d.a < LoadCommandCount) {
-    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-    if (LCI.Command.Type == macho::LCT_Segment) {
-      InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
-      MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
-      if (DRI.d.b < SegmentLoadCmd->NumSections)
-        return;
-    } else if (LCI.Command.Type == macho::LCT_Segment64) {
-      InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
-      MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
-      if (DRI.d.b < Segment64LoadCmd->NumSections)
-        return;
-    }
+std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const {
+  SectionList::const_iterator loc =
+    std::find(Sections.begin(), Sections.end(), Sec);
+  assert(loc != Sections.end() && "Sec is not a valid section!");
+  return std::distance(Sections.begin(), loc);
+}
 
-    DRI.d.a++;
-    DRI.d.b = 0;
-  }
+const MachOObjectFileBase::SectionBase*
+MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const {
+  const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
+  uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
+
+  bool Is64 = is64Bit();
+  unsigned SegmentLoadSize =
+    Is64 ? sizeof(MachOFormat::SegmentLoadCommand<true>) :
+           sizeof(MachOFormat::SegmentLoadCommand<false>);
+  unsigned SectionSize = Is64 ? sizeof(MachOFormat::Section<true>) :
+                                sizeof(MachOFormat::Section<false>);
+
+  uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
+  return reinterpret_cast<const SectionBase*>(SectionAddr);
 }
 
-error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
-                                           SectionRef &Result) const {
-  DRI.d.b++;
-  moveToNextSection(DRI);
-  Result = SectionRef(DRI, this);
-  return object_error::success;
+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);
 }
 
-void
-MachOObjectFile::getSection(DataRefImpl DRI,
-                            InMemoryStruct<macho::Section> &Res) const {
-  InMemoryStruct<macho::SegmentLoadCommand> SLC;
-  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-  MachOObj->ReadSegmentLoadCommand(LCI, SLC);
-  MachOObj->ReadSection(LCI, DRI.d.b, Res);
+ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const {
+  const SectionBase *Base = getSectionBase(DRI);
+  return ArrayRef<char>(Base->Name);
 }
 
-void
-MachOObjectFile::getSection64(DataRefImpl DRI,
-                            InMemoryStruct<macho::Section64> &Res) const {
-  InMemoryStruct<macho::Segment64LoadCommand> SLC;
-  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-  MachOObj->ReadSegment64LoadCommand(LCI, SLC);
-  MachOObj->ReadSection64(LCI, DRI.d.b, Res);
-}
-
-static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
-  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-  if (LCI.Command.Type == macho::LCT_Segment64)
-    return true;
-  assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
-  return false;
-}
-
-error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
-                                           StringRef &Result) const {
-  // FIXME: thread safety.
-  static char result[34];
-  if (is64BitLoadCommand(MachOObj, DRI)) {
-    InMemoryStruct<macho::Segment64LoadCommand> SLC;
-    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-    MachOObj->ReadSegment64LoadCommand(LCI, SLC);
-    InMemoryStruct<macho::Section64> Sect;
-    MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
-
-    strcpy(result, Sect->SegmentName);
-    strcat(result, ",");
-    strcat(result, Sect->Name);
-  } else {
-    InMemoryStruct<macho::SegmentLoadCommand> SLC;
-    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
-    MachOObj->ReadSegmentLoadCommand(LCI, SLC);
-    InMemoryStruct<macho::Section> Sect;
-    MachOObj->ReadSection(LCI, DRI.d.b, Sect);
-
-    strcpy(result, Sect->SegmentName);
-    strcat(result, ",");
-    strcat(result, Sect->Name);
-  }
-  Result = StringRef(result);
+error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI,
+                                               StringRef &Result) const {
+  ArrayRef<char> Raw = getSectionRawName(DRI);
+  Result = parseSegmentOrSectionName(Raw.data());
   return object_error::success;
 }
 
-error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
-                                              uint64_t &Result) const {
-  if (is64BitLoadCommand(MachOObj, DRI)) {
-    InMemoryStruct<macho::Section64> Sect;
-    getSection64(DRI, Sect);
-    Result = Sect->Address;
-  } else {
-    InMemoryStruct<macho::Section> Sect;
-    getSection(DRI, Sect);
-    Result = Sect->Address;
-  }
+ArrayRef<char>
+MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
+  const SectionBase *Base = getSectionBase(Sec);
+  return ArrayRef<char>(Base->SegmentName);
+}
+
+StringRef
+MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const {
+  ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
+  return parseSegmentOrSectionName(Raw.data());
+}
+
+error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI,
+                                              bool &Result) const {
+  // FIXME: Unimplemented.
+  Result = false;
   return object_error::success;
 }
 
-error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
-                                           uint64_t &Result) const {
-  if (is64BitLoadCommand(MachOObj, DRI)) {
-    InMemoryStruct<macho::Section64> Sect;
-    getSection64(DRI, Sect);
-    Result = Sect->Size;
-  } else {
-    InMemoryStruct<macho::Section> Sect;
-    getSection(DRI, Sect);
-    Result = Sect->Size;
-  }
+error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
+                                             bool &Result) const {
+  // FIXME: Unimplemented.
+  Result = false;
   return object_error::success;
 }
 
-error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
-                                               StringRef &Result) const {
-  if (is64BitLoadCommand(MachOObj, DRI)) {
-    InMemoryStruct<macho::Section64> Sect;
-    getSection64(DRI, Sect);
-    Result = MachOObj->getData(Sect->Offset, Sect->Size);
-  } else {
-    InMemoryStruct<macho::Section> Sect;
-    getSection(DRI, Sect);
-    Result = MachOObj->getData(Sect->Offset, Sect->Size);
-  }
+error_code
+MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
+                                                   bool &Result) const {
+  // FIXME: Unimplemented.
+  Result = true;
   return object_error::success;
 }
 
-error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
-                                          bool &Result) const {
-  if (is64BitLoadCommand(MachOObj, DRI)) {
-    InMemoryStruct<macho::Section64> Sect;
-    getSection64(DRI, Sect);
-    Result = !strcmp(Sect->Name, "__text");
-  } else {
-    InMemoryStruct<macho::Section> Sect;
-    getSection(DRI, Sect);
-    Result = !strcmp(Sect->Name, "__text");
-  }
+error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec,
+                                                 bool &Result) const {
+  // FIXME: Unimplemented.
+  Result = false;
   return object_error::success;
 }
 
-error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
-                                                  DataRefImpl Symb,
-                                                  bool &Result) const {
-  if (MachOObj->is64Bit()) {
-    InMemoryStruct<macho::Symbol64TableEntry> Entry;
-    getSymbol64TableEntry(Symb, Entry);
-    Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
-  } else {
-    InMemoryStruct<macho::SymbolTableEntry> Entry;
-    getSymbolTableEntry(Symb, Entry);
-    Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
-  }
+error_code MachOObjectFileBase::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;
 }
 
-ObjectFile::section_iterator MachOObjectFile::begin_sections() const {
-  DataRefImpl DRI;
-  DRI.d.a = DRI.d.b = 0;
-  moveToNextSection(DRI);
-  return section_iterator(SectionRef(DRI, this));
+relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
+  DataRefImpl ret;
+  ret.d.b = getSectionIndex(Sec);
+  return relocation_iterator(RelocationRef(ret, this));
 }
 
-ObjectFile::section_iterator MachOObjectFile::end_sections() const {
+section_iterator MachOObjectFileBase::end_sections() const {
   DataRefImpl DRI;
-  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
-  DRI.d.b = 0;
+  DRI.d.a = getHeader()->NumLoadCommands;
   return section_iterator(SectionRef(DRI, this));
 }
 
+/*===-- Relocations -------------------------------------------------------===*/
+
+error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel,
+                                                  RelocationRef &Res) const {
+  ++Rel.d.a;
+  Res = RelocationRef(Rel, this);
+  return object_error::success;
+}
+
+// Helper to advance a section or symbol iterator multiple increments at a time.
+template<class T>
+error_code advance(T &it, size_t Val) {
+  error_code ec;
+  while (Val--) {
+    it.increment(ec);
+  }
+  return ec;
+}
+
+template<class T>
+void advanceTo(T &it, size_t Val) {
+  if (error_code ec = advance(it, Val))
+    report_fatal_error(ec.message());
+}
+
+void
+MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
+                                               raw_string_ostream &fmt) const {
+  unsigned Arch = getArch();
+  bool isScattered = (Arch != Triple::x86_64) &&
+                     (RE->Word0 & macho::RF_Scattered);
+
+  // 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 = RE->Word1;
+
+    error_code ec;
+    for (symbol_iterator SI = begin_symbols(), SE = 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 = begin_sections(), SE = 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 = (RE->Word1 >> 27) & 1;
+  uint32_t Val = RE->Word1 & 0xFFFFFF;
+
+  if (isExtern) {
+    symbol_iterator SI = begin_symbols();
+    advanceTo(SI, Val);
+    SI->getName(S);
+  } else {
+    section_iterator SI = begin_sections();
+    advanceTo(SI, Val);
+    SI->getName(S);
+  }
+
+  fmt << S;
+}
+
+error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData,
+                                               LibraryRef &Res) const {
+  report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
+}
+
+error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData,
+                                               StringRef &Res) const {
+  report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
+}
+
+
 /*===-- Miscellaneous -----------------------------------------------------===*/
 
-uint8_t MachOObjectFile::getBytesInAddress() const {
-  return MachOObj->is64Bit() ? 8 : 4;
+uint8_t MachOObjectFileBase::getBytesInAddress() const {
+  return is64Bit() ? 8 : 4;
 }
 
-StringRef MachOObjectFile::getFileFormatName() const {
-  if (!MachOObj->is64Bit()) {
-    switch (MachOObj->getHeader().CPUType) {
+StringRef MachOObjectFileBase::getFileFormatName() const {
+  if (!is64Bit()) {
+    switch (getHeader()->CPUType) {
     case llvm::MachO::CPUTypeI386:
       return "Mach-O 32-bit i386";
     case llvm::MachO::CPUTypeARM:
@@ -430,26 +529,29 @@ StringRef MachOObjectFile::getFileFormatName() const {
     case llvm::MachO::CPUTypePowerPC:
       return "Mach-O 32-bit ppc";
     default:
-      assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
+      assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
              "64-bit object file when we're not 64-bit?");
       return "Mach-O 32-bit unknown";
     }
   }
 
-  switch (MachOObj->getHeader().CPUType) {
+  // Make sure the cpu type has the correct mask.
+  assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
+        == llvm::MachO::CPUArchABI64 &&
+        "32-bit object file when we're 64-bit?");
+
+  switch (getHeader()->CPUType) {
   case llvm::MachO::CPUTypeX86_64:
     return "Mach-O 64-bit x86-64";
   case llvm::MachO::CPUTypePowerPC64:
     return "Mach-O 64-bit ppc64";
   default:
-    assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
-           "32-bit object file when we're 64-bit?");
     return "Mach-O 64-bit unknown";
   }
 }
 
-unsigned MachOObjectFile::getArch() const {
-  switch (MachOObj->getHeader().CPUType) {
+unsigned MachOObjectFileBase::getArch() const {
+  switch (getHeader()->CPUType) {
   case llvm::MachO::CPUTypeI386:
     return Triple::x86;
   case llvm::MachO::CPUTypeX86_64:
@@ -465,5 +567,5 @@ unsigned MachOObjectFile::getArch() const {
   }
 }
 
+} // end namespace object
 } // end namespace llvm
-