Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/iwasm/aot/aot_reloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ typedef struct {
#define REG_COMMON_SYMBOLS \
REG_SYM(aot_set_exception_with_id), \
REG_SYM(aot_invoke_native), \
REG_SYM(aot_bounds_check), \
REG_SYM(aot_call_indirect), \
REG_SYM(aot_enlarge_memory), \
REG_SYM(aot_set_exception), \
Expand Down
11 changes: 11 additions & 0 deletions core/iwasm/aot/aot_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -3109,6 +3109,17 @@ aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str,
return ret;
}

#if WASM_ENABLE_MEMORY64 == 0
uint64
aot_bounds_check(AOTModuleInstance *module_inst, uint32 offset, uint32 bytes)
#else
uint64
aot_bounds_check(AOTModuleInstance *module_inst, uint64 offset, uint32 bytes)
#endif
{
return offset;
}

void *
aot_memmove(void *dest, const void *src, size_t n)
{
Expand Down
11 changes: 11 additions & 0 deletions core/iwasm/aot/aot_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,17 @@ aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str,
uint64 app_buf_addr, uint64 app_buf_size,
void **p_native_addr);

/**
* Check whether the memory offset is out of bounds
*/
#if WASM_ENABLE_MEMORY64 == 0
uint64
aot_bounds_check(AOTModuleInstance *module_inst, uint32 offset, uint32 bytes);
#else
uint64
aot_bounds_check(AOTModuleInstance *module_inst, uint64 offset, uint32 bytes);
#endif

uint32
aot_get_plt_table_size();

Expand Down
116 changes: 101 additions & 15 deletions core/iwasm/compilation/aot_emit_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,40 @@ get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
static LLVMValueRef
get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);

static LLVMValueRef
aot_call_runtime_bounds_check(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, LLVMValueRef offset,
uint32 bytes)
{
LLVMValueRef param_values[3], value, maddr, func;
LLVMTypeRef param_types[3], ret_type = 0, func_type = 0, func_ptr_type = 0;
uint32 argc = 3;

param_types[0] = INT8_PTR_TYPE;
#if WASM_ENABLE_MEMORY64 == 0
param_types[1] = I32_TYPE;
#else
param_types[1] = I64_TYPE;
#endif
param_types[2] = I32_TYPE;
ret_type = INT8_PTR_TYPE;

param_values[0] = func_ctx->aot_inst;
param_values[1] = offset;
param_values[2] = I32_CONST(bytes);

GET_AOT_FUNCTION(aot_bounds_check, argc);

if (!(maddr = LLVMBuildCall2(comp_ctx->builder, func_type, func,
param_values, argc, "maddr"))) {
aot_set_last_error("llvm build call failed.");
goto fail;
}
return maddr;
fail:
return NULL;
}

LLVMValueRef
aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
mem_offset_t offset, uint32 bytes, bool enable_segue,
Expand All @@ -104,7 +138,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef addr, maddr, offset1, cmp1, cmp2, cmp;
LLVMValueRef mem_base_addr, mem_check_bound;
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMBasicBlockRef check_succ;
LLVMBasicBlockRef check_succ, runtime_bounds_check;
AOTValue *aot_value_top;
uint32 local_idx_of_aot_value = 0;
uint64 const_value;
Expand Down Expand Up @@ -170,7 +204,6 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}

POP_MEM_OFFSET(addr);

/*
* Note: not throw the integer-overflow-exception here since it must
* have been thrown when converting float to integer before
Expand Down Expand Up @@ -295,24 +328,76 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}

/* Add basic blocks */
ADD_BASIC_BLOCK(check_succ, "check_succ");
LLVMMoveBasicBlockAfter(check_succ, block_curr);

