Implement option for skipping function index in the callstack (#3785)
Also add a script that converts instruction pointers to function indexes (or function names). https://github.com/bytecodealliance/wasm-micro-runtime/issues/3758
This commit is contained in:
@ -134,6 +134,15 @@ is_frame_per_function(WASMExecEnv *exec_env)
|
||||
return module->feature_flags & WASM_FEATURE_FRAME_PER_FUNCTION;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_frame_func_idx_disabled(WASMExecEnv *exec_env)
|
||||
{
|
||||
AOTModule *module =
|
||||
(AOTModule *)((AOTModuleInstance *)exec_env->module_inst)->module;
|
||||
|
||||
return module->feature_flags & WASM_FEATURE_FRAME_NO_FUNC_IDX;
|
||||
}
|
||||
|
||||
static void *
|
||||
get_top_frame(WASMExecEnv *exec_env)
|
||||
{
|
||||
@ -3952,7 +3961,7 @@ aot_create_call_stack(struct WASMExecEnv *exec_env)
|
||||
#endif
|
||||
}
|
||||
WASMCApiFrame frame = { 0 };
|
||||
uint32 max_local_cell_num, max_stack_cell_num;
|
||||
uint32 max_local_cell_num = 0, max_stack_cell_num = 0;
|
||||
uint32 all_cell_num, lp_size;
|
||||
|
||||
frame.instance = module_inst;
|
||||
@ -3961,16 +3970,20 @@ aot_create_call_stack(struct WASMExecEnv *exec_env)
|
||||
frame.func_offset = ip_offset;
|
||||
frame.func_name_wp = get_func_name_from_index(module_inst, func_index);
|
||||
|
||||
if (func_index >= module->import_func_count) {
|
||||
uint32 aot_func_idx = func_index - module->import_func_count;
|
||||
max_local_cell_num = module->max_local_cell_nums[aot_func_idx];
|
||||
max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx];
|
||||
}
|
||||
else {
|
||||
AOTFuncType *func_type = module->import_funcs[func_index].func_type;
|
||||
max_local_cell_num =
|
||||
func_type->param_cell_num > 2 ? func_type->param_cell_num : 2;
|
||||
max_stack_cell_num = 0;
|
||||
if (!is_frame_func_idx_disabled(exec_env)) {
|
||||
if (func_index >= module->import_func_count) {
|
||||
uint32 aot_func_idx = func_index - module->import_func_count;
|
||||
max_local_cell_num = module->max_local_cell_nums[aot_func_idx];
|
||||
max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx];
|
||||
}
|
||||
else {
|
||||
AOTFuncType *func_type =
|
||||
module->import_funcs[func_index].func_type;
|
||||
max_local_cell_num = func_type->param_cell_num > 2
|
||||
? func_type->param_cell_num
|
||||
: 2;
|
||||
max_stack_cell_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
all_cell_num = max_local_cell_num + max_stack_cell_num;
|
||||
|
||||
@ -34,6 +34,7 @@ extern "C" {
|
||||
/* Stack frame is created at the beginning of the function,
|
||||
* and not at the beginning of each function call */
|
||||
#define WASM_FEATURE_FRAME_PER_FUNCTION (1 << 12)
|
||||
#define WASM_FEATURE_FRAME_NO_FUNC_IDX (1 << 13)
|
||||
|
||||
typedef enum AOTSectionType {
|
||||
AOT_SECTION_TYPE_TARGET_INFO = 0,
|
||||
|
||||
@ -4439,6 +4439,9 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
|
||||
if (comp_ctx->call_stack_features.frame_per_function) {
|
||||
obj_data->target_info.feature_flags |= WASM_FEATURE_FRAME_PER_FUNCTION;
|
||||
}
|
||||
if (!comp_ctx->call_stack_features.func_idx) {
|
||||
obj_data->target_info.feature_flags |= WASM_FEATURE_FRAME_NO_FUNC_IDX;
|
||||
}
|
||||
|
||||
bh_print_time("Begin to resolve object file info");
|
||||
|
||||
|
||||
@ -885,25 +885,28 @@ alloc_frame_for_aot_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
}
|
||||
|
||||
if (!comp_ctx->is_jit_mode) {
|
||||
/* aot mode: new_frame->func_idx = func_idx */
|
||||
func_idx_val = comp_ctx->pointer_size == sizeof(uint64)
|
||||
? I64_CONST(func_idx)
|
||||
: I32_CONST(func_idx);
|
||||
offset = I32_CONST(comp_ctx->pointer_size);
|
||||
CHECK_LLVM_CONST(func_idx_val);
|
||||
CHECK_LLVM_CONST(offset);
|
||||
if (!(func_idx_ptr =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, new_frame,
|
||||
&offset, 1, "func_idx_addr"))
|
||||
|| !(func_idx_ptr =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_idx_ptr,
|
||||
INTPTR_T_PTR_TYPE, "func_idx_ptr"))) {
|
||||
aot_set_last_error("llvm get func_idx_ptr failed");
|
||||
return false;
|
||||
}
|
||||
if (!LLVMBuildStore(comp_ctx->builder, func_idx_val, func_idx_ptr)) {
|
||||
aot_set_last_error("llvm build store failed");
|
||||
return false;
|
||||
if (comp_ctx->call_stack_features.func_idx) {
|
||||
/* aot mode: new_frame->func_idx = func_idx */
|
||||
func_idx_val = comp_ctx->pointer_size == sizeof(uint64)
|
||||
? I64_CONST(func_idx)
|
||||
: I32_CONST(func_idx);
|
||||
offset = I32_CONST(comp_ctx->pointer_size);
|
||||
CHECK_LLVM_CONST(func_idx_val);
|
||||
CHECK_LLVM_CONST(offset);
|
||||
if (!(func_idx_ptr = LLVMBuildInBoundsGEP2(
|
||||
comp_ctx->builder, INT8_TYPE, new_frame, &offset, 1,
|
||||
"func_idx_addr"))
|
||||
|| !(func_idx_ptr =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_idx_ptr,
|
||||
INTPTR_T_PTR_TYPE, "func_idx_ptr"))) {
|
||||
aot_set_last_error("llvm get func_idx_ptr failed");
|
||||
return false;
|
||||
}
|
||||
if (!LLVMBuildStore(comp_ctx->builder, func_idx_val,
|
||||
func_idx_ptr)) {
|
||||
aot_set_last_error("llvm build store failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@ -70,7 +70,9 @@ aot_alloc_tiny_frame_for_aot_func(AOTCompContext *comp_ctx,
|
||||
}
|
||||
|
||||
/* Save the func_idx on the top of the stack */
|
||||
ADD_STORE(func_index, wasm_stack_top);
|
||||
if (comp_ctx->call_stack_features.func_idx) {
|
||||
ADD_STORE(func_index, wasm_stack_top);
|
||||
}
|
||||
|
||||
/* increment the stack pointer */
|
||||
INT_CONST(offset, sizeof(AOTTinyFrame), I32_TYPE, true);
|
||||
|
||||
@ -12,11 +12,19 @@ typedef struct {
|
||||
* bounds of the current stack frame (and if not, traps). */
|
||||
bool bounds_checks;
|
||||
|
||||
/* Enables or disables instruction pointer (IP) tracking.*/
|
||||
/* Enables or disables instruction pointer (IP) tracking. */
|
||||
bool ip;
|
||||
|
||||
/* Enables or disables function index in the stack trace. Please note that
|
||||
* function index can be recovered from the instruction pointer using
|
||||
* ip2function.py script, so enabling this feature along with `ip` might
|
||||
* often be redundant.
|
||||
* This option will automatically be enabled for GC and Perf Profiling mode.
|
||||
*/
|
||||
bool func_idx;
|
||||
|
||||
/* Enables or disables tracking instruction pointer of a trap. Only takes
|
||||
* effect when `ip` is enabled.*/
|
||||
* effect when `ip` is enabled. */
|
||||
bool trap_ip;
|
||||
|
||||
/* Enables or disables parameters, locals and stack operands. */
|
||||
|
||||
Reference in New Issue
Block a user