diff options
| author | Tillmann Karras <tilkax@gmail.com> | 2015-05-02 11:57:17 +0200 |
|---|---|---|
| committer | Tillmann Karras <tilkax@gmail.com> | 2015-06-03 21:44:31 +0200 |
| commit | d4538c762ff1d42b69c325abea9bd0ce3854f486 (patch) | |
| tree | 0a0c0387b501ccaa4bf5bb4ae1dbf48ee12995b2 /Source/Core/Common/MemoryUtil.cpp | |
| parent | a0597f0d626a919c6eeb4725b0efd189fddd4341 (diff) | |
MemoryUtil: get executable pages near static data
and clean up a bit.
Diffstat (limited to 'Source/Core/Common/MemoryUtil.cpp')
| -rw-r--r-- | Source/Core/Common/MemoryUtil.cpp | 120 |
1 files changed, 19 insertions, 101 deletions
diff --git a/Source/Core/Common/MemoryUtil.cpp b/Source/Core/Common/MemoryUtil.cpp index 510b258b09..e4563e3409 100644 --- a/Source/Core/Common/MemoryUtil.cpp +++ b/Source/Core/Common/MemoryUtil.cpp @@ -27,71 +27,29 @@ #endif #endif -// Valgrind doesn't support MAP_32BIT. -// Uncomment the following line to be able to run Dolphin in Valgrind. -//#undef MAP_32BIT - -#if !defined(_WIN32) && defined(_M_X86_64) && !defined(MAP_32BIT) -#include <unistd.h> -#define PAGE_MASK (getpagesize() - 1) -#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) -#endif - -// This is purposely not a full wrapper for virtualalloc/mmap, but it -// provides exactly the primitive operations that Dolphin needs. - -void* AllocateExecutableMemory(size_t size, bool low) +void* AllocateExecutableMemory(size_t size, void* map_hint) { #if defined(_WIN32) void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - static char *map_hint = nullptr; -#if defined(_M_X86_64) && !defined(MAP_32BIT) - // This OS has no flag to enforce allocation below the 4 GB boundary, - // but if we hint that we want a low address it is very likely we will - // get one. - // An older version of this code used MAP_FIXED, but that has the side - // effect of discarding already mapped pages that happen to be in the - // requested virtual memory range (such as the emulated RAM, sometimes). - if (low && (!map_hint)) - map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */ -#endif void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_ANON | MAP_PRIVATE -#if defined(_M_X86_64) && defined(MAP_32BIT) - | (low ? MAP_32BIT : 0) -#endif - , -1, 0); + MAP_ANON | MAP_PRIVATE, -1, 0); #endif /* defined(_WIN32) */ - // printf("Mapped executable memory at %p (size %ld)\n", ptr, - // (unsigned long)size); - #ifdef _WIN32 if (ptr == nullptr) - { #else if (ptr == MAP_FAILED) - { - ptr = nullptr; #endif - PanicAlert("Failed to allocate executable memory. If you are running Dolphin in Valgrind, try '#undef MAP_32BIT'."); - } -#if !defined(_WIN32) && defined(_M_X86_64) && !defined(MAP_32BIT) - else { - if (low) - { - map_hint += size; - map_hint = (char*)round_page(map_hint); /* round up to the next page */ - // printf("Next map will (hopefully) be at %p\n", map_hint); - } + ptr = nullptr; + PanicAlert("Failed to allocate executable memory."); } -#endif -#if _M_X86_64 - if ((u64)ptr >= 0x80000000 && low == true) - PanicAlert("Executable memory ended up above 2GB!"); +#ifdef _X86_64 + ptrdiff_t ofs = (u8*)ptr - (u8*)map_hint; + if (ofs < -0x80000000ll || ofs + size > 0x80000000ll) + PanicAlert("Executable range can't be used for RIP-relative addressing."); #endif return ptr; @@ -117,18 +75,12 @@ void* AllocateMemoryPages(size_t size) void* AllocateAlignedMemory(size_t size, size_t alignment) { + void* ptr = nullptr; #ifdef _WIN32 - void* ptr = _aligned_malloc(size, alignment); + if (!(ptr = _aligned_malloc(size, alignment))) #else - void* ptr = nullptr; - if (posix_memalign(&ptr, alignment, size) != 0) - ERROR_LOG(MEMMAP, "Failed to allocate aligned memory"); + if (posix_memalign(&ptr, alignment, size)) #endif - - // printf("Mapped memory at %p (size %ld)\n", ptr, - // (unsigned long)size); - - if (ptr == nullptr) PanicAlert("Failed to allocate aligned memory"); return ptr; @@ -136,23 +88,12 @@ void* AllocateAlignedMemory(size_t size, size_t alignment) void FreeMemoryPages(void* ptr, size_t size) { - if (ptr) - { - bool error_occurred = false; - #ifdef _WIN32 - if (!VirtualFree(ptr, 0, MEM_RELEASE)) - error_occurred = true; + if (ptr && !VirtualFree(ptr, 0, MEM_RELEASE)) #else - int retval = munmap(ptr, size); - - if (retval != 0) - error_occurred = true; + if (ptr && munmap(ptr, size)) #endif - - if (error_occurred) - PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg().c_str()); - } + PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg().c_str()); } void FreeAlignedMemory(void* ptr) @@ -169,58 +110,34 @@ void FreeAlignedMemory(void* ptr) void ReadProtectMemory(void* ptr, size_t size) { - bool error_occurred = false; - #ifdef _WIN32 DWORD oldValue; if (!VirtualProtect(ptr, size, PAGE_NOACCESS, &oldValue)) - error_occurred = true; #else - int retval = mprotect(ptr, size, PROT_NONE); - - if (retval != 0) - error_occurred = true; + if (mprotect(ptr, size, PROT_NONE)) #endif - - if (error_occurred) PanicAlert("ReadProtectMemory failed!\n%s", GetLastErrorMsg().c_str()); } void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) { - bool error_occurred = false; - #ifdef _WIN32 DWORD oldValue; if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue)) - error_occurred = true; #else - int retval = mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ); - - if (retval != 0) - error_occurred = true; + if (mprotect(ptr, size, PROT_READ | (allowExecute ? PROT_EXEC : 0))) #endif - - if (error_occurred) PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg().c_str()); } void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) { - bool error_occurred = false; - #ifdef _WIN32 DWORD oldValue; if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue)) - error_occurred = true; #else - int retval = mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ); - - if (retval != 0) - error_occurred = true; + if (mprotect(ptr, size, PROT_READ | PROT_WRITE | (allowExecute ? PROT_EXEC : 0))) #endif - - if (error_occurred) PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg().c_str()); } @@ -236,7 +153,8 @@ std::string MemUsage() // Print information about the memory usage of the process. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); - if (nullptr == hProcess) return "MemUsage Error"; + if (nullptr == hProcess) + return "MemUsage Error"; if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str()); |
