mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-03 14:21:30 +00:00 
			
		
		
		
	For now it is templated only on being 64 or 32 bits. I will add little/big endian next. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179097 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			572 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			572 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===- 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/Casting.h"
 | 
						|
#include "llvm/Support/DataExtractor.h"
 | 
						|
#include "llvm/Support/Format.h"
 | 
						|
#include "llvm/Support/MemoryBuffer.h"
 | 
						|
#include <cctype>
 | 
						|
#include <cstring>
 | 
						|
#include <limits>
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
using namespace object;
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
namespace object {
 | 
						|
 | 
						|
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;
 | 
						|
  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 Ret;
 | 
						|
}
 | 
						|
 | 
						|
/*===-- Symbols -----------------------------------------------------------===*/
 | 
						|
 | 
						|
void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const {
 | 
						|
  uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
 | 
						|
  while (DRI.d.a < LoadCommandCount) {
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    DRI.d.a++;
 | 
						|
    DRI.d.b = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
const MachOObjectFileBase::SymbolTableEntryBase *
 | 
						|
MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI,
 | 
						|
                                 const SymtabLoadCommand *SymtabLoadCmd) const {
 | 
						|
  uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
 | 
						|
  unsigned Index = DRI.d.b;
 | 
						|
 | 
						|
  unsigned SymbolTableEntrySize = is64Bit() ?
 | 
						|
    sizeof(MachOFormat::SymbolTableEntry<true>) :
 | 
						|
    sizeof(MachOFormat::SymbolTableEntry<false>);
 | 
						|
 | 
						|
  uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
 | 
						|
  StringRef Data = getData(Offset, SymbolTableEntrySize);
 | 
						|
  return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI,
 | 
						|
                                              SymbolRef &Result) const {
 | 
						|
  DRI.d.b++;
 | 
						|
  moveToNextSymbol(DRI);
 | 
						|
  Result = SymbolRef(DRI, this);
 | 
						|
  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);
 | 
						|
 | 
						|
  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);
 | 
						|
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
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) {
 | 
						|
    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));
 | 
						|
  Result = Char;
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
  moveToNextSymbol(DRI);
 | 
						|
  return symbol_iterator(SymbolRef(DRI, this));
 | 
						|
}
 | 
						|
 | 
						|
symbol_iterator MachOObjectFileBase::end_symbols() const {
 | 
						|
  DataRefImpl DRI;
 | 
						|
  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 ----------------------------------------------------------===*/
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const {
 | 
						|
  const SectionBase *Base = getSectionBase(DRI);
 | 
						|
  return ArrayRef<char>(Base->Name);
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI,
 | 
						|
                                               StringRef &Result) const {
 | 
						|
  ArrayRef<char> Raw = getSectionRawName(DRI);
 | 
						|
  Result = parseSegmentOrSectionName(Raw.data());
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
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 MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
 | 
						|
                                             bool &Result) const {
 | 
						|
  // FIXME: Unimplemented.
 | 
						|
  Result = false;
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code
 | 
						|
MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
 | 
						|
                                                   bool &Result) const {
 | 
						|
  // FIXME: Unimplemented.
 | 
						|
  Result = true;
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec,
 | 
						|
                                                 bool &Result) const {
 | 
						|
  // FIXME: Unimplemented.
 | 
						|
  Result = false;
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
 | 
						|
  DataRefImpl ret;
 | 
						|
  ret.d.b = getSectionIndex(Sec);
 | 
						|
  return relocation_iterator(RelocationRef(ret, this));
 | 
						|
}
 | 
						|
 | 
						|
section_iterator MachOObjectFileBase::end_sections() const {
 | 
						|
  DataRefImpl DRI;
 | 
						|
  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 MachOObjectFileBase::getBytesInAddress() const {
 | 
						|
  return is64Bit() ? 8 : 4;
 | 
						|
}
 | 
						|
 | 
						|
StringRef MachOObjectFileBase::getFileFormatName() const {
 | 
						|
  if (!is64Bit()) {
 | 
						|
    switch (getHeader()->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((getHeader()->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((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:
 | 
						|
    return "Mach-O 64-bit unknown";
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
unsigned MachOObjectFileBase::getArch() const {
 | 
						|
  switch (getHeader()->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;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
} // end namespace object
 | 
						|
} // end namespace llvm
 |