if (!aot_emit_exception(comp_ctx, func_ctx,
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
check_succ)) {
goto fail;
if (!comp_ctx->enable_runtime_bound_check) {
ADD_BASIC_BLOCK(check_succ, "check_succ");
LLVMMoveBasicBlockAfter(check_succ, block_curr);
if (!aot_emit_exception(comp_ctx, func_ctx,
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
check_succ)) {
goto fail;
}
SET_BUILD_POS(check_succ);
if (is_local_of_aot_value) {
if (!aot_checked_addr_list_add(func_ctx, local_idx_of_aot_value,
offset, bytes))
goto fail;
}
}
else {
LLVMValueRef maddr1, maddr2;

ADD_BASIC_BLOCK(runtime_bounds_check, "runtime_bounds_check");
ADD_BASIC_BLOCK(check_succ, "check_succ");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move before line 330

if (!enable_segue) {
/* maddr = mem_base_addr + offset1 */
if (!(maddr2 = LLVMBuildInBoundsGEP2(comp_ctx->builder,
INT8_TYPE, mem_base_addr,
&offset1, 1, "maddr"))) {
aot_set_last_error("llvm build add failed.");
goto fail;
}
}
else {
LLVMValueRef maddr_base;

SET_BUILD_POS(check_succ);
if (!(maddr_base =
LLVMBuildIntToPtr(comp_ctx->builder, addr,
INT8_PTR_TYPE_GS, "maddr_base"))) {
aot_set_last_error("llvm build int to ptr failed.");
goto fail;
}
if (!(maddr2 = LLVMBuildInBoundsGEP2(
comp_ctx->builder, INT8_TYPE, maddr_base,
&offset_const, 1, "maddr"))) {
aot_set_last_error("llvm build inboundgep failed.");
goto fail;
}
}

if (is_local_of_aot_value) {
if (!aot_checked_addr_list_add(func_ctx, local_idx_of_aot_value,
offset, bytes))
goto fail;
LLVMBuildCondBr(comp_ctx->builder, cmp, runtime_bounds_check,
check_succ);
if (is_local_of_aot_value) {
if (!aot_checked_addr_list_add(func_ctx, local_idx_of_aot_value,
offset, bytes))
goto fail;
}

SET_BUILD_POS(runtime_bounds_check);
maddr1 = aot_call_runtime_bounds_check(comp_ctx, func_ctx, offset1,
bytes);
LLVMBuildBr(comp_ctx->builder, check_succ);
SET_BUILD_POS(check_succ);

LLVMValueRef phi = LLVMBuildPhi(comp_ctx->builder, OPQ_PTR_TYPE, "phi");
LLVMValueRef incoming_values[] = {
maddr1, // Value from 'then' block
maddr2 // Value from 'else' block
};
LLVMBasicBlockRef incoming_blocks[] = { runtime_bounds_check, block_curr };
LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
return phi;
}
}

if (!enable_segue) {
/* maddr = mem_base_addr + offset1 */
if (!(maddr =
Expand All @@ -337,6 +422,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
}
}

return maddr;
fail:
return NULL;
Expand Down
6 changes: 6 additions & 0 deletions core/iwasm/compilation/aot_llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2621,6 +2621,8 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)

#ifndef OS_ENABLE_HW_BOUND_CHECK
comp_ctx->enable_bound_check = true;
comp_ctx->enable_runtime_bound_check =
option->enable_runtime_bound_check;
/* Always enable stack boundary check if `bounds-checks`
is enabled */
comp_ctx->enable_stack_bound_check = true;
Expand Down Expand Up @@ -2954,6 +2956,8 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
/* Set by user */
comp_ctx->enable_bound_check =
(option->bounds_checks == 1) ? true : false;
comp_ctx->enable_runtime_bound_check =
option->enable_runtime_bound_check;
}
else {
/* Unset by user, use default value */
Expand All @@ -2963,6 +2967,8 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
}
else {
comp_ctx->enable_bound_check = true;
comp_ctx->enable_runtime_bound_check =
option->enable_runtime_bound_check;
}
}

Expand Down
3 changes: 3 additions & 0 deletions core/iwasm/compilation/aot_llvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ typedef struct AOTCompContext {
/* Boundary Check */
bool enable_bound_check;

/* Boundary Check by calling runtime function*/
bool enable_runtime_bound_check;

/* Native stack boundary Check */
bool enable_stack_bound_check;

Expand Down
1 change: 1 addition & 0 deletions core/iwasm/include/aot_comp_option.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ typedef struct AOTCompOption {
bool enable_llvm_pgo;
bool enable_stack_estimation;
bool quick_invoke_c_api_import;
bool enable_runtime_bound_check;
char *use_prof_file;
uint32_t opt_level;
uint32_t size_level;
Expand Down
4 changes: 4 additions & 0 deletions wamr-compiler/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ print_help()
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(" --runtime-bounds-checks Enable bounds check by call runtime function:\n");
printf(" --stack-usage=<file> Generate a stack-usage file.\n");
printf(" Similarly to `clang -fstack-usage`.\n");
printf(" --format=<format> Specifies the format of the output file\n");
Expand Down Expand Up @@ -545,6 +546,9 @@ main(int argc, char *argv[])
else if (!strcmp(argv[0], "--invoke-c-api-import")) {
option.quick_invoke_c_api_import = true;
}
else if (!strcmp(argv[0], "--runtime-bounds-checks")) {
option.enable_runtime_bound_check = true;
}
#if WASM_ENABLE_LINUX_PERF != 0
else if (!strcmp(argv[0], "--enable-linux-perf")) {
enable_linux_perf = true;
Expand Down