void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; if (tsk != current) { data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.pc = thread_saved_pc(tsk); } else { data.no_sched_functions = 0; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_stack_pointer; frame.pc = (unsigned long)save_stack_trace_tsk; } #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame.graph = tsk->curr_ret_stack; #endif walk_stackframe(tsk, &frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile // #define GATOR_KERNEL_STACK_UNWINDING static void kernel_backtrace(int cpu, struct pt_regs *const regs) { #if defined(__arm__) || defined(__aarch64__) #ifdef GATOR_KERNEL_STACK_UNWINDING int depth = gator_backtrace_depth; #else int depth = 1; #endif struct stackframe frame; if (depth == 0) depth = 1; #if defined(__arm__) frame.fp = regs->ARM_fp; frame.sp = regs->ARM_sp; frame.lr = regs->ARM_lr; frame.pc = regs->ARM_pc; #else frame.fp = regs->regs[29]; frame.sp = regs->sp; frame.pc = regs->pc; #endif walk_stackframe(&frame, report_trace, &depth); #else marshal_backtrace(PC_REG & ~1, NO_COOKIE); #endif }
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output, const struct pt_regs *regs, unsigned int depth, void *ssp) { struct thread_info *real_thread_info = THREAD_INFO(ssp); struct stacktrace_state sts; sts.depth = depth; sts.output = output; *current_thread_info() = *real_thread_info; if (!current) output->printf(output, "current NULL\n"); else output->printf(output, "pid: %d comm: %s\n", current->pid, current->comm); fiq_debugger_dump_regs(output, regs); if (!user_mode(regs)) { struct stackframe frame; frame.fp = regs->regs[29]; frame.sp = regs->sp; frame.pc = regs->pc; output->printf(output, "\n"); walk_stackframe(&frame, report_trace, &sts); } }
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; if (tsk != current) { data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.pc = thread_saved_pc(tsk); } else { register unsigned long current_sp asm("sp"); data.no_sched_functions = 0; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.pc = (unsigned long)save_stack_trace_tsk; } walk_stackframe(&frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
unsigned long get_wchan(struct task_struct *task) { unsigned long pc = 0; if (likely(task && task != current && task->state != TASK_RUNNING)) walk_stackframe(task, NULL, save_wchan, &pc); return pc; }
unsigned long return_address(unsigned level) { struct return_addr_data r = { .skip = level + 1, }; walk_stackframe(stack_pointer(NULL), return_address_cb, &r); return r.addr; } EXPORT_SYMBOL(return_address);
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; if (tsk != current) { #ifdef CONFIG_SMP /* 20110630, [email protected], Merge Black DCM, Power Management. [UB_START] */ #if 1 /* * What guarantees do we have here that 'tsk' is not * running on another CPU? For now, ignore it as we * can't guarantee we won't explode. */ if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; return; #else // old /* 20110630, [email protected], Merge Black DCM, Power Management. [UB_END] */ /* * What guarantees do we have here that 'tsk' is not * running on another CPU? For now, ignore it as we * can't guarantee we won't explode. */ BUG(); /* 20110630, [email protected], Merge Black DCM, Power Management. [UB_START] */ #endif /* 20110630, [email protected], Merge Black DCM, Power Management. [UB_END] */ #else data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.lr = 0; /* recovered from the stack */ frame.pc = thread_saved_pc(tsk); #endif } else { register unsigned long current_sp asm ("sp"); data.no_sched_functions = 0; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)save_stack_trace_tsk; } walk_stackframe(&frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; if (tsk != current) { /* CORE-HC-ANR_Kernel_Stack-00*[ */ /*#ifdef CONFIG_SMP*/ #if defined(CONFIG_SMP) && !defined(CONFIG_FIH_DUMP_KERNEL_STACK) /* * What guarantees do we have here that 'tsk' is not * running on another CPU? For now, ignore it as we * can't guarantee we won't explode. */ if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; return; #else pr_info("save_stack_trace_tsk: %s[%d] %s[%d]\r\n", current->comm, smp_processor_id(), tsk->comm, task_thread_info(tsk)->cpu); data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.lr = 0; /* recovered from the stack */ frame.pc = thread_saved_pc(tsk); #endif /* CORE-HC-ANR_Kernel_Stack-00*] */ } else { register unsigned long current_sp asm ("sp"); data.no_sched_functions = 0; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)save_stack_trace_tsk; } walk_stackframe(&frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace) { struct stack_trace_data trace_data = { .trace = trace, .skip = trace->skip, }; walk_stackframe(stack_pointer(task), stack_trace_cb, &trace_data); } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); void save_stack_trace(struct stack_trace *trace) { save_stack_trace_tsk(current, trace); }
void arm_backtrace(struct pt_regs * const regs, unsigned int depth) { struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1; if (!user_mode(regs)) { unsigned long base = ((unsigned long)regs) & ~(THREAD_SIZE - 1); walk_stackframe(regs->ARM_fp, base, base + THREAD_SIZE, report_trace, &depth); return; } while (depth-- && tail && !((unsigned long) tail & 3)) tail = user_backtrace(tail); }
void arm_backtrace(struct pt_regs * const regs, unsigned int depth) { int step = 0; void **frame = (void **)regs->ARM_fp; if (!user_mode(regs)) { unsigned long base = ((unsigned long)regs) & ~(THREAD_SIZE - 1); walk_stackframe(regs->ARM_fp, base, base + THREAD_SIZE, report_trace, &depth); return; } while (depth-- && frame && !((unsigned long) frame & 3)) frame = user_backtrace(regs, frame, step++); }
static void arm_backtrace(struct pt_regs * const regs, unsigned int depth) { struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1; if (!user_mode(regs)) { struct stackframe frame; frame.fp = regs->ARM_fp; frame.sp = regs->ARM_sp; frame.lr = regs->ARM_lr; frame.pc = regs->ARM_pc; walk_stackframe(&frame, report_trace, &depth); return; } while (depth-- && tail && !((unsigned long) tail & 3)) tail = user_backtrace(tail); }
void arch_save_stacktrace(struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; register unsigned long current_sp asm ("sp"); frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)arch_save_stacktrace; walk_stackframe(&frame, save_trace, &data); }
void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; data.no_sched_functions = 0; frame.fp = regs->ARM_fp; frame.sp = regs->ARM_sp; frame.lr = regs->ARM_lr; frame.pc = regs->ARM_pc; walk_stackframe(&frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
/* This must be noinline to so that our skip calculation works correctly */ static noinline void __save_stack_trace(struct task_struct *tsk, struct stack_trace *trace, unsigned int nosched) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; data.no_sched_functions = nosched; if (tsk != current) { /* Bright Lee, 20130322, enable stack trace when android hang in debug stage { */ // #ifdef CONFIG_SMP #if 0 /* } Bright Lee, 20130322 */ /* * What guarantees do we have here that 'tsk' is not * running on another CPU? For now, ignore it as we * can't guarantee we won't explode. */ if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; return; #else frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.lr = 0; /* recovered from the stack */ frame.pc = thread_saved_pc(tsk); #endif } else { register unsigned long current_sp asm ("sp"); /* We don't want this function nor the caller */ data.skip += 2; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)__save_stack_trace; } walk_stackframe(&frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { struct stackframe frame; if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { /* We don't support guest os callchain now */ return; } frame.fp = regs->regs[29]; frame.sp = regs->sp; frame.pc = regs->pc; #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame.graph = current->curr_ret_stack; #endif walk_stackframe(current, &frame, callchain_trace, entry); }
void *return_address(unsigned int level) { struct return_address_data data; struct stackframe frame; register unsigned long current_sp asm ("sp"); data.level = level + 1; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)return_address; walk_stackframe(&frame, save_return_addr, &data); if (!data.level) return data.addr; else return NULL; }
// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile // #define GATOR_KERNEL_STACK_UNWINDING static void kernel_backtrace(int cpu, int buftype, struct pt_regs * const regs) { #if defined(__arm__) #ifdef GATOR_KERNEL_STACK_UNWINDING int depth = gator_backtrace_depth; #else int depth = 1; #endif struct stackframe frame; if (depth == 0) depth = 1; frame.fp = regs->ARM_fp; frame.sp = regs->ARM_sp; frame.lr = regs->ARM_lr; frame.pc = regs->ARM_pc; per_cpu(backtrace_buffer, cpu) = buftype; walk_stackframe(&frame, report_trace, &depth); #else marshal_backtrace(PC_REG & ~1, NO_COOKIE); #endif }
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; if (tsk != current) { /* enable call stack in smp arch */ #if defined(CONFIG_SMP) && !defined(CONFIG_HUAWEI_KERNEL) /* * What guarantees do we have here that 'tsk' is not * running on another CPU? For now, ignore it as we * can't guarantee we won't explode. */ if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; return; #else data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.lr = 0; /* recovered from the stack */ frame.pc = thread_saved_pc(tsk); #endif } else { register unsigned long current_sp asm ("sp"); data.no_sched_functions = 0; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)save_stack_trace_tsk; } walk_stackframe(&frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
unsigned int kernel_backtrace(struct pt_regs * const regs, unsigned int cpu, pid_t pid, pid_t tid, PXD32_CSS_Call_Stack_V2 * css_data) { unsigned int depth = 0; struct report_trace_data data; struct stackframe frame; data.depth = depth; data.pid = pid; data.cpu = cpu; data.css_data = css_data; frame.fp = regs->ARM_fp; frame.sp = regs->ARM_sp; frame.lr = regs->ARM_lr; frame.pc = regs->ARM_pc; walk_stackframe(&frame, kernel_report_trace, &data); depth = data.depth; return depth; }
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; if (tsk != current) { #ifdef CONFIG_SMP /* * What guarantees do we have here that 'tsk' * is not running on another CPU? */ /* 20101006 [email protected] temporary block because of reset */ /* BUG(); */ return; #else data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.lr = 0; /* recovered from the stack */ frame.pc = thread_saved_pc(tsk); #endif } else { register unsigned long current_sp asm ("sp"); data.no_sched_functions = 0; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)save_stack_trace_tsk; } walk_stackframe(&frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
/* This must be noinline to so that our skip calculation works correctly */ static noinline void __save_stack_trace(struct task_struct *tsk, struct stack_trace *trace, unsigned int nosched) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; data.no_sched_functions = nosched; if (tsk != current) { #ifdef CONFIG_SMP if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; return; #else frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.lr = 0; frame.pc = thread_saved_pc(tsk); #endif } else { register unsigned long current_sp asm ("sp"); /* We don't want this function nor the caller */ data.skip += 2; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)__save_stack_trace; } walk_stackframe(&frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
/* * Save stack-backtrace addresses into a stack_trace buffer. */ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { walk_stackframe(tsk, NULL, save_trace, trace); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; }
void show_stack(struct task_struct *task, unsigned long *sp) { pr_cont("Call Trace:\n"); walk_stackframe(task, NULL, print_trace_address, NULL); }
/* * Save stack-backtrace addresses into a stack_trace buffer. */ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { walk_stackframe(tsk, NULL, save_trace, trace); }