Просмотр исходного кода

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
Wenyong Huang 3 лет назад
Родитель
Сommit
7fd37190e8

+ 1 - 0
build-scripts/SConscript_config

@@ -92,6 +92,7 @@ else:
 
 
 if GetDepend(['WAMR_DISABLE_HW_BOUND_CHECK']):
 if GetDepend(['WAMR_DISABLE_HW_BOUND_CHECK']):
     CPPDEFINES += ['WASM_DISABLE_HW_BOUND_CHECK=1']
     CPPDEFINES += ['WASM_DISABLE_HW_BOUND_CHECK=1']
+    CPPDEFINES += ['WASM_DISABLE_STACK_HW_BOUND_CHECK=1']
     print("[WAMR] Hardware boundary check disabled")
     print("[WAMR] Hardware boundary check disabled")
 
 
 if GetDepend(['WAMR_BUILD_SIMD']):
 if GetDepend(['WAMR_BUILD_SIMD']):

+ 7 - 0
build-scripts/config_common.cmake

@@ -205,9 +205,16 @@ else ()
 endif ()
 endif ()
 if (WAMR_DISABLE_HW_BOUND_CHECK EQUAL 1)
 if (WAMR_DISABLE_HW_BOUND_CHECK EQUAL 1)
   add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=1)
   add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=1)
+  add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=1)
   message ("     Hardware boundary check disabled")
   message ("     Hardware boundary check disabled")
 else ()
 else ()
   add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=0)
   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 ()
 endif ()
 if (WAMR_BUILD_SIMD EQUAL 1)
 if (WAMR_BUILD_SIMD EQUAL 1)
   if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
   if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")

+ 6 - 0
core/config.h

@@ -260,6 +260,12 @@
 #define WASM_DISABLE_HW_BOUND_CHECK 0
 #define WASM_DISABLE_HW_BOUND_CHECK 0
 #endif
 #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 */
 /* Disable SIMD unless it is manualy enabled somewhere */
 #ifndef WASM_ENABLE_SIMD
 #ifndef WASM_ENABLE_SIMD
 #define WASM_ENABLE_SIMD 0
 #define WASM_ENABLE_SIMD 0

+ 8 - 0
core/iwasm/common/wasm_runtime_common.c

