From dd89baf6f88b5e111dbe21b24a2f951f0799a5e2 Mon Sep 17 00:00:00 2001 From: jj Date: Mon, 12 Nov 2012 19:18:03 +0100 Subject: [PATCH] add raw mmap/mprotect access --- library/Process-darwin.cpp | 27 ++++++++++++++++++++++++- library/Process-linux.cpp | 27 ++++++++++++++++++++++++- library/Process-windows.cpp | 39 +++++++++++++++++++++++++++++++++++++ library/include/MemAccess.h | 21 ++++++++++++++++++++ 4 files changed, 112 insertions(+), 2 deletions(-) diff --git a/library/Process-darwin.cpp b/library/Process-darwin.cpp index d081c8c5c..72311e83a 100644 --- a/library/Process-darwin.cpp +++ b/library/Process-darwin.cpp @@ -304,4 +304,29 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange) result=mprotect((void *)range.start, (size_t)range.end-(size_t)range.start,protect); return result==0; -} \ No newline at end of file +} + +// returns -1 on error +void* Process::memAlloc(const int length) +{ + return mmap(0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); +} + +int Process::memDealloc(const void *ptr, const int length) +{ + return munmap(ptr, length); +} + +int Process::memProtect(const void *ptr, const int length, const int prot) +{ + int prot_native = 0; + + if (prot & Process::MemProt::READ) + prot_native |= PROT_READ; + if (prot & Process::MemProt::WRITE) + prot_native |= PROT_WRITE; + if (prot & Process::MemProt::EXEC) + prot_native |= PROT_EXEC; + + return mprotect(ptr, length, prot_native); +} diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp index 046b7696d..c3995a2aa 100644 --- a/library/Process-linux.cpp +++ b/library/Process-linux.cpp @@ -235,4 +235,29 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange) result=mprotect((void *)range.start, (size_t)range.end-(size_t)range.start,protect); return result==0; -} \ No newline at end of file +} + +// returns -1 on error +void* Process::memAlloc(const int length) +{ + return mmap(0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +} + +int Process::memDealloc(void *ptr, const int length) +{ + return munmap(ptr, length); +} + +int Process::memProtect(void *ptr, const int length, const int prot) +{ + int prot_native = 0; + + if (prot & Process::MemProt::READ) + prot_native |= PROT_READ; + if (prot & Process::MemProt::WRITE) + prot_native |= PROT_WRITE; + if (prot & Process::MemProt::EXEC) + prot_native |= PROT_EXEC; + + return mprotect(ptr, length, prot_native); +} diff --git a/library/Process-windows.cpp b/library/Process-windows.cpp index 6f79236f9..cfa0b688d 100644 --- a/library/Process-windows.cpp +++ b/library/Process-windows.cpp @@ -473,3 +473,42 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange) return result; } + +void* Process::memAlloc(const int length) +{ + void *ret; + // returns 0 on error + ret = VirtualAlloc(0, length, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if (!ret) + ret = (void*)-1; + return ret; +} + +int Process::memDealloc(const void *ptr, const int length) +{ + // can only free the whole region at once + // vfree returns 0 on error + return !VirtualFree(ptr, 0, MEM_RELEASE) +} + +int Process::memProtect(const void *ptr, const int length, const int prot) +{ + int prot_native = 0; + int old_prot = 0; + + // only support a few constant combinations + if (prot == 0) + prot_native = PAGE_NOACCESS; + else if (prot == Process::MemProt::READ) + prot_native = PAGE_READONLY; + else if (prot == Process::MemProt::READ | Process::MemProt::WRITE) + prot_native = PAGE_READWRITE; + else if (prot == Process::MemProt::READ | Process::MemProt::WRITE | Process::MemProt::EXECUTE) + prot_native = PAGE_EXECUTE_READWRITE; + else if (prot == Process::MemProt::READ | Process::MemProt::EXECUTE) + prot_native = PAGE_EXECUTE_READ; + else + return -1; + + return !VirtualProtect(ptr, length, prot_native, &old_prot); +} diff --git a/library/include/MemAccess.h b/library/include/MemAccess.h index 22f15eecf..31647a25e 100644 --- a/library/include/MemAccess.h +++ b/library/include/MemAccess.h @@ -291,6 +291,27 @@ namespace DFHack /// write a possibly read-only memory area bool patchMemory(void *target, const void* src, size_t count); + + /// allocate new memory pages for code or stuff + /// returns -1 on error (0 is a valid address) + void* memAlloc(const int length); + + /// free memory pages from memAlloc + /// should have length = alloced length for portability + /// returns 0 on success + int memDealloc(void *ptr, const int length); + + /// change memory page permissions + /// prot is a bitwise OR of the MemProt enum + /// returns 0 on success + int memProtect(void *ptr, const int length, const int prot); + + enum MemProt { + READ = 1, + WRITE = 2, + EXEC = 4 + }; + private: VersionInfo * my_descriptor; PlatformSpecific *d;