From 6f3deee62da7ac60a104835fb859a36d7a319043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Herczeg?= <hzmester@freemail.hu> Date: Fri, 9 Dec 2016 14:22:11 +0000 Subject: [PATCH] JIT compiler update. --- src/sljit/sljitConfig.h | 12 ++- src/sljit/sljitConfigInternal.h | 8 ++ src/sljit/sljitLir.c | 27 +++++++ src/sljit/sljitLir.h | 14 ++++ src/sljit/sljitNativeARM_32.c | 3 + src/sljit/sljitNativeARM_64.c | 3 + src/sljit/sljitNativeARM_T2_32.c | 3 + src/sljit/sljitNativeMIPS_common.c | 5 ++ src/sljit/sljitNativePPC_common.c | 3 + src/sljit/sljitNativeSPARC_common.c | 3 + src/sljit/sljitNativeTILEGX_64.c | 3 + src/sljit/sljitNativeX86_common.c | 3 + src/sljit/sljitProtExecAllocator.c | 113 ++++++++++++++++++++++++++++ 13 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 src/sljit/sljitProtExecAllocator.c diff --git a/src/sljit/sljitConfig.h b/src/sljit/sljitConfig.h index a548c37..eb9c608 100644 --- a/src/sljit/sljitConfig.h +++ b/src/sljit/sljitConfig.h @@ -90,10 +90,20 @@ /* Executable code allocation: If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should - define both SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. */ + define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_ENABLE_EXEC. */ #ifndef SLJIT_EXECUTABLE_ALLOCATOR /* Enabled by default. */ #define SLJIT_EXECUTABLE_ALLOCATOR 1 + +/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses + an allocator which does not set writable and executable + permission flags at the same time. The trade-of is increased + memory consumption and disabled dynamic code modifications. */ +#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR +/* Disabled by default. */ +#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0 +#endif + #endif /* Force cdecl calling convention even if a better calling diff --git a/src/sljit/sljitConfigInternal.h b/src/sljit/sljitConfigInternal.h index 566c368..4dc452f 100644 --- a/src/sljit/sljitConfigInternal.h +++ b/src/sljit/sljitConfigInternal.h @@ -545,6 +545,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr); SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size) #define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr) + +#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) +SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to); +#define SLJIT_ENABLE_EXEC(from, to) sljit_enable_exec((from), (to)) +#else +#define SLJIT_ENABLE_EXEC(from, to) +#endif + #endif /**********************************************/ diff --git a/src/sljit/sljitLir.c b/src/sljit/sljitLir.c index ec1781e..a6ecc01 100644 --- a/src/sljit/sljitLir.c +++ b/src/sljit/sljitLir.c @@ -242,9 +242,15 @@ #if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) + +#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) +#include "sljitProtExecAllocator.c" +#else #include "sljitExecAllocator.c" #endif +#endif + /* Argument checking features. */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -283,6 +289,13 @@ } \ } while (0) +#define CHECK_DYN_CODE_MOD(extra_check) \ + if ((extra_check) && !sljit_is_dyn_code_modification_enabled()) \ + { \ + compiler->error = SLJIT_ERR_DYN_CODE_MOD; \ + return NULL; \ + } + #elif (defined SLJIT_DEBUG && SLJIT_DEBUG) /* Assertion failure occures if an invalid argument is passed. */ @@ -295,6 +308,7 @@ #define CHECK(x) x #define CHECK_PTR(x) x #define CHECK_REG_INDEX(x) x +#define CHECK_DYN_CODE_MOD(extra_check) SLJIT_ASSERT(!(extra_check) || sljit_is_dyn_code_modification_enabled()) #elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -304,6 +318,7 @@ #define CHECK(x) x #define CHECK_PTR(x) x #define CHECK_REG_INDEX(x) x +#define CHECK_DYN_CODE_MOD(extra_check) #else @@ -311,6 +326,7 @@ #define CHECK(x) #define CHECK_PTR(x) #define CHECK_REG_INDEX(x) +#define CHECK_DYN_CODE_MOD(extra_check) #endif /* SLJIT_ARGUMENT_CHECKS */ @@ -441,6 +457,15 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compi compiler->error = SLJIT_ERR_ALLOC_FAILED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_dyn_code_modification_enabled(void) +{ +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \ + && (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) + return 0; +#endif + return 1; +} + #if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) { @@ -1601,6 +1626,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler sljit_sw tmp_srcw; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w)); condition = type & 0xff; @@ -1681,6 +1707,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile sljit_s32 flags, condition; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w)); condition = type & 0xff; diff --git a/src/sljit/sljitLir.h b/src/sljit/sljitLir.h index df69b86..facddb6 100644 --- a/src/sljit/sljitLir.h +++ b/src/sljit/sljitLir.h @@ -99,6 +99,8 @@ of sljitConfigInternal.h */ #define SLJIT_ERR_UNSUPPORTED 4 /* An ivalid argument is passed to any SLJIT function. */ #define SLJIT_ERR_BAD_ARGUMENT 5 +/* Dynamic code modification is not enabled. */ +#define SLJIT_ERR_DYN_CODE_MOD 6 /* --------------------------------------------------------------------- */ /* Registers */ @@ -455,7 +457,19 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compile SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose); #endif +/* Returns with non-zero if dynamic code modification is enabled. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_dyn_code_modification_enabled(void); + +/* + Create executable code from the sljit instruction stream. This is the final step + of the code generation so no more instructions can be added after this call. +*/ + SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler); + +/* Free executable code. */ + SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code); /* diff --git a/src/sljit/sljitNativeARM_32.c b/src/sljit/sljitNativeARM_32.c index b92808f..a756f82 100644 --- a/src/sljit/sljitNativeARM_32.c +++ b/src/sljit/sljitNativeARM_32.c @@ -793,6 +793,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = (code_ptr - code) * sizeof(sljit_uw); + SLJIT_ENABLE_EXEC(code, code_ptr); SLJIT_CACHE_FLUSH(code, code_ptr); return code; } @@ -2402,6 +2403,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile struct sljit_jump *jump; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -2534,6 +2536,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi sljit_s32 reg; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(1); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); diff --git a/src/sljit/sljitNativeARM_64.c b/src/sljit/sljitNativeARM_64.c index d995851..75777a8 100644 --- a/src/sljit/sljitNativeARM_64.c +++ b/src/sljit/sljitNativeARM_64.c @@ -309,6 +309,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); + SLJIT_ENABLE_EXEC(code, code_ptr); SLJIT_CACHE_FLUSH(code, code_ptr); return code; } @@ -1882,6 +1883,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile struct sljit_jump *jump; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -2020,6 +2022,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi sljit_s32 dst_r; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(1); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); diff --git a/src/sljit/sljitNativeARM_T2_32.c b/src/sljit/sljitNativeARM_T2_32.c index 1ed44a8..2952a3e 100644 --- a/src/sljit/sljitNativeARM_T2_32.c +++ b/src/sljit/sljitNativeARM_T2_32.c @@ -415,6 +415,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16); + SLJIT_ENABLE_EXEC(code, code_ptr); SLJIT_CACHE_FLUSH(code, code_ptr); /* Set thumb mode flag. */ return (void*)((sljit_uw)code | 0x1); @@ -1917,6 +1918,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile sljit_ins cc; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -2060,6 +2062,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi sljit_s32 dst_r; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(1); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); diff --git a/src/sljit/sljitNativeMIPS_common.c b/src/sljit/sljitNativeMIPS_common.c index c2c251b..3d58bb5 100644 --- a/src/sljit/sljitNativeMIPS_common.c +++ b/src/sljit/sljitNativeMIPS_common.c @@ -477,6 +477,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); + SLJIT_ENABLE_EXEC(code, code_ptr); #ifndef __GNUC__ SLJIT_CACHE_FLUSH(code, code_ptr); #else @@ -1625,6 +1626,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile sljit_s32 delay_check = UNMOVABLE_INS; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -1742,6 +1744,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler sljit_ins inst; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); @@ -1863,6 +1866,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile sljit_s32 if_true; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w)); compiler->cache_arg = 0; @@ -2121,6 +2125,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi sljit_s32 reg; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(1); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); diff --git a/src/sljit/sljitNativePPC_common.c b/src/sljit/sljitNativePPC_common.c index a364732..8621f52 100644 --- a/src/sljit/sljitNativePPC_common.c +++ b/src/sljit/sljitNativePPC_common.c @@ -493,6 +493,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); + SLJIT_ENABLE_EXEC(code, code_ptr); SLJIT_CACHE_FLUSH(code, code_ptr); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) @@ -2138,6 +2139,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile sljit_ins bo_bi_flags; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_jump(compiler, type)); bo_bi_flags = get_bo_bi_flags(type & 0xff); @@ -2362,6 +2364,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi sljit_s32 reg; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(1); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); diff --git a/src/sljit/sljitNativeSPARC_common.c b/src/sljit/sljitNativeSPARC_common.c index f3a33a1..ba77c70 100644 --- a/src/sljit/sljitNativeSPARC_common.c +++ b/src/sljit/sljitNativeSPARC_common.c @@ -379,6 +379,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); + SLJIT_ENABLE_EXEC(code, code_ptr); SLJIT_CACHE_FLUSH(code, code_ptr); return code; } @@ -1295,6 +1296,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile struct sljit_jump *jump; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -1422,6 +1424,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi struct sljit_const *const_; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(1); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); diff --git a/src/sljit/sljitNativeTILEGX_64.c b/src/sljit/sljitNativeTILEGX_64.c index 462a8b9..d92b858 100644 --- a/src/sljit/sljitNativeTILEGX_64.c +++ b/src/sljit/sljitNativeTILEGX_64.c @@ -1113,6 +1113,7 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); + SLJIT_ENABLE_EXEC(code, code_ptr); SLJIT_CACHE_FLUSH(code, code_ptr); return code; } @@ -2412,6 +2413,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil flush_buffer(compiler); CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -2510,6 +2512,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp flush_buffer(compiler); CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(1); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); diff --git a/src/sljit/sljitNativeX86_common.c b/src/sljit/sljitNativeX86_common.c index aa5ba08..960bdc2 100644 --- a/src/sljit/sljitNativeX86_common.c +++ b/src/sljit/sljitNativeX86_common.c @@ -581,6 +581,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_ASSERT(code_ptr <= code + compiler->size); compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = code_ptr - code; + SLJIT_ENABLE_EXEC(code, code_ptr); return (void*)code; } @@ -2580,6 +2581,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile struct sljit_jump *jump; CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP); CHECK_PTR(check_sljit_emit_jump(compiler, type)); if (SLJIT_UNLIKELY(compiler->flags_saved)) { @@ -2908,6 +2910,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi #endif CHECK_ERROR_PTR(); + CHECK_DYN_CODE_MOD(1); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); diff --git a/src/sljit/sljitProtExecAllocator.c b/src/sljit/sljitProtExecAllocator.c new file mode 100644 index 0000000..90088e2 --- /dev/null +++ b/src/sljit/sljitProtExecAllocator.c @@ -0,0 +1,113 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + This file contains a simple executable memory allocator where the + allocated regions are not writable and executable in the same time. + + This allocator usually uses more memory than sljitExecAllocator. +*/ + +#ifdef _WIN32 + +static SLJIT_INLINE void* alloc_chunk(sljit_uw size) +{ + return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); +} + +static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size) +{ + SLJIT_UNUSED_ARG(size); + VirtualFree(chunk, 0, MEM_RELEASE); +} + +static SLJIT_INLINE void enable_exec_permission(void* chunk, sljit_uw size) +{ + sljit_uw *uw_ptr = (sljit_uw *)ptr; + + VirtualProtect(chunk, size, PAGE_EXECUTE_READ, NULL); +} + +#else + +static SLJIT_INLINE void* alloc_chunk(sljit_uw size) +{ + void* retval; + +#ifdef MAP_ANON + retval = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); +#else + if (dev_zero < 0) { + if (open_dev_zero()) + return NULL; + } + retval = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0); +#endif + + return (retval != MAP_FAILED) ? retval : NULL; +} + +static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size) +{ + munmap(chunk, size); +} + +static SLJIT_INLINE void enable_exec_permission(void* chunk, sljit_uw size) +{ + sljit_uw *uw_ptr = (sljit_uw *)chunk; + + mprotect(uw_ptr - 1, size + sizeof(sljit_uw), PROT_READ | PROT_EXEC); +} + +#endif + +/* --------------------------------------------------------------------- */ +/* Common functions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) +{ + sljit_uw *ptr = (sljit_uw *)alloc_chunk(size + sizeof (sljit_uw)); + + *ptr = size; + return (void*)(ptr + 1); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) +{ + sljit_uw *uw_ptr = (sljit_uw *)ptr; + + free_chunk(uw_ptr - 1, uw_ptr[-1]); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to) +{ + enable_exec_permission(from, ((sljit_u8 *)to) - ((sljit_u8 *)from)); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) +{ +}