@@ -143,9 +143,11 @@ runtime_signal_handler(void *sig_addr)
     WASMJmpBuf *jmpbuf_node;
     WASMJmpBuf *jmpbuf_node;
     uint8 *mapped_mem_start_addr = NULL;
     uint8 *mapped_mem_start_addr = NULL;
     uint8 *mapped_mem_end_addr = NULL;
     uint8 *mapped_mem_end_addr = NULL;
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     uint8 *stack_min_addr;
     uint8 *stack_min_addr;
     uint32 page_size;
     uint32 page_size;
     uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
     uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+#endif
 
 
     /* Check whether current thread is running wasm function */
     /* Check whether current thread is running wasm function */
     if (exec_env_tls && exec_env_tls->handle == os_self_thread()
     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;
             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 */
         /* Get stack info of current thread */
         page_size = os_getpagesize();
         page_size = os_getpagesize();
         stack_min_addr = os_thread_get_stack_boundary();
         stack_min_addr = os_thread_get_stack_boundary();
+#endif
 
 
         if (memory_inst
         if (memory_inst
             && (mapped_mem_start_addr <= (uint8 *)sig_addr
             && (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");
             wasm_set_exception(module_inst, "out of bounds memory access");
             os_longjmp(jmpbuf_node->jmpbuf, 1);
             os_longjmp(jmpbuf_node->jmpbuf, 1);
         }
         }
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
         else if (stack_min_addr - page_size <= (uint8 *)sig_addr
         else if (stack_min_addr - page_size <= (uint8 *)sig_addr
                  && (uint8 *)sig_addr
                  && (uint8 *)sig_addr
                         < stack_min_addr + page_size * guard_page_count) {
                         < 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");
             wasm_set_exception(module_inst, "native stack overflow");
             os_longjmp(jmpbuf_node->jmpbuf, 1);
             os_longjmp(jmpbuf_node->jmpbuf, 1);
         }
         }
+#endif
     }
     }
 }
 }
 #else
 #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) {
         else if (ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
             /* Set stack overflow exception and let the wasm func continue
             /* Set stack overflow exception and let the wasm func continue
                to run, when the wasm func returns, the caller will check
                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;
                 return EXCEPTION_CONTINUE_EXECUTION;
             }
             }
         }
         }
+#endif
     }
     }
 
 
     os_printf("Unhandled exception thrown:  exception code: 0x%lx, "
     os_printf("Unhandled exception thrown:  exception code: 0x%lx, "

+ 2 - 2
core/iwasm/compilation/aot_emit_function.c

@@ -797,7 +797,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         callee_cell_num =
         callee_cell_num =
             aot_func->param_cell_num + aot_func->local_cell_num + 1;
             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))
             && !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
             goto fail;
             goto fail;
 
 
@@ -1411,7 +1411,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* Translate call non-import block */
     /* Translate call non-import block */
     LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
     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,
         && !check_stack_boundary(comp_ctx, func_ctx,
                                  param_cell_num + ext_cell_num
                                  param_cell_num + ext_cell_num
                                      + 1
                                      + 1

+ 26 - 0
core/iwasm/compilation/aot_llvm.c

@@ -1555,8 +1555,22 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
 
 
 #ifndef OS_ENABLE_HW_BOUND_CHECK
 #ifndef OS_ENABLE_HW_BOUND_CHECK
         comp_ctx->enable_bound_check = true;
         comp_ctx->enable_bound_check = true;
+        /* Always enable stack boundary check if `bounds-checks`
+           is enabled */
+        comp_ctx->enable_stack_bound_check = true;
 #else
 #else
         comp_ctx->enable_bound_check = false;
         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
 #endif
     }
     }
     else {
     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("Create AoT compiler with:\n");
         os_printf("  target:        %s\n", comp_ctx->target_arch);
         os_printf("  target:        %s\n", comp_ctx->target_arch);
         os_printf("  target cpu:    %s\n", cpu);
         os_printf("  target cpu:    %s\n", cpu);

+ 4 - 0
core/iwasm/compilation/aot_llvm.h

@@ -310,6 +310,9 @@ typedef struct AOTCompContext {
     /* Bounday Check */
     /* Bounday Check */
     bool enable_bound_check;
     bool enable_bound_check;
 
 
+    /* Native stack bounday Check */
+    bool enable_stack_bound_check;
+
     /* 128-bit SIMD */
     /* 128-bit SIMD */
     bool enable_simd;
     bool enable_simd;
 
 
@@ -404,6 +407,7 @@ typedef struct AOTCompOption {
     uint32 size_level;
     uint32 size_level;
     uint32 output_format;
     uint32 output_format;
     uint32 bounds_checks;
     uint32 bounds_checks;
+    uint32 stack_bounds_checks;
     char **custom_sections;
     char **custom_sections;
     uint32 custom_sections_count;
     uint32 custom_sections_count;
 } AOTCompOption, *aot_comp_option_t;
 } AOTCompOption, *aot_comp_option_t;

+ 1 - 0
core/iwasm/include/aot_export.h

@@ -59,6 +59,7 @@ typedef struct AOTCompOption {
     uint32_t size_level;
     uint32_t size_level;
     uint32_t output_format;
     uint32_t output_format;
     uint32_t bounds_checks;
     uint32_t bounds_checks;
+    uint32_t stack_bounds_checks;
     char **custom_sections;
     char **custom_sections;
     uint32_t custom_sections_count;
     uint32_t custom_sections_count;
 } AOTCompOption, *aot_comp_option_t;
 } AOTCompOption, *aot_comp_option_t;

+ 2 - 1
core/iwasm/interpreter/wasm_interp_classic.c

@@ -4115,7 +4115,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     }
     }
     argc = function->param_cell_num;
     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) {
     if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
         wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
         wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
                            "native stack overflow");
                            "native stack overflow");

+ 2 - 1
core/iwasm/interpreter/wasm_interp_fast.c

@@ -3911,7 +3911,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     }
     }
     argc = function->param_cell_num;
     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) {
     if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
         wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
         wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
                            "native stack overflow");
                            "native stack overflow");

+ 20 - 1
core/shared/platform/common/posix/posix_thread.c

@@ -425,6 +425,7 @@ os_thread_get_stack_boundary()
  */
  */
 static os_thread_local_attribute bool thread_signal_inited = false;
 static os_thread_local_attribute bool thread_signal_inited = false;
 
 
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
 /* The signal alternate stack base addr */
 /* The signal alternate stack base addr */
 static os_thread_local_attribute uint8 *sigalt_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,
     os_mprotect(stack_min_addr, page_size * guard_page_count,
                 MMAP_PROT_READ | MMAP_PROT_WRITE);
                 MMAP_PROT_READ | MMAP_PROT_WRITE);
 }
 }
+#endif /* end of WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 */
 
 
 static void
 static void
 mask_signals(int how)
 mask_signals(int how)
