diff --git a/core/iwasm/aot/arch/aot_reloc_arm.c b/core/iwasm/aot/arch/aot_reloc_arm.c index 1389bfb25a..fbf9be13c8 100644 --- a/core/iwasm/aot/arch/aot_reloc_arm.c +++ b/core/iwasm/aot/arch/aot_reloc_arm.c @@ -37,6 +37,9 @@ void __aeabi_idivmod(); void __aeabi_l2d(); void __aeabi_l2f(); void __aeabi_ldivmod(); +void __aeabi_memcpy(); +void __aeabi_memmove(); +void __aeabi_memset(); void __aeabi_uidiv(); void __aeabi_uidivmod(); void __aeabi_ul2d(); @@ -120,6 +123,9 @@ static SymbolMap target_sym_map[] = { REG_SYM(__aeabi_l2d), REG_SYM(__aeabi_l2f), REG_SYM(__aeabi_ldivmod), + REG_SYM(__aeabi_memcpy), + REG_SYM(__aeabi_memmove), + REG_SYM(__aeabi_memset), REG_SYM(__aeabi_uidiv), REG_SYM(__aeabi_uidivmod), REG_SYM(__aeabi_ul2d), diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 212a778019..6908fbf449 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -2112,6 +2112,7 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out) memset(&module_name, 0, sizeof(wasm_val_vec_t)); memset(&name, 0, sizeof(wasm_val_vec_t)); extern_type = NULL; + import_type = NULL; if (i < import_func_count) { wasm_functype_t *type = NULL; diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index c7be95fcf0..0fa5962771 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -379,10 +379,11 @@ wasm_native_unregister_natives(const char *module_name, bool wasm_native_init() { -#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ - || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ - || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ - || WASM_ENABLE_APP_FRAMEWORK != 0 +#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ + || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ + || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ + || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ + || WASM_ENABLE_LIB_PTHREAD != 0 NativeSymbol *native_symbols; uint32 n_native_symbols; #endif @@ -461,10 +462,11 @@ wasm_native_init() #endif return true; -#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ - || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ - || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ - || WASM_ENABLE_APP_FRAMEWORK != 0 +#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ + || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ + || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ + || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ + || WASM_ENABLE_LIB_PTHREAD != 0 fail: wasm_native_destroy(); return false; diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 17cf9da31b..8ddf4af437 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -143,9 +143,9 @@ runtime_signal_handler(void *sig_addr) WASMJmpBuf *jmpbuf_node; uint8 *mapped_mem_start_addr = NULL; uint8 *mapped_mem_end_addr = NULL; + uint32 page_size = os_getpagesize(); #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 @@ -163,7 +163,6 @@ runtime_signal_handler(void *sig_addr) #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 @@ -216,29 +215,41 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) mapped_mem_start_addr = memory_inst->memory_data; mapped_mem_end_addr = memory_inst->memory_data + 8 * (uint64)BH_GB; - if (mapped_mem_start_addr <= (uint8 *)sig_addr - && (uint8 *)sig_addr < mapped_mem_end_addr) { - /* The address which causes segmentation fault is inside - the memory instance's guard regions. - Set exception and let the wasm func continue to run, when - the wasm func returns, the caller will check whether the - exception is thrown and return to runtime. */ - wasm_set_exception(module_inst, - "out of bounds memory access"); - if (module_inst->module_type == Wasm_Module_Bytecode) { - /* Continue to search next exception handler for - interpreter mode as it can be caught by - `__try { .. } __except { .. }` sentences in - wasm_runtime.c */ - return EXCEPTION_CONTINUE_SEARCH; - } - else { - /* Skip current instruction and continue to run for - AOT mode. TODO: implement unwind support for AOT - code in Windows platform */ - exce_info->ContextRecord->Rip++; - return EXCEPTION_CONTINUE_EXECUTION; - } + } + + if (memory_inst && mapped_mem_start_addr <= (uint8 *)sig_addr + && (uint8 *)sig_addr < mapped_mem_end_addr) { + /* The address which causes segmentation fault is inside + the memory instance's guard regions. + Set exception and let the wasm func continue to run, when + the wasm func returns, the caller will check whether the + exception is thrown and return to runtime. */ + wasm_set_exception(module_inst, "out of bounds memory access"); + if (module_inst->module_type == Wasm_Module_Bytecode) { + /* Continue to search next exception handler for + interpreter mode as it can be caught by + `__try { .. } __except { .. }` sentences in + wasm_runtime.c */ + return EXCEPTION_CONTINUE_SEARCH; + } + else { + /* Skip current instruction and continue to run for + AOT mode. TODO: implement unwind support for AOT + code in Windows platform */ + exce_info->ContextRecord->Rip++; + return EXCEPTION_CONTINUE_EXECUTION; + } + } + 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)); + if (module_inst->module_type == Wasm_Module_Bytecode) { + return EXCEPTION_CONTINUE_SEARCH; + } + else { + exce_info->ContextRecord->Rip++; + return EXCEPTION_CONTINUE_EXECUTION; } } } diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 6d452b04f0..68c286f43c 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -462,6 +462,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, false, NULL, NULL))) { goto fail; } + aot_block_destroy(block); return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); } diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index f009ca875c..af116a8234 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -5125,10 +5125,11 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, /* Free the emit data */ wasm_runtime_free(emit_data); - return true; fail: + /* Free the emit data */ + wasm_runtime_free(emit_data); return false; } #endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index a1e3e37388..0d44ae7da1 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -3081,14 +3081,15 @@ wasi_ssp_sock_addr_resolve( size_t _max_info_size; size_t actual_info_size; - if (!ns_lookup_list_search(ns_lookup_list, host)) { - return __WASI_EACCES; - } - if (!wamr_addr_info) { return __WASI_ENOMEM; } + if (!ns_lookup_list_search(ns_lookup_list, host)) { + wasm_runtime_free(wamr_addr_info); + return __WASI_EACCES; + } + int ret = os_socket_addr_resolve( host, service, hints->hints_enabled ? &hints_is_tcp : NULL, hints->hints_enabled ? &hints_is_ipv4 : NULL, wamr_addr_info, diff --git a/samples/file/src/main.c b/samples/file/src/main.c index de5eb29184..2fb99e2555 100644 --- a/samples/file/src/main.c +++ b/samples/file/src/main.c @@ -26,7 +26,6 @@ main(int argc, char *argv_main[]) wasm_module_inst_t module_inst = NULL; wasm_exec_env_t exec_env = NULL; uint32 buf_size, stack_size = 8092, heap_size = 8092; - uint32_t wasm_buffer = 0; RuntimeInitArgs init_args; memset(&init_args, 0, sizeof(RuntimeInitArgs)); @@ -103,11 +102,8 @@ main(int argc, char *argv_main[]) fail: if (exec_env) wasm_runtime_destroy_exec_env(exec_env); - if (module_inst) { - if (wasm_buffer) - wasm_runtime_module_free(module_inst, wasm_buffer); + if (module_inst) wasm_runtime_deinstantiate(module_inst); - } if (module) wasm_runtime_unload(module); if (buffer) diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index 2b3a02db49..3fce87c017 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -199,11 +199,16 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") if(VALGRIND) foreach(EX ${EXAMPLES}) - add_custom_target(${EX}_LEAK_TEST - COMMAND ${VALGRIND} --tool=memcheck --leak-check=yes ./${EX} + add_custom_command( + OUTPUT ${EX}_leak_check.report DEPENDS ${EX} ${EX}_WASM - VERBATIM - COMMENT "run a leak check on ${EX}" + COMMAND ${VALGRIND} --tool=memcheck --leak-check=summary -- ./${EX} > ${EX}_leak_check.report 2>&1 + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + add_custom_target(${EX}_LEAK_TEST ALL + DEPENDS ${EX}_leak_check.report + COMMAND grep "All heap blocks were freed -- no leaks are possible" ${EX}_leak_check.report + COMMENT "Please read ${EX}_leak_check.report when meeting Error" ) endforeach() endif (VALGRIND) diff --git a/samples/wasm-c-api/src/callback.c b/samples/wasm-c-api/src/callback.c index b1294670d3..ccb9ec0675 100644 --- a/samples/wasm-c-api/src/callback.c +++ b/samples/wasm-c-api/src/callback.c @@ -169,9 +169,11 @@ int main(int argc, const char* argv[]) { wasm_val_t rs[1] = { WASM_INIT_VAL }; wasm_val_vec_t args = WASM_ARRAY_VEC(as); wasm_val_vec_t results = WASM_ARRAY_VEC(rs); - if (wasm_func_call(run_func, &args, &results)) { - printf("> Error calling function!\n"); - return 1; + wasm_trap_t *trap = wasm_func_call(run_func, &args, &results); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + return 1; } wasm_extern_vec_delete(&exports); diff --git a/samples/wasm-c-api/src/clone.c b/samples/wasm-c-api/src/clone.c index bfe621758e..ce8ebd8bdb 100644 --- a/samples/wasm-c-api/src/clone.c +++ b/samples/wasm-c-api/src/clone.c @@ -231,10 +231,13 @@ vm_function_set_byte(const wasm_vm_t *vm, uint32_t offset, uint8_t byte) wasm_val_vec_t args = WASM_ARRAY_VEC(a_v); wasm_val_vec_t results = WASM_EMPTY_VEC; wasm_trap_t *trap = wasm_func_call(vm->function_list[0], &args, &results); - if (trap) + if (trap) { printf("call wasm_set_byte failed"); + wasm_trap_delete(trap); + return false; + } - return trap != NULL; + return true; } bool @@ -247,6 +250,7 @@ vm_function_get_byte(const wasm_vm_t *vm, uint32_t offset, uint8_t *byte) wasm_trap_t *trap = wasm_func_call(vm->function_list[1], &args, &results); if (trap) { printf("call wasm_get_byte failed"); + wasm_trap_delete(trap); return false; } diff --git a/samples/wasm-c-api/src/empty_imports.c b/samples/wasm-c-api/src/empty_imports.c index 5858ed6b54..c8788b51ac 100644 --- a/samples/wasm-c-api/src/empty_imports.c +++ b/samples/wasm-c-api/src/empty_imports.c @@ -97,10 +97,16 @@ int main(int argc, const char* argv[]) { wasm_val_t results[1] = { WASM_INIT_VAL }; wasm_val_vec_t results_vec = WASM_ARRAY_VEC(results); - if (wasm_func_call(add_func, &args_vec, &results_vec) - || results_vec.data[0].of.i32 != 7) { - printf("> Error calling function!\n"); - return 1; + wasm_trap_t *trap = wasm_func_call(add_func, &args_vec, &results_vec); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + return 1; + } + + if (results_vec.data[0].of.i32 != 7) { + printf("> Error calling function!\n"); + return 1; } wasm_extern_vec_delete(&exports); diff --git a/samples/wasm-c-api/src/global.c b/samples/wasm-c-api/src/global.c index bc4671d239..91c8cb654d 100644 --- a/samples/wasm-c-api/src/global.c +++ b/samples/wasm-c-api/src/global.c @@ -37,15 +37,22 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { check(val, type, expected); \ } -#define check_call(func, type, expected) \ - { \ - wasm_val_t vs[1]; \ - wasm_val_vec_t args = WASM_EMPTY_VEC; \ - wasm_val_vec_t results = WASM_ARRAY_VEC(vs); \ - wasm_func_call(func, &args, &results); \ - check(vs[0], type, expected); \ - } - +#define check_trap(trap) \ + if (trap) { \ + printf("> Error calling function\n"); \ + wasm_trap_delete(trap); \ + exit(1); \ + } + +#define check_call(func, type, expected) \ + { \ + wasm_val_t vs[1]; \ + wasm_val_vec_t args = WASM_EMPTY_VEC; \ + wasm_val_vec_t results = WASM_ARRAY_VEC(vs); \ + wasm_trap_t *trap = wasm_func_call(func, &args, &results); \ + check_trap(trap); \ + check(vs[0], type, expected); \ + } int main(int argc, const char* argv[]) { // Initialize. @@ -225,16 +232,23 @@ int main(int argc, const char* argv[]) { wasm_val_vec_t res = WASM_EMPTY_VEC; wasm_val_t vs73[] = { WASM_F32_VAL(73) }; wasm_val_vec_t args73 = WASM_ARRAY_VEC(vs73); - wasm_func_call(set_var_f32_import, &args73, &res); + wasm_trap_t *trap = wasm_func_call(set_var_f32_import, &args73, &res); + check_trap(trap); + wasm_val_t vs74[] = { WASM_I64_VAL(74) }; wasm_val_vec_t args74 = WASM_ARRAY_VEC(vs74); - wasm_func_call(set_var_i64_import, &args74, &res); + trap = wasm_func_call(set_var_i64_import, &args74, &res); + check_trap(trap); + wasm_val_t vs77[] = { WASM_F32_VAL(77) }; wasm_val_vec_t args77 = WASM_ARRAY_VEC(vs77); - wasm_func_call(set_var_f32_export, &args77, &res); + trap = wasm_func_call(set_var_f32_export, &args77, &res); + check_trap(trap); + wasm_val_t vs78[] = { WASM_I64_VAL(78) }; wasm_val_vec_t args78 = WASM_ARRAY_VEC(vs78); - wasm_func_call(set_var_i64_export, &args78, &res); + trap = wasm_func_call(set_var_i64_export, &args78, &res); + check_trap(trap); check_global(var_f32_import, f32, 73); check_global(var_i64_import, i64, 74); diff --git a/samples/wasm-c-api/src/globalexportimport.c b/samples/wasm-c-api/src/globalexportimport.c index 92420a1b9f..1c1715f2e5 100644 --- a/samples/wasm-c-api/src/globalexportimport.c +++ b/samples/wasm-c-api/src/globalexportimport.c @@ -50,13 +50,21 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { check(val, type, expected); \ } -#define check_call(func, type, expected) \ - { \ - wasm_val_vec_t results; \ - wasm_val_vec_new_uninitialized(&results, 1); \ - wasm_func_call(func, NULL, &results); \ - check(results.data[0], type, expected); \ - } +#define check_trap(trap) \ + if (trap) { \ + printf("> Error calling function\n"); \ + wasm_trap_delete(trap); \ + exit(1); \ + } + +#define check_call(func, type, expected) \ + { \ + wasm_val_vec_t results; \ + wasm_val_vec_new_uninitialized(&results, 1); \ + wasm_trap_t *trap = wasm_func_call(func, NULL, &results); \ + check_trap(trap); \ + check(results.data[0], type, expected); \ + } wasm_module_t * create_module_from_file(wasm_store_t* store, const char * filename) { @@ -149,7 +157,9 @@ int main(int argc, const char* argv[]) { printf("Modify the variable to 77.0...\n"); wasm_val_vec_t args77; wasm_val_vec_new(&args77, 1, (wasm_val_t []){ {.kind = WASM_F32, .of = {.f32 = 77.0}} }); - wasm_func_call(set_var_f32_export, &args77, NULL); //Call to module export + wasm_trap_t *trap = wasm_func_call(set_var_f32_export, &args77, + NULL); // Call to module export + check_trap(trap); check_call(get_var_f32_export, f32, 77.0); //Call to module export check_global(var_f32_export, f32, 77.0); //Failed here, still 37 check_call(get_var_f32_import, f32, 77.0); //Call to module import Failed here, still 37 @@ -158,7 +168,8 @@ int main(int argc, const char* argv[]) { printf("Modify the variable to 78.0...\n"); wasm_val_vec_t args78; wasm_val_vec_new(&args78, 1, (wasm_val_t []){ {.kind = WASM_F32, .of = {.f32 = 78.0}} }); - wasm_func_call(set_var_f32_import, &args78, NULL); + trap = wasm_func_call(set_var_f32_import, &args78, NULL); + check_trap(trap); check_global(var_f32_export, f32, 78.0); check_call(get_var_f32_export, f32, 78.0); //Call to module export Failed here, still 77 check_call(get_var_f32_import, f32, 78.0); //Call to module import diff --git a/samples/wasm-c-api/src/hello.c b/samples/wasm-c-api/src/hello.c index 5a2b9843e7..3ebea87b08 100644 --- a/samples/wasm-c-api/src/hello.c +++ b/samples/wasm-c-api/src/hello.c @@ -118,9 +118,11 @@ int main(int argc, const char* argv[]) { printf("Calling export...\n"); wasm_val_vec_t args = WASM_EMPTY_VEC; wasm_val_vec_t results = WASM_EMPTY_VEC; - if (wasm_func_call(run_func, &args, &results)) { - printf("> Error calling function!\n"); - return 1; + wasm_trap_t *trap = wasm_func_call(run_func, &args, &results); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + return 1; } wasm_extern_vec_delete(&exports); diff --git a/samples/wasm-c-api/src/hostref.c b/samples/wasm-c-api/src/hostref.c index a411ddd9f4..219c862d68 100644 --- a/samples/wasm-c-api/src/hostref.c +++ b/samples/wasm-c-api/src/hostref.c @@ -50,9 +50,11 @@ own wasm_ref_t* call_v_r(const wasm_func_t* func) { wasm_val_t rs[] = { WASM_INIT_VAL }; wasm_val_vec_t args = WASM_EMPTY_VEC; wasm_val_vec_t results = WASM_ARRAY_VEC(rs); - if (wasm_func_call(func, &args, &results)) { - printf("> Error calling function!\n"); - exit(1); + wasm_trap_t *trap = wasm_func_call(func, &args, &results); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + exit(1); } printf("okay\n"); return rs[0].of.ref; @@ -63,9 +65,11 @@ void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) { wasm_val_t vs[1] = { WASM_REF_VAL(ref) }; wasm_val_vec_t args = WASM_ARRAY_VEC(vs); wasm_val_vec_t results = WASM_EMPTY_VEC; - if (wasm_func_call(func, &args, &results)) { - printf("> Error calling function!\n"); - exit(1); + wasm_trap_t *trap = wasm_func_call(func, &args, &results); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + exit(1); } printf("okay\n"); } @@ -76,9 +80,11 @@ own wasm_ref_t* call_r_r(const wasm_func_t* func, wasm_ref_t* ref) { wasm_val_t rs[1] = { WASM_INIT_VAL }; wasm_val_vec_t args = WASM_ARRAY_VEC(vs); wasm_val_vec_t results = WASM_ARRAY_VEC(rs); - if (wasm_func_call(func, &args, &results)) { - printf("> Error calling function!\n"); - exit(1); + wasm_trap_t *trap = wasm_func_call(func, &args, &results); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + exit(1); } printf("okay\n"); return rs[0].of.ref; @@ -89,9 +95,11 @@ void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) { wasm_val_t vs[2] = { WASM_I32_VAL(i), WASM_REF_VAL(ref) }; wasm_val_vec_t args = WASM_ARRAY_VEC(vs); wasm_val_vec_t results = WASM_EMPTY_VEC; - if (wasm_func_call(func, &args, &results)) { - printf("> Error calling function!\n"); - exit(1); + wasm_trap_t *trap = wasm_func_call(func, &args, &results); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + exit(1); } printf("okay\n"); } @@ -102,9 +110,11 @@ own wasm_ref_t* call_i_r(const wasm_func_t* func, int32_t i) { wasm_val_t rs[1] = { WASM_INIT_VAL }; wasm_val_vec_t args = WASM_ARRAY_VEC(vs); wasm_val_vec_t results = WASM_ARRAY_VEC(rs); - if (wasm_func_call(func, &args, &results)) { - printf("> Error calling function!\n"); - exit(1); + wasm_trap_t *trap = wasm_func_call(func, &args, &results); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + exit(1); } printf("okay\n"); return rs[0].of.ref; diff --git a/samples/wasm-c-api/src/memory.c b/samples/wasm-c-api/src/memory.c index 64d1c07778..737dd8501d 100644 --- a/samples/wasm-c-api/src/memory.c +++ b/samples/wasm-c-api/src/memory.c @@ -36,9 +36,16 @@ void check_call(wasm_func_t* func, int i, wasm_val_t args[], int32_t expected) { wasm_val_t r[] = {WASM_INIT_VAL}; wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t), NULL}; wasm_val_vec_t results = WASM_ARRAY_VEC(r); - if (wasm_func_call(func, &args_, &results) || r[0].of.i32 != expected) { - printf("> Error on result\n"); - exit(1); + wasm_trap_t *trap = wasm_func_call(func, &args_, &results); + if (trap) { + printf("> Error on result\n"); + wasm_trap_delete(trap); + exit(1); + } + + if (r[0].of.i32 != expected) { + printf("> Error on result\n"); + exit(1); } } @@ -59,9 +66,11 @@ void check_call2(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected void check_ok(wasm_func_t* func, int i, wasm_val_t args[]) { wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t), NULL}; wasm_val_vec_t results = WASM_EMPTY_VEC; - if (wasm_func_call(func, &args_, &results)) { - printf("> Error on result, expected empty\n"); - exit(1); + wasm_trap_t *trap = wasm_func_call(func, &args_, &results); + if (trap) { + printf("> Error on result, expected empty\n"); + wasm_trap_delete(trap); + exit(1); } } diff --git a/samples/wasm-c-api/src/multi.c b/samples/wasm-c-api/src/multi.c index 92ef0eea77..a1c8fa9fc9 100644 --- a/samples/wasm-c-api/src/multi.c +++ b/samples/wasm-c-api/src/multi.c @@ -133,9 +133,11 @@ int main(int argc, const char* argv[]) { }; wasm_val_vec_t args = WASM_ARRAY_VEC(vals); wasm_val_vec_t results = WASM_ARRAY_VEC(res); - if (wasm_func_call(run_func, &args, &results)) { - printf("> Error calling function!\n"); - return 1; + wasm_trap_t *trap = wasm_func_call(run_func, &args, &results); + if (trap) { + printf("> Error calling function!\n"); + wasm_trap_delete(trap); + return 1; } wasm_extern_vec_delete(&exports); diff --git a/samples/wasm-c-api/src/serialize.c b/samples/wasm-c-api/src/serialize.c index d65706916c..83436817f2 100644 --- a/samples/wasm-c-api/src/serialize.c +++ b/samples/wasm-c-api/src/serialize.c @@ -111,8 +111,10 @@ main(int argc, const char *argv[]) // Call. printf("Calling export...\n"); wasm_val_vec_t empty = WASM_EMPTY_VEC; - if (wasm_func_call(run_func, &empty, &empty)) { + wasm_trap_t *trap = wasm_func_call(run_func, &empty, &empty); + if (trap) { printf("> Error calling function!\n"); + wasm_trap_delete(trap); return 1; } diff --git a/samples/wasm-c-api/src/table.c b/samples/wasm-c-api/src/table.c index 0bf68e05a7..c4a7da8bcf 100644 --- a/samples/wasm-c-api/src/table.c +++ b/samples/wasm-c-api/src/table.c @@ -53,9 +53,16 @@ void check_call(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) wasm_val_t r[1] = { WASM_INIT_VAL }; wasm_val_vec_t args = WASM_ARRAY_VEC(vs); wasm_val_vec_t results = WASM_ARRAY_VEC(r); - if (wasm_func_call(func, &args, &results) || r[0].of.i32 != expected) { - printf("> Error on result\n"); - exit(1); + wasm_trap_t *trap = wasm_func_call(func, &args, &results); + if (trap) { + printf("> Error on calling\n"); + wasm_trap_delete(trap); + exit(1); + } + + if (r[0].of.i32 != expected) { + printf("> Error on result\n"); + exit(1); } } diff --git a/samples/wasm-c-api/src/threads.c b/samples/wasm-c-api/src/threads.c index d7ae48939c..cbe4aaf444 100644 --- a/samples/wasm-c-api/src/threads.c +++ b/samples/wasm-c-api/src/threads.c @@ -85,8 +85,10 @@ run(void *args_abs) // Call. wasm_val_vec_t empty = WASM_EMPTY_VEC; - if (wasm_func_call(run_func, &empty, &empty)) { + wasm_trap_t *trap = wasm_func_call(run_func, &empty, &empty); + if (trap) { printf("> Error calling function!\n"); + wasm_trap_delete(trap); return NULL; } diff --git a/test-tools/wamr-ide/VSCode-Extension/package.json b/test-tools/wamr-ide/VSCode-Extension/package.json index 4550452373..61d1387cce 100644 --- a/test-tools/wamr-ide/VSCode-Extension/package.json +++ b/test-tools/wamr-ide/VSCode-Extension/package.json @@ -129,7 +129,7 @@ "program": "./resource/debug/windows/bin/lldb-vscode.exe" }, "osx": { - "program": "./resource/debug/osx/bin/lldb-vscode" + "program": "./resource/debug/darwin/bin/lldb-vscode" }, "linux": { "program": "./resource/debug/linux/bin/lldb-vscode" @@ -237,7 +237,9 @@ "@types/glob": "^7.1.3", "@types/mocha": "^8.2.2", "@types/node": "14.x", + "@types/request": "^2.48.8", "@types/vscode": "^1.54.0", + "@types/yauzl": "^2.10.0", "@typescript-eslint/eslint-plugin": "^4.26.0", "@typescript-eslint/parser": "^4.26.0", "eslint": "^7.32.0", @@ -248,6 +250,8 @@ "vscode-test": "^1.5.2" }, "dependencies": { - "@vscode/webview-ui-toolkit": "^0.8.4" + "@vscode/webview-ui-toolkit": "^0.8.4", + "request": "^2.88.2", + "yauzl": "^2.10.0" } } diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/debug/osx/.placeholder b/test-tools/wamr-ide/VSCode-Extension/resource/debug/darwin/.placeholder similarity index 100% rename from test-tools/wamr-ide/VSCode-Extension/resource/debug/osx/.placeholder rename to test-tools/wamr-ide/VSCode-Extension/resource/debug/darwin/.placeholder diff --git a/test-tools/wamr-ide/VSCode-Extension/src/decorationProvider.ts b/test-tools/wamr-ide/VSCode-Extension/src/decorationProvider.ts index db636913e0..e9687f6902 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/decorationProvider.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/decorationProvider.ts @@ -4,7 +4,7 @@ */ import * as vscode from 'vscode'; -import { ReadFromFile } from './utilities/directoryUtilities'; +import { readFromFile } from './utilities/directoryUtilities'; import * as path from 'path'; import * as os from 'os'; @@ -63,8 +63,8 @@ export class DecorationProvider implements vscode.FileDecorationProvider { prjConfigDir = path.join(currentPrjDir, '.wamr'); configFilePath = path.join(prjConfigDir, 'compilation_config.json'); - if (ReadFromFile(configFilePath) !== '') { - configData = JSON.parse(ReadFromFile(configFilePath)); + if (readFromFile(configFilePath) !== '') { + configData = JSON.parse(readFromFile(configFilePath)); includePathArr = configData['include_paths']; excludeFileArr = configData['exclude_files']; diff --git a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts index 57f2aa09bd..7eb8b34a65 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts @@ -12,12 +12,13 @@ import { WasmTaskProvider } from './taskProvider'; import { TargetConfigPanel } from './view/TargetConfigPanel'; import { NewProjectPanel } from './view/NewProjectPanel'; import { - CheckIfDirectoryExist, - WriteIntoFile, - ReadFromFile, + checkIfDirectoryExists, + writeIntoFile, + readFromFile, } from './utilities/directoryUtilities'; import { decorationProvider } from './decorationProvider'; import { WasmDebugConfigurationProvider } from './debugConfigurationProvider'; +import { isLLDBInstalled, promptInstallLLDB } from './utilities/lldbUtilities'; let wasmTaskProvider: WasmTaskProvider; let wasmDebugConfigProvider: WasmDebugConfigurationProvider; @@ -213,7 +214,7 @@ export async function activate(context: vscode.ExtensionContext) { return; } }); - } else if (!CheckIfDirectoryExist(curWorkspace as string)) { + } else if (!checkIfDirectoryExists(curWorkspace as string)) { vscode.window .showWarningMessage( 'Invalid workspace:', @@ -369,7 +370,7 @@ export async function activate(context: vscode.ExtensionContext) { let disposableDebug = vscode.commands.registerCommand( 'wamride.debug', - () => { + async () => { if (!isWasmProject) { vscode.window.showErrorMessage('debug failed', { modal: true, @@ -378,6 +379,15 @@ export async function activate(context: vscode.ExtensionContext) { return; } + /* we should check again whether the user installed lldb, as this can be skipped during activation */ + try { + if (!isLLDBInstalled(context)) { + await promptInstallLLDB(context); + } + } catch (e) { + vscode.window.showWarningMessage((e as Error).message); + } + /* refuse to debug if build process failed */ if (!checkIfBuildSuccess()) { vscode.window.showErrorMessage('Debug failed', { @@ -582,7 +592,7 @@ export async function activate(context: vscode.ExtensionContext) { return; } }); - } else if (!CheckIfDirectoryExist(curWorkspace as string)) { + } else if (!checkIfDirectoryExists(curWorkspace as string)) { vscode.window .showWarningMessage( 'Invalid workspace:', @@ -686,6 +696,14 @@ export async function activate(context: vscode.ExtensionContext) { disposableToggleExcludeFile, disposableDebug ); + + try { + if (!isLLDBInstalled(context)) { + await promptInstallLLDB(context); + } + } catch (e) { + vscode.window.showWarningMessage((e as Error).message); + } } function openWindoWithSituation(uri: vscode.Uri) { @@ -736,13 +754,13 @@ export function writeIntoConfigFile( let prjConfigDir = path.join(currentPrjDir, '.wamr'); let configFilePath = path.join(prjConfigDir, 'compilation_config.json'); - WriteIntoFile(configFilePath, jsonStr); + writeIntoFile(configFilePath, jsonStr); } export function readFromConfigFile(): string { let prjConfigDir = path.join(currentPrjDir, '.wamr'); let configFilePath = path.join(prjConfigDir, 'compilation_config.json'); - return ReadFromFile(configFilePath); + return readFromFile(configFilePath); } /** @@ -854,7 +872,7 @@ function generateCMakeFile( .concat('\n', strSrcList) .concat('\n', strIncludeList); - WriteIntoFile(cmakeFilePath, fullStr); + writeIntoFile(cmakeFilePath, fullStr); } function getAllSrcFiles(_path: string) { diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts index cff54c7f02..348e5730a7 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts @@ -7,12 +7,14 @@ import fileSystem = require('fs'); import vscode = require('vscode'); import path = require('path'); import os = require('os'); +import request = require('request'); +import yauzl = require('yauzl'); /** * * @param path destination path */ -export function CreateDirectory( +export function createDirectory( dest: string, mode: string | number | null | undefined = undefined ): boolean { @@ -30,7 +32,7 @@ export function CreateDirectory( } let parent = path.dirname(dest); - if (!CreateDirectory(parent, mode)) { + if (!createDirectory(parent, mode)) { return false; } @@ -42,7 +44,7 @@ export function CreateDirectory( } } -export function CopyFiles(src: string, dest: string, flags?: number): boolean { +export function copyFiles(src: string, dest: string, flags?: number): boolean { try { fileSystem.copyFileSync(src, dest); return true; @@ -52,7 +54,7 @@ export function CopyFiles(src: string, dest: string, flags?: number): boolean { } } -export function WriteIntoFile(path: string, data: string): void { +export function writeIntoFile(path: string, data: string): void { try { fileSystem.writeFileSync(path, data, null); } catch (err) { @@ -60,7 +62,7 @@ export function WriteIntoFile(path: string, data: string): void { } } -export function ReadFromFile(path: string): string { +export function readFromFile(path: string): string { try { let data = fileSystem.readFileSync(path, { encoding: 'utf-8' }); return data as string; @@ -70,7 +72,7 @@ export function ReadFromFile(path: string): string { } } -export function WriteIntoFileAsync( +export function writeIntoFileAsync( path: string, data: string, callback: fileSystem.NoParamCallback @@ -83,7 +85,7 @@ export function WriteIntoFileAsync( } } -export function CheckIfDirectoryExist(path: string): boolean { +export function checkIfPathExists(path: string): boolean { try { if (fileSystem.existsSync(path)) { return true; @@ -96,6 +98,22 @@ export function CheckIfDirectoryExist(path: string): boolean { } } +export function checkIfDirectoryExists(path: string): boolean { + const doesPathExist = checkIfPathExists(path); + if (doesPathExist) { + return fileSystem.lstatSync(path).isDirectory(); + } + return false; +} + +export function checkIfFileExists(path: string): boolean { + const doesPathExist = checkIfPathExists(path); + if (doesPathExist) { + return fileSystem.lstatSync(path).isFile(); + } + return false; +} + export function checkFolderName(folderName: string) { let invalidCharacterArr: string[] = []; var valid = true; @@ -118,3 +136,54 @@ export function checkFolderName(folderName: string) { return valid; } + +export function downloadFile(url: string, destinationPath: string): Promise { + return new Promise((resolve, reject) => { + const file = fileSystem.createWriteStream(destinationPath); + const stream = request(url, undefined, (error, response, body) => { + if (response.statusCode !== 200) { + reject(new Error(`Download from ${url} failed with ${response.statusMessage}`)); + } + }).pipe(file); + stream.on("close", resolve); + stream.on("error", reject); + }); +} + +export function unzipFile(sourcePath: string, getDestinationFileName: (entryName: string) => string): Promise { + return new Promise((resolve, reject) => { + const unzippedFilePaths: string[] = []; + yauzl.open(sourcePath, { lazyEntries: true }, function(error, zipfile) { + if (error) { + reject(error); + return; + } + zipfile.readEntry(); + zipfile.on("entry", function(entry) { + // This entry is a directory so skip it + if (/\/$/.test(entry.fileName)) { + zipfile.readEntry(); + return; + } + + zipfile.openReadStream(entry, function(error, readStream) { + if (error) { + reject(error); + return; + } + readStream.on("end", () => zipfile.readEntry()); + const destinationFileName = getDestinationFileName(entry.fileName); + fileSystem.mkdirSync(path.dirname(destinationFileName), { recursive: true }); + + const file = fileSystem.createWriteStream(destinationFileName); + readStream.pipe(file).on("error", reject); + unzippedFilePaths.push(destinationFileName); + }); + }); + zipfile.on("end", function() { + zipfile.close(); + resolve(unzippedFilePaths); + }); + }); + }); +} \ No newline at end of file diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts new file mode 100644 index 0000000000..50d468b94a --- /dev/null +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +import * as vscode from 'vscode'; +import * as os from 'os'; +import * as path from 'path'; +import * as fs from 'fs'; +import { checkIfFileExists, downloadFile, unzipFile } from './directoryUtilities'; + +const LLDB_RESOURCE_DIR = "resource/debug"; +const LLDB_OS_DOWNLOAD_URL_SUFFIX_MAP: Partial> = { + "linux": "x86_64-ubuntu-22.04", + "darwin": "universal-macos-latest" +}; + +const WAMR_LLDB_NOT_SUPPORTED_ERROR = new Error("WAMR LLDB is not supported on this platform"); + +function getLLDBUnzipFilePath(destinationFolder: string, filename: string) { + const dirs = filename.split("/"); + if (dirs[0] === "inst") { + dirs.shift(); + } + + return path.join(destinationFolder, ...dirs); +} + +function getLLDBDownloadUrl(context: vscode.ExtensionContext): string { + const wamrVersion = require(path.join(context.extensionPath, "package.json")).version; + const lldbOsUrlSuffix = LLDB_OS_DOWNLOAD_URL_SUFFIX_MAP[os.platform()]; + + if (!lldbOsUrlSuffix) { + throw WAMR_LLDB_NOT_SUPPORTED_ERROR; + } + + return `https://github.com/bytecodealliance/wasm-micro-runtime/releases/download/WAMR-${wamrVersion}/wamr-lldb-${wamrVersion}-${lldbOsUrlSuffix}.zip`; +} + +export function isLLDBInstalled(context: vscode.ExtensionContext): boolean { + const extensionPath = context.extensionPath; + const lldbOSDir = os.platform(); + const lldbBinaryPath = path.join(extensionPath, LLDB_RESOURCE_DIR, lldbOSDir, "bin", "lldb"); + return checkIfFileExists(lldbBinaryPath); +} + +export async function promptInstallLLDB(context: vscode.ExtensionContext) { + const extensionPath = context.extensionPath; + const setupPrompt = "setup"; + const skipPrompt = "skip"; + const response = await vscode.window.showWarningMessage('No LLDB instance found. Setup now?', setupPrompt, skipPrompt); + + if (response === skipPrompt) { + return; + } + + const downloadUrl = getLLDBDownloadUrl(context); + const destinationDir = os.platform(); + + if (!downloadUrl) { + throw WAMR_LLDB_NOT_SUPPORTED_ERROR; + } + + const lldbDestinationFolder = path.join(extensionPath, LLDB_RESOURCE_DIR, destinationDir); + const lldbZipPath = path.join(lldbDestinationFolder, "bundle.zip"); + + vscode.window.showInformationMessage(`Downloading LLDB...`); + + await downloadFile(downloadUrl, lldbZipPath); + + vscode.window.showInformationMessage(`LLDB downloaded to ${lldbZipPath}. Installing...`); + + const lldbFiles = await unzipFile(lldbZipPath, filename => getLLDBUnzipFilePath(lldbDestinationFolder, filename)); + // Allow execution of lldb + lldbFiles.forEach(file => fs.chmodSync(file, "0775")); + + vscode.window.showInformationMessage(`LLDB installed at ${lldbDestinationFolder}`); + + // Remove the bundle.zip + fs.unlink(lldbZipPath, () => {}); +} + + diff --git a/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts b/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts index a7536564fc..29f1e05475 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts @@ -8,8 +8,8 @@ import * as path from 'path'; import * as fs from 'fs'; import * as os from 'os'; import { - CreateDirectory, - CopyFiles, + createDirectory, + copyFiles, checkFolderName, } from '../utilities/directoryUtilities'; import { getUri } from '../utilities/getUri'; @@ -84,16 +84,16 @@ export class NewProjectPanel { } } - CreateDirectory(path.join(ROOT_PATH, '.wamr')); - CreateDirectory(path.join(ROOT_PATH, 'include')); - CreateDirectory(path.join(ROOT_PATH, 'src')); + createDirectory(path.join(ROOT_PATH, '.wamr')); + createDirectory(path.join(ROOT_PATH, 'include')); + createDirectory(path.join(ROOT_PATH, 'src')); - CopyFiles( + copyFiles( path.join(EXT_PATH, 'resource/scripts/CMakeLists.txt'), path.join(ROOT_PATH, '.wamr/CMakeLists.txt') ); - CopyFiles( + copyFiles( path.join(EXT_PATH, 'resource/scripts/project.cmake'), path.join(ROOT_PATH, '.wamr/project.cmake') );