mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-03 14:21:30 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174079 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			1338 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1338 lines
		
	
	
		
			42 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/Format.h"
 | 
						|
#include "llvm/Support/MemoryBuffer.h"
 | 
						|
#include <cctype>
 | 
						|
#include <cstring>
 | 
						|
#include <limits>
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
using namespace object;
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
namespace object {
 | 
						|
 | 
						|
MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
 | 
						|
                                 error_code &ec)
 | 
						|
    : ObjectFile(Binary::ID_MachO, Object, ec),
 | 
						|
      MachOObj(MOO),
 | 
						|
      RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
 | 
						|
  DataRefImpl DRI;
 | 
						|
  moveToNextSection(DRI);
 | 
						|
  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
 | 
						|
  while (DRI.d.a < LoadCommandCount) {
 | 
						|
    Sections.push_back(DRI);
 | 
						|
    DRI.d.b++;
 | 
						|
    moveToNextSection(DRI);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
 | 
						|
  error_code ec;
 | 
						|
  std::string Err;
 | 
						|
  MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
 | 
						|
  if (!MachOObj)
 | 
						|
    return NULL;
 | 
						|
  // MachOObject takes ownership of the Buffer we passed to it, and
 | 
						|
  // MachOObjectFile does, too, so we need to make sure they don't get the
 | 
						|
  // same object. A MemoryBuffer is cheap (it's just a reference to memory,
 | 
						|
  // not a copy of the memory itself), so just make a new copy here for
 | 
						|
  // the MachOObjectFile.
 | 
						|
  MemoryBuffer *NewBuffer =
 | 
						|
    MemoryBuffer::getMemBuffer(Buffer->getBuffer(),
 | 
						|
                               Buffer->getBufferIdentifier(), false);
 | 
						|
  return new MachOObjectFile(NewBuffer, MachOObj, ec);
 | 
						|
}
 | 
						|
 | 
						|
/*===-- Symbols -----------------------------------------------------------===*/
 | 
						|
 | 
						|
void MachOObjectFile::moveToNextSymbol(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_Symtab) {
 | 
						|
      InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
 | 
						|
      MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
 | 
						|
      if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    DRI.d.a++;
 | 
						|
    DRI.d.b = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
 | 
						|
  if (RegisteredStringTable != DRI.d.a) {
 | 
						|
    MachOObj->RegisterStringTable(*SymtabLoadCmd);
 | 
						|
    RegisteredStringTable = DRI.d.a;
 | 
						|
  }
 | 
						|
 | 
						|
  MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
 | 
						|
                                   Res);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
