#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
sljit_update_wx_flags((from), (to), (enable_exec))
#ifndef _WIN32
#include <sys/types.h>
#include <sys/mman.h>
#ifdef __NetBSD__
#if defined(PROT_MPROTECT)
#define check_se_protected(ptr, size) (0)
#define SLJIT_PROT_WX PROT_MPROTECT(PROT_EXEC)
#else
#ifdef _NETBSD_SOURCE
#include <sys/param.h>
#else
typedef unsigned int u_int;
#define devmajor_t sljit_s32
#endif
#include <sys/sysctl.h>
#include <unistd.h>
#define check_se_protected(ptr, size) netbsd_se_protected()
static SLJIT_INLINE int netbsd_se_protected(void)
{
int mib[3];
int paxflags;
size_t len = sizeof(paxflags);
mib[0] = CTL_PROC;
mib[1] = getpid();
mib[2] = PROC_PID_PAXFLAGS;
if (SLJIT_UNLIKELY(sysctl(mib, 3, &paxflags, &len, NULL, 0) < 0))
return -1;
return (paxflags & CTL_PROC_PAXFLAGS_MPROTECT) ? -1 : 0;
}
#endif
#else
#define check_se_protected(ptr, size) generic_se_protected(ptr, size)
static SLJIT_INLINE int generic_se_protected(void *ptr, sljit_uw size)
{
if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC)))
return mprotect(ptr, size, PROT_READ | PROT_WRITE);
return -1;
}
#endif
#if defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED
#define SLJIT_SE_LOCK()
#define SLJIT_SE_UNLOCK()
#else
#include <pthread.h>
#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock)
#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock)
#endif
#ifndef SLJIT_PROT_WX
#define SLJIT_PROT_WX 0
#endif
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
{
#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
static int se_protected = !SLJIT_PROT_WX;
sljit_uw* ptr;
if (SLJIT_UNLIKELY(se_protected < 0))
return NULL;
size += sizeof(sljit_uw);
ptr = (sljit_uw*)mmap(NULL, size, PROT_READ | PROT_WRITE | SLJIT_PROT_WX,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)
return NULL;
if (SLJIT_UNLIKELY(se_protected > 0)) {
SLJIT_SE_LOCK();
se_protected = check_se_protected(ptr, size);
SLJIT_SE_UNLOCK();
if (SLJIT_UNLIKELY(se_protected < 0)) {
munmap((void *)ptr, size);
return NULL;
}
}
*ptr++ = size;
return ptr;
}
#undef SLJIT_PROT_WX
#undef SLJIT_SE_UNLOCK
#undef SLJIT_SE_LOCK
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
{
sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1;
munmap((void*)start_ptr, *start_ptr);
}
static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)
{
sljit_uw page_mask = (sljit_uw)get_page_alignment();
sljit_uw start = (sljit_uw)from;
sljit_uw end = (sljit_uw)to;
int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE);
SLJIT_ASSERT(start < end);
start &= ~page_mask;
end = (end + page_mask) & ~page_mask;
mprotect((void*)start, end - start, prot);
}
#else
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
{
sljit_uw *ptr;
size += sizeof(sljit_uw);
ptr = (sljit_uw*)VirtualAlloc(NULL, size,
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!ptr)
return NULL;
*ptr++ = size;
return ptr;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
{
sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw);
#if defined(SLJIT_DEBUG) && SLJIT_DEBUG
sljit_uw page_mask = (sljit_uw)get_page_alignment();
SLJIT_ASSERT(!(start & page_mask));
#endif
VirtualFree((void*)start, 0, MEM_RELEASE);
}
static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)
{
DWORD oldprot;
sljit_uw page_mask = (sljit_uw)get_page_alignment();
sljit_uw start = (sljit_uw)from;
sljit_uw end = (sljit_uw)to;
DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE;
SLJIT_ASSERT(start < end);
start &= ~page_mask;
end = (end + page_mask) & ~page_mask;
VirtualProtect((void*)start, end - start, prot, &oldprot);
}
#endif
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
{
}