Implement source debugging for interpreter and AOT (#769)

Implement source debugging feature for classic interpreter and AOT:
- use `cmake -DWAMR_BUILD_DEBUG_INTERP=1` to enable interpreter debugging
- use `cmake -DWAMR_BUILD_DEBUG_AOT=1` to enable AOT debugging

See doc/source_debugging.md for more details.
This commit is contained in:
Wenyong Huang
2021-09-29 13:36:46 +08:00
committed by GitHub
parent b5a67cb91e
commit 9ef37dd781
55 changed files with 10092 additions and 63 deletions

View File

@ -10,6 +10,9 @@
#include "wasm_opcode.h"
#include "wasm_runtime.h"
#include "../common/wasm_native.h"
#if WASM_ENABLE_DEBUG_INTERP != 0
#include "../libraries/debug-engine/debug_engine.h"
#endif
/* Read a value of given type from the address pointed to by the given
pointer and increase the pointer to the position just after the
@ -2934,6 +2937,10 @@ load_from_sections(WASMModule *module, WASMSection *sections,
if (section->section_type == SECTION_TYPE_CODE) {
buf_code = section->section_body;
buf_code_end = buf_code + section->section_body_size;
#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0
module->buf_code = (uint8 *)buf_code;
module->buf_code_size = section->section_body_size;
#endif
}
else if (section->section_type == SECTION_TYPE_FUNC) {
buf_func = section->section_body;
@ -3296,10 +3303,26 @@ create_module(char *error_buf, uint32 error_buf_size)
#if WASM_ENABLE_MULTI_MODULE != 0
module->import_module_list = &module->import_module_list_head;
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
bh_list_init(&module->fast_opcode_list);
#endif
return module;
}
#if WASM_ENABLE_DEBUG_INTERP != 0
static void
record_fast_op(WASMModule *module, uint8 * pos, uint8 orig_op)
{
WASMFastOPCodeNode *fast_op = wasm_runtime_malloc(sizeof(WASMFastOPCodeNode));
if (fast_op) {
fast_op->offset = pos - module->load_addr;
fast_op->orig_op = orig_op;
bh_list_insert(&module->fast_opcode_list, fast_op);
}
}
#endif
WASMModule *
wasm_loader_load_from_sections(WASMSection *section_list,
char *error_buf, uint32 error_buf_size)
@ -3493,6 +3516,11 @@ wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_bu
return NULL;
}
#if WASM_ENABLE_DEBUG_INTERP != 0
module->load_addr = (uint8 *)buf;
module->load_size = size;
#endif
if (!load(buf, size, module, error_buf, error_buf_size)) {
goto fail;
}
@ -3593,7 +3621,6 @@ wasm_loader_unload(WASMModule *module)
*/
wasm_runtime_free(node);
/*
*
* the module file reading buffer will be released
* in runtime_destroy()
*/
@ -3601,12 +3628,21 @@ wasm_loader_unload(WASMModule *module)
}
}
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
WASMFastOPCodeNode *fast_opcode =
bh_list_first_elem(&module->fast_opcode_list);
while(fast_opcode) {
WASMFastOPCodeNode * next = bh_list_elem_next(fast_opcode);
wasm_runtime_free(fast_opcode);
fast_opcode = next;
}
#endif
wasm_runtime_free(module);
}
bool
wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
wasm_loader_find_block_addr(WASMExecEnv *exec_env,
BlockAddr *block_addr_cache,
const uint8 *start_addr,
const uint8 *code_end_addr,
uint8 label_type,
@ -3638,7 +3674,9 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
while (p < code_end_addr) {
opcode = *p++;
#if WASM_ENABLE_DEBUG_INTERP != 0
op_break_retry:
#endif
switch (opcode) {
case WASM_OP_UNREACHABLE:
case WASM_OP_NOP:
@ -4156,6 +4194,31 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
break;
}
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
case DEBUG_OP_BREAK: {
WASMDebugInstance *debug_instance =
wasm_exec_env_get_instance(exec_env);
char orignal_opcode[1];
uint64 size = 1;
WASMModuleInstance *module_inst =
(WASMModuleInstance *)exec_env->module_inst;
uint64 offset = (p - 1) >= module_inst->module->load_addr
? (p - 1) - module_inst->module->load_addr
: ~0;
if (debug_instance) {
if (wasm_debug_instance_get_obj_mem(
debug_instance, offset, orignal_opcode, &size)
&& size == 1) {
LOG_VERBOSE("WASM loader find OP_BREAK , recover it "
"with %02x: ",
orignal_opcode[0]);
opcode = orignal_opcode[0];
goto op_break_retry;
}
}
break;
}
#endif
default:
return false;
@ -6317,6 +6380,9 @@ handle_op_block_and_loop:
* to new extended opcode so that interpreter can resolve the
* block quickly.
*/
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p - 2, *(p - 2));
#endif
*(p - 2) = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK);
#endif
}
@ -7196,13 +7262,28 @@ handle_op_block_and_loop:
#else
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
if (local_offset < 0x80) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = EXT_OP_GET_LOCAL_FAST;
if (is_32bit_type(local_type))
if (is_32bit_type(local_type)) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)local_offset;
else
}
else {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)(local_offset | 0x80);
while (p_org < p)
}
while (p_org < p) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = WASM_OP_NOP;
}
}
#endif
#endif
@ -7254,13 +7335,28 @@ handle_op_block_and_loop:
#else
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
if (local_offset < 0x80) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = EXT_OP_SET_LOCAL_FAST;
if (is_32bit_type(local_type))
if (is_32bit_type(local_type)) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)local_offset;
else
}
else {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)(local_offset | 0x80);
while (p_org < p)
}
while (p_org < p) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = WASM_OP_NOP;
}
}
#endif
#endif
@ -7309,13 +7405,28 @@ handle_op_block_and_loop:
#else
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
if (local_offset < 0x80) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = EXT_OP_TEE_LOCAL_FAST;
if (is_32bit_type(local_type))
if (is_32bit_type(local_type)) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)local_offset;
else
}
else {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = (uint8)(local_offset | 0x80);
while (p_org < p)
}
while (p_org < p) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org++ = WASM_OP_NOP;
}
}
#endif
#endif
@ -7344,6 +7455,9 @@ handle_op_block_and_loop:
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
if (global_type == VALUE_TYPE_I64
|| global_type == VALUE_TYPE_F64) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org = WASM_OP_GET_GLOBAL_64;
}
#endif
@ -7393,10 +7507,16 @@ handle_op_block_and_loop:
#if WASM_ENABLE_FAST_INTERP == 0
if (global_type == VALUE_TYPE_I64
|| global_type == VALUE_TYPE_F64) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org = WASM_OP_SET_GLOBAL_64;
}
else if (module->aux_stack_size > 0
&& global_idx == module->aux_stack_top_global_index) {
#if WASM_ENABLE_DEBUG_INTERP != 0
record_fast_op(module, p_org, *p_org);
#endif
*p_org = WASM_OP_SET_GLOBAL_AUX_STACK;
}
#else /* else of WASM_ENABLE_FAST_INTERP */