From 4b00432c1a374d9b24a0c57d66be35f7e4dea021 Mon Sep 17 00:00:00 2001 From: Xu Jun <693788454@qq.com> Date: Mon, 8 Aug 2022 11:15:30 +0800 Subject: [PATCH] Fix dump call stack issue in interpreter (#1358) Fix dump call stack issue in interpreter introduced by hw bound check: the call stack isn't dumped if the exception is thrown and caught by signal handler. And restore the wasm stack frame to the original status after calling a wasm function. --- core/iwasm/interpreter/wasm_interp.h | 12 +++++++++++ core/iwasm/interpreter/wasm_interp_classic.c | 20 +++++++++++++++++++ core/iwasm/interpreter/wasm_interp_fast.c | 21 ++++++++++++++++++++ core/iwasm/interpreter/wasm_runtime.c | 9 +++++++++ 4 files changed, 62 insertions(+) diff --git a/core/iwasm/interpreter/wasm_interp.h b/core/iwasm/interpreter/wasm_interp.h index d3692ff21..9010c942f 100644 --- a/core/iwasm/interpreter/wasm_interp.h +++ b/core/iwasm/interpreter/wasm_interp.h @@ -89,6 +89,18 @@ wasm_interp_call_wasm(struct WASMModuleInstance *module_inst, struct WASMFunctionInstance *function, uint32 argc, uint32 argv[]); +/** + * @brief Restore the wasm stack frame to the last native frame or the begging + * of the whole stack + * @note e.g. for stack "begin --> interp --> interp", it will back to the + * "begin", for stack "begin --> interp --> native --> interp", it will become + * "begin --> interp --> native" + * + * @param exec_env the execution environment + */ +void +wasm_interp_restore_wasm_frame(struct WASMExecEnv *exec_env); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index ab66bd093..24071cf18 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -781,6 +781,26 @@ FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame) wasm_exec_env_free_wasm_frame(exec_env, frame); } +void +wasm_interp_restore_wasm_frame(WASMExecEnv *exec_env) +{ + WASMInterpFrame *cur_frame, *prev_frame; + + cur_frame = wasm_exec_env_get_cur_frame(exec_env); + while (cur_frame) { + prev_frame = cur_frame->prev_frame; + if (cur_frame->ip) { + /* FREE_FRAME just set the wasm_stack.s.top pointer, we only need to + * call it once */ + FREE_FRAME(exec_env, cur_frame); + break; + } + cur_frame = prev_frame; + } + + wasm_exec_env_set_cur_frame(exec_env, cur_frame); +} + static void wasm_interp_call_func_native(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 184b0dc9b..49cbce5ca 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -845,6 +845,26 @@ FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame) wasm_exec_env_free_wasm_frame(exec_env, frame); } +void +wasm_interp_restore_wasm_frame(WASMExecEnv *exec_env) +{ + WASMInterpFrame *cur_frame, *prev_frame; + + cur_frame = wasm_exec_env_get_cur_frame(exec_env); + while (cur_frame) { + prev_frame = cur_frame->prev_frame; + if (cur_frame->ip) { + /* FREE_FRAME just set the wasm_stack.s.top pointer, we only need to + * call it once */ + FREE_FRAME(exec_env, cur_frame); + break; + } + cur_frame = prev_frame; + } + + wasm_exec_env_set_cur_frame(exec_env, cur_frame); +} + static void wasm_interp_call_func_native(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, @@ -3925,6 +3945,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, wasm_interp_dump_call_stack(exec_env, true, NULL, 0); } #endif + LOG_DEBUG("meet an exception %s", wasm_get_exception(module_inst)); } wasm_exec_env_set_cur_frame(exec_env, prev_frame); diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 6009b7492..1d590bd62 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1986,6 +1986,15 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, ret = false; } + if (wasm_get_exception(module_inst)) { +#if WASM_ENABLE_DUMP_CALL_STACK != 0 + if (wasm_interp_create_call_stack(exec_env)) { + wasm_interp_dump_call_stack(exec_env, true, NULL, 0); + } +#endif + wasm_interp_restore_wasm_frame(exec_env); + } + jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); bh_assert(&jmpbuf_node == jmpbuf_node_pop); if (!exec_env->jmpbuf_stack_top) {