Implement aux stack overflow/underflow check for AOT/interp (#601)

This commit is contained in:
Wenyong Huang
2021-04-07 16:15:59 +08:00
committed by GitHub
parent fe76c89c25
commit 77c3ddf7d0
18 changed files with 242 additions and 45 deletions

View File

@ -336,8 +336,12 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break;
case WASM_OP_SET_GLOBAL:
case WASM_OP_SET_GLOBAL_64:
case WASM_OP_SET_GLOBAL_AUX_STACK:
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
if (!aot_compile_op_set_global(comp_ctx, func_ctx, global_idx))
if (!aot_compile_op_set_global(comp_ctx, func_ctx, global_idx,
opcode == WASM_OP_SET_GLOBAL_AUX_STACK
? true : false))
return false;
break;

View File

@ -233,6 +233,9 @@ typedef enum FloatArithmetic {
#define I32_TWO (comp_ctx->llvm_consts.i32_two)
#define I32_THREE (comp_ctx->llvm_consts.i32_three)
#define I32_FOUR (comp_ctx->llvm_consts.i32_four)
#define I32_FIVE (comp_ctx->llvm_consts.i32_five)
#define I32_SIX (comp_ctx->llvm_consts.i32_six)
#define I32_SEVEN (comp_ctx->llvm_consts.i32_seven)
#define I32_EIGHT (comp_ctx->llvm_consts.i32_eight)
#define I32_NEG_ONE (comp_ctx->llvm_consts.i32_neg_one)
#define I64_NEG_ONE (comp_ctx->llvm_consts.i64_neg_one)

View File

@ -640,8 +640,7 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
LLVMBasicBlockRef terminate_block;
/* Offset of suspend_flags */
offset = I32_CONST(5);
CHECK_LLVM_CONST(offset);
offset = I32_FIVE;
if (!(terminate_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,

View File

@ -4,6 +4,7 @@
*/
#include "aot_emit_variable.h"
#include "aot_emit_exception.h"
#include "../aot/aot_runtime.h"
#define CHECK_LOCAL(idx) do { \
@ -107,7 +108,7 @@ fail:
static bool
compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 global_idx, bool is_set)
uint32 global_idx, bool is_set, bool is_aux_stack)
{
AOTCompData *comp_data = comp_ctx->comp_data;
uint32 import_global_count = comp_data->import_global_count;
@ -179,6 +180,61 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
else {
POP(global, global_type);
if (is_aux_stack && comp_ctx->enable_aux_stack_check) {
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMBasicBlockRef check_overflow_succ, check_underflow_succ;
LLVMValueRef cmp;
/* Add basic blocks */
if (!(check_overflow_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_overflow_succ"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
LLVMMoveBasicBlockAfter(check_overflow_succ, block_curr);
if (!(check_underflow_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_underflow_succ"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ);
/* Check aux stack overflow */
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE,
global, func_ctx->aux_stack_bound,
"cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
if (!aot_emit_exception(comp_ctx, func_ctx,
EXCE_AUX_STACK_OVERFLOW,
true, cmp, check_overflow_succ)) {
return false;
}
/* Check aux stack underflow */
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ);
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT,
global, func_ctx->aux_stack_bottom,
"cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
if (!aot_emit_exception(comp_ctx, func_ctx,
EXCE_AUX_STACK_UNDERFLOW,
true, cmp, check_underflow_succ)) {
return false;
}
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_underflow_succ);
}
if (!(res = LLVMBuildStore(comp_ctx->builder,
global, global_ptr))) {
aot_set_last_error("llvm build store failed.");
@ -197,13 +253,13 @@ bool
aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 global_idx)
{
return compile_global(comp_ctx, func_ctx, global_idx, false);
return compile_global(comp_ctx, func_ctx, global_idx, false, false);
}
bool
aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 global_idx)
uint32 global_idx, bool is_aux_stack)
{
return compile_global(comp_ctx, func_ctx, global_idx, true);
return compile_global(comp_ctx, func_ctx, global_idx, true, is_aux_stack);
}

View File

@ -30,7 +30,7 @@ aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
bool
aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 global_idx);
uint32 global_idx, bool is_aux_stack);
#ifdef __cplusplus
} /* end of extern "C" */

View File

@ -628,6 +628,8 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr;
LLVMValueRef argv_buf_offset = I32_THREE, argv_buf_addr;
LLVMValueRef stack_bound_offset = I32_FOUR, stack_bound_addr;
LLVMValueRef aux_stack_bound_offset = I32_SIX, aux_stack_bound_addr;
LLVMValueRef aux_stack_bottom_offset = I32_SEVEN, aux_stack_bottom_addr;
char local_name[32];
uint64 size;
uint32 i, j = 0;
@ -718,6 +720,53 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
goto fail;
}
/* Get aux stack boundary address */
if (!(aux_stack_bound_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
&aux_stack_bound_offset, 1,
"aux_stack_bound_addr"))) {
aot_set_last_error("llvm build in bounds gep failed");
goto fail;
}
if (!(aux_stack_bound_addr =
LLVMBuildBitCast(comp_ctx->builder,
aux_stack_bound_addr,
INT32_PTR_TYPE, "aux_stack_bound_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
goto fail;
}
if (!(func_ctx->aux_stack_bound =
LLVMBuildLoad(comp_ctx->builder,
aux_stack_bound_addr, "aux_stack_bound"))) {
aot_set_last_error("llvm build load failed");
goto fail;
}
/* Get aux stack bottom address */
if (!(aux_stack_bottom_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
&aux_stack_bottom_offset, 1,
"aux_stack_bottom_addr"))) {
aot_set_last_error("llvm build in bounds gep failed");
goto fail;
}
if (!(aux_stack_bottom_addr =
LLVMBuildBitCast(comp_ctx->builder,
aux_stack_bottom_addr,
INT32_PTR_TYPE, "aux_stack_bottom_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
goto fail;
}
if (!(func_ctx->aux_stack_bottom =
LLVMBuildLoad(comp_ctx->builder,
aux_stack_bottom_addr, "aux_stack_bottom"))) {
aot_set_last_error("llvm build load failed");
goto fail;
}
for (i = 0; i < aot_func_type->param_count; i++, j++) {
snprintf(local_name, sizeof(local_name), "l%d", i);
func_ctx->locals[i] =
@ -953,6 +1002,9 @@ aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx)
consts->i32_two = I32_CONST(2);
consts->i32_three = I32_CONST(3);
consts->i32_four = I32_CONST(4);
consts->i32_five = I32_CONST(5);
consts->i32_six = I32_CONST(6);
consts->i32_seven = I32_CONST(7);
consts->i32_eight = I32_CONST(8);
consts->i32_neg_one = I32_CONST((uint32)-1);
consts->i64_neg_one = I64_CONST((uint64)-1);
@ -978,6 +1030,9 @@ aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx)
&& consts->i32_two
&& consts->i32_three
&& consts->i32_four
&& consts->i32_five
&& consts->i32_six
&& consts->i32_seven
&& consts->i32_eight
&& consts->i32_neg_one
&& consts->i64_neg_one
@ -1192,6 +1247,9 @@ aot_create_comp_context(AOTCompData *comp_data,
if (option->enable_aux_stack_frame)
comp_ctx->enable_aux_stack_frame = true;
if (option->enable_aux_stack_check)
comp_ctx->enable_aux_stack_check = true;
if (option->is_jit_mode) {
char *triple_jit = NULL;

View File

@ -122,6 +122,8 @@ typedef struct AOTFuncContext {
LLVMValueRef table_base;
LLVMValueRef argv_buf;
LLVMValueRef native_stack_bound;
LLVMValueRef aux_stack_bound;
LLVMValueRef aux_stack_bottom;
LLVMValueRef last_alloca;
LLVMValueRef func_ptrs;
@ -185,6 +187,9 @@ typedef struct AOTLLVMConsts {
LLVMValueRef i32_two;
LLVMValueRef i32_three;
LLVMValueRef i32_four;
LLVMValueRef i32_five;
LLVMValueRef i32_six;
LLVMValueRef i32_seven;
LLVMValueRef i32_eight;
LLVMValueRef i32_neg_one;
LLVMValueRef i64_neg_one;
@ -224,7 +229,10 @@ typedef struct AOTCompContext {
/* 128-bit SIMD */
bool enable_simd;
/* generate auxiliary stack frame */
/* Auxiliary stack overflow/underflow check */
bool enable_aux_stack_check;
/* Generate auxiliary stack frame */
bool enable_aux_stack_frame;
/* Thread Manager */
@ -275,6 +283,7 @@ typedef struct AOTCompOption{
bool enable_thread_mgr;
bool enable_tail_call;
bool enable_simd;
bool enable_aux_stack_check;
bool enable_aux_stack_frame;
bool is_sgx_platform;
uint32 opt_level;