mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
Interface changes to allow RuntimeDyld memory managers to set memory permissions after an object has been loaded.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168114 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -48,7 +48,7 @@ public:
|
|||||||
/// assigned by the JIT engine, and optionally recorded by the memory manager
|
/// assigned by the JIT engine, and optionally recorded by the memory manager
|
||||||
/// to access a loaded section.
|
/// to access a loaded section.
|
||||||
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID) = 0;
|
unsigned SectionID, bool IsReadOnly) = 0;
|
||||||
|
|
||||||
/// getPointerToNamedFunction - This method returns the address of the
|
/// getPointerToNamedFunction - This method returns the address of the
|
||||||
/// specified function. As such it is only useful for resolving library
|
/// specified function. As such it is only useful for resolving library
|
||||||
@@ -59,6 +59,15 @@ public:
|
|||||||
/// message to stderr and aborts.
|
/// message to stderr and aborts.
|
||||||
virtual void *getPointerToNamedFunction(const std::string &Name,
|
virtual void *getPointerToNamedFunction(const std::string &Name,
|
||||||
bool AbortOnFailure = true) = 0;
|
bool AbortOnFailure = true) = 0;
|
||||||
|
|
||||||
|
/// applyPermissions - 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. Returns true if an error occurred, false
|
||||||
|
/// otherwise.
|
||||||
|
virtual bool applyPermissions(std::string *ErrMsg = 0) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RuntimeDyld {
|
class RuntimeDyld {
|
||||||
|
@@ -501,10 +501,14 @@ namespace {
|
|||||||
|
|
||||||
/// allocateDataSection - Allocate memory for a data section.
|
/// allocateDataSection - Allocate memory for a data section.
|
||||||
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID) {
|
unsigned SectionID, bool IsReadOnly) {
|
||||||
return (uint8_t*)DataAllocator.Allocate(Size, Alignment);
|
return (uint8_t*)DataAllocator.Allocate(Size, Alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool applyPermissions(std::string *ErrMsg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// startExceptionTable - Use startFunctionBody to allocate memory for the
|
/// startExceptionTable - Use startFunctionBody to allocate memory for the
|
||||||
/// function's exception table.
|
/// function's exception table.
|
||||||
uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
|
uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
|
||||||
|
@@ -118,17 +118,26 @@ void MCJIT::emitObject(Module *m) {
|
|||||||
|
|
||||||
// FIXME: Add a parameter to identify which object is being finalized when
|
// FIXME: Add a parameter to identify which object is being finalized when
|
||||||
// MCJIT supports multiple modules.
|
// MCJIT supports multiple modules.
|
||||||
|
// FIXME: Provide a way to separate code emission, relocations and page
|
||||||
|
// protection in the interface.
|
||||||
void MCJIT::finalizeObject() {
|
void MCJIT::finalizeObject() {
|
||||||
// If the module hasn't been compiled, just do that.
|
// If the module hasn't been compiled, just do that.
|
||||||
if (!isCompiled) {
|
if (!isCompiled) {
|
||||||
// If the call to Dyld.resolveRelocations() is removed from emitObject()
|
// If the call to Dyld.resolveRelocations() is removed from emitObject()
|
||||||
// we'll need to do that here.
|
// we'll need to do that here.
|
||||||
emitObject(M);
|
emitObject(M);
|
||||||
|
|
||||||
|
// Set page permissions.
|
||||||
|
MemMgr->applyPermissions();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve any relocations.
|
// Resolve any relocations.
|
||||||
Dyld.resolveRelocations();
|
Dyld.resolveRelocations();
|
||||||
|
|
||||||
|
// Set page permissions.
|
||||||
|
MemMgr->applyPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
|
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
|
||||||
|
@@ -182,7 +182,7 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
|
|||||||
// Allocate memory for the section
|
// Allocate memory for the section
|
||||||
unsigned SectionID = Sections.size();
|
unsigned SectionID = Sections.size();
|
||||||
uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void*),
|
uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void*),
|
||||||
SectionID);
|
SectionID, false);
|
||||||
if (!Addr)
|
if (!Addr)
|
||||||
report_fatal_error("Unable to allocate memory for common symbols!");
|
report_fatal_error("Unable to allocate memory for common symbols!");
|
||||||
uint64_t Offset = 0;
|
uint64_t Offset = 0;
|
||||||
@@ -237,11 +237,13 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
|||||||
bool IsRequired;
|
bool IsRequired;
|
||||||
bool IsVirtual;
|
bool IsVirtual;
|
||||||
bool IsZeroInit;
|
bool IsZeroInit;
|
||||||
|
bool IsReadOnly;
|
||||||
uint64_t DataSize;
|
uint64_t DataSize;
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
Check(Section.isRequiredForExecution(IsRequired));
|
Check(Section.isRequiredForExecution(IsRequired));
|
||||||
Check(Section.isVirtual(IsVirtual));
|
Check(Section.isVirtual(IsVirtual));
|
||||||
Check(Section.isZeroInit(IsZeroInit));
|
Check(Section.isZeroInit(IsZeroInit));
|
||||||
|
Check(Section.isReadOnlyData(IsReadOnly));
|
||||||
Check(Section.getSize(DataSize));
|
Check(Section.getSize(DataSize));
|
||||||
Check(Section.getName(Name));
|
Check(Section.getName(Name));
|
||||||
|
|
||||||
@@ -256,7 +258,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
|||||||
Allocate = DataSize + StubBufSize;
|
Allocate = DataSize + StubBufSize;
|
||||||
Addr = IsCode
|
Addr = IsCode
|
||||||
? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID)
|
? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID)
|
||||||
: MemMgr->allocateDataSection(Allocate, Alignment, SectionID);
|
: MemMgr->allocateDataSection(Allocate, Alignment, SectionID, IsReadOnly);
|
||||||
if (!Addr)
|
if (!Addr)
|
||||||
report_fatal_error("Unable to allocate section memory!");
|
report_fatal_error("Unable to allocate section memory!");
|
||||||
|
|
||||||
@@ -451,6 +453,12 @@ void RuntimeDyldImpl::resolveExternalSymbols() {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// RuntimeDyld class implementation
|
// RuntimeDyld class implementation
|
||||||
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
|
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
|
||||||
|
// FIXME: There's a potential issue lurking here if a single instance of
|
||||||
|
// RuntimeDyld is used to load multiple objects. The current implementation
|
||||||
|
// associates a single memory manager with a RuntimeDyld instance. Even
|
||||||
|
// though the public class spawns a new 'impl' instance for each load,
|
||||||
|
// they share a single memory manager. This can become a problem when page
|
||||||
|
// permissions are applied.
|
||||||
Dyld = 0;
|
Dyld = 0;
|
||||||
MM = mm;
|
MM = mm;
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,8 @@ allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *RecordingMemoryManager::
|
uint8_t *RecordingMemoryManager::
|
||||||
allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
|
allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||||
|
unsigned SectionID, bool IsReadOnly) {
|
||||||
// The recording memory manager is just a local copy of the remote target.
|
// The recording memory manager is just a local copy of the remote target.
|
||||||
// The alignment requirement is just stored here for later use. Regular
|
// The alignment requirement is just stored here for later use. Regular
|
||||||
// heap storage is sufficient here.
|
// heap storage is sufficient here.
|
||||||
|
@@ -47,10 +47,13 @@ public:
|
|||||||
unsigned SectionID);
|
unsigned SectionID);
|
||||||
|
|
||||||
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID);
|
unsigned SectionID, bool IsReadOnly);
|
||||||
|
|
||||||
void *getPointerToNamedFunction(const std::string &Name,
|
void *getPointerToNamedFunction(const std::string &Name,
|
||||||
bool AbortOnFailure = true);
|
bool AbortOnFailure = true);
|
||||||
|
|
||||||
|
bool applyPermissions(std::string *ErrMsg) { return false; }
|
||||||
|
|
||||||
// The following obsolete JITMemoryManager calls are stubbed out for
|
// The following obsolete JITMemoryManager calls are stubbed out for
|
||||||
// this model.
|
// this model.
|
||||||
void setMemoryWritable();
|
void setMemoryWritable();
|
||||||
|
@@ -231,11 +231,13 @@ public:
|
|||||||
unsigned SectionID);
|
unsigned SectionID);
|
||||||
|
|
||||||
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID);
|
unsigned SectionID, bool IsReadOnly);
|
||||||
|
|
||||||
virtual void *getPointerToNamedFunction(const std::string &Name,
|
virtual void *getPointerToNamedFunction(const std::string &Name,
|
||||||
bool AbortOnFailure = true);
|
bool AbortOnFailure = true);
|
||||||
|
|
||||||
|
virtual bool applyPermissions(std::string *ErrMsg) { return false; }
|
||||||
|
|
||||||
// Invalidate instruction cache for code sections. Some platforms with
|
// Invalidate instruction cache for code sections. Some platforms with
|
||||||
// separate data cache and instruction cache require explicit cache flush,
|
// separate data cache and instruction cache require explicit cache flush,
|
||||||
// otherwise JIT code manipulations (like resolved relocations) will get to
|
// otherwise JIT code manipulations (like resolved relocations) will get to
|
||||||
@@ -301,7 +303,8 @@ public:
|
|||||||
|
|
||||||
uint8_t *LLIMCJITMemoryManager::allocateDataSection(uintptr_t Size,
|
uint8_t *LLIMCJITMemoryManager::allocateDataSection(uintptr_t Size,
|
||||||
unsigned Alignment,
|
unsigned Alignment,
|
||||||
unsigned SectionID) {
|
unsigned SectionID,
|
||||||
|
bool IsReadOnly) {
|
||||||
if (!Alignment)
|
if (!Alignment)
|
||||||
Alignment = 16;
|
Alignment = 16;
|
||||||
// Ensure that enough memory is requested to allow aligning.
|
// Ensure that enough memory is requested to allow aligning.
|
||||||
|
@@ -58,13 +58,15 @@ public:
|
|||||||
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
|
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID);
|
unsigned SectionID);
|
||||||
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID);
|
unsigned SectionID, bool IsReadOnly);
|
||||||
|
|
||||||
virtual void *getPointerToNamedFunction(const std::string &Name,
|
virtual void *getPointerToNamedFunction(const std::string &Name,
|
||||||
bool AbortOnFailure = true) {
|
bool AbortOnFailure = true) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool applyPermissions(std::string *ErrMsg) { return false; }
|
||||||
|
|
||||||
// Invalidate instruction cache for sections with execute permissions.
|
// Invalidate instruction cache for sections with execute permissions.
|
||||||
// Some platforms with separate data cache and instruction cache require
|
// Some platforms with separate data cache and instruction cache require
|
||||||
// explicit cache flush, otherwise JIT code manipulations (like resolved
|
// explicit cache flush, otherwise JIT code manipulations (like resolved
|
||||||
@@ -82,7 +84,8 @@ uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size,
|
|||||||
|
|
||||||
uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size,
|
uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size,
|
||||||
unsigned Alignment,
|
unsigned Alignment,
|
||||||
unsigned SectionID) {
|
unsigned SectionID,
|
||||||
|
bool IsReadOnly) {
|
||||||
sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0);
|
sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0);
|
||||||
DataMemory.push_back(MB);
|
DataMemory.push_back(MB);
|
||||||
return (uint8_t*)MB.base();
|
return (uint8_t*)MB.base();
|
||||||
|
@@ -118,13 +118,14 @@ public:
|
|||||||
Base->endFunctionBody(F, FunctionStart, FunctionEnd);
|
Base->endFunctionBody(F, FunctionStart, FunctionEnd);
|
||||||
}
|
}
|
||||||
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID) {
|
unsigned SectionID, bool IsReadOnly) {
|
||||||
return Base->allocateDataSection(Size, Alignment, SectionID);
|
return Base->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
|
||||||
}
|
}
|
||||||
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
|
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID) {
|
unsigned SectionID) {
|
||||||
return Base->allocateCodeSection(Size, Alignment, SectionID);
|
return Base->allocateCodeSection(Size, Alignment, SectionID);
|
||||||
}
|
}
|
||||||
|
virtual bool applyPermissions(std::string *ErrMsg) { return false; }
|
||||||
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
|
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
|
||||||
return Base->allocateSpace(Size, Alignment);
|
return Base->allocateSpace(Size, Alignment);
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,8 @@ namespace llvm {
|
|||||||
|
|
||||||
uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
|
uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
|
||||||
unsigned Alignment,
|
unsigned Alignment,
|
||||||
unsigned SectionID) {
|
unsigned SectionID,
|
||||||
|
bool IsReadOnly) {
|
||||||
if (!Alignment)
|
if (!Alignment)
|
||||||
Alignment = 16;
|
Alignment = 16;
|
||||||
// Ensure that enough memory is requested to allow aligning.
|
// Ensure that enough memory is requested to allow aligning.
|
||||||
|
@@ -34,7 +34,9 @@ public:
|
|||||||
unsigned SectionID);
|
unsigned SectionID);
|
||||||
|
|
||||||
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||||
unsigned SectionID);
|
unsigned SectionID, bool IsReadOnly);
|
||||||
|
|
||||||
|
virtual bool applyPermissions(std::string *ErrMsg) { return false; }
|
||||||
|
|
||||||
virtual void *getPointerToNamedFunction(const std::string &Name,
|
virtual void *getPointerToNamedFunction(const std::string &Name,
|
||||||
bool AbortOnFailure = true);
|
bool AbortOnFailure = true);
|
||||||
|
Reference in New Issue
Block a user