llvm-6502/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h
Andrew Kaylor cc7773bdcb Implementing page permission setting in MCJIT unit test SectionMemoryManager.cpp
This commit is primarily here for the revision history.  I'm about to move the SectionMemoryManager into the RuntimeDyld library, but I wanted to check the changes in here so people could see the differences in the updated implementation.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168718 91177308-0d34-0410-b5e6-96231b3b80d8
2012-11-27 19:00:17 +00:00

177 lines
6.7 KiB
C++

//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of a section-based memory manager used by
// the MCJIT execution engine and RuntimeDyld.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
#define LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Memory.h"
namespace llvm {
/// This is a simple memory manager which implements the methods called by
/// the RuntimeDyld class to allocate memory for section-based loading of
/// objects, usually those generated by the MCJIT execution engine.
///
/// This memory manager allocates all section memory as read-write. The
/// RuntimeDyld will copy JITed section memory into these allocated blocks
/// and perform any necessary linking and relocations.
///
/// Any client using this memory manager MUST ensure that section-specific
/// page permissions have been applied before attempting to execute functions
/// in the JITed object. Permissions can be applied either by calling
/// MCJIT::finalizeObject or by calling SectionMemoryManager::applyPermissions
/// directly. Clients of MCJIT should call MCJIT::finalizeObject.
class SectionMemoryManager : public JITMemoryManager {
SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION;
void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION;
public:
SectionMemoryManager() { }
virtual ~SectionMemoryManager();
/// \brief Allocates a memory block of (at least) the given size suitable for
/// executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is zero
/// a default alignment of 16 will be used.
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID);
/// \brief Allocates a memory block of (at least) the given size suitable for
/// executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is zero
/// a default alignment of 16 will be used.
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
bool isReadOnly);
/// \brief Applies section-specific memory permissions.
///
/// This method is called when object loading is complete and section page
/// permissions can be applied. It is up to the memory manager implementation
/// to decide whether or not to act on this method. The memory manager will
/// typically allocate all sections as read-write and then apply specific
/// permissions when this method is called. Code sections cannot be executed
/// until this function has been called.
///
/// \returns true if an error occurred, false otherwise.
virtual bool applyPermissions(std::string *ErrMsg = 0);
/// This method returns the address of the specified function. As such it is
/// only useful for resolving library symbols, not code generated symbols.
///
/// If \p AbortOnFailure is false and no function with the given name is
/// found, this function returns a null pointer. Otherwise, it prints a
/// message to stderr and aborts.
virtual void *getPointerToNamedFunction(const std::string &Name,
bool AbortOnFailure = true);
/// \brief Invalidate instruction cache for code sections.
///
/// Some platforms with separate data cache and instruction cache require
/// explicit cache flush, otherwise JIT code manipulations (like resolved
/// relocations) will get to the data cache but not to the instruction cache.
///
/// This method is not called by RuntimeDyld or MCJIT during the load
/// process. Clients may call this function when needed. See the lli
/// tool for example use.
virtual void invalidateInstructionCache();
private:
struct MemoryGroup {
SmallVector<sys::MemoryBlock, 16> AllocatedMem;
SmallVector<sys::MemoryBlock, 16> FreeMem;
sys::MemoryBlock Near;
};
uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size,
unsigned Alignment);
error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
unsigned Permissions);
MemoryGroup CodeMem;
MemoryGroup RWDataMem;
MemoryGroup RODataMem;
public:
///
/// Functions below are not used by MCJIT or RuntimeDyld, but must be
/// implemented because they are declared as pure virtuals in the base class.
///
virtual void setMemoryWritable() {
llvm_unreachable("Unexpected call!");
}
virtual void setMemoryExecutable() {
llvm_unreachable("Unexpected call!");
}
virtual void setPoisonMemory(bool poison) {
llvm_unreachable("Unexpected call!");
}
virtual void AllocateGOT() {
llvm_unreachable("Unexpected call!");
}
virtual uint8_t *getGOTBase() const {
llvm_unreachable("Unexpected call!");
return 0;
}
virtual uint8_t *startFunctionBody(const Function *F,
uintptr_t &ActualSize){
llvm_unreachable("Unexpected call!");
return 0;
}
virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
unsigned Alignment) {
llvm_unreachable("Unexpected call!");
return 0;
}
virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
uint8_t *FunctionEnd) {
llvm_unreachable("Unexpected call!");
}
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
llvm_unreachable("Unexpected call!");
return 0;
}
virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
llvm_unreachable("Unexpected call!");
return 0;
}
virtual void deallocateFunctionBody(void *Body) {
llvm_unreachable("Unexpected call!");
}
virtual uint8_t *startExceptionTable(const Function *F,
uintptr_t &ActualSize) {
llvm_unreachable("Unexpected call!");
return 0;
}
virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
uint8_t *TableEnd, uint8_t *FrameRegister) {
llvm_unreachable("Unexpected call!");
}
virtual void deallocateExceptionTable(void *ET) {
llvm_unreachable("Unexpected call!");
}
};
}
#endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H