@@ -4103,6 +4103,136 @@ aot_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame)
41034103}
41044104#endif /* end of WASM_ENABLE_AOT_STACK_FRAME != 0 */
41054105
4106+ #if WAMR_ENABLE_COPY_CALLSTACK != 0
4107+ uint32
4108+ aot_copy_callstack_tiny_frame (WASMExecEnv * exec_env , wasm_frame_t * buffer ,
4109+ const uint32 length , const uint32 skip_n ,
4110+ char * error_buf , uint32 error_buf_size )
4111+ {
4112+ /*
4113+ * Note for devs: please refrain from such modifications inside of
4114+ * aot_copy_callstack_tiny_frame
4115+ * - any allocations/freeing memory
4116+ * - dereferencing any pointers other than: exec_env, exec_env->module_inst,
4117+ * exec_env->module_inst->module, pointers between stack's bottom and
4118+ * top_boundary For more details check wasm_copy_callstack in
4119+ * wasm_export.h
4120+ */
4121+ uint8 * top_boundary = exec_env -> wasm_stack .top_boundary ;
4122+ uint8 * top = exec_env -> wasm_stack .top ;
4123+ uint8 * bottom = exec_env -> wasm_stack .bottom ;
4124+ uint32 count = 0 ;
4125+
4126+ bool is_top_index_in_range =
4127+ top_boundary >= top && top >= (bottom + sizeof (AOTTinyFrame ));
4128+ if (!is_top_index_in_range ) {
4129+ char * err_msg =
4130+ "Top of the stack pointer is outside of the stack boundaries" ;
4131+ strncpy (error_buf , err_msg , error_buf_size );
4132+ return 0 ;
4133+ }
4134+ bool is_top_aligned_with_bottom =
4135+ (unsigned long )(top - bottom ) % sizeof (AOTTinyFrame ) == 0 ;
4136+ if (!is_top_aligned_with_bottom ) {
4137+ char * err_msg = "Top of the stack is not aligned with the bottom" ;
4138+ strncpy (error_buf , err_msg , error_buf_size );
4139+ return 0 ;
4140+ }
4141+
4142+ AOTTinyFrame * frame = (AOTTinyFrame * )(top - sizeof (AOTTinyFrame ));
4143+ WASMCApiFrame record_frame ;
4144+ while (frame && (uint8_t * )frame >= bottom && count < (skip_n + length )) {
4145+ if (count < skip_n ) {
4146+ ++ count ;
4147+ frame -= 1 ;
4148+ continue ;
4149+ }
4150+ record_frame .instance = exec_env -> module_inst ;
4151+ record_frame .module_offset = 0 ;
4152+ record_frame .func_index = frame -> func_index ;
4153+ record_frame .func_offset = frame -> ip_offset ;
4154+ buffer [count - skip_n ] = record_frame ;
4155+ frame -= 1 ;
4156+ ++ count ;
4157+ }
4158+ return count >= skip_n ? count - skip_n : 0 ;
4159+ }
4160+
4161+ uint32
4162+ aot_copy_callstack_standard_frame (WASMExecEnv * exec_env , wasm_frame_t * buffer ,
4163+ const uint32 length , const uint32 skip_n ,
4164+ char * error_buf , uint32_t error_buf_size )
4165+ {
4166+ /*
4167+ * Note for devs: please refrain from such modifications inside of
4168+ * aot_iterate_callstack_standard_frame
4169+ * - any allocations/freeing memory
4170+ * - dereferencing any pointers other than: exec_env, exec_env->module_inst,
4171+ * exec_env->module_inst->module, pointers between stack's bottom and
4172+ * top_boundary For more details check wasm_iterate_callstack in
4173+ * wasm_export.h
4174+ */
4175+
4176+ uint32 count = 0 ;
4177+ #if WASM_ENABLE_GC == 0
4178+ WASMModuleInstance * module_inst =
4179+ (WASMModuleInstance * )wasm_exec_env_get_module_inst (exec_env );
4180+ AOTFrame * cur_frame = (AOTFrame * )wasm_exec_env_get_cur_frame (exec_env );
4181+ uint8 * top_boundary = exec_env -> wasm_stack .top_boundary ;
4182+ uint8 * bottom = exec_env -> wasm_stack .bottom ;
4183+ uint32 frame_size = (uint32 )offsetof(AOTFrame , lp );
4184+
4185+ WASMCApiFrame record_frame ;
4186+ while (cur_frame && (uint8_t * )cur_frame >= bottom
4187+ && (uint8_t * )cur_frame + frame_size <= top_boundary
4188+ && count < (skip_n + length )) {
4189+ if (count < skip_n ) {
4190+ ++ count ;
4191+ cur_frame = cur_frame -> prev_frame ;
4192+ continue ;
4193+ }
4194+ record_frame .instance = module_inst ;
4195+ record_frame .module_offset = 0 ;
4196+ record_frame .func_index = (uint32 )cur_frame -> func_index ;
4197+ record_frame .func_offset = (uint32 )cur_frame -> ip_offset ;
4198+ buffer [count - skip_n ] = record_frame ;
4199+ cur_frame = cur_frame -> prev_frame ;
4200+ ++ count ;
4201+ }
4202+ #else
4203+ /*
4204+ * TODO: add support for standard frames when GC is enabled
4205+ * now it poses a risk due to variable size of the frame
4206+ */
4207+ #endif
4208+ return count >= skip_n ? count - skip_n : 0 ;
4209+ }
4210+
4211+ uint32
4212+ aot_copy_callstack (WASMExecEnv * exec_env , wasm_frame_t * buffer ,
4213+ const uint32 length , const uint32 skip_n , char * error_buf ,
4214+ uint32_t error_buf_size )
4215+ {
4216+ /*
4217+ * Note for devs: please refrain from such modifications inside of
4218+ * aot_iterate_callstack
4219+ * - any allocations/freeing memory
4220+ * - dereferencing any pointers other than: exec_env, exec_env->module_inst,
4221+ * exec_env->module_inst->module, pointers between stack's bottom and
4222+ * top_boundary For more details check wasm_iterate_callstack in
4223+ * wasm_export.h
4224+ */
4225+ if (!is_tiny_frame (exec_env )) {
4226+ return aot_copy_callstack_standard_frame (
4227+ exec_env , buffer , length , skip_n , error_buf , error_buf_size );
4228+ }
4229+ else {
4230+ return aot_copy_callstack_tiny_frame (exec_env , buffer , length , skip_n ,
4231+ error_buf , error_buf_size );
4232+ }
4233+ }
4234+ #endif // WAMR_ENABLE_COPY_CALLSTACK
4235+
41064236#if WASM_ENABLE_DUMP_CALL_STACK != 0
41074237bool
41084238aot_create_call_stack (struct WASMExecEnv * exec_env )
0 commit comments