From 5cbe7170de736af1b89c9887dcc1f0086bc5ea98 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Thu, 13 Oct 2011 23:16:01 +0000 Subject: [PATCH] Support/Windows: Add support modifying memory permissions on Windows. Patch by Aaron Ballman! llvm-svn: 141910 --- lib/Support/Windows/Memory.inc | 52 ++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/lib/Support/Windows/Memory.inc b/lib/Support/Windows/Memory.inc index 9f69e7367e6..8609d39dd6d 100644 --- a/lib/Support/Windows/Memory.inc +++ b/lib/Support/Windows/Memory.inc @@ -54,20 +54,62 @@ bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { return false; } +static DWORD getProtection(const void *addr) { + MEMORY_BASIC_INFORMATION info; + if (sizeof(info) == ::VirtualQuery(addr, &info, sizeof(info))) { + return info.Protect; + } + return 0; +} + bool Memory::setWritable(MemoryBlock &M, std::string *ErrMsg) { + if (!setRangeWritable(M.Address, M.Size)) { + return MakeErrMsg(ErrMsg, "Cannot set memory to writeable: "); + } return true; } bool Memory::setExecutable(MemoryBlock &M, std::string *ErrMsg) { - return false; -} - -bool Memory::setRangeWritable(const void *Addr, size_t Size) { + if (!setRangeExecutable(M.Address, M.Size)) { + return MakeErrMsg(ErrMsg, "Cannot set memory to executable: "); + } return true; } +bool Memory::setRangeWritable(const void *Addr, size_t Size) { + DWORD prot = getProtection(Addr); + if (!prot) + return false; + + if (prot == PAGE_EXECUTE || prot == PAGE_EXECUTE_READ) { + prot = PAGE_EXECUTE_READWRITE; + } else if (prot == PAGE_NOACCESS || prot == PAGE_READONLY) { + prot = PAGE_READWRITE; + } + + DWORD oldProt; + sys::Memory::InvalidateInstructionCache(Addr, Size); + return ::VirtualProtect(const_cast(Addr), Size, prot, &oldProt) + == TRUE; +} + bool Memory::setRangeExecutable(const void *Addr, size_t Size) { - return false; + DWORD prot = getProtection(Addr); + if (!prot) + return false; + + if (prot == PAGE_NOACCESS) { + prot = PAGE_EXECUTE; + } else if (prot == PAGE_READONLY) { + prot = PAGE_EXECUTE_READ; + } else if (prot == PAGE_READWRITE) { + prot = PAGE_EXECUTE_READWRITE; + } + + DWORD oldProt; + sys::Memory::InvalidateInstructionCache(Addr, Size); + return ::VirtualProtect(const_cast(Addr), Size, prot, &oldProt) + == TRUE; } }