mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 06:55:07 +00:00
Add control for the native stack check with hardware trap (#1682)
Add a new options to control the native stack hw bound check feature: - Besides the original option `cmake -DWAMR_DISABLE_HW_BOUND_CHECK=1/0`, add a new option `cmake -DWAMR_DISABLE_STACK_HW_BOUND_CHECK=1/0` - When the linear memory hw bound check is disabled, the stack hw bound check will be disabled automatically, no matter what the input option is - When the linear memory hw bound check is enabled, the stack hw bound check is enabled/disabled according to the value of input option - Besides the original option `--bounds-checks=1/0`, add a new option `--stack-bounds-checks=1/0` for wamrc Refer to: https://github.com/bytecodealliance/wasm-micro-runtime/issues/1677
This commit is contained in:
parent
810007857b
commit
7fd37190e8
|
@ -92,6 +92,7 @@ else:
|
|||
|
||||
if GetDepend(['WAMR_DISABLE_HW_BOUND_CHECK']):
|
||||
CPPDEFINES += ['WASM_DISABLE_HW_BOUND_CHECK=1']
|
||||
CPPDEFINES += ['WASM_DISABLE_STACK_HW_BOUND_CHECK=1']
|
||||
print("[WAMR] Hardware boundary check disabled")
|
||||
|
||||
if GetDepend(['WAMR_BUILD_SIMD']):
|
||||
|
|
|
@ -205,9 +205,16 @@ else ()
|
|||
endif ()
|
||||
if (WAMR_DISABLE_HW_BOUND_CHECK EQUAL 1)
|
||||
add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=1)
|
||||
add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=1)
|
||||
message (" Hardware boundary check disabled")
|
||||
else ()
|
||||
add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=0)
|
||||
if (WAMR_DISABLE_STACK_HW_BOUND_CHECK EQUAL 1)
|
||||
add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=1)
|
||||
message (" Hardware boundary check for native stack disabled")
|
||||
else ()
|
||||
add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0)
|
||||
endif ()
|
||||
endif ()
|
||||
if (WAMR_BUILD_SIMD EQUAL 1)
|
||||
if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
|
||||
|
|
|
@ -260,6 +260,12 @@
|
|||
#define WASM_DISABLE_HW_BOUND_CHECK 0
|
||||
#endif
|
||||
|
||||
/* Disable native stack access boundary check with hardware
|
||||
* trap or not, enable it by default if it is supported */
|
||||
#ifndef WASM_DISABLE_STACK_HW_BOUND_CHECK
|
||||
#define WASM_DISABLE_STACK_HW_BOUND_CHECK 0
|
||||
#endif
|
||||
|
||||
/* Disable SIMD unless it is manualy enabled somewhere */
|
||||
#ifndef WASM_ENABLE_SIMD
|
||||
#define WASM_ENABLE_SIMD 0
|
||||
|
|
|
@ -143,9 +143,11 @@ runtime_signal_handler(void *sig_addr)
|
|||
WASMJmpBuf *jmpbuf_node;
|
||||
uint8 *mapped_mem_start_addr = NULL;
|
||||
uint8 *mapped_mem_end_addr = NULL;
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
uint8 *stack_min_addr;
|
||||
uint32 page_size;
|
||||
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
|
||||
#endif
|
||||
|
||||
/* Check whether current thread is running wasm function */
|
||||
if (exec_env_tls && exec_env_tls->handle == os_self_thread()
|
||||
|
@ -159,9 +161,11 @@ runtime_signal_handler(void *sig_addr)
|
|||
mapped_mem_end_addr = memory_inst->memory_data + 8 * (uint64)BH_GB;
|
||||
}
|
||||
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
/* Get stack info of current thread */
|
||||
page_size = os_getpagesize();
|
||||
stack_min_addr = os_thread_get_stack_boundary();
|
||||
#endif
|
||||
|
||||
if (memory_inst
|
||||
&& (mapped_mem_start_addr <= (uint8 *)sig_addr
|
||||
|
@ -171,6 +175,7 @@ runtime_signal_handler(void *sig_addr)
|
|||
wasm_set_exception(module_inst, "out of bounds memory access");
|
||||
os_longjmp(jmpbuf_node->jmpbuf, 1);
|
||||
}
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
else if (stack_min_addr - page_size <= (uint8 *)sig_addr
|
||||
&& (uint8 *)sig_addr
|
||||
< stack_min_addr + page_size * guard_page_count) {
|
||||
|
@ -179,6 +184,7 @@ runtime_signal_handler(void *sig_addr)
|
|||
wasm_set_exception(module_inst, "native stack overflow");
|
||||
os_longjmp(jmpbuf_node->jmpbuf, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -230,6 +236,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
|
|||
}
|
||||
}
|
||||
}
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
else if (ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
|
||||
/* Set stack overflow exception and let the wasm func continue
|
||||
to run, when the wasm func returns, the caller will check
|
||||
|
@ -243,6 +250,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
|
|||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
os_printf("Unhandled exception thrown: exception code: 0x%lx, "
|
||||
|
|
|
@ -797,7 +797,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
callee_cell_num =
|
||||
aot_func->param_cell_num + aot_func->local_cell_num + 1;
|
||||
|
||||
if (comp_ctx->enable_bound_check
|
||||
if (comp_ctx->enable_stack_bound_check
|
||||
&& !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
|
||||
goto fail;
|
||||
|
||||
|
@ -1411,7 +1411,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
/* Translate call non-import block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
|
||||
|
||||
if (comp_ctx->enable_bound_check
|
||||
if (comp_ctx->enable_stack_bound_check
|
||||
&& !check_stack_boundary(comp_ctx, func_ctx,
|
||||
param_cell_num + ext_cell_num
|
||||
+ 1
|
||||
|
|
|
@ -1555,8 +1555,22 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
comp_ctx->enable_bound_check = true;
|
||||
/* Always enable stack boundary check if `bounds-checks`
|
||||
is enabled */
|
||||
comp_ctx->enable_stack_bound_check = true;
|
||||
#else
|
||||
comp_ctx->enable_bound_check = false;
|
||||
/* When `bounds-checks` is disabled, we set stack boundary
|
||||
check status according to the compilation option */
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK != 0
|
||||
/* Native stack overflow check with hardware trap is disabled,
|
||||
we need to enable the check by LLVM JITed/AOTed code */
|
||||
comp_ctx->enable_stack_bound_check = true;
|
||||
#else
|
||||
/* Native stack overflow check with hardware trap is enabled,
|
||||
no need to enable the check by LLVM JITed/AOTed code */
|
||||
comp_ctx->enable_stack_bound_check = false;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
@ -1868,6 +1882,18 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
}
|
||||
}
|
||||
|
||||
if (comp_ctx->enable_bound_check) {
|
||||
/* Always enable stack boundary check if `bounds-checks`
|
||||
is enabled */
|
||||
comp_ctx->enable_stack_bound_check = true;
|
||||
}
|
||||
else {
|
||||
/* When `bounds-checks` is disabled, we set stack boundary
|
||||
check status according to the input option */
|
||||
comp_ctx->enable_stack_bound_check =
|
||||
(option->stack_bounds_checks == 1) ? true : false;
|
||||
}
|
||||
|
||||
os_printf("Create AoT compiler with:\n");
|
||||
os_printf(" target: %s\n", comp_ctx->target_arch);
|
||||
os_printf(" target cpu: %s\n", cpu);
|
||||
|
|
|
@ -310,6 +310,9 @@ typedef struct AOTCompContext {
|
|||
/* Bounday Check */
|
||||
bool enable_bound_check;
|
||||
|
||||
/* Native stack bounday Check */
|
||||
bool enable_stack_bound_check;
|
||||
|
||||
/* 128-bit SIMD */
|
||||
bool enable_simd;
|
||||
|
||||
|
@ -404,6 +407,7 @@ typedef struct AOTCompOption {
|
|||
uint32 size_level;
|
||||
uint32 output_format;
|
||||
uint32 bounds_checks;
|
||||
uint32 stack_bounds_checks;
|
||||
char **custom_sections;
|
||||
uint32 custom_sections_count;
|
||||
} AOTCompOption, *aot_comp_option_t;
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef struct AOTCompOption {
|
|||
uint32_t size_level;
|
||||
uint32_t output_format;
|
||||
uint32_t bounds_checks;
|
||||
uint32_t stack_bounds_checks;
|
||||
char **custom_sections;
|
||||
uint32_t custom_sections_count;
|
||||
} AOTCompOption, *aot_comp_option_t;
|
||||
|
|
|
@ -4115,7 +4115,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
|||
}
|
||||
argc = function->param_cell_num;
|
||||
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
|
||||
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
|
||||
wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
|
||||
"native stack overflow");
|
||||
|
|
|
@ -3911,7 +3911,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
|||
}
|
||||
argc = function->param_cell_num;
|
||||
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
|
||||
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
|
||||
wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
|
||||
"native stack overflow");
|
||||
|
|
|
@ -425,6 +425,7 @@ os_thread_get_stack_boundary()
|
|||
*/
|
||||
static os_thread_local_attribute bool thread_signal_inited = false;
|
||||
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
/* The signal alternate stack base addr */
|
||||
static os_thread_local_attribute uint8 *sigalt_stack_base_addr;
|
||||
|
||||
|
@ -488,6 +489,7 @@ destroy_stack_guard_pages()
|
|||
os_mprotect(stack_min_addr, page_size * guard_page_count,
|
||||
MMAP_PROT_READ | MMAP_PROT_WRITE);
|
||||
}
|
||||
#endif /* end of WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 */
|
||||
|
||||
static void
|
||||
mask_signals(int how)
|
||||
|
@ -553,13 +555,16 @@ int
|
|||
os_thread_signal_init(os_signal_handler handler)
|
||||
{
|
||||
struct sigaction sig_act;
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
stack_t sigalt_stack_info;
|
||||
uint32 map_size = SIG_ALT_STACK_SIZE;
|
||||
uint8 *map_addr;
|
||||
#endif
|
||||
|
||||
if (thread_signal_inited)
|
||||
return 0;
|
||||
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
if (!init_stack_guard_pages()) {
|
||||
os_printf("Failed to init stack guard pages\n");
|
||||
return -1;
|
||||
|
@ -581,13 +586,17 @@ os_thread_signal_init(os_signal_handler handler)
|
|||
os_printf("Failed to init signal alternate stack\n");
|
||||
goto fail2;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&prev_sig_act_SIGSEGV, 0, sizeof(struct sigaction));
|
||||
memset(&prev_sig_act_SIGBUS, 0, sizeof(struct sigaction));
|
||||
|
||||
/* Install signal hanlder */
|
||||
sig_act.sa_sigaction = signal_callback;
|
||||
sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER;
|
||||
sig_act.sa_flags = SA_SIGINFO | SA_NODEFER;
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
sig_act.sa_flags |= SA_ONSTACK;
|
||||
#endif
|
||||
sigemptyset(&sig_act.sa_mask);
|
||||
if (sigaction(SIGSEGV, &sig_act, &prev_sig_act_SIGSEGV) != 0
|
||||
|| sigaction(SIGBUS, &sig_act, &prev_sig_act_SIGBUS) != 0) {
|
||||
|
@ -595,12 +604,15 @@ os_thread_signal_init(os_signal_handler handler)
|
|||
goto fail3;
|
||||
}
|
||||
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
sigalt_stack_base_addr = map_addr;
|
||||
#endif
|
||||
signal_handler = handler;
|
||||
thread_signal_inited = true;
|
||||
return 0;
|
||||
|
||||
fail3:
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
memset(&sigalt_stack_info, 0, sizeof(stack_t));
|
||||
sigalt_stack_info.ss_flags = SS_DISABLE;
|
||||
sigalt_stack_info.ss_size = map_size;
|
||||
|
@ -609,17 +621,21 @@ fail2:
|
|||
os_munmap(map_addr, map_size);
|
||||
fail1:
|
||||
destroy_stack_guard_pages();
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
os_thread_signal_destroy()
|
||||
{
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
stack_t sigalt_stack_info;
|
||||
#endif
|
||||
|
||||
if (!thread_signal_inited)
|
||||
return;
|
||||
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
/* Disable signal alternate stack */
|
||||
memset(&sigalt_stack_info, 0, sizeof(stack_t));
|
||||
sigalt_stack_info.ss_flags = SS_DISABLE;
|
||||
|
@ -629,6 +645,7 @@ os_thread_signal_destroy()
|
|||
os_munmap(sigalt_stack_base_addr, SIG_ALT_STACK_SIZE);
|
||||
|
||||
destroy_stack_guard_pages();
|
||||
#endif
|
||||
|
||||
thread_signal_inited = false;
|
||||
}
|
||||
|
@ -648,6 +665,7 @@ os_signal_unmask()
|
|||
void
|
||||
os_sigreturn()
|
||||
{
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
#if defined(__APPLE__)
|
||||
#define UC_RESET_ALT_STACK 0x80000000
|
||||
extern int __sigreturn(void *, int);
|
||||
|
@ -656,5 +674,6 @@ os_sigreturn()
|
|||
after exiting the signal handler. */
|
||||
__sigreturn(NULL, UC_RESET_ALT_STACK);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
|
||||
|
|
|
@ -706,13 +706,19 @@ static os_thread_local_attribute bool thread_signal_inited = false;
|
|||
int
|
||||
os_thread_signal_init()
|
||||
{
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
ULONG StackSizeInBytes = 16 * 1024;
|
||||
#endif
|
||||
bool ret;
|
||||
|
||||
if (thread_signal_inited)
|
||||
return 0;
|
||||
|
||||
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
|
||||
ret = SetThreadStackGuarantee(&StackSizeInBytes);
|
||||
#else
|
||||
ret = true;
|
||||
#endif
|
||||
if (ret)
|
||||
thread_signal_inited = true;
|
||||
return ret ? 0 : -1;
|
||||
|
|
|
@ -80,9 +80,13 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
|
|||
- **WAMR_BUILD_LIB_PTHREAD_SEMAPHORE**=1/0, default to disable if not set
|
||||
> Note: This feature depends on `lib-pthread`, it will be enabled automatically if this feature is enabled.
|
||||
|
||||
#### **Disable boundary check with hardware trap in AOT or JIT mode**
|
||||
#### **Disable boundary check with hardware trap**
|
||||
- **WAMR_DISABLE_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform
|
||||
> Note: by default only platform linux/darwin/android/vxworks 64-bit will enable boundary check with hardware trap in AOT or JIT mode, and the wamrc tool will generate AOT code without boundary check instructions in all 64-bit targets except SGX to improve performance.
|
||||
> Note: by default only platform linux/darwin/android/windows/vxworks 64-bit will enable the boundary check with hardware trap feature, and the wamrc tool will generate AOT code without boundary check instructions in all 64-bit targets except SGX to improve performance. The boundary check includes linear memory access boundary and native stack access boundary, if `WAMR_DISABLE_STACK_HW_BOUND_CHECK` below isn't set.
|
||||
|
||||
#### **Disable native stack boundary check with hardware trap**
|
||||
- **WAMR_DISABLE_STACK_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform, same as `WAMR_DISABLE_HW_BOUND_CHECK`.
|
||||
> Note: When boundary check with hardware trap is disabled, or `WAMR_DISABLE_HW_BOUND_CHECK` is set to 1, the native stack boundary check with hardware trap will be disabled too, no matter what value is set to `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. And when boundary check with hardware trap is enabled, the status of this feature is set according to the value of `WAMR_DISABLE_STACK_HW_BOUND_CHECK`.
|
||||
|
||||
#### **Enable tail call feature**
|
||||
- **WAMR_BUILD_TAIL_CALL**=1/0, default to disable if not set
|
||||
|
|
|
@ -268,8 +268,10 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_DISABLE_HW_BOUND_CHECK),y)
|
||||
CFLAGS += -DWASM_DISABLE_HW_BOUND_CHECK=1
|
||||
CFLAGS += -DWASM_DISABLE_STACK_HW_BOUND_CHECK=1
|
||||
else
|
||||
CFLAGS += -DWASM_DISABLE_HW_BOUND_CHECK=0
|
||||
CFLAGS += -DWASM_DISABLE_STACK_HW_BOUND_CHECK=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_CUSTOM_NAME_SECTIONS),y)
|
||||
|
|
|
@ -37,6 +37,11 @@ print_help()
|
|||
printf(" by default it is disabled in all 64-bit platforms except SGX and\n");
|
||||
printf(" in these platforms runtime does bounds checks with hardware trap,\n");
|
||||
printf(" and by default it is enabled in all 32-bit platforms\n");
|
||||
printf(" --stack-bounds-checks=1/0 Enable or disable the bounds checks for native stack:\n");
|
||||
printf(" if the option isn't set, the status is same as `--bounds-check`,\n");
|
||||
printf(" if the option is set:\n");
|
||||
printf(" (1) it is always enabled when `--bounds-checks` is enabled,\n");
|
||||
printf(" (2) else it is enabled/disabled according to the option value\n");
|
||||
printf(" --format=<format> Specifies the format of the output file\n");
|
||||
printf(" The format supported:\n");
|
||||
printf(" aot (default) AoT file\n");
|
||||
|
@ -139,6 +144,8 @@ main(int argc, char *argv[])
|
|||
option.output_format = AOT_FORMAT_FILE;
|
||||
/* default value, enable or disable depends on the platform */
|
||||
option.bounds_checks = 2;
|
||||
/* default value, enable or disable depends on the platform */
|
||||
option.stack_bounds_checks = 2;
|
||||
option.enable_simd = true;
|
||||
option.enable_aux_stack_check = true;
|
||||
option.enable_bulk_memory = true;
|
||||
|
@ -193,6 +200,9 @@ main(int argc, char *argv[])
|
|||
else if (!strncmp(argv[0], "--bounds-checks=", 16)) {
|
||||
option.bounds_checks = (atoi(argv[0] + 16) == 1) ? 1 : 0;
|
||||
}
|
||||
else if (!strncmp(argv[0], "--stack-bounds-checks=", 22)) {
|
||||
option.stack_bounds_checks = (atoi(argv[0] + 22) == 1) ? 1 : 0;
|
||||
}
|
||||
else if (!strncmp(argv[0], "--format=", 9)) {
|
||||
if (argv[0][9] == '\0')
|
||||
PRINT_HELP_AND_EXIT();
|
||||
|
|
Loading…
Reference in New Issue
Block a user