Skip to content

Commit

Permalink
MemoryUtil: Use mach vm functions on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
OatmealDome committed Nov 23, 2019
1 parent 4749a9c commit d3e100a
Showing 1 changed file with 66 additions and 0 deletions.
66 changes: 66 additions & 0 deletions Source/Core/Common/MemoryUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@
#ifdef _WIN32
#include <windows.h>
#include "Common/StringUtil.h"

#else
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#if defined __APPLE__ || defined __FreeBSD__ || defined __OpenBSD__
#ifdef IPHONEOS
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <mach/vm_param.h>
#endif
#include <sys/sysctl.h>
#elif defined __HAIKU__
#include <OS.h>
Expand All @@ -37,6 +43,25 @@ void* AllocateExecutableMemory(size_t size)
{
#if defined(_WIN32)
void* ptr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined(IPHONEOS)
void* ptr = nullptr;
vm_address_t vm_ptr;
kern_return_t retval = vm_allocate(mach_task_self(), &vm_ptr, size, VM_FLAGS_ANYWHERE);

if (retval == KERN_SUCCESS)
{
vm_prot_t protection = VM_PROT_READ | VM_PROT_WRITE;
#ifdef _M_X86_64
protection |= VM_PROT_EXECUTE;
#endif

retval = vm_protect(mach_task_self(), vm_ptr, size, false, protection);

if (retval == KERN_SUCCESS)
{
ptr = (void*)vm_ptr;
}
}
#else
void* ptr =
mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
Expand All @@ -55,6 +80,19 @@ void* AllocateMemoryPages(size_t size)
{
#ifdef _WIN32
void* ptr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE);
#elif defined(IPHONEOS)
vm_address_t vm_ptr;
kern_return_t retval = vm_allocate(mach_task_self(), &vm_ptr, size, VM_FLAGS_ANYWHERE);

void* ptr;
if (retval == KERN_SUCCESS)
{
ptr = (void*)vm_ptr;
}
else
{
ptr = nullptr;
}
#else
void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);

Expand Down Expand Up @@ -91,6 +129,10 @@ void FreeMemoryPages(void* ptr, size_t size)
#ifdef _WIN32
if (!VirtualFree(ptr, 0, MEM_RELEASE))
PanicAlert("FreeMemoryPages failed!\nVirtualFree: %s", GetLastErrorString().c_str());
#elif defined(IPHONEOS)
kern_return_t retval = vm_deallocate(mach_task_self(), (vm_address_t)ptr, size);
if (retval != KERN_SUCCESS)
PanicAlert("FreeMemoryPages failed!\nvm_deallocate: 0x%x", retval);
#else
if (munmap(ptr, size) != 0)
PanicAlert("FreeMemoryPages failed!\nmunmap: %s", LastStrerrorString().c_str());
Expand All @@ -116,6 +158,10 @@ void ReadProtectMemory(void* ptr, size_t size)
DWORD oldValue;
if (!VirtualProtect(ptr, size, PAGE_NOACCESS, &oldValue))
PanicAlert("ReadProtectMemory failed!\nVirtualProtect: %s", GetLastErrorString().c_str());
#elif defined(IPHONEOS)
kern_return_t retval = vm_protect(mach_task_self(), (vm_address_t)ptr, size, false, VM_PROT_NONE);
if (retval != KERN_SUCCESS)
PanicAlert("ReadProtectMemory failed!\nvm_protect: 0x%x", retval);
#else
if (mprotect(ptr, size, PROT_NONE) != 0)
PanicAlert("ReadProtectMemory failed!\nmprotect: %s", LastStrerrorString().c_str());
Expand All @@ -128,6 +174,10 @@ void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
PanicAlert("WriteProtectMemory failed!\nVirtualProtect: %s", GetLastErrorString().c_str());
#elif defined(IPHONEOS)
kern_return_t retval = vm_protect(mach_task_self(), (vm_address_t)ptr, size, false, allowExecute ? (VM_PROT_READ | VM_PROT_EXECUTE) : VM_PROT_READ);
if (retval != KERN_SUCCESS)
PanicAlert("WriteProtectMemory failed!\nvm_protect: 0x%x", retval);
#else
if (mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ) != 0)
PanicAlert("WriteProtectMemory failed!\nmprotect: %s", LastStrerrorString().c_str());
Expand All @@ -140,6 +190,22 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue))
PanicAlert("UnWriteProtectMemory failed!\nVirtualProtect: %s", GetLastErrorString().c_str());
#elif defined(IPHONEOS)
vm_prot_t protection = VM_PROT_READ | VM_PROT_WRITE;
if (allowExecute)
{
#ifdef _M_X86_64
protection |= VM_PROT_EXECUTE;
#else
WARN_LOG(COMMON, "UnWriteProtectMemory: Cannot have memory be simultaneously executable and writable on iOS");
#endif
}

kern_return_t retval = vm_protect(mach_task_self(), (vm_address_t)ptr, size, false, protection);
if (retval != KERN_SUCCESS)
{
PanicAlert("UnWriteProtectMemory failed!\nvm_protect: 0x%x", retval);
}
#else
if (mprotect(ptr, size,
allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ) != 0)
Expand Down

0 comments on commit d3e100a

Please sign in to comment.