diff --git a/src/backtrace.c b/src/backtrace.c index fa6dfd64f..c9d176785 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -17,6 +17,10 @@ #include #include +#define MAX_IREP_REFCNT UINT16_MAX +#define UNKNOWN_LINENO -1 +#define UNKNOWN_LOCATION "(unknown):0" + static void copy_backtrace(mrb_state *mrb, const struct mrb_backtrace_location *loc, @@ -25,7 +29,7 @@ copy_backtrace(mrb_state *mrb, { ptr[n] = *loc; if (loc->irep) { - if (loc->irep->refcnt == UINT16_MAX) { + if (loc->irep->refcnt == MAX_IREP_REFCNT) { ptr[n].irep = NULL; } else { @@ -34,6 +38,16 @@ copy_backtrace(mrb_state *mrb, } } +/** + * Creates a packed backtrace from the current call stack + * + * @param mrb The mruby state + * @param ciidx The current callinfo index + * @param ptr Pointer to store the backtrace locations + * @return Number of backtrace entries + * @note This function handles both proc and non-proc cases, managing IREP references + * and building location entries for each stack frame. + */ static size_t pack_backtrace(mrb_state *mrb, ptrdiff_t ciidx, struct mrb_backtrace_location *ptr) { @@ -129,19 +143,30 @@ decode_location(mrb_state *mrb, const struct mrb_backtrace_location *entry) int32_t lineno; const char *filename; - if (!entry->irep || !mrb_debug_get_position(mrb, entry->irep, entry->idx, &lineno, &filename)) { - btline = mrb_str_new_lit(mrb, "(unknown):0"); + // Case 1: No IREP or debug info available + if (!entry->irep) { + return mrb_str_new_lit(mrb, UNKNOWN_LOCATION); } - else if (lineno != -1) {//debug info was available + + // Case 2: Debug info lookup failed + if (!mrb_debug_get_position(mrb, entry->irep, entry->idx, &lineno, &filename)) { + return mrb_str_new_lit(mrb, UNKNOWN_LOCATION); + } + + // Case 3: Valid debug info + if (lineno != UNKNOWN_LINENO) { btline = mrb_format(mrb, "%s:%d", filename, (int)lineno); } else { //all that was left was the stack frame btline = mrb_format(mrb, "%s:0", filename); } + + // Add method name if available if (entry->method_id != 0) { mrb_str_cat_lit(mrb, btline, ":in "); mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id)); } + return btline; } @@ -233,7 +258,7 @@ print_backtrace(mrb_state *mrb, struct RObject *exc, struct RBasic *ptr) } } else { - fputs("(unknown):0: ", stderr); + fputs(UNKNOWN_LOCATION ": ", stderr); } if (exc == mrb->nomem_err) {