int try_stack_unwind(struct task_struct *task, struct pt_regs *regs, unsigned long **stack, unsigned long *bp, const struct stacktrace_ops *ops, void *data) { #ifdef CONFIG_STACK_UNWIND int unw_ret = 0; struct unwind_frame_info info; if (call_trace < 0) return 0; if (regs) { if (unwind_init_frame_info(&info, task, regs) == 0) unw_ret = dump_trace_unwind(&info, ops, data); } else if (task == current) unw_ret = unwind_init_running(&info, dump_trace_unwind, ops, data); #ifdef CONFIG_SMP else if (task->on_cpu) /* nothing */; #endif else if (unwind_init_blocked(&info, task) == 0) unw_ret = dump_trace_unwind(&info, ops, data); if (unw_ret > 0) { if (call_trace == 1 && !arch_unw_user_mode(&info)) { ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n", UNW_PC(&info)); if (UNW_SP(&info) >= PAGE_OFFSET) { ops->warning(data, "Leftover inexact backtrace:\n"); *stack = (void *)UNW_SP(&info); *bp = UNW_FP(&info); return 0; } } else if (call_trace >= 1) return -1; ops->warning(data, "Full inexact backtrace again:\n"); } else ops->warning(data, "Inexact backtrace:\n"); #endif return 0; }
if (!__get_user(link, (unsigned long *) (UNW_FP(frame) + FRAME_LINK_OFFSET)) #if FRAME_RETADDR_OFFSET < 0 && link > bottom && link < UNW_FP(frame) #else && link > UNW_FP(frame) && link < bottom #endif && !(link & (sizeof(link) - 1)) && !__get_user(UNW_PC(frame), (unsigned long *)(UNW_FP(frame) + FRAME_RETADDR_OFFSET))) { UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET #if FRAME_RETADDR_OFFSET < 0 - #else + #endif sizeof(UNW_PC(frame)); UNW_FP(frame) = link; return 0; }