@@ -4103,6 +4103,136 @@ aot_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame)
4103
4103
}
4104
4104
#endif /* end of WASM_ENABLE_AOT_STACK_FRAME != 0 */
4105
4105
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
+
4106
4236
#if WASM_ENABLE_DUMP_CALL_STACK != 0
4107
4237
bool
4108
4238
aot_create_call_stack (struct WASMExecEnv * exec_env )
0 commit comments