The callstack is for a project of mine very important and I would like to read and modify it. For clarification: the callstack is the place, where the interpreter stores where to return when a return-statement is executed. It could also be used when raising (and catching) an Exception to determine what happened and print a traceback.
Are there any modules integrated in Micropython which are there to read the callstack? In CPython there is sys._getframe(), which could be helpful to read the frames on the stack. Are there any facilities that would allow me to modify the currently used stack, either by writing a previously saved stack in that spot or by declaring a different stack as the currently used one?
Where is the stack located? Is it in the heap or seperate to that? I haven't looked that closely in the code so: can someone explain what the format is, that is used and when the data is updated to represent the current state? I have already found, that on calling a bytecode function there are some information written onto the stack. Can I read and write these from Python-level or do I have to write my own module for that at the moment?
Code: Select all
// py/objfun.c
// line 213
#define INIT_CODESTATE(code_state, _fun_bc, n_args, n_kw, args) \
code_state->fun_bc = _fun_bc; \
code_state->ip = 0; \
mp_setup_code_state(code_state, n_args, n_kw, args); \
code_state->old_globals = mp_globals_get();
// line 251
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
MP_STACK_CHECK();
DEBUG_printf("Input n_args: " UINT_FMT ", n_kw: " UINT_FMT "\n", n_args, n_kw);
DEBUG_printf("Input pos args: ");
dump_args(args, n_args);
DEBUG_printf("Input kw args: ");
dump_args(args + n_args, n_kw * 2);
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
DEBUG_printf("Func n_def_args: %d\n", self->n_def_args);
size_t n_state, state_size;
DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size);
// allocate state for locals and stack
mp_code_state_t *code_state = NULL;
#if MICROPY_ENABLE_PYSTACK
code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size);
#else
if (state_size > VM_MAX_STATE_ON_STACK) {
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
}
if (code_state == NULL) {
code_state = alloca(sizeof(mp_code_state_t) + state_size);
state_size = 0; // indicate that we allocated using alloca
}
#endif
INIT_CODESTATE(code_state, self, n_args, n_kw, args);
// ...
PS: I assume MICROPY_ENABLE_PYSTACK to be set.