diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 2f675235e2..06a921001d 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -47,12 +47,12 @@ concurrency: env: # For BUILD - AOT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 _DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" - CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 _DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" - FAST_INTERP_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 _DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" - FAST_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 _DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" - LLVM_LAZY_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 _DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" - LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 _DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0" + AOT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" + CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" + FAST_INTERP_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" + FAST_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" + LLVM_LAZY_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" + LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0" # LLVM LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex" # For Spec Test @@ -183,6 +183,9 @@ jobs: make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + # Fast-JIT mode doesn't support android(X86-32) + - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS + platform: android steps: - name: checkout uses: actions/checkout@v3 diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 1f340fc7ef..f10b5b4eb7 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -311,3 +311,6 @@ endif () if (WAMR_BUILD_WASI_NN EQUAL 1) message (" WASI-NN enabled") endif () +if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1) + add_definitions(-DWASM_MEM_ALLOC_WITH_USER_DATA=1) +endif() diff --git a/core/config.h b/core/config.h index 0ba617ce55..288160d020 100644 --- a/core/config.h +++ b/core/config.h @@ -426,4 +426,8 @@ #define WASM_ENABLE_SGX_IPFS 0 #endif +#ifndef WASM_MEM_ALLOC_WITH_USER_DATA +#define WASM_MEM_ALLOC_WITH_USER_DATA 0 +#endif + #endif /* end of _CONFIG_H_ */ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 1c3f033c61..1077c3af82 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1500,7 +1500,11 @@ aot_set_exception(AOTModuleInstance *module_inst, const char *exception) void aot_set_exception_with_id(AOTModuleInstance *module_inst, uint32 id) { - wasm_set_exception_with_id(module_inst, id); + if (id != EXCE_ALREADY_THROWN) + wasm_set_exception_with_id(module_inst, id); +#ifdef OS_ENABLE_HW_BOUND_CHECK + wasm_runtime_access_exce_check_guard_page(); +#endif } const char * @@ -1755,6 +1759,7 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, const char *signature; void *attachment; char buf[96]; + bool ret = false; bh_assert(func_idx < aot_module->import_func_count); @@ -1764,27 +1769,34 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, "failed to call unlinked import function (%s, %s)", import_func->module_name, import_func->func_name); aot_set_exception(module_inst, buf); - return false; + goto fail; } attachment = import_func->attachment; if (import_func->call_conv_wasm_c_api) { - return wasm_runtime_invoke_c_api_native( + ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc, argv, import_func->wasm_c_api_with_env, attachment); } else if (!import_func->call_conv_raw) { signature = import_func->signature; - return wasm_runtime_invoke_native(exec_env, func_ptr, func_type, - signature, attachment, argv, argc, - argv); + ret = + wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, + attachment, argv, argc, argv); } else { signature = import_func->signature; - return wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, - signature, attachment, argv, argc, - argv); + ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, + signature, attachment, argv, argc, + argv); } + +fail: +#ifdef OS_ENABLE_HW_BOUND_CHECK + if (!ret) + wasm_runtime_access_exce_check_guard_page(); +#endif + return ret; } bool @@ -1811,7 +1823,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, if ((uint8 *)&module_inst < exec_env->native_stack_boundary) { aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); - return false; + goto fail; } tbl_inst = module_inst->tables[tbl_idx]; @@ -1819,13 +1831,13 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, if (table_elem_idx >= tbl_inst->cur_size) { aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT); - return false; + goto fail; } func_idx = tbl_inst->elems[table_elem_idx]; if (func_idx == NULL_REF) { aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT); - return false; + goto fail; } func_type_idx = func_type_indexes[func_idx]; @@ -1843,7 +1855,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, "failed to call unlinked import function (%s, %s)", import_func->module_name, import_func->func_name); aot_set_exception(module_inst, buf); - return false; + goto fail; } if (func_idx < aot_module->import_func_count) { @@ -1852,9 +1864,13 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, signature = import_func->signature; if (import_func->call_conv_raw) { attachment = import_func->attachment; - return wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, - signature, attachment, argv, - argc, argv); + ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, + signature, attachment, argv, + argc, argv); + if (!ret) + goto fail; + + return true; } } @@ -1878,7 +1894,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, && !(argv1 = runtime_malloc(size, module_inst->cur_exception, sizeof(module_inst->cur_exception)))) { aot_set_exception_with_id(module_inst, EXCE_OUT_OF_MEMORY); - return false; + goto fail; } /* Copy original arguments */ @@ -1897,12 +1913,10 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, ret = invoke_native_internal(exec_env, func_ptr, func_type, signature, attachment, argv1, argc, argv); - if (!ret || aot_get_exception(module_inst)) { + if (!ret) { if (argv1 != argv1_buf) wasm_runtime_free(argv1); - if (clear_wasi_proc_exit_exception(module_inst)) - return true; - return false; + goto fail; } /* Get extra result values */ @@ -1941,10 +1955,20 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, else { ret = invoke_native_internal(exec_env, func_ptr, func_type, signature, attachment, argv, argc, argv); - if (clear_wasi_proc_exit_exception(module_inst)) - return true; - return ret; + if (!ret) + goto fail; + + return true; } + +fail: + if (clear_wasi_proc_exit_exception(module_inst)) + return true; + +#ifdef OS_ENABLE_HW_BOUND_CHECK + wasm_runtime_access_exce_check_guard_page(); +#endif + return false; } bool @@ -1952,8 +1976,17 @@ aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str, uint32 app_buf_addr, uint32 app_buf_size, void **p_native_addr) { - return wasm_check_app_addr_and_convert(module_inst, is_str, app_buf_addr, - app_buf_size, p_native_addr); + bool ret; + + ret = wasm_check_app_addr_and_convert(module_inst, is_str, app_buf_addr, + app_buf_size, p_native_addr); + +#ifdef OS_ENABLE_HW_BOUND_CHECK + if (!ret) + wasm_runtime_access_exce_check_guard_page(); +#endif + + return ret; } void * diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 7a24b17a41..212a778019 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -340,6 +340,10 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts) opts->allocator.free_func; init_args.mem_alloc_option.allocator.realloc_func = opts->allocator.realloc_func; +#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 + init_args.mem_alloc_option.allocator.user_data = + opts->allocator.user_data; +#endif } else { init_args.mem_alloc_option.pool.heap_buf = NULL; diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index cd8b570893..515a60b8e9 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -56,6 +56,12 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, #endif #endif +#ifdef OS_ENABLE_HW_BOUND_CHECK + if (!(exec_env->exce_check_guard_page = + os_mmap(NULL, os_getpagesize(), MMAP_PROT_NONE, MMAP_MAP_NONE))) + goto fail5; +#endif + exec_env->module_inst = module_inst; exec_env->wasm_stack_size = stack_size; exec_env->wasm_stack.s.top_boundary = @@ -76,6 +82,12 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, return exec_env; +#ifdef OS_ENABLE_HW_BOUND_CHECK +fail5: +#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 + wasm_cluster_destroy_exenv_status(exec_env->current_status); +#endif +#endif #if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_DEBUG_INTERP != 0 fail4: @@ -96,6 +108,9 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, void wasm_exec_env_destroy_internal(WASMExecEnv *exec_env) { +#ifdef OS_ENABLE_HW_BOUND_CHECK + os_munmap(exec_env->exce_check_guard_page, os_getpagesize()); +#endif #if WASM_ENABLE_THREAD_MGR != 0 os_mutex_destroy(&exec_env->wait_lock); os_cond_destroy(&exec_env->wait_cond); diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index d4d7ce00a1..398292079a 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -137,6 +137,8 @@ typedef struct WASMExecEnv { #ifdef OS_ENABLE_HW_BOUND_CHECK WASMJmpBuf *jmpbuf_stack_top; + /* One guard page for the exception check */ + uint8 *exce_check_guard_page; #endif #if WASM_ENABLE_MEMORY_PROFILING != 0 @@ -199,7 +201,8 @@ wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size) the outs area contains const cells, its size may be larger than current frame size, we should check again before putting the function arguments into the outs area. */ - if (addr + size * 2 > exec_env->wasm_stack.s.top_boundary) { + if (size * 2 + > (uint32)(uintptr_t)(exec_env->wasm_stack.s.top_boundary - addr)) { /* WASM stack overflow. */ return NULL; } diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index ffe21857da..0aa2d6415c 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -11,16 +11,25 @@ typedef enum Memory_Mode { MEMORY_MODE_UNKNOWN = 0, MEMORY_MODE_POOL, - MEMORY_MODE_ALLOCATOR + MEMORY_MODE_ALLOCATOR, + MEMORY_MODE_SYSTEM_ALLOCATOR } Memory_Mode; static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN; static mem_allocator_t pool_allocator = NULL; +#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 +static void *allocator_user_data = NULL; +static void *(*malloc_func)(void *user_data, unsigned int size) = NULL; +static void *(*realloc_func)(void *user_data, void *ptr, + unsigned int size) = NULL; +static void (*free_func)(void *user_data, void *ptr) = NULL; +#else static void *(*malloc_func)(unsigned int size) = NULL; static void *(*realloc_func)(void *ptr, unsigned int size) = NULL; static void (*free_func)(void *ptr) = NULL; +#endif static unsigned int global_pool_size; @@ -39,6 +48,24 @@ wasm_memory_init_with_pool(void *mem, unsigned int bytes) return false; } +#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 +static bool +wasm_memory_init_with_allocator(void *_user_data, void *_malloc_func, + void *_realloc_func, void *_free_func) +{ + if (_malloc_func && _free_func && _malloc_func != _free_func) { + memory_mode = MEMORY_MODE_ALLOCATOR; + allocator_user_data = _user_data; + malloc_func = _malloc_func; + realloc_func = _realloc_func; + free_func = _free_func; + return true; + } + LOG_ERROR("Init memory with allocator (%p, %p, %p, %p) failed.\n", + _user_data, _malloc_func, _realloc_func, _free_func); + return false; +} +#else static bool wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func, void *_free_func) @@ -54,23 +81,37 @@ wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func, _realloc_func, _free_func); return false; } +#endif bool wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type, const MemAllocOption *alloc_option) { - if (mem_alloc_type == Alloc_With_Pool) + if (mem_alloc_type == Alloc_With_Pool) { return wasm_memory_init_with_pool(alloc_option->pool.heap_buf, alloc_option->pool.heap_size); - else if (mem_alloc_type == Alloc_With_Allocator) + } + else if (mem_alloc_type == Alloc_With_Allocator) { +#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 return wasm_memory_init_with_allocator( + alloc_option->allocator.user_data, alloc_option->allocator.malloc_func, alloc_option->allocator.realloc_func, alloc_option->allocator.free_func); - else if (mem_alloc_type == Alloc_With_System_Allocator) - return wasm_memory_init_with_allocator(os_malloc, os_realloc, os_free); - else +#else + return wasm_memory_init_with_allocator( + alloc_option->allocator.malloc_func, + alloc_option->allocator.realloc_func, + alloc_option->allocator.free_func); +#endif + } + else if (mem_alloc_type == Alloc_With_System_Allocator) { + memory_mode = MEMORY_MODE_SYSTEM_ALLOCATOR; + return true; + } + else { return false; + } } void @@ -110,8 +151,15 @@ wasm_runtime_malloc_internal(unsigned int size) else if (memory_mode == MEMORY_MODE_POOL) { return mem_allocator_malloc(pool_allocator, size); } - else { + else if (memory_mode == MEMORY_MODE_ALLOCATOR) { +#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 + return malloc_func(allocator_user_data, size); +#else return malloc_func(size); +#endif + } + else { + return os_malloc(size); } } @@ -126,12 +174,19 @@ wasm_runtime_realloc_internal(void *ptr, unsigned int size) else if (memory_mode == MEMORY_MODE_POOL) { return mem_allocator_realloc(pool_allocator, ptr, size); } - else { + else if (memory_mode == MEMORY_MODE_ALLOCATOR) { if (realloc_func) +#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 + return realloc_func(allocator_user_data, ptr, size); +#else return realloc_func(ptr, size); +#endif else return NULL; } + else { + return os_realloc(ptr, size); + } } static inline void @@ -152,8 +207,15 @@ wasm_runtime_free_internal(void *ptr) else if (memory_mode == MEMORY_MODE_POOL) { mem_allocator_free(pool_allocator, ptr); } - else { + else if (memory_mode == MEMORY_MODE_ALLOCATOR) { +#if WASM_MEM_ALLOC_WITH_USER_DATA != 0 + free_func(allocator_user_data, ptr); +#else free_func(ptr); +#endif + } + else { + os_free(ptr); } } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index fbcdfcd009..17cf9da31b 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -185,6 +185,12 @@ runtime_signal_handler(void *sig_addr) os_longjmp(jmpbuf_node->jmpbuf, 1); } #endif + else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr + && (uint8 *)sig_addr + < exec_env_tls->exce_check_guard_page + page_size) { + bh_assert(wasm_get_exception(module_inst)); + os_longjmp(jmpbuf_node->jmpbuf, 1); + } } } #else @@ -1435,6 +1441,17 @@ wasm_runtime_get_user_data(WASMExecEnv *exec_env) return exec_env->user_data; } +#ifdef OS_ENABLE_HW_BOUND_CHECK +void +wasm_runtime_access_exce_check_guard_page() +{ + if (exec_env_tls && exec_env_tls->handle == os_self_thread()) { + uint32 page_size = os_getpagesize(); + memset(exec_env_tls->exce_check_guard_page, 0, page_size); + } +} +#endif + WASMType * wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function, uint32 module_type) diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index cc311ba730..3e7f3725d2 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -554,6 +554,12 @@ wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data); WASM_RUNTIME_API_EXTERN void * wasm_runtime_get_user_data(WASMExecEnv *exec_env); +#ifdef OS_ENABLE_HW_BOUND_CHECK +/* Access exception check guard page to trigger the signal handler */ +void +wasm_runtime_access_exce_check_guard_page(); +#endif + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_call_wasm(WASMExecEnv *exec_env, diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index 862bbe964c..b2b63de5c5 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -386,7 +386,8 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, os_mutex_lock(&wait_node->wait_lock); os_cond_reltimedwait(&wait_node->wait_cond, &wait_node->wait_lock, - timeout < 0 ? BHT_WAIT_FOREVER : timeout / 1000); + timeout < 0 ? BHT_WAIT_FOREVER + : (uint64)timeout / 1000); os_mutex_unlock(&wait_node->wait_lock); diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index cbcdebffc1..fb2fca5656 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -35,7 +35,14 @@ create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) /* Create return IR */ LLVMPositionBuilderAtEnd(comp_ctx->builder, func_ctx->func_return_block); - if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) { + if (!comp_ctx->enable_bound_check) { + if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ALREADY_THROWN, + false, NULL, NULL)) { + return false; + } + } + else if (!aot_build_zero_function_ret(comp_ctx, func_ctx, + aot_func_type)) { return false; } } @@ -494,7 +501,8 @@ check_app_addr_and_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Check whether exception was thrown when executing the function */ - if (!check_call_return(comp_ctx, func_ctx, res)) { + if (comp_ctx->enable_bound_check + && !check_call_return(comp_ctx, func_ctx, res)) { return false; } @@ -707,7 +715,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; /* Check whether there was exception thrown when executing the function */ - if (!check_call_return(comp_ctx, func_ctx, res)) + if (comp_ctx->enable_bound_check + && !check_call_return(comp_ctx, func_ctx, res)) goto fail; } else { /* call native func directly */ @@ -823,7 +832,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Check whether there was exception thrown when executing the function */ - if (!tail_call && !recursive_call + if (!tail_call && !recursive_call && comp_ctx->enable_bound_check && !check_exception_thrown(comp_ctx, func_ctx)) goto fail; } @@ -1395,7 +1404,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; /* Check whether exception was thrown when executing the function */ - if (!check_call_return(comp_ctx, func_ctx, res)) + if (comp_ctx->enable_bound_check + && !check_call_return(comp_ctx, func_ctx, res)) goto fail; block_curr = LLVMGetInsertBlock(comp_ctx->builder); @@ -1454,7 +1464,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Check whether exception was thrown when executing the function */ - if (!check_exception_thrown(comp_ctx, func_ctx)) + if (comp_ctx->enable_bound_check + && !check_exception_thrown(comp_ctx, func_ctx)) goto fail; if (func_result_count > 0) { diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index 52e219b2d2..9b77f5e6a1 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -344,11 +344,12 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) if (!disable_llvm_lto) { /* Apply LTO for AOT mode */ -#if LLVM_VERSION_MAJOR < 14 - MPM.addPass(PB.buildLTODefaultPipeline(OL, NULL)); -#else - MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(OL)); -#endif + if (comp_ctx->comp_data->func_count >= 10) + /* Adds the pre-link optimizations if the func count + is large enough */ + MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(OL)); + else + MPM.addPass(PB.buildLTODefaultPipeline(OL, NULL)); } else { MPM.addPass(PB.buildPerModuleDefaultPipeline(OL)); diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index 50cc3717f6..995bfb80a1 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -1286,11 +1286,8 @@ jit_compile_func(JitCompContext *cc) #if WASM_ENABLE_TAIL_CALL != 0 case WASM_OP_RETURN_CALL: - if (!cc->enable_tail_call) { - jit_set_last_error(cc, "unsupported opcode"); - return false; - } read_leb_uint32(frame_ip, frame_ip_end, func_idx); + if (!jit_compile_op_call(cc, func_idx, true)) return false; if (!jit_compile_op_return(cc, &frame_ip)) @@ -1301,11 +1298,6 @@ jit_compile_func(JitCompContext *cc) { uint32 tbl_idx; - if (!cc->enable_tail_call) { - jit_set_last_error(cc, "unsupported opcode"); - return false; - } - read_leb_uint32(frame_ip, frame_ip_end, type_idx); #if WASM_ENABLE_REF_TYPES != 0 read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); diff --git a/core/iwasm/include/wasm_c_api.h b/core/iwasm/include/wasm_c_api.h index 8900978957..85fcd1868a 100644 --- a/core/iwasm/include/wasm_c_api.h +++ b/core/iwasm/include/wasm_c_api.h @@ -186,6 +186,9 @@ typedef union MemAllocOption { void *malloc_func; void *realloc_func; void *free_func; + /* allocator user data, only used when + WASM_MEM_ALLOC_WITH_USER_DATA is defined */ + void *user_data; } allocator; } MemAllocOption; #endif diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index cc173af92d..2d5e85155d 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -117,6 +117,9 @@ typedef union MemAllocOption { void *malloc_func; void *realloc_func; void *free_func; + /* allocator user data, only used when + WASM_MEM_ALLOC_WITH_USER_DATA is defined */ + void *user_data; } allocator; } MemAllocOption; #endif diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index f702a0e843..8e8f96b5c3 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2781,7 +2781,11 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf, void jit_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id) { - wasm_set_exception_with_id(module_inst, id); + if (id != EXCE_ALREADY_THROWN) + wasm_set_exception_with_id(module_inst, id); +#ifdef OS_ENABLE_HW_BOUND_CHECK + wasm_runtime_access_exce_check_guard_page(); +#endif } bool @@ -2789,8 +2793,15 @@ jit_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, uint32 app_buf_addr, uint32 app_buf_size, void **p_native_addr) { - return wasm_check_app_addr_and_convert(module_inst, is_str, app_buf_addr, - app_buf_size, p_native_addr); + bool ret = wasm_check_app_addr_and_convert( + module_inst, is_str, app_buf_addr, app_buf_size, p_native_addr); + +#ifdef OS_ENABLE_HW_BOUND_CHECK + if (!ret) + wasm_runtime_access_exce_check_guard_page(); +#endif + + return ret; } #endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ || WASM_ENABLE_WAMR_COMPILER != 0 */ @@ -2811,12 +2822,20 @@ bool llvm_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, uint32 argc, uint32 *argv) { + bool ret; + #if WASM_ENABLE_JIT != 0 if (Wasm_Module_AoT == exec_env->module_inst->module_type) { return aot_call_indirect(exec_env, tbl_idx, elem_idx, argc, argv); } #endif - return call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, false, 0); + + ret = call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, false, 0); +#ifdef OS_ENABLE_HW_BOUND_CHECK + if (!ret) + wasm_runtime_access_exce_check_guard_page(); +#endif + return ret; } bool @@ -2833,6 +2852,7 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, const char *signature; void *attachment; char buf[96]; + bool ret = false; #if WASM_ENABLE_JIT != 0 if (Wasm_Module_AoT == exec_env->module_inst->module_type) { @@ -2855,27 +2875,34 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, "failed to call unlinked import function (%s, %s)", import_func->module_name, import_func->field_name); wasm_set_exception(module_inst, buf); - return false; + goto fail; } attachment = import_func->attachment; if (import_func->call_conv_wasm_c_api) { - return wasm_runtime_invoke_c_api_native( + ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc, argv, import_func->wasm_c_api_with_env, attachment); } else if (!import_func->call_conv_raw) { signature = import_func->signature; - return wasm_runtime_invoke_native(exec_env, func_ptr, func_type, - signature, attachment, argv, argc, - argv); + ret = + wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, + attachment, argv, argc, argv); } else { signature = import_func->signature; - return wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, - signature, attachment, argv, argc, - argv); + ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, + signature, attachment, argv, argc, + argv); } + +fail: +#ifdef OS_ENABLE_HW_BOUND_CHECK + if (!ret) + wasm_runtime_access_exce_check_guard_page(); +#endif + return ret; } #if WASM_ENABLE_BULK_MEMORY != 0 diff --git a/doc/source_debugging.md b/doc/source_debugging.md index a07cebc43b..c18c61267e 100644 --- a/doc/source_debugging.md +++ b/doc/source_debugging.md @@ -28,6 +28,7 @@ mkdir build && cd build cmake .. -DWAMR_BUILD_DEBUG_INTERP=1 make ``` +> Note: On MacOS M1 environment, pass the additional `-DWAMR_DISABLE_HW_BOUND_CHECK=1` cmake configuration. 3. Execute iwasm with debug engine enabled ``` bash @@ -43,6 +44,7 @@ mkdir build-lldb && cd build-lldb cmake -DCMAKE_BUILD_TYPE:STRING="Release" -DLLVM_ENABLE_PROJECTS="clang;lldb" -DLLVM_TARGETS_TO_BUILD:STRING="X86;WebAssembly" -DLLVM_ENABLE_LIBXML2:BOOL=ON ../llvm make -j $(nproc) ``` +> Note: If using `CommandLineTools` on MacOS, make sure only one SDK is present in `/Library/Developer/CommandLineTools/SDKs`. 5. Launch customized lldb and connect to iwasm ``` bash