static void stack_capture(struct stack *st, vm_offset_t frame) { vm_offset_t callpc; stack_zero(st); if (frame < PAGE_SIZE) return; while (1) { frame = *(vm_offset_t *)frame; if (frame < PAGE_SIZE) break; #ifdef __powerpc64__ callpc = *(vm_offset_t *)(frame + 16) - 4; #else callpc = *(vm_offset_t *)(frame + 4) - 4; #endif if ((callpc & 3) || (callpc < 0x100)) break; /* * Don't bother traversing trap-frames - there should * be enough info down to the frame to work out where * things are going wrong. Plus, prevents this shortened * version of code from accessing user-space frames */ if (callpc + CALLOFFSET == (vm_offset_t) &trapexit || callpc + CALLOFFSET == (vm_offset_t) &asttrapexit) break; if (stack_put(st, callpc) == -1) break; } }
static void stack_capture(struct stack *st, struct frame *frame) { struct frame *fp; vm_offset_t callpc; stack_zero(st); fp = frame; for (;;) { if (!INKERNEL((vm_offset_t)fp) || !ALIGNED_POINTER(fp, uint64_t)) break; callpc = fp->fr_pc; if (!INKERNEL(callpc)) break; /* Don't bother traversing trap frames. */ if ((callpc > (uint64_t)tl_trap_begin && callpc < (uint64_t)tl_trap_end) || (callpc > (uint64_t)tl_text_begin && callpc < (uint64_t)tl_text_end)) break; if (stack_put(st, callpc) == -1) break; if (v9next_frame(fp) <= fp || v9next_frame(fp) >= frame + KSTACK_PAGES * PAGE_SIZE) break; fp = v9next_frame(fp); } }
void stack_save(struct stack *st) { u_int32_t *frame; frame = (u_int32_t *)__builtin_frame_address(0); stack_zero(st); stack_capture(st, frame); }
void stack_save(struct stack *st) { stack_zero(st); /* * Nothing for now. * Is libuwx reentrant? * Can unw_create* sleep? */ }
void stack_save_td(struct stack *st, struct thread *td) { if (TD_IS_SWAPPED(td)) panic("stack_save_td: swapped"); if (TD_IS_RUNNING(td)) panic("stack_save_td: running"); stack_zero(st); }
void stack_save_td(struct stack *st, struct thread *td) { u_int32_t *frame; if (TD_IS_SWAPPED(td)) panic("stack_save_td: swapped"); if (TD_IS_RUNNING(td)) panic("stack_save_td: running"); frame = (u_int32_t *)td->td_pcb->un_32.pcb32_r11; stack_zero(st); stack_capture(st, frame); }
static void stack_capture(struct stack *st, u_int32_t *frame) { vm_offset_t callpc; stack_zero(st); while (1) { if (!INKERNEL(frame)) break; callpc = frame[FR_SCP]; if (stack_put(st, callpc) == -1) break; frame = (u_int32_t *)(frame[FR_RFP]); } }
/* * Similar to kdb_backtrace() except that it prints a backtrace of an * arbitrary thread rather than the calling thread. */ void kdb_backtrace_thread(struct thread *td) { if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace_thread != NULL) { printf("KDB: stack backtrace of thread %d:\n", td->td_tid); kdb_dbbe->dbbe_trace_thread(td); } #ifdef STACK else { struct stack st; printf("KDB: stack backtrace of thread %d:\n", td->td_tid); stack_zero(&st); stack_save_td(&st, td); stack_print_ddb(&st); } #endif }
void kdb_backtrace(void) { if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace != NULL) { printf("KDB: stack backtrace:\n"); kdb_dbbe->dbbe_trace(); } #ifdef STACK else { struct stack st; printf("KDB: stack backtrace:\n"); stack_zero(&st); stack_save(&st); stack_print_ddb(&st); } #endif }
void stack_save_td(struct stack *st, struct thread *td) { u_int32_t *frame; if (TD_IS_SWAPPED(td)) panic("stack_save_td: swapped"); if (TD_IS_RUNNING(td)) panic("stack_save_td: running"); /* * This register, the frame pointer, is incorrect for the ARM EABI * as it doesn't have a frame pointer, however it's value is not used * when building for EABI. */ frame = (u_int32_t *)td->td_pcb->un_32.pcb32_r11; stack_zero(st); stack_capture(st, frame); }
static int xendebug_filter(void *arg) { #if defined(STACK) && defined(DDB) struct stack st; struct trapframe *frame; frame = arg; stack_zero(&st); stack_save(&st); mtx_lock_spin(&lock); sbuf_clear(buf); xc_printf("Printing stack trace vCPU%d\n", PCPU_GET(vcpu_id)); stack_sbuf_print_ddb(buf, &st); sbuf_finish(buf); mtx_unlock_spin(&lock); #endif return (FILTER_HANDLED); }
static void stack_capture(struct stack *st, u_register_t pc, u_register_t sp) { u_register_t ra = 0, i, stacksize; short ra_stack_pos = 0; InstFmt insn; stack_zero(st); for (;;) { stacksize = 0; if (pc <= (u_register_t)(intptr_t)btext) break; for (i = pc; i >= (u_register_t)(intptr_t)btext; i -= sizeof (insn)) { bcopy((void *)(intptr_t)i, &insn, sizeof insn); switch (insn.IType.op) { case OP_ADDI: case OP_ADDIU: case OP_DADDI: case OP_DADDIU: if (insn.IType.rs != SP || insn.IType.rt != SP) break; stacksize = -(short)insn.IType.imm; break; case OP_SW: case OP_SD: if (insn.IType.rs != SP || insn.IType.rt != RA) break; ra_stack_pos = (short)insn.IType.imm; break; default: break; } if (stacksize) break; } if (stack_put(st, pc) == -1) break; for (i = pc; !ra; i += sizeof (insn)) { bcopy((void *)(intptr_t)i, &insn, sizeof insn); switch (insn.IType.op) { case OP_SPECIAL: if((insn.RType.func == OP_JR)) { if (ra >= (u_register_t)(intptr_t)btext) break; if (insn.RType.rs != RA) break; ra = stack_register_fetch(sp, ra_stack_pos); if (!ra) goto done; ra -= 8; } break; default: break; } /* eret */ if (insn.word == 0x42000018) goto done; } if (pc == ra && stacksize == 0) break; sp += stacksize; pc = ra; ra = 0; } done: return; }