X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/1fe5f5eb5378a47bf0f3451762743c162e40faad..b9f4a7b7475e62dbff22da6dd768222f03889c00:/lunaix-os/kernel/debug/trace.c diff --git a/lunaix-os/kernel/debug/trace.c b/lunaix-os/kernel/debug/trace.c index c08a6f7..a3553f1 100644 --- a/lunaix-os/kernel/debug/trace.c +++ b/lunaix-os/kernel/debug/trace.c @@ -1,10 +1,19 @@ #include #include +#include #include +#include #include +#include +#include + #include +#define NB_TRACEBACK 16 + +LOG_MODULE("TRACE") + static struct trace_context trace_ctx; void @@ -26,12 +35,137 @@ trace_modksyms_init(struct boot_handoff* bhctx) } struct ksym_entry* -trace_sym_lookup(ptr_t pc) +trace_sym_lookup(ptr_t addr) +{ + int c = trace_ctx.ksym_table->ksym_count; + struct ksym_entry* ksent = trace_ctx.ksym_table->syms; + + int i = c - 1, j = 0, m = 0; + + if (addr > ksent[i].pc || addr < ksent[j].pc || addr < KERNEL_EXEC) { + return NULL; + } + + while (i - j != 1) { + m = (i + j) / 2; + if (ksent[m].pc > addr) { + i = m; + } else if (ksent[m].pc < addr) { + j = m; + } else { + break; + } + } + + struct ksym_entry* result = &ksent[MIN(i, j)]; + if (result->pc > addr) { + return NULL; + } + + return result; +} + +static char* +ksym_getstr(struct ksym_entry* sym) +{ + if (!sym) { + return "???"; + } + + return (char*)((ptr_t)trace_ctx.ksym_table + + trace_ctx.ksym_table->ksym_label_off + sym->label_off); +} + +int +trace_walkback(struct trace_record* tb_buffer, + ptr_t fp, + int limit, + ptr_t* last_fp) +{ + ptr_t* frame = (ptr_t*)fp; + struct ksym_entry* current = NULL; + int i = 0; + + while (frame && i < limit) { + ptr_t pc = *(frame + 1); + + current = trace_sym_lookup(pc); + tb_buffer[i] = (struct trace_record){ .pc = current ? current->pc : pc, + .symbol = ksym_getstr(current) }; + + frame = (ptr_t*)*frame; + i++; + } + + if (last_fp) { + *last_fp = (ptr_t)frame; + } + + return i; +} + +void +trace_printstack_of(ptr_t fp) +{ + struct trace_record tbs[NB_TRACEBACK]; + + int n = trace_walkback(tbs, fp, NB_TRACEBACK, &fp); + + if (fp) { + kprintf(KDEBUG "...\n"); + } + + for (int i = 0; i < n; i++) { + kprintf(KDEBUG "%p: %s\n", tbs[i].pc, tbs[i].symbol); + } +} + +void +trace_printstack() { - return NULL; + trace_printstack_of(cpu_get_fp()); } void -trace_walkback(ptr_t fp) +trace_printswctx(const isr_param* p, char* direction) { + + struct ksym_entry* sym = trace_sym_lookup(p->execp->eip); + + kprintf( + KDEBUG ">> (sw:%s) iv:%d, errno:%p <<\n", direction, p->execp->vector); + kprintf(KDEBUG "%p:%s\n", p->execp->eip, ksym_getstr(sym)); +} + +void +trace_printstack_isr(const isr_param* isrm) +{ + isr_param* p = isrm; + ptr_t fp = cpu_get_fp(); + int prev_fromusr = uspace_context(p); + + kprintf(KDEBUG "\n"); + kprintf(KDEBUG "stack trace (pid=%d)\n", __current->pid); + + trace_printstack_of(fp); + + while (p) { + if (!prev_fromusr) { + if (uspace_context(p)) { + trace_printswctx(p, "s/u"); + } else { + trace_printswctx(p, "s/s"); + } + } else { + trace_printswctx(p, "u/s"); + } + + fp = saved_fp(p); + trace_printstack_of(fp); + + prev_fromusr = uspace_context(p); + + p = p->execp->saved_prev_ctx; + } + kprintf(KDEBUG "\n"); } \ No newline at end of file