error_code MachOObjectFile::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 MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
 | 
						|
                                                uint64_t &Result) const {
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Symbol64TableEntry> Entry;
 | 
						|
    getSymbol64TableEntry(DRI, Entry);
 | 
						|
    Result = Entry->Value;
 | 
						|
    if (Entry->SectionIndex) {
 | 
						|
      InMemoryStruct<macho::Section64> Section;
 | 
						|
      getSection64(Sections[Entry->SectionIndex-1], Section);
 | 
						|
      Result += Section->Offset - Section->Address;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::SymbolTableEntry> Entry;
 | 
						|
    getSymbolTableEntry(DRI, Entry);
 | 
						|
    Result = Entry->Value;
 | 
						|
    if (Entry->SectionIndex) {
 | 
						|
      InMemoryStruct<macho::Section> Section;
 | 
						|
      getSection(Sections[Entry->SectionIndex-1], Section);
 | 
						|
      Result += Section->Offset - Section->Address;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
 | 
						|
                                          uint64_t &Result) const {
 | 
						|
  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
 | 
						|
  uint64_t BeginOffset;
 | 
						|
  uint64_t EndOffset = 0;
 | 
						|
  uint8_t SectionIndex;
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Symbol64TableEntry> Entry;
 | 
						|
    getSymbol64TableEntry(DRI, Entry);
 | 
						|
    BeginOffset = Entry->Value;
 | 
						|
    SectionIndex = Entry->SectionIndex;
 | 
						|
    if (!SectionIndex) {
 | 
						|
      uint32_t flags = SymbolRef::SF_None;
 | 
						|
      getSymbolFlags(DRI, flags);
 | 
						|
      if (flags & SymbolRef::SF_Common)
 | 
						|
        Result = Entry->Value;
 | 
						|
      else
 | 
						|
        Result = UnknownAddressOrSize;
 | 
						|
      return object_error::success;
 | 
						|
    }
 | 
						|
    // Unfortunately symbols are unsorted so we need to touch all
 | 
						|
    // symbols from load command
 | 
						|
    DRI.d.b = 0;
 | 
						|
    uint32_t Command = DRI.d.a;
 | 
						|
    while (Command == DRI.d.a) {
 | 
						|
      moveToNextSymbol(DRI);
 | 
						|
      if (DRI.d.a < LoadCommandCount) {
 | 
						|
        getSymbol64TableEntry(DRI, Entry);
 | 
						|
        if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
 | 
						|
          if (!EndOffset || Entry->Value < EndOffset)
 | 
						|
            EndOffset = Entry->Value;
 | 
						|
      }
 | 
						|
      DRI.d.b++;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::SymbolTableEntry> Entry;
 | 
						|
    getSymbolTableEntry(DRI, Entry);
 | 
						|
    BeginOffset = Entry->Value;
 | 
						|
    SectionIndex = Entry->SectionIndex;
 | 
						|
    if (!SectionIndex) {
 | 
						|
      uint32_t flags = SymbolRef::SF_None;
 | 
						|
      getSymbolFlags(DRI, flags);
 | 
						|
      if (flags & SymbolRef::SF_Common)
 | 
						|
        Result = Entry->Value;
 | 
						|
      else
 | 
						|
        Result = UnknownAddressOrSize;
 | 
						|
      return object_error::success;
 | 
						|
    }
 | 
						|
    // Unfortunately symbols are unsorted so we need to touch all
 | 
						|
    // symbols from load command
 | 
						|
    DRI.d.b = 0;
 | 
						|
    uint32_t Command = DRI.d.a;
 | 
						|
    while (Command == DRI.d.a) {
 | 
						|
      moveToNextSymbol(DRI);
 | 
						|
      if (DRI.d.a < LoadCommandCount) {
 | 
						|
        getSymbolTableEntry(DRI, Entry);
 | 
						|
        if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
 | 
						|
          if (!EndOffset || Entry->Value < EndOffset)
 | 
						|
            EndOffset = Entry->Value;
 | 
						|
      }
 | 
						|
      DRI.d.b++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (!EndOffset) {
 | 
						|
    uint64_t Size;
 | 
						|
    getSectionSize(Sections[SectionIndex-1], Size);
 | 
						|
    getSectionAddress(Sections[SectionIndex-1], EndOffset);
 | 
						|
    EndOffset += Size;
 | 
						|
  }
 | 
						|
  Result = EndOffset - BeginOffset;
 | 
						|
  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;
 | 
						|
  }
 | 
						|
 | 
						|
  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(Char);
 | 
						|
  Result = Char;
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
 | 
						|
                                           uint32_t &Result) const {
 | 
						|
  uint16_t MachOFlags;
 | 
						|
  uint8_t MachOType;
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Symbol64TableEntry> Entry;
 | 
						|
    getSymbol64TableEntry(DRI, Entry);
 | 
						|
    MachOFlags = Entry->Flags;
 | 
						|
    MachOType = Entry->Type;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::SymbolTableEntry> Entry;
 | 
						|
    getSymbolTableEntry(DRI, Entry);
 | 
						|
    MachOFlags = Entry->Flags;
 | 
						|
    MachOType = Entry->Type;
 | 
						|
  }
 | 
						|
 | 
						|
  // 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 MachOObjectFile::getSymbolSection(DataRefImpl Symb,
 | 
						|
                                             section_iterator &Res) const {
 | 
						|
  uint8_t index;
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Symbol64TableEntry> Entry;
 | 
						|
    getSymbol64TableEntry(Symb, Entry);
 | 
						|
    index = Entry->SectionIndex;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::SymbolTableEntry> Entry;
 | 
						|
    getSymbolTableEntry(Symb, Entry);
 | 
						|
    index = Entry->SectionIndex;
 | 
						|
  }
 | 
						|
 | 
						|
  if (index == 0)
 | 
						|
    Res = end_sections();
 | 
						|
  else
 | 
						|
    Res = section_iterator(SectionRef(Sections[index-1], this));
 | 
						|
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
 | 
						|
                                          SymbolRef::Type &Res) const {
 | 
						|
  uint8_t n_type;
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Symbol64TableEntry> Entry;
 | 
						|
    getSymbol64TableEntry(Symb, Entry);
 | 
						|
    n_type = Entry->Type;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::SymbolTableEntry> Entry;
 | 
						|
    getSymbolTableEntry(Symb, Entry);
 | 
						|
    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::getSymbolValue(DataRefImpl Symb,
 | 
						|
                                           uint64_t &Val) const {
 | 
						|
  report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
 | 
						|
}
 | 
						|
 | 
						|
symbol_iterator MachOObjectFile::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 MachOObjectFile::end_symbols() const {
 | 
						|
  DataRefImpl DRI;
 | 
						|
  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
 | 
						|
  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");
 | 
						|
}
 | 
						|
 | 
						|
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");
 | 
						|
}
 | 
						|
 | 
						|
StringRef MachOObjectFile::getLoadName() const {
 | 
						|
  // TODO: Implement
 | 
						|
  report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
 | 
						|
}
 | 
						|
 | 
						|
/*===-- 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;
 | 
						|
    }
 | 
						|
 | 
						|
    DRI.d.a++;
 | 
						|
    DRI.d.b = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
 | 
						|
                                           SectionRef &Result) const {
 | 
						|
  DRI.d.b++;
 | 
						|
  moveToNextSection(DRI);
 | 
						|
  Result = SectionRef(DRI, this);
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
MachOObjectFile::getSection(DataRefImpl DRI,
 | 
						|
                            InMemoryStruct<macho::Section> &Res) const {
 | 
						|
  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
 | 
						|
  MachOObj->ReadSection(LCI, DRI.d.b, Res);
 | 
						|
}
 | 
						|
 | 
						|
std::size_t MachOObjectFile::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);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
MachOObjectFile::getSection64(DataRefImpl DRI,
 | 
						|
                            InMemoryStruct<macho::Section64> &Res) const {
 | 
						|
  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
 | 
						|
                                           StringRef &Result) const {
 | 
						|
  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
 | 
						|
    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
 | 
						|
    unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) +
 | 
						|
      DRI.d.b * sizeof(macho::Section64);
 | 
						|
    StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64));
 | 
						|
    const macho::Section64 *sec =
 | 
						|
      reinterpret_cast<const macho::Section64*>(Data.data());
 | 
						|
    Result = parseSegmentOrSectionName(sec->Name);
 | 
						|
  } else {
 | 
						|
    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
 | 
						|
    unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) +
 | 
						|
      DRI.d.b * sizeof(macho::Section);
 | 
						|
    StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section));
 | 
						|
    const macho::Section *sec =
 | 
						|
      reinterpret_cast<const macho::Section*>(Data.data());
 | 
						|
    Result = parseSegmentOrSectionName(sec->Name);
 | 
						|
  }
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec,
 | 
						|
                                                       StringRef &Res) const {
 | 
						|
  if (is64BitLoadCommand(MachOObj.get(), Sec)) {
 | 
						|
    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(Sec.d.a);
 | 
						|
    unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) +
 | 
						|
      Sec.d.b * sizeof(macho::Section64);
 | 
						|
    StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64));
 | 
						|
    const macho::Section64 *sec =
 | 
						|
      reinterpret_cast<const macho::Section64*>(Data.data());
 | 
						|
    Res = parseSegmentOrSectionName(sec->SegmentName);
 | 
						|
  } else {
 | 
						|
    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(Sec.d.a);
 | 
						|
    unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) +
 | 
						|
      Sec.d.b * sizeof(macho::Section);
 | 
						|
    StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section));
 | 
						|
    const macho::Section *sec =
 | 
						|
      reinterpret_cast<const macho::Section*>(Data.data());
 | 
						|
    Res = parseSegmentOrSectionName(sec->SegmentName);
 | 
						|
  }
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
 | 
						|
                                              uint64_t &Result) const {
 | 
						|
  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
 | 
						|
    InMemoryStruct<macho::Section64> Sect;
 | 
						|
    getSection64(DRI, Sect);
 | 
						|
    Result = Sect->Address;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::Section> Sect;
 | 
						|
    getSection(DRI, Sect);
 | 
						|
    Result = Sect->Address;
 | 
						|
  }
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
 | 
						|
                                           uint64_t &Result) const {
 | 
						|
  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
 | 
						|
    InMemoryStruct<macho::Section64> Sect;
 | 
						|
    getSection64(DRI, Sect);
 | 
						|
    Result = Sect->Size;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::Section> Sect;
 | 
						|
    getSection(DRI, Sect);
 | 
						|
    Result = Sect->Size;
 | 
						|
  }
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
 | 
						|
                                               StringRef &Result) const {
 | 
						|
  if (is64BitLoadCommand(MachOObj.get(), 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);
 | 
						|
  }
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
 | 
						|
                                                uint64_t &Result) const {
 | 
						|
  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
 | 
						|
    InMemoryStruct<macho::Section64> Sect;
 | 
						|
    getSection64(DRI, Sect);
 | 
						|
    Result = uint64_t(1) << Sect->Align;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::Section> Sect;
 | 
						|
    getSection(DRI, Sect);
 | 
						|
    Result = uint64_t(1) << Sect->Align;
 | 
						|
  }
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
 | 
						|
                                          bool &Result) const {
 | 
						|
  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
 | 
						|
    InMemoryStruct<macho::Section64> Sect;
 | 
						|
    getSection64(DRI, Sect);
 | 
						|
    Result = Sect->Flags & macho::SF_PureInstructions;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::Section> Sect;
 | 
						|
    getSection(DRI, Sect);
 | 
						|
    Result = Sect->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 DRI,
 | 
						|
                                              bool &Result) const {
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Section64> Sect;
 | 
						|
    getSection64(DRI, Sect);
 | 
						|
    unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
 | 
						|
    Result = (SectionType == MachO::SectionTypeZeroFill ||
 | 
						|
              SectionType == MachO::SectionTypeZeroFillLarge);
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::Section> Sect;
 | 
						|
    getSection(DRI, Sect);
 | 
						|
    unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
 | 
						|
    Result = (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;
 | 
						|
  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;
 | 
						|
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Symbol64TableEntry> Entry;
 | 
						|
    getSymbol64TableEntry(Symb, Entry);
 | 
						|
    uint64_t SymAddr= Entry->Value;
 | 
						|
    Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::SymbolTableEntry> Entry;
 | 
						|
    getSymbolTableEntry(Symb, Entry);
 | 
						|
    uint64_t SymAddr= Entry->Value;
 | 
						|
    Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
 | 
						|
  }
 | 
						|
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
 | 
						|
  DataRefImpl ret;
 | 
						|
  ret.d.b = getSectionIndex(Sec);
 | 
						|
  return relocation_iterator(RelocationRef(ret, this));
 | 
						|
}
 | 
						|
relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
 | 
						|
  uint32_t last_reloc;
 | 
						|
  if (is64BitLoadCommand(MachOObj.get(), Sec)) {
 | 
						|
    InMemoryStruct<macho::Section64> Sect;
 | 
						|
    getSection64(Sec, Sect);
 | 
						|
    last_reloc = Sect->NumRelocationTableEntries;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::Section> Sect;
 | 
						|
    getSection(Sec, Sect);
 | 
						|
    last_reloc = Sect->NumRelocationTableEntries;
 | 
						|
  }
 | 
						|
  DataRefImpl ret;
 | 
						|
  ret.d.a = last_reloc;
 | 
						|
  ret.d.b = getSectionIndex(Sec);
 | 
						|
  return relocation_iterator(RelocationRef(ret, this));
 | 
						|
}
 | 
						|
 | 
						|
section_iterator MachOObjectFile::begin_sections() const {
 | 
						|
  DataRefImpl DRI;
 | 
						|
  moveToNextSection(DRI);
 | 
						|
  return section_iterator(SectionRef(DRI, this));
 | 
						|
}
 | 
						|
 | 
						|
section_iterator MachOObjectFile::end_sections() const {
 | 
						|
  DataRefImpl DRI;
 | 
						|
  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
 | 
						|
  return section_iterator(SectionRef(DRI, this));
 | 
						|
}
 | 
						|
 | 
						|
/*===-- Relocations -------------------------------------------------------===*/
 | 
						|
 | 
						|
void MachOObjectFile::
 | 
						|
getRelocation(DataRefImpl Rel,
 | 
						|
              InMemoryStruct<macho::RelocationEntry> &Res) const {
 | 
						|
  uint32_t relOffset;
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Section64> Sect;
 | 
						|
    getSection64(Sections[Rel.d.b], Sect);
 | 
						|
    relOffset = Sect->RelocationTableOffset;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::Section> Sect;
 | 
						|
    getSection(Sections[Rel.d.b], Sect);
 | 
						|
    relOffset = Sect->RelocationTableOffset;
 | 
						|
  }
 | 
						|
  MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
 | 
						|
}
 | 
						|
