2016-01-13 09:39:23 +00:00
|
|
|
#include "stdafx.h"
|
2016-04-28 07:27:17 +00:00
|
|
|
#ifdef _WIN32
|
2016-01-13 09:39:23 +00:00
|
|
|
#include <windows.h>
|
2016-04-28 07:27:17 +00:00
|
|
|
#else
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#endif
|
2016-01-13 09:39:23 +00:00
|
|
|
#include "MemoryManagement.h"
|
|
|
|
|
2016-01-17 05:54:08 +00:00
|
|
|
static bool TranslateFromMemProtect(MEM_PROTECTION memProtection, int & OsMemProtection)
|
2016-01-13 09:39:23 +00:00
|
|
|
{
|
2016-08-07 06:15:27 +00:00
|
|
|
#ifdef _WIN32
|
2016-01-17 05:54:08 +00:00
|
|
|
switch (memProtection)
|
|
|
|
{
|
|
|
|
case MEM_NOACCESS: OsMemProtection = PAGE_NOACCESS; break;
|
|
|
|
case MEM_READONLY: OsMemProtection = PAGE_READONLY; break;
|
|
|
|
case MEM_READWRITE: OsMemProtection = PAGE_READWRITE; break;
|
|
|
|
case MEM_EXECUTE_READWRITE: OsMemProtection = PAGE_EXECUTE_READWRITE; break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2016-08-07 06:15:27 +00:00
|
|
|
#else
|
|
|
|
switch (memProtection)
|
|
|
|
{
|
|
|
|
case MEM_NOACCESS: OsMemProtection = PROT_NONE; break;
|
|
|
|
case MEM_READONLY: OsMemProtection = PROT_READ; break;
|
2017-08-20 22:48:31 +00:00
|
|
|
case MEM_READWRITE: OsMemProtection = PROT_READ | PROT_WRITE; break;
|
|
|
|
case MEM_EXECUTE_READWRITE: OsMemProtection = PROT_READ | PROT_WRITE | PROT_EXEC; break;
|
2016-08-07 06:15:27 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
2016-01-17 05:54:08 +00:00
|
|
|
return true;
|
2016-01-13 09:39:23 +00:00
|
|
|
}
|
|
|
|
|
2016-08-07 06:15:27 +00:00
|
|
|
#ifdef _WIN32
|
2016-01-17 05:55:44 +00:00
|
|
|
static bool TranslateToMemProtect(int OsMemProtection, MEM_PROTECTION & memProtection)
|
|
|
|
{
|
|
|
|
switch (OsMemProtection)
|
|
|
|
{
|
|
|
|
case PAGE_NOACCESS: memProtection = MEM_NOACCESS; break;
|
|
|
|
case PAGE_READONLY: memProtection = MEM_READONLY; break;
|
|
|
|
case PAGE_READWRITE: memProtection = MEM_READWRITE; break;
|
|
|
|
case PAGE_EXECUTE_READWRITE: memProtection = MEM_EXECUTE_READWRITE; break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2016-04-28 07:27:17 +00:00
|
|
|
#endif
|
2016-01-17 05:55:44 +00:00
|
|
|
|
2017-08-22 08:08:54 +00:00
|
|
|
void* AllocateAddressSpace(size_t size, void * base_address)
|
2016-01-13 09:39:23 +00:00
|
|
|
{
|
2016-04-28 07:27:17 +00:00
|
|
|
#ifdef _WIN32
|
2017-08-22 08:08:54 +00:00
|
|
|
return VirtualAlloc(base_address, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS);
|
2016-04-28 07:27:17 +00:00
|
|
|
#else
|
2017-08-20 22:48:31 +00:00
|
|
|
void * ptr = mmap((void*)0, size, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
2016-09-17 03:32:01 +00:00
|
|
|
if (ptr == MAP_FAILED)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
msync(ptr, size, MS_SYNC | MS_INVALIDATE);
|
2016-04-28 07:27:17 +00:00
|
|
|
return ptr;
|
|
|
|
#endif
|
2016-01-13 09:39:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FreeAddressSpace(void* addr, size_t size)
|
|
|
|
{
|
2016-04-28 07:27:17 +00:00
|
|
|
#ifdef _WIN32
|
2018-11-18 01:06:02 +00:00
|
|
|
size = 0; //unused
|
2016-01-17 05:54:08 +00:00
|
|
|
return VirtualFree(addr, 0, MEM_RELEASE) != 0;
|
2016-04-28 07:27:17 +00:00
|
|
|
#else
|
|
|
|
msync(addr, size, MS_SYNC);
|
|
|
|
munmap(addr, size);
|
2016-11-27 20:23:12 +00:00
|
|
|
return true;
|
2016-04-28 07:27:17 +00:00
|
|
|
#endif
|
2016-01-13 09:39:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void* CommitMemory(void* addr, size_t size, MEM_PROTECTION memProtection)
|
|
|
|
{
|
2016-01-17 05:54:08 +00:00
|
|
|
int OsMemProtection;
|
|
|
|
if (!TranslateFromMemProtect(memProtection, OsMemProtection))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-08-07 06:15:27 +00:00
|
|
|
#ifdef _WIN32
|
2016-01-17 05:54:08 +00:00
|
|
|
return VirtualAlloc(addr, size, MEM_COMMIT, OsMemProtection);
|
2016-04-28 07:27:17 +00:00
|
|
|
#else
|
2016-09-17 03:32:01 +00:00
|
|
|
void * ptr = mmap(addr, size, OsMemProtection, MAP_FIXED | MAP_SHARED | MAP_ANON, -1, 0);
|
|
|
|
msync(addr, size, MS_SYNC | MS_INVALIDATE);
|
2016-04-28 07:27:17 +00:00
|
|
|
return ptr;
|
|
|
|
#endif
|
2016-01-13 09:39:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DecommitMemory(void* addr, size_t size)
|
|
|
|
{
|
2016-04-28 07:27:17 +00:00
|
|
|
#ifdef _WIN32
|
2016-01-13 09:39:23 +00:00
|
|
|
return VirtualFree((void*)addr, size, MEM_DECOMMIT) != 0;
|
2016-04-28 07:27:17 +00:00
|
|
|
#else
|
2016-09-17 03:32:01 +00:00
|
|
|
// instead of unmapping the address, we're just gonna trick
|
|
|
|
// the TLB to mark this as a new mapped area which, due to
|
2016-04-28 07:27:17 +00:00
|
|
|
// demand paging, will not be committed until used.
|
2016-09-17 03:32:01 +00:00
|
|
|
|
|
|
|
mmap(addr, size, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
|
|
msync(addr, size, MS_SYNC | MS_INVALIDATE);
|
|
|
|
|
|
|
|
return true;
|
2016-04-28 07:27:17 +00:00
|
|
|
#endif
|
2016-01-13 09:39:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ProtectMemory(void* addr, size_t size, MEM_PROTECTION memProtection, MEM_PROTECTION * OldProtect)
|
|
|
|
{
|
2016-01-17 05:54:08 +00:00
|
|
|
int OsMemProtection;
|
|
|
|
if (!TranslateFromMemProtect(memProtection, OsMemProtection))
|
|
|
|
{
|
2016-08-07 06:15:27 +00:00
|
|
|
return false;
|
2016-01-17 05:54:08 +00:00
|
|
|
}
|
2016-01-13 09:39:23 +00:00
|
|
|
|
2016-08-07 06:15:27 +00:00
|
|
|
#ifdef _WIN32
|
2016-01-17 05:54:08 +00:00
|
|
|
DWORD OldOsProtect;
|
2016-01-13 09:39:23 +00:00
|
|
|
BOOL res = VirtualProtect(addr, size, OsMemProtection, &OldOsProtect);
|
2016-01-17 05:54:08 +00:00
|
|
|
if (OldProtect != NULL)
|
|
|
|
{
|
2016-01-17 05:55:44 +00:00
|
|
|
if (!TranslateToMemProtect(OldOsProtect, *OldProtect))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-01-17 05:54:08 +00:00
|
|
|
}
|
|
|
|
return res != 0;
|
2016-04-28 07:27:17 +00:00
|
|
|
#else
|
2016-09-17 03:32:01 +00:00
|
|
|
return mprotect(addr, size, OsMemProtection) == 0;
|
2016-04-28 07:27:17 +00:00
|
|
|
#endif
|
2016-01-17 05:54:08 +00:00
|
|
|
}
|