static inline void write_thread_trace(struct exception_handler_data *data, THREADENTRY32 *entry) { bool crash_thread = entry->th32ThreadID == GetCurrentThreadId(); struct stack_trace trace = {0}; struct stack_trace *ptrace; HANDLE thread; if (entry->th32OwnerProcessID != GetCurrentProcessId()) return; thread = OpenThread(THREAD_ALL_ACCESS, false, entry->th32ThreadID); if (!thread) return; trace.context.ContextFlags = CONTEXT_ALL; GetThreadContext(thread, &trace.context); init_instruction_data(&trace); dstr_catf(&data->str, "\r\nThread %lX%s\r\n"TRACE_TOP, entry->th32ThreadID, crash_thread ? " (Crashed)" : ""); ptrace = crash_thread ? &data->main_trace : &trace; while (walk_stack(data, thread, ptrace)); CloseHandle(thread); }
static void walk_stack_all(spdid_t spdid, struct cos_regs *regs) { unsigned long *fp, *stack, fp_off; int i, tid = cos_get_thd_id(); printc("Stack trace for thread %d [spdid, instruction pointer]:\n", tid); fp = (unsigned long *)regs->regs.bp; stack = map_stack(spdid, (vaddr_t)fp); printc("\t[%d, %lx]\n", spdid, (unsigned long)regs->regs.ip); walk_stack(spdid, fp, stack); unmap_stack(spdid, stack); assert(cos_spd_id() == cos_thd_cntl(COS_THD_INV_FRAME, tid, 0, 0)); assert(spdid == cos_thd_cntl(COS_THD_INV_FRAME, tid, 1, 0)); for (i = 2 ; (spdid = cos_thd_cntl(COS_THD_INV_FRAME, tid, i, 0)) != 0 ; i++) { unsigned long sp; /* We're ignoring the initial IPs the IP is in the * invocation stubs, and noone cares about the * stubs */ sp = cos_thd_cntl(COS_THD_INVFRM_SP, tid, i, 0); assert(sp); stack = map_stack(spdid, sp); /* The invocation stubs save ebp last, thus *(esp+16) * = ebp. This offset corresponds to the number of * registers pushed in * SS_ipc_client_marshal_args... */ fp_off = ((sp & (~PAGE_MASK))/sizeof(unsigned long)); fp = (unsigned long *)&stack[fp_off]; walk_stack(spdid, fp, stack); unmap_stack(spdid, stack); } }
void __attribute__((optimize("O0"))) panic(char* error, ...) { if(unlikely(!spinlock_get(&lock, 30))) { freeze(); } va_list va; va_start(va, error); interrupts_disable(); panic_printf("\nKernel Panic: "); vprintf(error, va); serial_vprintf(error, va); panic_printf("\n"); va_end(va); panic_printf("Last PIT tick: %d (rate %d, uptime: %d seconds)\n", (uint32_t)timer_tick, timer_rate, uptime()); task_t* task = scheduler_get_current(); if(task) { panic_printf("Running task: %d <%s>", task->pid, task->name); /* uint32_t task_offset = task->state->eip - task->entry; if(task_offset >= 0) { panic_printf("+%x at 0x%x", task_offset, task->state->eip); } */ panic_printf("\n"); } else { panic_printf("Running task: [No task running]\n"); } panic_printf("Paging context: %s\n\n", vmem_get_name(vmem_currentContext)); panic_printf("Call trace:\n"); intptr_t addresses[10]; int read = walk_stack(addresses, 10); for(int i = 0; i < read; i++) { panic_printf("#%-6d %s <%#x>\n", i, addr2name(addresses[i]), addresses[i]); } freeze(); }