llvm-6502/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
Chandler Carruth a1514e24cc Sort includes for all of the .h files under the 'lib' tree. These were
missed in the first pass because the script didn't yet handle include
guards.

Note that the script is now able to handle all of these headers without
manual edits. =]

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169224 91177308-0d34-0410-b5e6-96231b3b80d8
2012-12-04 07:12:27 +00:00

345 lines
12 KiB
C++

//===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Interface for the implementations of runtime dynamic linker facilities.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_RUNTIME_DYLD_IMPL_H
#define LLVM_RUNTIME_DYLD_IMPL_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/ObjectImage.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/SwapByteOrder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
#include <map>
using namespace llvm;
using namespace llvm::object;
namespace llvm {
class ObjectBuffer;
class Twine;
/// SectionEntry - represents a section emitted into memory by the dynamic
/// linker.
class SectionEntry {
public:
/// Name - section name.
StringRef Name;
/// Address - address in the linker's memory where the section resides.
uint8_t *Address;
/// Size - section size.
size_t Size;
/// LoadAddress - the address of the section in the target process's memory.
/// Used for situations in which JIT-ed code is being executed in the address
/// space of a separate process. If the code executes in the same address
/// space where it was JIT-ed, this just equals Address.
uint64_t LoadAddress;
/// StubOffset - used for architectures with stub functions for far
/// relocations (like ARM).
uintptr_t StubOffset;
/// ObjAddress - address of the section in the in-memory object file. Used
/// for calculating relocations in some object formats (like MachO).
uintptr_t ObjAddress;
SectionEntry(StringRef name, uint8_t *address, size_t size,
uintptr_t stubOffset, uintptr_t objAddress)
: Name(name), Address(address), Size(size), LoadAddress((uintptr_t)address),
StubOffset(stubOffset), ObjAddress(objAddress) {}
};
/// RelocationEntry - used to represent relocations internally in the dynamic
/// linker.
class RelocationEntry {
public:
/// SectionID - the section this relocation points to.
unsigned SectionID;
/// Offset - offset into the section.
uintptr_t Offset;
/// RelType - relocation type.
uint32_t RelType;
/// Addend - the relocation addend encoded in the instruction itself. Also
/// used to make a relocation section relative instead of symbol relative.
intptr_t Addend;
RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend)
: SectionID(id), Offset(offset), RelType(type), Addend(addend) {}
};
/// ObjRelocationInfo - relocation information as read from the object file.
/// Used to pass around data taken from object::RelocationRef, together with
/// the section to which the relocation points (represented by a SectionID).
class ObjRelocationInfo {
public:
unsigned SectionID;
uint64_t Offset;
SymbolRef Symbol;
uint64_t Type;
int64_t AdditionalInfo;
};
class RelocationValueRef {
public:
unsigned SectionID;
intptr_t Addend;
const char *SymbolName;
RelocationValueRef(): SectionID(0), Addend(0), SymbolName(0) {}
inline bool operator==(const RelocationValueRef &Other) const {
return std::memcmp(this, &Other, sizeof(RelocationValueRef)) == 0;
}
inline bool operator <(const RelocationValueRef &Other) const {
return std::memcmp(this, &Other, sizeof(RelocationValueRef)) < 0;
}
};
class RuntimeDyldImpl {
protected:
// The MemoryManager to load objects into.
RTDyldMemoryManager *MemMgr;
// A list of all sections emitted by the dynamic linker. These sections are
// referenced in the code by means of their index in this list - SectionID.
typedef SmallVector<SectionEntry, 64> SectionList;
SectionList Sections;
// Keep a map of sections from object file to the SectionID which
// references it.
typedef std::map<SectionRef, unsigned> ObjSectionToIDMap;
// A global symbol table for symbols from all loaded modules. Maps the
// symbol name to a (SectionID, offset in section) pair.
typedef std::pair<unsigned, uintptr_t> SymbolLoc;
typedef StringMap<SymbolLoc> SymbolTableMap;
SymbolTableMap GlobalSymbolTable;
// Pair representing the size and alignment requirement for a common symbol.
typedef std::pair<unsigned, unsigned> CommonSymbolInfo;
// Keep a map of common symbols to their info pairs
typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap;
// For each symbol, keep a list of relocations based on it. Anytime
// its address is reassigned (the JIT re-compiled the function, e.g.),
// the relocations get re-resolved.
// The symbol (or section) the relocation is sourced from is the Key
// in the relocation list where it's stored.
typedef SmallVector<RelocationEntry, 64> RelocationList;
// Relocations to sections already loaded. Indexed by SectionID which is the
// source of the address. The target where the address will be written is
// SectionID/Offset in the relocation itself.
DenseMap<unsigned, RelocationList> Relocations;
// Relocations to external symbols that are not yet resolved. Symbols are
// external when they aren't found in the global symbol table of all loaded
// modules. This map is indexed by symbol name.
StringMap<RelocationList> ExternalSymbolRelocations;
typedef std::map<RelocationValueRef, uintptr_t> StubMap;
Triple::ArchType Arch;
inline unsigned getMaxStubSize() {
if (Arch == Triple::arm || Arch == Triple::thumb)
return 8; // 32-bit instruction and 32-bit address
else if (Arch == Triple::mipsel || Arch == Triple::mips)
return 16;
else if (Arch == Triple::ppc64)
return 44;
else
return 0;
}
bool HasError;
std::string ErrorStr;
// Set the error state and record an error string.
bool Error(const Twine &Msg) {
ErrorStr = Msg.str();
HasError = true;
return true;
}
uint64_t getSectionLoadAddress(unsigned SectionID) {
return Sections[SectionID].LoadAddress;
}
uint8_t *getSectionAddress(unsigned SectionID) {
return (uint8_t*)Sections[SectionID].Address;
}
// Subclasses can override this method to get the alignment requirement of
// a common symbol. Returns no alignment requirement if not implemented.
virtual unsigned getCommonSymbolAlignment(const SymbolRef &Sym) {
return 0;
}
void writeInt16BE(uint8_t *Addr, uint16_t Value) {
if (sys::isLittleEndianHost())
Value = sys::SwapByteOrder(Value);
*Addr = (Value >> 8) & 0xFF;
*(Addr+1) = Value & 0xFF;
}
void writeInt32BE(uint8_t *Addr, uint32_t Value) {
if (sys::isLittleEndianHost())
Value = sys::SwapByteOrder(Value);
*Addr = (Value >> 24) & 0xFF;
*(Addr+1) = (Value >> 16) & 0xFF;
*(Addr+2) = (Value >> 8) & 0xFF;
*(Addr+3) = Value & 0xFF;
}
void writeInt64BE(uint8_t *Addr, uint64_t Value) {
if (sys::isLittleEndianHost())
Value = sys::SwapByteOrder(Value);
*Addr = (Value >> 56) & 0xFF;
*(Addr+1) = (Value >> 48) & 0xFF;
*(Addr+2) = (Value >> 40) & 0xFF;
*(Addr+3) = (Value >> 32) & 0xFF;
*(Addr+4) = (Value >> 24) & 0xFF;
*(Addr+5) = (Value >> 16) & 0xFF;
*(Addr+6) = (Value >> 8) & 0xFF;
*(Addr+7) = Value & 0xFF;
}
/// \brief Given the common symbols discovered in the object file, emit a
/// new section for them and update the symbol mappings in the object and
/// symbol table.
void emitCommonSymbols(ObjectImage &Obj,
const CommonSymbolMap &CommonSymbols,
uint64_t TotalSize,
SymbolTableMap &SymbolTable);
/// \brief Emits section data from the object file to the MemoryManager.
/// \param IsCode if it's true then allocateCodeSection() will be
/// used for emits, else allocateDataSection() will be used.
/// \return SectionID.
unsigned emitSection(ObjectImage &Obj,
const SectionRef &Section,
bool IsCode);
/// \brief Find Section in LocalSections. If the secton is not found - emit
/// it and store in LocalSections.
/// \param IsCode if it's true then allocateCodeSection() will be
/// used for emmits, else allocateDataSection() will be used.
/// \return SectionID.
unsigned findOrEmitSection(ObjectImage &Obj,
const SectionRef &Section,
bool IsCode,
ObjSectionToIDMap &LocalSections);
// \brief Add a relocation entry that uses the given section.
void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID);
// \brief Add a relocation entry that uses the given symbol. This symbol may
// be found in the global symbol table, or it may be external.
void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName);
/// \brief Emits long jump instruction to Addr.
/// \return Pointer to the memory area for emitting target address.
uint8_t* createStubFunction(uint8_t *Addr);
/// \brief Resolves relocations from Relocs list with address from Value.
void resolveRelocationList(const RelocationList &Relocs, uint64_t Value);
void resolveRelocationEntry(const RelocationEntry &RE, uint64_t Value);
/// \brief A object file specific relocation resolver
/// \param Section The section where the relocation is being applied
/// \param Offset The offset into the section for this relocation
/// \param Value Target symbol address to apply the relocation action
/// \param Type object file specific relocation type
/// \param Addend A constant addend used to compute the value to be stored
/// into the relocatable field
virtual void resolveRelocation(const SectionEntry &Section,
uint64_t Offset,
uint64_t Value,
uint32_t Type,
int64_t Addend) = 0;
/// \brief Parses the object file relocation and stores it to Relocations
/// or SymbolRelocations (this depends on the object file type).
virtual void processRelocationRef(const ObjRelocationInfo &Rel,
ObjectImage &Obj,
ObjSectionToIDMap &ObjSectionToID,
const SymbolTableMap &Symbols,
StubMap &Stubs) = 0;
/// \brief Resolve relocations to external symbols.
void resolveExternalSymbols();
virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
public:
RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
virtual ~RuntimeDyldImpl();
ObjectImage *loadObject(ObjectBuffer *InputBuffer);
void *getSymbolAddress(StringRef Name) {
// FIXME: Just look up as a function for now. Overly simple of course.
// Work in progress.
if (GlobalSymbolTable.find(Name) == GlobalSymbolTable.end())
return 0;
SymbolLoc Loc = GlobalSymbolTable.lookup(Name);
return getSectionAddress(Loc.first) + Loc.second;
}
uint64_t getSymbolLoadAddress(StringRef Name) {
// FIXME: Just look up as a function for now. Overly simple of course.
// Work in progress.
if (GlobalSymbolTable.find(Name) == GlobalSymbolTable.end())
return 0;
SymbolLoc Loc = GlobalSymbolTable.lookup(Name);
return getSectionLoadAddress(Loc.first) + Loc.second;
}
void resolveRelocations();
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress);
// Is the linker in an error state?
bool hasError() { return HasError; }
// Mark the error condition as handled and continue.
void clearError() { HasError = false; }
// Get the error message.
StringRef getErrorString() { return ErrorStr; }
virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0;
};
} // end namespace llvm
#endif