1ecea4ab6SPaul Gortmaker #include <linux/export.h> 2f16fb1ecSRussell King #include <linux/sched.h> 3b17b0153SIngo Molnar #include <linux/sched/debug.h> 4f16fb1ecSRussell King #include <linux/stacktrace.h> 5f16fb1ecSRussell King 62d7c11bfSCatalin Marinas #include <asm/stacktrace.h> 707b40341SRussell King #include <asm/traps.h> 8f16fb1ecSRussell King 92d7c11bfSCatalin Marinas #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) 102d7c11bfSCatalin Marinas /* 112d7c11bfSCatalin Marinas * Unwind the current stack frame and store the new register values in the 122d7c11bfSCatalin Marinas * structure passed as argument. Unwinding is equivalent to a function return, 132d7c11bfSCatalin Marinas * hence the new PC value rather than LR should be used for backtrace. 142d7c11bfSCatalin Marinas * 152d7c11bfSCatalin Marinas * With framepointer enabled, a simple function prologue looks like this: 162d7c11bfSCatalin Marinas * mov ip, sp 172d7c11bfSCatalin Marinas * stmdb sp!, {fp, ip, lr, pc} 182d7c11bfSCatalin Marinas * sub fp, ip, #4 192d7c11bfSCatalin Marinas * 202d7c11bfSCatalin Marinas * A simple function epilogue looks like this: 212d7c11bfSCatalin Marinas * ldm sp, {fp, sp, pc} 222d7c11bfSCatalin Marinas * 232d7c11bfSCatalin Marinas * Note that with framepointer enabled, even the leaf functions have the same 242d7c11bfSCatalin Marinas * prologue and epilogue, therefore we can ignore the LR value in this case. 252d7c11bfSCatalin Marinas */ 264bf1fa5aSUwe Kleine-König int notrace unwind_frame(struct stackframe *frame) 272d7c11bfSCatalin Marinas { 282d7c11bfSCatalin Marinas unsigned long high, low; 292d7c11bfSCatalin Marinas unsigned long fp = frame->fp; 302d7c11bfSCatalin Marinas 312d7c11bfSCatalin Marinas /* only go to a higher address on the stack */ 322d7c11bfSCatalin Marinas low = frame->sp; 33d33aadbfSWill Deacon high = ALIGN(low, THREAD_SIZE); 342d7c11bfSCatalin Marinas 352d7c11bfSCatalin Marinas /* check current frame pointer is within bounds */ 363abb6671SKonstantin Khlebnikov if (fp < low + 12 || fp > high - 4) 372d7c11bfSCatalin Marinas return -EINVAL; 382d7c11bfSCatalin Marinas 392d7c11bfSCatalin Marinas /* restore the registers from the stack frame */ 402d7c11bfSCatalin Marinas frame->fp = *(unsigned long *)(fp - 12); 412d7c11bfSCatalin Marinas frame->sp = *(unsigned long *)(fp - 8); 422d7c11bfSCatalin Marinas frame->pc = *(unsigned long *)(fp - 4); 432d7c11bfSCatalin Marinas 442d7c11bfSCatalin Marinas return 0; 452d7c11bfSCatalin Marinas } 462d7c11bfSCatalin Marinas #endif 472d7c11bfSCatalin Marinas 484bf1fa5aSUwe Kleine-König void notrace walk_stackframe(struct stackframe *frame, 49f16fb1ecSRussell King int (*fn)(struct stackframe *, void *), void *data) 50f16fb1ecSRussell King { 512d7c11bfSCatalin Marinas while (1) { 522d7c11bfSCatalin Marinas int ret; 53f16fb1ecSRussell King 54f16fb1ecSRussell King if (fn(frame, data)) 55f16fb1ecSRussell King break; 562d7c11bfSCatalin Marinas ret = unwind_frame(frame); 572d7c11bfSCatalin Marinas if (ret < 0) 582d7c11bfSCatalin Marinas break; 592d7c11bfSCatalin Marinas } 60f16fb1ecSRussell King } 617b104bcbSAl Viro EXPORT_SYMBOL(walk_stackframe); 62f16fb1ecSRussell King 63f16fb1ecSRussell King #ifdef CONFIG_STACKTRACE 64f16fb1ecSRussell King struct stack_trace_data { 65f16fb1ecSRussell King struct stack_trace *trace; 6607b40341SRussell King unsigned long last_pc; 67f76e9154SNicolas Pitre unsigned int no_sched_functions; 68f16fb1ecSRussell King unsigned int skip; 69f16fb1ecSRussell King }; 70f16fb1ecSRussell King 71f16fb1ecSRussell King static int save_trace(struct stackframe *frame, void *d) 72f16fb1ecSRussell King { 73f16fb1ecSRussell King struct stack_trace_data *data = d; 74f16fb1ecSRussell King struct stack_trace *trace = data->trace; 7507b40341SRussell King struct pt_regs *regs; 762d7c11bfSCatalin Marinas unsigned long addr = frame->pc; 77f16fb1ecSRussell King 78f76e9154SNicolas Pitre if (data->no_sched_functions && in_sched_functions(addr)) 79f76e9154SNicolas Pitre return 0; 80f16fb1ecSRussell King if (data->skip) { 81f16fb1ecSRussell King data->skip--; 82f16fb1ecSRussell King return 0; 83f16fb1ecSRussell King } 84f16fb1ecSRussell King 85f76e9154SNicolas Pitre trace->entries[trace->nr_entries++] = addr; 86f16fb1ecSRussell King 8707b40341SRussell King if (trace->nr_entries >= trace->max_entries) 8807b40341SRussell King return 1; 8907b40341SRussell King 9007b40341SRussell King /* 9107b40341SRussell King * in_exception_text() is designed to test if the PC is one of 9207b40341SRussell King * the functions which has an exception stack above it, but 9307b40341SRussell King * unfortunately what is in frame->pc is the return LR value, 9407b40341SRussell King * not the saved PC value. So, we need to track the previous 9507b40341SRussell King * frame PC value when doing this. 9607b40341SRussell King */ 9707b40341SRussell King addr = data->last_pc; 9807b40341SRussell King data->last_pc = frame->pc; 9907b40341SRussell King if (!in_exception_text(addr)) 10007b40341SRussell King return 0; 10107b40341SRussell King 10207b40341SRussell King regs = (struct pt_regs *)frame->sp; 10307b40341SRussell King 10407b40341SRussell King trace->entries[trace->nr_entries++] = regs->ARM_pc; 10507b40341SRussell King 106f16fb1ecSRussell King return trace->nr_entries >= trace->max_entries; 107f16fb1ecSRussell King } 108f16fb1ecSRussell King 1093683f44cSRussell King /* This must be noinline to so that our skip calculation works correctly */ 1103683f44cSRussell King static noinline void __save_stack_trace(struct task_struct *tsk, 1113683f44cSRussell King struct stack_trace *trace, unsigned int nosched) 112f16fb1ecSRussell King { 113f16fb1ecSRussell King struct stack_trace_data data; 1142d7c11bfSCatalin Marinas struct stackframe frame; 115f16fb1ecSRussell King 116f16fb1ecSRussell King data.trace = trace; 11707b40341SRussell King data.last_pc = ULONG_MAX; 118f16fb1ecSRussell King data.skip = trace->skip; 1193683f44cSRussell King data.no_sched_functions = nosched; 120f76e9154SNicolas Pitre 121f76e9154SNicolas Pitre if (tsk != current) { 122f76e9154SNicolas Pitre #ifdef CONFIG_SMP 123f76e9154SNicolas Pitre /* 124d5996b2fSRussell King * What guarantees do we have here that 'tsk' is not 125d5996b2fSRussell King * running on another CPU? For now, ignore it as we 126d5996b2fSRussell King * can't guarantee we won't explode. 127f76e9154SNicolas Pitre */ 128d5996b2fSRussell King if (trace->nr_entries < trace->max_entries) 129d5996b2fSRussell King trace->entries[trace->nr_entries++] = ULONG_MAX; 130d5996b2fSRussell King return; 131f76e9154SNicolas Pitre #else 1322d7c11bfSCatalin Marinas frame.fp = thread_saved_fp(tsk); 1332d7c11bfSCatalin Marinas frame.sp = thread_saved_sp(tsk); 1342d7c11bfSCatalin Marinas frame.lr = 0; /* recovered from the stack */ 1352d7c11bfSCatalin Marinas frame.pc = thread_saved_pc(tsk); 136f76e9154SNicolas Pitre #endif 137f76e9154SNicolas Pitre } else { 1383683f44cSRussell King /* We don't want this function nor the caller */ 1393683f44cSRussell King data.skip += 2; 1402d7c11bfSCatalin Marinas frame.fp = (unsigned long)__builtin_frame_address(0); 14174dbeee0SBehan Webster frame.sp = current_stack_pointer; 1422d7c11bfSCatalin Marinas frame.lr = (unsigned long)__builtin_return_address(0); 1433683f44cSRussell King frame.pc = (unsigned long)__save_stack_trace; 144f76e9154SNicolas Pitre } 145f16fb1ecSRussell King 1462d7c11bfSCatalin Marinas walk_stackframe(&frame, save_trace, &data); 147f76e9154SNicolas Pitre if (trace->nr_entries < trace->max_entries) 148f76e9154SNicolas Pitre trace->entries[trace->nr_entries++] = ULONG_MAX; 149f76e9154SNicolas Pitre } 150f76e9154SNicolas Pitre 1519c986661SLin Yongting void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) 1529c986661SLin Yongting { 1539c986661SLin Yongting struct stack_trace_data data; 1549c986661SLin Yongting struct stackframe frame; 1559c986661SLin Yongting 1569c986661SLin Yongting data.trace = trace; 1579c986661SLin Yongting data.skip = trace->skip; 1589c986661SLin Yongting data.no_sched_functions = 0; 1599c986661SLin Yongting 1609c986661SLin Yongting frame.fp = regs->ARM_fp; 1619c986661SLin Yongting frame.sp = regs->ARM_sp; 1629c986661SLin Yongting frame.lr = regs->ARM_lr; 1639c986661SLin Yongting frame.pc = regs->ARM_pc; 1649c986661SLin Yongting 1659c986661SLin Yongting walk_stackframe(&frame, save_trace, &data); 1669c986661SLin Yongting if (trace->nr_entries < trace->max_entries) 1679c986661SLin Yongting trace->entries[trace->nr_entries++] = ULONG_MAX; 1689c986661SLin Yongting } 1699c986661SLin Yongting 1703683f44cSRussell King void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 1713683f44cSRussell King { 1723683f44cSRussell King __save_stack_trace(tsk, trace, 1); 1733683f44cSRussell King } 174*9a3dc318SDustin Brown EXPORT_SYMBOL(save_stack_trace_tsk); 1753683f44cSRussell King 176f76e9154SNicolas Pitre void save_stack_trace(struct stack_trace *trace) 177f76e9154SNicolas Pitre { 1783683f44cSRussell King __save_stack_trace(current, trace, 0); 179f16fb1ecSRussell King } 1807b4c9505SIngo Molnar EXPORT_SYMBOL_GPL(save_stack_trace); 181f16fb1ecSRussell King #endif 182