diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 150d55626..0c97df44d 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -14,6 +14,7 @@ #endif #if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 #include "../libraries/thread-mgr/thread_manager.h" +#include "../libraries/debug-engine/debug_engine.h" #endif typedef int32 CellType_I32; @@ -930,6 +931,9 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 #define HANDLE_OP_END() \ do { \ + /* Record the current frame_ip, so when exception occurs, \ + debugger can know the exact opcode who caused the exception */ \ + frame_ip_orig = frame_ip; \ while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \ && exec_env->current_status->step_count++ == 1) { \ exec_env->current_status->step_count = 0; \ @@ -1007,6 +1011,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 cache_index, type_index, param_cell_num, cell_num; uint8 value_type; +#if WASM_ENABLE_DEBUG_INTERP != 0 + uint8 *frame_ip_orig = NULL; +#endif + #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op DEFINE_GOTO_TABLE(const void *, handle_table); @@ -3734,6 +3742,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, wasm_set_exception(module, "out of bounds memory access"); got_exception: +#if WASM_ENABLE_DEBUG_INTERP != 0 + if (wasm_exec_env_get_instance(exec_env) != NULL) { + uint8 *frame_ip_temp = frame_ip; + frame_ip = frame_ip_orig; + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP); + CHECK_SUSPEND_FLAGS(); + frame_ip = frame_ip_temp; + } +#endif SYNC_ALL_TO_FRAME(); return; diff --git a/core/iwasm/libraries/debug-engine/debug_engine.c b/core/iwasm/libraries/debug-engine/debug_engine.c index a20d19669..31f45a1f8 100644 --- a/core/iwasm/libraries/debug-engine/debug_engine.c +++ b/core/iwasm/libraries/debug-engine/debug_engine.c @@ -456,7 +456,7 @@ wasm_debug_instance_destroy(WASMCluster *cluster) } } -static WASMExecEnv * +WASMExecEnv * wasm_debug_instance_get_current_env(WASMDebugInstance *instance) { WASMExecEnv *exec_env = NULL; @@ -829,7 +829,10 @@ WASMDebugInstance * wasm_exec_env_get_instance(WASMExecEnv *exec_env) { WASMDebugInstance *instance = NULL; - bh_assert(g_debug_engine); + + if (!g_debug_engine) { + return NULL; + } os_mutex_lock(&g_debug_engine->instance_list_lock); instance = bh_list_first_elem(&g_debug_engine->debug_instance_list); diff --git a/core/iwasm/libraries/debug-engine/debug_engine.h b/core/iwasm/libraries/debug-engine/debug_engine.h index 6057b0ce3..015f20d7b 100644 --- a/core/iwasm/libraries/debug-engine/debug_engine.h +++ b/core/iwasm/libraries/debug-engine/debug_engine.h @@ -128,6 +128,9 @@ wasm_debug_set_engine_active(bool active); bool wasm_debug_get_engine_active(void); +WASMExecEnv * +wasm_debug_instance_get_current_env(WASMDebugInstance *instance); + uint64 wasm_debug_instance_get_pid(WASMDebugInstance *instance); diff --git a/core/iwasm/libraries/debug-engine/handler.c b/core/iwasm/libraries/debug-engine/handler.c index 1b9bd8de4..4761bd99f 100644 --- a/core/iwasm/libraries/debug-engine/handler.c +++ b/core/iwasm/libraries/debug-engine/handler.c @@ -334,6 +334,8 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid) char pc_string[17]; uint32 tids_count, i = 0; uint32 gdb_status = status; + WASMExecEnv *exec_env; + const char *exception; if (status == 0) { os_mutex_lock(&tmpbuf_lock); @@ -370,20 +372,41 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid) mem2hex((void *)&pc, pc_string, 8); pc_string[8 * 2] = '\0'; - if (status == WAMR_SIG_TRAP) { - len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, - "thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc, - pc_string, "breakpoint"); + exec_env = wasm_debug_instance_get_current_env( + (WASMDebugInstance *)server->thread->debug_instance); + exception = + wasm_runtime_get_exception(wasm_runtime_get_module_inst(exec_env)); + if (exception) { + /* When exception occurs, use reason:exception so the description can be + * correctly processed by LLDB */ + uint32 exception_len = strlen(exception); + len += + snprintf(tmpbuf + len, sizeof(tmpbuf) - len, + "thread-pcs:%" PRIx64 ";00:%s;reason:%s;description:", pc, + pc_string, "exception"); + /* The description should be encoded as HEX */ + for (i = 0; i < exception_len; i++) { + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, "%02x", + exception[i]); + } + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, ";"); } - else if (status == WAMR_SIG_SINGSTEP) { - len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, - "thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc, - pc_string, "trace"); - } - else if (status > 0) { - len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, - "thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc, - pc_string, "signal"); + else { + if (status == WAMR_SIG_TRAP) { + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, + "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc, + pc_string, "breakpoint"); + } + else if (status == WAMR_SIG_SINGSTEP) { + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, + "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc, + pc_string, "trace"); + } + else if (status > 0) { + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, + "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc, + pc_string, "signal"); + } } write_packet(server, tmpbuf); os_mutex_unlock(&tmpbuf_lock);