error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
 | 
						|
                                              RelocationRef &Res) const {
 | 
						|
  ++Rel.d.a;
 | 
						|
  Res = RelocationRef(Rel, this);
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
 | 
						|
                                                 uint64_t &Res) const {
 | 
						|
  const uint8_t* sectAddress = 0;
 | 
						|
  if (MachOObj->is64Bit()) {
 | 
						|
    InMemoryStruct<macho::Section64> Sect;
 | 
						|
    getSection64(Sections[Rel.d.b], Sect);
 | 
						|
    sectAddress += Sect->Address;
 | 
						|
  } else {
 | 
						|
    InMemoryStruct<macho::Section> Sect;
 | 
						|
    getSection(Sections[Rel.d.b], Sect);
 | 
						|
    sectAddress += Sect->Address;
 | 
						|
  }
 | 
						|
  InMemoryStruct<macho::RelocationEntry> RE;
 | 
						|
  getRelocation(Rel, RE);
 | 
						|
 | 
						|
  unsigned Arch = getArch();
 | 
						|
  bool isScattered = (Arch != Triple::x86_64) &&
 | 
						|
                     (RE->Word0 & macho::RF_Scattered);
 | 
						|
  uint64_t RelAddr = 0;
 | 
						|
  if (isScattered)
 | 
						|
    RelAddr = RE->Word0 & 0xFFFFFF;
 | 
						|
  else
 | 
						|
    RelAddr = RE->Word0;
 | 
						|
 | 
						|
  Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
 | 
						|
                                                uint64_t &Res) const {
 | 
						|
  InMemoryStruct<macho::RelocationEntry> RE;
 | 
						|
  getRelocation(Rel, RE);
 | 
						|
 | 
						|
  unsigned Arch = getArch();
 | 
						|
  bool isScattered = (Arch != Triple::x86_64) &&
 | 
						|
                     (RE->Word0 & macho::RF_Scattered);
 | 
						|
  if (isScattered)
 | 
						|
    Res = RE->Word0 & 0xFFFFFF;
 | 
						|
  else
 | 
						|
    Res = RE->Word0;
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
 | 
						|
                                                SymbolRef &Res) const {
 | 
						|
  InMemoryStruct<macho::RelocationEntry> RE;
 | 
						|
  getRelocation(Rel, RE);
 | 
						|
  uint32_t SymbolIdx = RE->Word1 & 0xffffff;
 | 
						|
  bool isExtern = (RE->Word1 >> 27) & 1;
 | 
						|
 | 
						|
  DataRefImpl Sym;
 | 
						|
  moveToNextSymbol(Sym);
 | 
						|
  if (isExtern) {
 | 
						|
    for (unsigned i = 0; i < SymbolIdx; i++) {
 | 
						|
      Sym.d.b++;
 | 
						|
      moveToNextSymbol(Sym);
 | 
						|
      assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
 | 
						|
             "Relocation symbol index out of range!");
 | 
						|
    }
 | 
						|
  }
 | 
						|
  Res = SymbolRef(Sym, this);
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
 | 
						|
                                              uint64_t &Res) const {
 | 
						|
  InMemoryStruct<macho::RelocationEntry> RE;
 | 
						|
  getRelocation(Rel, RE);
 | 
						|
  Res = RE->Word0;
 | 
						|
  Res <<= 32;
 | 
						|
  Res |= RE->Word1;
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
 | 
						|
                                          SmallVectorImpl<char> &Result) const {
 | 
						|
  // TODO: Support scattered relocations.
 | 
						|
  StringRef res;
 | 
						|
  InMemoryStruct<macho::RelocationEntry> RE;
 | 
						|
  getRelocation(Rel, RE);
 | 
						|
 | 
						|
  unsigned Arch = getArch();
 | 
						|
  bool isScattered = (Arch != Triple::x86_64) &&
 | 
						|
                     (RE->Word0 & macho::RF_Scattered);
 | 
						|
 | 
						|
  unsigned r_type;
 | 
						|
  if (isScattered)
 | 
						|
    r_type = (RE->Word0 >> 24) & 0xF;
 | 
						|
  else
 | 
						|
    r_type = (RE->Word1 >> 28) & 0xF;
 | 
						|
 | 
						|
  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 (r_type > 6)
 | 
						|
        res = "Unknown";
 | 
						|
      else
 | 
						|
        res = Table[r_type];
 | 
						|
      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 (r_type > 9)
 | 
						|
        res = "Unknown";
 | 
						|
      else
 | 
						|
        res = Table[r_type];
 | 
						|
      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 (r_type > 9)
 | 
						|
        res = "Unknown";
 | 
						|
      else
 | 
						|
        res = Table[r_type];
 | 
						|
      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[r_type];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    case Triple::UnknownArch:
 | 
						|
      res = "Unknown";
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  Result.append(res.begin(), res.end());
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
 | 
						|
                                                        int64_t &Res) const {
 | 
						|
  InMemoryStruct<macho::RelocationEntry> RE;
 | 
						|
  getRelocation(Rel, RE);
 | 
						|
  bool isExtern = (RE->Word1 >> 27) & 1;
 | 
						|
  Res = 0;
 | 
						|
  if (!isExtern) {
 | 
						|
    const uint8_t* sectAddress = base();
 | 
						|
    if (MachOObj->is64Bit()) {
 | 
						|
      InMemoryStruct<macho::Section64> Sect;
 | 
						|
      getSection64(Sections[Rel.d.b], Sect);
 | 
						|
      sectAddress += Sect->Offset;
 | 
						|
    } else {
 | 
						|
      InMemoryStruct<macho::Section> Sect;
 | 
						|
      getSection(Sections[Rel.d.b], Sect);
 | 
						|
      sectAddress += Sect->Offset;
 | 
						|
    }
 | 
						|
    Res = reinterpret_cast<uintptr_t>(sectAddress);
 | 
						|
  }
 | 
						|
  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 MachOObjectFile::printRelocationTargetName(
 | 
						|
                                     InMemoryStruct<macho::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 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
 | 
						|
                                          SmallVectorImpl<char> &Result) const {
 | 
						|
  InMemoryStruct<macho::RelocationEntry> RE;
 | 
						|
  getRelocation(Rel, RE);
 | 
						|
 | 
						|
  unsigned Arch = getArch();
 | 
						|
  bool isScattered = (Arch != Triple::x86_64) &&
 | 
						|
                     (RE->Word0 & macho::RF_Scattered);
 | 
						|
 | 
						|
  std::string fmtbuf;
 | 
						|
  raw_string_ostream fmt(fmtbuf);
 | 
						|
 | 
						|
  unsigned Type;
 | 
						|
  if (isScattered)
 | 
						|
    Type = (RE->Word0 >> 24) & 0xF;
 | 
						|
  else
 | 
						|
    Type = (RE->Word1 >> 28) & 0xF;
 | 
						|
 | 
						|
  bool isPCRel;
 | 
						|
  if (isScattered)
 | 
						|
    isPCRel = ((RE->Word0 >> 30) & 1);
 | 
						|
  else
 | 
						|
    isPCRel = ((RE->Word1 >> 24) & 1);
 | 
						|
 | 
						|
  // 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 = ((RE->Word1 >> 24) & 1);
 | 
						|
 | 
						|
    switch (Type) {
 | 
						|
      case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
 | 
						|
      case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
 | 
						|
        printRelocationTargetName(RE, fmt);
 | 
						|
        fmt << "@GOT";
 | 
						|
        if (isPCRel) fmt << "PCREL";
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
 | 
						|
        InMemoryStruct<macho::RelocationEntry> RENext;
 | 
						|
        DataRefImpl RelNext = Rel;
 | 
						|
        RelNext.d.a++;
 | 
						|
        getRelocation(RelNext, RENext);
 | 
						|
 | 
						|
        // 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 = (RENext->Word1 >> 28) & 0xF;
 | 
						|
        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(RENext, fmt);
 | 
						|
        fmt << "-";
 | 
						|
        printRelocationTargetName(RE, fmt);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      case macho::RIT_X86_64_TLV:
 | 
						|
        printRelocationTargetName(RE, fmt);
 | 
						|
        fmt << "@TLV";
 | 
						|
        if (isPCRel) fmt << "P";
 | 
						|
        break;
 | 
						|
      case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
 | 
						|
        printRelocationTargetName(RE, fmt);
 | 
						|
        fmt << "-1";
 | 
						|
        break;
 | 
						|
      case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
 | 
						|
        printRelocationTargetName(RE, fmt);
 | 
						|
        fmt << "-2";
 | 
						|
        break;
 | 
						|
      case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
 | 
						|
        printRelocationTargetName(RE, fmt);
 | 
						|
        fmt << "-4";
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        printRelocationTargetName(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
 | 
						|
        InMemoryStruct<macho::RelocationEntry> RENext;
 | 
						|
        DataRefImpl RelNext = Rel;
 | 
						|
        RelNext.d.a++;
 | 
						|
        getRelocation(RelNext, RENext);
 | 
						|
 | 
						|
        // X86 sect diff's must be followed by a relocation of type
 | 
						|
        // GENERIC_RELOC_PAIR.
 | 
						|
        bool isNextScattered = (Arch != Triple::x86_64) &&
 | 
						|
                               (RENext->Word0 & macho::RF_Scattered);
 | 
						|
        unsigned RType;
 | 
						|
        if (isNextScattered)
 | 
						|
          RType = (RENext->Word0 >> 24) & 0xF;
 | 
						|
        else
 | 
						|
          RType = (RENext->Word1 >> 28) & 0xF;
 | 
						|
        if (RType != 1)
 | 
						|
          report_fatal_error("Expected GENERIC_RELOC_PAIR after "
 | 
						|
                             "GENERIC_RELOC_SECTDIFF.");
 | 
						|
 | 
						|
        printRelocationTargetName(RE, fmt);
 | 
						|
        fmt << "-";
 | 
						|
        printRelocationTargetName(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
 | 
						|
          InMemoryStruct<macho::RelocationEntry> RENext;
 | 
						|
          DataRefImpl RelNext = Rel;
 | 
						|
          RelNext.d.a++;
 | 
						|
          getRelocation(RelNext, RENext);
 | 
						|
 | 
						|
          // X86 sect diff's must be followed by a relocation of type
 | 
						|
          // GENERIC_RELOC_PAIR.
 | 
						|
          bool isNextScattered = (Arch != Triple::x86_64) &&
 | 
						|
                               (RENext->Word0 & macho::RF_Scattered);
 | 
						|
          unsigned RType;
 | 
						|
          if (isNextScattered)
 | 
						|
            RType = (RENext->Word0 >> 24) & 0xF;
 | 
						|
          else
 | 
						|
            RType = (RENext->Word1 >> 28) & 0xF;
 | 
						|
          if (RType != 1)
 | 
						|
            report_fatal_error("Expected GENERIC_RELOC_PAIR after "
 | 
						|
                               "GENERIC_RELOC_LOCAL_SECTDIFF.");
 | 
						|
 | 
						|
          printRelocationTargetName(RE, fmt);
 | 
						|
          fmt << "-";
 | 
						|
          printRelocationTargetName(RENext, fmt);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        case macho::RIT_Generic_TLV: {
 | 
						|
          printRelocationTargetName(RE, fmt);
 | 
						|
          fmt << "@TLV";
 | 
						|
          if (isPCRel) fmt << "P";
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        default:
 | 
						|
          printRelocationTargetName(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;
 | 
						|
          if (isScattered)
 | 
						|
            isUpper = (RE->Word0 >> 28) & 1;
 | 
						|
          else
 | 
						|
            isUpper = (RE->Word1 >> 25) & 1;
 | 
						|
 | 
						|
          if (isUpper)
 | 
						|
            fmt << ":upper16:(";
 | 
						|
          else
 | 
						|
            fmt << ":lower16:(";
 | 
						|
          printRelocationTargetName(RE, fmt);
 | 
						|
 | 
						|
          InMemoryStruct<macho::RelocationEntry> RENext;
 | 
						|
          DataRefImpl RelNext = Rel;
 | 
						|
          RelNext.d.a++;
 | 
						|
          getRelocation(RelNext, RENext);
 | 
						|
 | 
						|
          // ARM half relocs must be followed by a relocation of type
 | 
						|
          // ARM_RELOC_PAIR.
 | 
						|
          bool isNextScattered = (Arch != Triple::x86_64) &&
 | 
						|
                                 (RENext->Word0 & macho::RF_Scattered);
 | 
						|
          unsigned RType;
 | 
						|
          if (isNextScattered)
 | 
						|
            RType = (RENext->Word0 >> 24) & 0xF;
 | 
						|
          else
 | 
						|
            RType = (RENext->Word1 >> 28) & 0xF;
 | 
						|
 | 
						|
          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(RENext, fmt);
 | 
						|
          }
 | 
						|
 | 
						|
          fmt << ")";
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        default: {
 | 
						|
          printRelocationTargetName(RE, fmt);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else
 | 
						|
    printRelocationTargetName(RE, fmt);
 | 
						|
 | 
						|
  fmt.flush();
 | 
						|
  Result.append(fmtbuf.begin(), fmtbuf.end());
 | 
						|
  return object_error::success;
 | 
						|
}
 | 
						|
 | 
						|
error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
 | 
						|
                                                bool &Result) const {
 | 
						|
  InMemoryStruct<macho::RelocationEntry> RE;
 | 
						|
  getRelocation(Rel, RE);
 | 
						|
 | 
						|
  unsigned Arch = getArch();
 | 
						|
  bool isScattered = (Arch != Triple::x86_64) &&
 | 
						|
                     (RE->Word0 & macho::RF_Scattered);
 | 
						|
  unsigned Type;
 | 
						|
  if (isScattered)
 | 
						|
    Type = (RE->Word0 >> 24) & 0xF;
 | 
						|
  else
 | 
						|
    Type = (RE->Word1 >> 28) & 0xF;
 | 
						|
 | 
						|
  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 X864_64_RELOC_SUBTRACTOR.
 | 
						|
    if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
 | 
						|
      DataRefImpl RelPrev = Rel;
 | 
						|
      RelPrev.d.a--;
 | 
						|
      InMemoryStruct<macho::RelocationEntry> REPrev;
 | 
						|
      getRelocation(RelPrev, REPrev);
 | 
						|
 | 
						|
      unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
 | 
						|
 | 
						|
      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");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*===-- Miscellaneous -----------------------------------------------------===*/
 | 
						|
 | 
						|
uint8_t MachOObjectFile::getBytesInAddress() const {
 | 
						|
  return MachOObj->is64Bit() ? 8 : 4;
 | 
						|
}
 | 
						|
 | 
						|
StringRef MachOObjectFile::getFileFormatName() const {
 | 
						|
  if (!MachOObj->is64Bit()) {
 | 
						|
    switch (MachOObj->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((MachOObj->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) {
 | 
						|
  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) {
 | 
						|
  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
 |