@@ -553,13 +555,16 @@ int
 os_thread_signal_init(os_signal_handler handler)
 os_thread_signal_init(os_signal_handler handler)
 {
 {
     struct sigaction sig_act;
     struct sigaction sig_act;
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     stack_t sigalt_stack_info;
     stack_t sigalt_stack_info;
     uint32 map_size = SIG_ALT_STACK_SIZE;
     uint32 map_size = SIG_ALT_STACK_SIZE;
     uint8 *map_addr;
     uint8 *map_addr;
+#endif
 
 
     if (thread_signal_inited)
     if (thread_signal_inited)
         return 0;
         return 0;
 
 
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     if (!init_stack_guard_pages()) {
     if (!init_stack_guard_pages()) {
         os_printf("Failed to init stack guard pages\n");
         os_printf("Failed to init stack guard pages\n");
         return -1;
         return -1;
@@ -581,13 +586,17 @@ os_thread_signal_init(os_signal_handler handler)
         os_printf("Failed to init signal alternate stack\n");
         os_printf("Failed to init signal alternate stack\n");
         goto fail2;
         goto fail2;
     }
     }
+#endif
 
 
     memset(&prev_sig_act_SIGSEGV, 0, sizeof(struct sigaction));
     memset(&prev_sig_act_SIGSEGV, 0, sizeof(struct sigaction));
     memset(&prev_sig_act_SIGBUS, 0, sizeof(struct sigaction));
     memset(&prev_sig_act_SIGBUS, 0, sizeof(struct sigaction));
 
 
     /* Install signal hanlder */
     /* Install signal hanlder */
     sig_act.sa_sigaction = signal_callback;
     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);
     sigemptyset(&sig_act.sa_mask);
     if (sigaction(SIGSEGV, &sig_act, &prev_sig_act_SIGSEGV) != 0
     if (sigaction(SIGSEGV, &sig_act, &prev_sig_act_SIGSEGV) != 0
         || sigaction(SIGBUS, &sig_act, &prev_sig_act_SIGBUS) != 0) {
         || sigaction(SIGBUS, &sig_act, &prev_sig_act_SIGBUS) != 0) {
@@ -595,12 +604,15 @@ os_thread_signal_init(os_signal_handler handler)
         goto fail3;
         goto fail3;
     }
     }
 
 
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     sigalt_stack_base_addr = map_addr;
     sigalt_stack_base_addr = map_addr;
+#endif
     signal_handler = handler;
     signal_handler = handler;
     thread_signal_inited = true;
     thread_signal_inited = true;
     return 0;
     return 0;
 
 
 fail3:
 fail3:
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     memset(&sigalt_stack_info, 0, sizeof(stack_t));
     memset(&sigalt_stack_info, 0, sizeof(stack_t));
     sigalt_stack_info.ss_flags = SS_DISABLE;
     sigalt_stack_info.ss_flags = SS_DISABLE;
     sigalt_stack_info.ss_size = map_size;
     sigalt_stack_info.ss_size = map_size;
@@ -609,17 +621,21 @@ fail2:
     os_munmap(map_addr, map_size);
     os_munmap(map_addr, map_size);
 fail1:
 fail1:
     destroy_stack_guard_pages();
     destroy_stack_guard_pages();
+#endif
     return -1;
     return -1;
 }
 }
 
 
 void
 void
 os_thread_signal_destroy()
 os_thread_signal_destroy()
 {
 {
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     stack_t sigalt_stack_info;
     stack_t sigalt_stack_info;
+#endif
 
 
     if (!thread_signal_inited)
     if (!thread_signal_inited)
         return;
         return;
 
 
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     /* Disable signal alternate stack */
     /* Disable signal alternate stack */
     memset(&sigalt_stack_info, 0, sizeof(stack_t));
     memset(&sigalt_stack_info, 0, sizeof(stack_t));
     sigalt_stack_info.ss_flags = SS_DISABLE;
     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);
     os_munmap(sigalt_stack_base_addr, SIG_ALT_STACK_SIZE);
 
 
     destroy_stack_guard_pages();
     destroy_stack_guard_pages();
+#endif
 
 
     thread_signal_inited = false;
     thread_signal_inited = false;
 }
 }
