mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-13 21:21:22 +00:00
Enable dump call stack to a buffer (#1244)
Enable dump call stack to a buffer, use API `wasm_runtime_get_call_stack_buf_size` to get the required buffer size and use API `wasm_runtime_dump_call_stack_to_buf` to dump call stack to a buffer
This commit is contained in:
parent
53b775aa4b
commit
471cac4719
|
@ -1511,7 +1511,9 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
|
||||||
|
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
aot_dump_call_stack(exec_env);
|
if (aot_create_call_stack(exec_env)) {
|
||||||
|
aot_dump_call_stack(exec_env, true, NULL, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1568,7 +1570,9 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
|
||||||
|
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
if (aot_get_exception(module_inst)) {
|
if (aot_get_exception(module_inst)) {
|
||||||
aot_dump_call_stack(exec_env);
|
if (aot_create_call_stack(exec_env)) {
|
||||||
|
aot_dump_call_stack(exec_env, true, NULL, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3018,38 +3022,24 @@ aot_free_frame(WASMExecEnv *exec_env)
|
||||||
|| (WASM_ENABLE_PERF_PROFILING != 0) */
|
|| (WASM_ENABLE_PERF_PROFILING != 0) */
|
||||||
|
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
void
|
bool
|
||||||
aot_dump_call_stack(WASMExecEnv *exec_env)
|
aot_create_call_stack(struct WASMExecEnv *exec_env)
|
||||||
{
|
{
|
||||||
AOTFrame *cur_frame = (AOTFrame *)exec_env->cur_frame,
|
AOTFrame *cur_frame = (AOTFrame *)exec_env->cur_frame,
|
||||||
*first_frame = cur_frame;
|
*first_frame = cur_frame;
|
||||||
AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
|
AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
|
||||||
const char *func_name;
|
|
||||||
uint32 n = 0;
|
uint32 n = 0;
|
||||||
|
|
||||||
os_printf("\n");
|
|
||||||
while (cur_frame) {
|
while (cur_frame) {
|
||||||
func_name =
|
|
||||||
get_func_name_from_index(module_inst, cur_frame->func_index);
|
|
||||||
|
|
||||||
/* function name not exported, print number instead */
|
|
||||||
if (func_name == NULL) {
|
|
||||||
os_printf("#%02d $f%d \n", n, cur_frame->func_index);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
os_printf("#%02d %s \n", n, func_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frame = cur_frame->prev_frame;
|
cur_frame = cur_frame->prev_frame;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
os_printf("\n");
|
|
||||||
|
|
||||||
/* release previous stack frames and create new ones */
|
/* release previous stack frames and create new ones */
|
||||||
if (!bh_vector_destroy(module_inst->frames.ptr)
|
if (!bh_vector_destroy(module_inst->frames.ptr)
|
||||||
|| !bh_vector_init(module_inst->frames.ptr, n, sizeof(WASMCApiFrame),
|
|| !bh_vector_init(module_inst->frames.ptr, n, sizeof(WASMCApiFrame),
|
||||||
false)) {
|
false)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frame = first_frame;
|
cur_frame = first_frame;
|
||||||
|
@ -3059,14 +3049,85 @@ aot_dump_call_stack(WASMExecEnv *exec_env)
|
||||||
frame.module_offset = 0;
|
frame.module_offset = 0;
|
||||||
frame.func_index = cur_frame->func_index;
|
frame.func_index = cur_frame->func_index;
|
||||||
frame.func_offset = 0;
|
frame.func_offset = 0;
|
||||||
|
frame.func_name_wp =
|
||||||
|
get_func_name_from_index(module_inst, cur_frame->func_index);
|
||||||
|
|
||||||
if (!bh_vector_append(module_inst->frames.ptr, &frame)) {
|
if (!bh_vector_append(module_inst->frames.ptr, &frame)) {
|
||||||
bh_vector_destroy(module_inst->frames.ptr);
|
bh_vector_destroy(module_inst->frames.ptr);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frame = cur_frame->prev_frame;
|
cur_frame = cur_frame->prev_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRINT_OR_DUMP() \
|
||||||
|
do { \
|
||||||
|
total_len += \
|
||||||
|
wasm_runtime_dump_line_buf_impl(line_buf, print, &buf, &len); \
|
||||||
|
if ((!print) && buf && (len == 0)) { \
|
||||||
|
return total_len; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
uint32
|
||||||
|
aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len)
|
||||||
|
{
|
||||||
|
AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
|
||||||
|
uint32 n = 0, total_len = 0, total_frames;
|
||||||
|
/* reserve 256 bytes for line buffer, any line longer than 256 bytes
|
||||||
|
* will be truncated */
|
||||||
|
char line_buf[256];
|
||||||
|
|
||||||
|
if (!module_inst->frames.ptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_frames = bh_vector_size(module_inst->frames.ptr);
|
||||||
|
if (total_frames == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(line_buf, sizeof(line_buf), "\n");
|
||||||
|
PRINT_OR_DUMP();
|
||||||
|
|
||||||
|
while (n < total_frames) {
|
||||||
|
WASMCApiFrame frame = { 0 };
|
||||||
|
uint32 line_length, i;
|
||||||
|
|
||||||
|
if (!bh_vector_get(module_inst->frames.ptr, n, &frame)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* function name not exported, print number instead */
|
||||||
|
if (frame.func_name_wp == NULL) {
|
||||||
|
line_length = snprintf(line_buf, sizeof(line_buf), "#%02d $f%d\n",
|
||||||
|
n, frame.func_index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
line_length = snprintf(line_buf, sizeof(line_buf), "#%02d %s\n", n,
|
||||||
|
frame.func_name_wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_length >= sizeof(line_buf)) {
|
||||||
|
uint32 line_buffer_len = sizeof(line_buf);
|
||||||
|
/* If line too long, ensure the last character is '\n' */
|
||||||
|
for (i = line_buffer_len - 5; i < line_buffer_len - 2; i++) {
|
||||||
|
line_buf[i] = '.';
|
||||||
|
}
|
||||||
|
line_buf[line_buffer_len - 2] = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_OR_DUMP();
|
||||||
|
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
snprintf(line_buf, sizeof(line_buf), "\n");
|
||||||
|
PRINT_OR_DUMP();
|
||||||
|
|
||||||
|
return total_len + 1;
|
||||||
}
|
}
|
||||||
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
|
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
|
||||||
|
|
||||||
|
|
|
@ -731,8 +731,24 @@ aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
|
||||||
void
|
void
|
||||||
aot_free_frame(WASMExecEnv *exec_env);
|
aot_free_frame(WASMExecEnv *exec_env);
|
||||||
|
|
||||||
void
|
bool
|
||||||
aot_dump_call_stack(WASMExecEnv *exec_env);
|
aot_create_call_stack(struct WASMExecEnv *exec_env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dump wasm call stack or get the size
|
||||||
|
*
|
||||||
|
* @param exec_env the execution environment
|
||||||
|
* @param print whether to print to stdout or not
|
||||||
|
* @param buf buffer to store the dumped content
|
||||||
|
* @param len length of the buffer
|
||||||
|
*
|
||||||
|
* @return when print is true, return the bytes printed out to stdout; when
|
||||||
|
* print is false and buf is NULL, return the size required to store the
|
||||||
|
* callstack content; when print is false and buf is not NULL, return the size
|
||||||
|
* dumped to the buffer, 0 means error and data in buf may be invalid
|
||||||
|
*/
|
||||||
|
uint32
|
||||||
|
aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len);
|
||||||
|
|
||||||
void
|
void
|
||||||
aot_dump_perf_profiling(const AOTModuleInstance *module_inst);
|
aot_dump_perf_profiling(const AOTModuleInstance *module_inst);
|
||||||
|
|
|
@ -4527,6 +4527,30 @@ wasm_externref_retain(uint32 externref_idx)
|
||||||
#endif /* end of WASM_ENABLE_REF_TYPES */
|
#endif /* end of WASM_ENABLE_REF_TYPES */
|
||||||
|
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
|
uint32
|
||||||
|
wasm_runtime_dump_line_buf_impl(const char *line_buf, bool dump_or_print,
|
||||||
|
char **buf, uint32 *len)
|
||||||
|
{
|
||||||
|
if (dump_or_print) {
|
||||||
|
return (uint32)os_printf("%s", line_buf);
|
||||||
|
}
|
||||||
|
else if (*buf) {
|
||||||
|
uint32 dump_len;
|
||||||
|
|
||||||
|
dump_len = snprintf(*buf, *len, "%s", line_buf);
|
||||||
|
if (dump_len >= *len) {
|
||||||
|
dump_len = *len;
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = *len - dump_len;
|
||||||
|
*buf = *buf + dump_len;
|
||||||
|
return dump_len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return strlen(line_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wasm_runtime_dump_call_stack(WASMExecEnv *exec_env)
|
wasm_runtime_dump_call_stack(WASMExecEnv *exec_env)
|
||||||
{
|
{
|
||||||
|
@ -4534,15 +4558,56 @@ wasm_runtime_dump_call_stack(WASMExecEnv *exec_env)
|
||||||
wasm_exec_env_get_module_inst(exec_env);
|
wasm_exec_env_get_module_inst(exec_env);
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||||
wasm_interp_dump_call_stack(exec_env);
|
wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_AOT != 0
|
#if WASM_ENABLE_AOT != 0
|
||||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||||
aot_dump_call_stack(exec_env);
|
aot_dump_call_stack(exec_env, true, NULL, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32
|
||||||
|
wasm_runtime_get_call_stack_buf_size(wasm_exec_env_t exec_env)
|
||||||
|
{
|
||||||
|
WASMModuleInstanceCommon *module_inst =
|
||||||
|
wasm_exec_env_get_module_inst(exec_env);
|
||||||
|
|
||||||
|
#if WASM_ENABLE_INTERP != 0
|
||||||
|
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||||
|
return wasm_interp_dump_call_stack(exec_env, false, NULL, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_AOT != 0
|
||||||
|
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||||
|
return aot_dump_call_stack(exec_env, false, NULL, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32
|
||||||
|
wasm_runtime_dump_call_stack_to_buf(wasm_exec_env_t exec_env, char *buf,
|
||||||
|
uint32 len)
|
||||||
|
{
|
||||||
|
WASMModuleInstanceCommon *module_inst =
|
||||||
|
wasm_exec_env_get_module_inst(exec_env);
|
||||||
|
|
||||||
|
#if WASM_ENABLE_INTERP != 0
|
||||||
|
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||||
|
return wasm_interp_dump_call_stack(exec_env, false, buf, len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_AOT != 0
|
||||||
|
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||||
|
return aot_dump_call_stack(exec_env, false, buf, len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
|
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -404,6 +404,7 @@ typedef struct wasm_frame_t {
|
||||||
uint32 module_offset;
|
uint32 module_offset;
|
||||||
uint32 func_index;
|
uint32 func_index;
|
||||||
uint32 func_offset;
|
uint32 func_offset;
|
||||||
|
const char *func_name_wp;
|
||||||
} WASMCApiFrame;
|
} WASMCApiFrame;
|
||||||
|
|
||||||
/* See wasm_export.h for description */
|
/* See wasm_export.h for description */
|
||||||
|
@ -803,6 +804,28 @@ void
|
||||||
wasm_externref_cleanup(WASMModuleInstanceCommon *module_inst);
|
wasm_externref_cleanup(WASMModuleInstanceCommon *module_inst);
|
||||||
#endif /* end of WASM_ENABLE_REF_TYPES */
|
#endif /* end of WASM_ENABLE_REF_TYPES */
|
||||||
|
|
||||||
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
|
/**
|
||||||
|
* @brief Internal implementation for dumping or printing callstack line
|
||||||
|
*
|
||||||
|
* @note if dump_or_print is true, then print to stdout directly;
|
||||||
|
* if dump_or_print is false, but *buf is NULL, then return the length of the
|
||||||
|
* line;
|
||||||
|
* if dump_or_print is false, and *buf is not NULL, then dump content to
|
||||||
|
* the memory pointed by *buf, and adjust *buf and *len according to actual
|
||||||
|
* bytes dumped, and return the actual dumped length
|
||||||
|
*
|
||||||
|
* @param line_buf current line to dump or print
|
||||||
|
* @param dump_or_print whether to print to stdout or dump to buf
|
||||||
|
* @param buf [INOUT] pointer to the buffer
|
||||||
|
* @param len [INOUT] pointer to remaining length
|
||||||
|
* @return bytes printed to stdout or dumped to buf
|
||||||
|
*/
|
||||||
|
uint32
|
||||||
|
wasm_runtime_dump_line_buf_impl(const char *line_buf, bool dump_or_print,
|
||||||
|
char **buf, uint32 *len);
|
||||||
|
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK != 0 */
|
||||||
|
|
||||||
/* Get module of the current exec_env */
|
/* Get module of the current exec_env */
|
||||||
WASMModuleCommon *
|
WASMModuleCommon *
|
||||||
wasm_exec_env_get_module(WASMExecEnv *exec_env);
|
wasm_exec_env_get_module(WASMExecEnv *exec_env);
|
||||||
|
|
|
@ -919,6 +919,7 @@ wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env);
|
||||||
*/
|
*/
|
||||||
WASM_RUNTIME_API_EXTERN void
|
WASM_RUNTIME_API_EXTERN void
|
||||||
wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data);
|
wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the user data within execution environment.
|
* Get the user data within execution environment.
|
||||||
*
|
*
|
||||||
|
@ -963,7 +964,7 @@ WASM_RUNTIME_API_EXTERN void
|
||||||
wasm_runtime_set_max_thread_num(uint32_t num);
|
wasm_runtime_set_max_thread_num(uint32_t num);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* spawn a new exec_env, the spawned exec_env
|
* Spawn a new exec_env, the spawned exec_env
|
||||||
* can be used in other threads
|
* can be used in other threads
|
||||||
*
|
*
|
||||||
* @param num the original exec_env
|
* @param num the original exec_env
|
||||||
|
@ -982,7 +983,7 @@ WASM_RUNTIME_API_EXTERN void
|
||||||
wasm_runtime_destroy_spawned_exec_env(wasm_exec_env_t exec_env);
|
wasm_runtime_destroy_spawned_exec_env(wasm_exec_env_t exec_env);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* spawn a thread from the given exec_env
|
* Spawn a thread from the given exec_env
|
||||||
*
|
*
|
||||||
* @param exec_env the original exec_env
|
* @param exec_env the original exec_env
|
||||||
* @param tid thread id to be returned to the caller
|
* @param tid thread id to be returned to the caller
|
||||||
|
@ -996,7 +997,7 @@ wasm_runtime_spawn_thread(wasm_exec_env_t exec_env, wasm_thread_t *tid,
|
||||||
wasm_thread_callback_t callback, void *arg);
|
wasm_thread_callback_t callback, void *arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* waits a spawned thread to terminate
|
* Waits a spawned thread to terminate
|
||||||
*
|
*
|
||||||
* @param tid thread id
|
* @param tid thread id
|
||||||
* @param retval if not NULL, output the return value of the thread
|
* @param retval if not NULL, output the return value of the thread
|
||||||
|
@ -1046,13 +1047,41 @@ WASM_RUNTIME_API_EXTERN bool
|
||||||
wasm_externref_retain(uint32_t externref_idx);
|
wasm_externref_retain(uint32_t externref_idx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dump the call stack
|
* Dump the call stack to stdout
|
||||||
*
|
*
|
||||||
* @param exec_env the execution environment
|
* @param exec_env the execution environment
|
||||||
*/
|
*/
|
||||||
WASM_RUNTIME_API_EXTERN void
|
WASM_RUNTIME_API_EXTERN void
|
||||||
wasm_runtime_dump_call_stack(wasm_exec_env_t exec_env);
|
wasm_runtime_dump_call_stack(wasm_exec_env_t exec_env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size required to store the call stack contents, including
|
||||||
|
* the space for terminating null byte ('\0')
|
||||||
|
*
|
||||||
|
* @param exec_env the execution environment
|
||||||
|
*
|
||||||
|
* @return size required to store the contents, 0 means error
|
||||||
|
*/
|
||||||
|
WASM_RUNTIME_API_EXTERN uint32_t
|
||||||
|
wasm_runtime_get_call_stack_buf_size(wasm_exec_env_t exec_env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump the call stack to buffer.
|
||||||
|
*
|
||||||
|
* @note this function is not thread-safe, please only use this API
|
||||||
|
* when the exec_env is not executing
|
||||||
|
*
|
||||||
|
* @param exec_env the execution environment
|
||||||
|
* @param buf buffer to store the dumped content
|
||||||
|
* @param len length of the buffer
|
||||||
|
*
|
||||||
|
* @return bytes dumped to the buffer, including the terminating null
|
||||||
|
* byte ('\0'), 0 means error and data in buf may be invalid
|
||||||
|
*/
|
||||||
|
WASM_RUNTIME_API_EXTERN uint32_t
|
||||||
|
wasm_runtime_dump_call_stack_to_buf(wasm_exec_env_t exec_env, char *buf,
|
||||||
|
uint32_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a custom section by name
|
* Get a custom section by name
|
||||||
*
|
*
|
||||||
|
|
|
@ -3834,7 +3834,9 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
wasm_interp_dump_call_stack(exec_env);
|
if (wasm_interp_create_call_stack(exec_env)) {
|
||||||
|
wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
LOG_DEBUG("meet an exception %s", wasm_get_exception(module_inst));
|
LOG_DEBUG("meet an exception %s", wasm_get_exception(module_inst));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3847,7 +3847,9 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
wasm_interp_dump_call_stack(exec_env);
|
if (wasm_interp_create_call_stack(exec_env)) {
|
||||||
|
wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2485,8 +2485,8 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst,
|
||||||
|| (WASM_ENABLE_MEMORY_TRACING != 0) */
|
|| (WASM_ENABLE_MEMORY_TRACING != 0) */
|
||||||
|
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
void
|
bool
|
||||||
wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
|
wasm_interp_create_call_stack(struct WASMExecEnv *exec_env)
|
||||||
{
|
{
|
||||||
WASMModuleInstance *module_inst =
|
WASMModuleInstance *module_inst =
|
||||||
(WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
|
(WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
|
||||||
|
@ -2507,12 +2507,12 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
|
||||||
if (!bh_vector_destroy(module_inst->frames)
|
if (!bh_vector_destroy(module_inst->frames)
|
||||||
|| !bh_vector_init(module_inst->frames, n, sizeof(WASMCApiFrame),
|
|| !bh_vector_init(module_inst->frames, n, sizeof(WASMCApiFrame),
|
||||||
false)) {
|
false)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frame = first_frame;
|
cur_frame = first_frame;
|
||||||
n = 0;
|
n = 0;
|
||||||
os_printf("\n");
|
|
||||||
while (cur_frame) {
|
while (cur_frame) {
|
||||||
WASMCApiFrame frame = { 0 };
|
WASMCApiFrame frame = { 0 };
|
||||||
WASMFunctionInstance *func_inst = cur_frame->function;
|
WASMFunctionInstance *func_inst = cur_frame->function;
|
||||||
|
@ -2560,20 +2560,86 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* function name not exported, print number instead */
|
frame.func_name_wp = func_name;
|
||||||
if (func_name == NULL) {
|
|
||||||
os_printf("#%02d $f%d \n", n, func_inst - module_inst->functions);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
os_printf("#%02d %s \n", n, func_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keep print */
|
if (!bh_vector_append(module_inst->frames, &frame)) {
|
||||||
bh_vector_append(module_inst->frames, &frame);
|
bh_vector_destroy(module_inst->frames);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
cur_frame = cur_frame->prev_frame;
|
cur_frame = cur_frame->prev_frame;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
os_printf("\n");
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRINT_OR_DUMP() \
|
||||||
|
do { \
|
||||||
|
total_len += \
|
||||||
|
wasm_runtime_dump_line_buf_impl(line_buf, print, &buf, &len); \
|
||||||
|
if ((!print) && buf && (len == 0)) { \
|
||||||
|
return total_len; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
uint32
|
||||||
|
wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf,
|
||||||
|
uint32 len)
|
||||||
|
{
|
||||||
|
WASMModuleInstance *module_inst =
|
||||||
|
(WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
|
||||||
|
uint32 n = 0, total_len = 0, total_frames;
|
||||||
|
/* reserve 256 bytes for line buffer, any line longer than 256 bytes
|
||||||
|
* will be truncated */
|
||||||
|
char line_buf[256];
|
||||||
|
|
||||||
|
if (!module_inst->frames) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_frames = bh_vector_size(module_inst->frames);
|
||||||
|
if (total_frames == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(line_buf, sizeof(line_buf), "\n");
|
||||||
|
PRINT_OR_DUMP();
|
||||||
|
|
||||||
|
while (n < total_frames) {
|
||||||
|
WASMCApiFrame frame = { 0 };
|
||||||
|
uint32 line_length, i;
|
||||||
|
|
||||||
|
if (!bh_vector_get(module_inst->frames, n, &frame)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* function name not exported, print number instead */
|
||||||
|
if (frame.func_name_wp == NULL) {
|
||||||
|
line_length = snprintf(line_buf, sizeof(line_buf), "#%02d $f%d\n",
|
||||||
|
n, frame.func_index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
line_length = snprintf(line_buf, sizeof(line_buf), "#%02d %s\n", n,
|
||||||
|
frame.func_name_wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_length >= sizeof(line_buf)) {
|
||||||
|
uint32 line_buffer_len = sizeof(line_buf);
|
||||||
|
/* If line too long, ensure the last character is '\n' */
|
||||||
|
for (i = line_buffer_len - 5; i < line_buffer_len - 2; i++) {
|
||||||
|
line_buf[i] = '.';
|
||||||
|
}
|
||||||
|
line_buf[line_buffer_len - 2] = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_OR_DUMP();
|
||||||
|
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
snprintf(line_buf, sizeof(line_buf), "\n");
|
||||||
|
PRINT_OR_DUMP();
|
||||||
|
|
||||||
|
return total_len + 1;
|
||||||
}
|
}
|
||||||
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
|
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
|
||||||
|
|
|
@ -432,8 +432,25 @@ wasm_get_table_inst(const WASMModuleInstance *module_inst, const uint32 tbl_idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||||
void
|
bool
|
||||||
wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env);
|
wasm_interp_create_call_stack(struct WASMExecEnv *exec_env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dump wasm call stack or get the size
|
||||||
|
*
|
||||||
|
* @param exec_env the execution environment
|
||||||
|
* @param print whether to print to stdout or not
|
||||||
|
* @param buf buffer to store the dumped content
|
||||||
|
* @param len length of the buffer
|
||||||
|
*
|
||||||
|
* @return when print is true, return the bytes printed out to stdout; when
|
||||||
|
* print is false and buf is NULL, return the size required to store the
|
||||||
|
* callstack content; when print is false and buf is not NULL, return the size
|
||||||
|
* dumped to the buffer, 0 means error and data in buf may be invalid
|
||||||
|
*/
|
||||||
|
uint32
|
||||||
|
wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf,
|
||||||
|
uint32 len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const uint8 *
|
const uint8 *
|
||||||
|
|
Loading…
Reference in New Issue
Block a user