@@ -648,6 +665,7 @@ os_signal_unmask()
 void
 void
 os_sigreturn()
 os_sigreturn()
 {
 {
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
 #if defined(__APPLE__)
 #if defined(__APPLE__)
 #define UC_RESET_ALT_STACK 0x80000000
 #define UC_RESET_ALT_STACK 0x80000000
     extern int __sigreturn(void *, int);
     extern int __sigreturn(void *, int);
@@ -656,5 +674,6 @@ os_sigreturn()
        after exiting the signal handler. */
        after exiting the signal handler. */
     __sigreturn(NULL, UC_RESET_ALT_STACK);
     __sigreturn(NULL, UC_RESET_ALT_STACK);
 #endif
 #endif
+#endif
 }
 }
 #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
 #endif /* end of OS_ENABLE_HW_BOUND_CHECK */

+ 6 - 0
core/shared/platform/windows/win_thread.c

@@ -706,13 +706,19 @@ static os_thread_local_attribute bool thread_signal_inited = false;
 int
 int
 os_thread_signal_init()
 os_thread_signal_init()
 {
 {
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     ULONG StackSizeInBytes = 16 * 1024;
     ULONG StackSizeInBytes = 16 * 1024;
+#endif
     bool ret;
     bool ret;
 
 
     if (thread_signal_inited)
     if (thread_signal_inited)
         return 0;
         return 0;
 
 
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     ret = SetThreadStackGuarantee(&StackSizeInBytes);
     ret = SetThreadStackGuarantee(&StackSizeInBytes);
+#else
+    ret = true;
+#endif
     if (ret)
     if (ret)
         thread_signal_inited = true;
         thread_signal_inited = true;
     return ret ? 0 : -1;
     return ret ? 0 : -1;

+ 6 - 2
doc/build_wamr.md

@@ -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
 - **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.
 > 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
 - **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**
 #### **Enable tail call feature**
 - **WAMR_BUILD_TAIL_CALL**=1/0, default to disable if not set
 - **WAMR_BUILD_TAIL_CALL**=1/0, default to disable if not set

+ 2 - 0
product-mini/platforms/nuttx/wamr.mk

@@ -268,8 +268,10 @@ endif
 
 
 ifeq ($(CONFIG_INTERPRETERS_WAMR_DISABLE_HW_BOUND_CHECK),y)
 ifeq ($(CONFIG_INTERPRETERS_WAMR_DISABLE_HW_BOUND_CHECK),y)
 CFLAGS += -DWASM_DISABLE_HW_BOUND_CHECK=1
 CFLAGS += -DWASM_DISABLE_HW_BOUND_CHECK=1
+CFLAGS += -DWASM_DISABLE_STACK_HW_BOUND_CHECK=1
 else
 else
 CFLAGS += -DWASM_DISABLE_HW_BOUND_CHECK=0
 CFLAGS += -DWASM_DISABLE_HW_BOUND_CHECK=0
+CFLAGS += -DWASM_DISABLE_STACK_HW_BOUND_CHECK=0
 endif
 endif
 
 
 ifeq ($(CONFIG_INTERPRETERS_WAMR_CUSTOM_NAME_SECTIONS),y)
 ifeq ($(CONFIG_INTERPRETERS_WAMR_CUSTOM_NAME_SECTIONS),y)

+ 10 - 0
wamr-compiler/main.c

@@ -37,6 +37,11 @@ print_help()
     printf("                              by default it is disabled in all 64-bit platforms except SGX and\n");
     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("                              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("                              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("  --format=<format>         Specifies the format of the output file\n");
     printf("                            The format supported:\n");
     printf("                            The format supported:\n");
     printf("                              aot (default)  AoT file\n");
     printf("                              aot (default)  AoT file\n");
@@ -139,6 +144,8 @@ main(int argc, char *argv[])
     option.output_format = AOT_FORMAT_FILE;
     option.output_format = AOT_FORMAT_FILE;
     /* default value, enable or disable depends on the platform */
     /* default value, enable or disable depends on the platform */
     option.bounds_checks = 2;
     option.bounds_checks = 2;
+    /* default value, enable or disable depends on the platform */
+    option.stack_bounds_checks = 2;
     option.enable_simd = true;
     option.enable_simd = true;
     option.enable_aux_stack_check = true;
     option.enable_aux_stack_check = true;
     option.enable_bulk_memory = true;
     option.enable_bulk_memory = true;
@@ -193,6 +200,9 @@ main(int argc, char *argv[])
         else if (!strncmp(argv[0], "--bounds-checks=", 16)) {
         else if (!strncmp(argv[0], "--bounds-checks=", 16)) {
             option.bounds_checks = (atoi(argv[0] + 16) == 1) ? 1 : 0;
             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)) {
         else if (!strncmp(argv[0], "--format=", 9)) {
             if (argv[0][9] == '\0')
             if (argv[0][9] == '\0')
                 PRINT_HELP_AND_EXIT();
                 PRINT_HELP_AND_EXIT();