1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2ecea4ab6SPaul Gortmaker #include <linux/export.h> 3fed240d9SMasami Hiramatsu #include <linux/kprobes.h> 4f16fb1ecSRussell King #include <linux/sched.h> 5b17b0153SIngo Molnar #include <linux/sched/debug.h> 6f16fb1ecSRussell King #include <linux/stacktrace.h> 7f16fb1ecSRussell King 8c6089061SRussell King #include <asm/sections.h> 92d7c11bfSCatalin Marinas #include <asm/stacktrace.h> 1007b40341SRussell King #include <asm/traps.h> 11f16fb1ecSRussell King 125854e4d8SLi Huafei #include "reboot.h" 135854e4d8SLi Huafei 142d7c11bfSCatalin Marinas #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) 152d7c11bfSCatalin Marinas /* 162d7c11bfSCatalin Marinas * Unwind the current stack frame and store the new register values in the 172d7c11bfSCatalin Marinas * structure passed as argument. Unwinding is equivalent to a function return, 182d7c11bfSCatalin Marinas * hence the new PC value rather than LR should be used for backtrace. 192d7c11bfSCatalin Marinas * 202d7c11bfSCatalin Marinas * With framepointer enabled, a simple function prologue looks like this: 212d7c11bfSCatalin Marinas * mov ip, sp 222d7c11bfSCatalin Marinas * stmdb sp!, {fp, ip, lr, pc} 232d7c11bfSCatalin Marinas * sub fp, ip, #4 242d7c11bfSCatalin Marinas * 252d7c11bfSCatalin Marinas * A simple function epilogue looks like this: 262d7c11bfSCatalin Marinas * ldm sp, {fp, sp, pc} 272d7c11bfSCatalin Marinas * 28b4d5ec9bSNathan Huckleberry * When compiled with clang, pc and sp are not pushed. A simple function 29b4d5ec9bSNathan Huckleberry * prologue looks like this when built with clang: 30b4d5ec9bSNathan Huckleberry * 31b4d5ec9bSNathan Huckleberry * stmdb {..., fp, lr} 32b4d5ec9bSNathan Huckleberry * add fp, sp, #x 33b4d5ec9bSNathan Huckleberry * sub sp, sp, #y 34b4d5ec9bSNathan Huckleberry * 35b4d5ec9bSNathan Huckleberry * A simple function epilogue looks like this when built with clang: 36b4d5ec9bSNathan Huckleberry * 37b4d5ec9bSNathan Huckleberry * sub sp, fp, #x 38b4d5ec9bSNathan Huckleberry * ldm {..., fp, pc} 39b4d5ec9bSNathan Huckleberry * 40b4d5ec9bSNathan Huckleberry * 412d7c11bfSCatalin Marinas * Note that with framepointer enabled, even the leaf functions have the same 422d7c11bfSCatalin Marinas * prologue and epilogue, therefore we can ignore the LR value in this case. 432d7c11bfSCatalin Marinas */ 445854e4d8SLi Huafei 455854e4d8SLi Huafei extern unsigned long call_with_stack_end; 465854e4d8SLi Huafei 475854e4d8SLi Huafei static int frame_pointer_check(struct stackframe *frame) 482d7c11bfSCatalin Marinas { 492d7c11bfSCatalin Marinas unsigned long high, low; 502d7c11bfSCatalin Marinas unsigned long fp = frame->fp; 515854e4d8SLi Huafei unsigned long pc = frame->pc; 525854e4d8SLi Huafei 535854e4d8SLi Huafei /* 545854e4d8SLi Huafei * call_with_stack() is the only place we allow SP to jump from one 555854e4d8SLi Huafei * stack to another, with FP and SP pointing to different stacks, 565854e4d8SLi Huafei * skipping the FP boundary check at this point. 575854e4d8SLi Huafei */ 585854e4d8SLi Huafei if (pc >= (unsigned long)&call_with_stack && 595854e4d8SLi Huafei pc < (unsigned long)&call_with_stack_end) 605854e4d8SLi Huafei return 0; 612d7c11bfSCatalin Marinas 622d7c11bfSCatalin Marinas /* only go to a higher address on the stack */ 632d7c11bfSCatalin Marinas low = frame->sp; 64d33aadbfSWill Deacon high = ALIGN(low, THREAD_SIZE); 652d7c11bfSCatalin Marinas 66b4d5ec9bSNathan Huckleberry /* check current frame pointer is within bounds */ 675854e4d8SLi Huafei #ifdef CONFIG_CC_IS_CLANG 68b4d5ec9bSNathan Huckleberry if (fp < low + 4 || fp > high - 4) 69b4d5ec9bSNathan Huckleberry return -EINVAL; 705854e4d8SLi Huafei #else 715854e4d8SLi Huafei if (fp < low + 12 || fp > high - 4) 725854e4d8SLi Huafei return -EINVAL; 735854e4d8SLi Huafei #endif 74b4d5ec9bSNathan Huckleberry 755854e4d8SLi Huafei return 0; 765854e4d8SLi Huafei } 775854e4d8SLi Huafei 785854e4d8SLi Huafei int notrace unwind_frame(struct stackframe *frame) 795854e4d8SLi Huafei { 805854e4d8SLi Huafei unsigned long fp = frame->fp; 815854e4d8SLi Huafei 825854e4d8SLi Huafei if (frame_pointer_check(frame)) 835854e4d8SLi Huafei return -EINVAL; 845854e4d8SLi Huafei 85752ec621SLi Huafei /* 86752ec621SLi Huafei * When we unwind through an exception stack, include the saved PC 87752ec621SLi Huafei * value into the stack trace. 88752ec621SLi Huafei */ 89752ec621SLi Huafei if (frame->ex_frame) { 90752ec621SLi Huafei struct pt_regs *regs = (struct pt_regs *)frame->sp; 91752ec621SLi Huafei 92752ec621SLi Huafei /* 93752ec621SLi Huafei * We check that 'regs + sizeof(struct pt_regs)' (that is, 94752ec621SLi Huafei * ®s[1]) does not exceed the bottom of the stack to avoid 95752ec621SLi Huafei * accessing data outside the task's stack. This may happen 96752ec621SLi Huafei * when frame->ex_frame is a false positive. 97752ec621SLi Huafei */ 98752ec621SLi Huafei if ((unsigned long)®s[1] > ALIGN(frame->sp, THREAD_SIZE)) 99752ec621SLi Huafei return -EINVAL; 100752ec621SLi Huafei 101752ec621SLi Huafei frame->pc = regs->ARM_pc; 102752ec621SLi Huafei frame->ex_frame = false; 103752ec621SLi Huafei return 0; 104752ec621SLi Huafei } 105752ec621SLi Huafei 1065854e4d8SLi Huafei /* restore the registers from the stack frame */ 1075854e4d8SLi Huafei #ifdef CONFIG_CC_IS_CLANG 108b4d5ec9bSNathan Huckleberry frame->sp = frame->fp; 1099be4c88bSlinyujun frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); 1109be4c88bSlinyujun frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4)); 111b4d5ec9bSNathan Huckleberry #else 1129be4c88bSlinyujun frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 12)); 1139be4c88bSlinyujun frame->sp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 8)); 1149be4c88bSlinyujun frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 4)); 115b4d5ec9bSNathan Huckleberry #endif 116fed240d9SMasami Hiramatsu #ifdef CONFIG_KRETPROBES 117fed240d9SMasami Hiramatsu if (is_kretprobe_trampoline(frame->pc)) 118fed240d9SMasami Hiramatsu frame->pc = kretprobe_find_ret_addr(frame->tsk, 119fed240d9SMasami Hiramatsu (void *)frame->fp, &frame->kr_cur); 120fed240d9SMasami Hiramatsu #endif 1212d7c11bfSCatalin Marinas 122752ec621SLi Huafei if (in_entry_text(frame->pc)) 123752ec621SLi Huafei frame->ex_frame = true; 124752ec621SLi Huafei 1252d7c11bfSCatalin Marinas return 0; 1262d7c11bfSCatalin Marinas } 1272d7c11bfSCatalin Marinas #endif 1282d7c11bfSCatalin Marinas 1294bf1fa5aSUwe Kleine-König void notrace walk_stackframe(struct stackframe *frame, 13070ccc7c0SLi Huafei bool (*fn)(void *, unsigned long), void *data) 131f16fb1ecSRussell King { 1322d7c11bfSCatalin Marinas while (1) { 1332d7c11bfSCatalin Marinas int ret; 134f16fb1ecSRussell King 13570ccc7c0SLi Huafei if (!fn(data, frame->pc)) 136f16fb1ecSRussell King break; 1372d7c11bfSCatalin Marinas ret = unwind_frame(frame); 1382d7c11bfSCatalin Marinas if (ret < 0) 1392d7c11bfSCatalin Marinas break; 1402d7c11bfSCatalin Marinas } 141f16fb1ecSRussell King } 1427b104bcbSAl Viro EXPORT_SYMBOL(walk_stackframe); 143f16fb1ecSRussell King 144f16fb1ecSRussell King #ifdef CONFIG_STACKTRACE 145*9fbed16cSLi Huafei static void start_stack_trace(struct stackframe *frame, struct task_struct *task, 146*9fbed16cSLi Huafei unsigned long fp, unsigned long sp, 147*9fbed16cSLi Huafei unsigned long lr, unsigned long pc) 148f16fb1ecSRussell King { 149*9fbed16cSLi Huafei frame->fp = fp; 150*9fbed16cSLi Huafei frame->sp = sp; 151*9fbed16cSLi Huafei frame->lr = lr; 152*9fbed16cSLi Huafei frame->pc = pc; 153*9fbed16cSLi Huafei #ifdef CONFIG_KRETPROBES 154*9fbed16cSLi Huafei frame->kr_cur = NULL; 155*9fbed16cSLi Huafei frame->tsk = task; 156*9fbed16cSLi Huafei #endif 157*9fbed16cSLi Huafei #ifdef CONFIG_UNWINDER_FRAME_POINTER 158*9fbed16cSLi Huafei frame->ex_frame = in_entry_text(frame->pc); 159*9fbed16cSLi Huafei #endif 160f16fb1ecSRussell King } 161f16fb1ecSRussell King 162*9fbed16cSLi Huafei void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie, 163*9fbed16cSLi Huafei struct task_struct *task, struct pt_regs *regs) 164f16fb1ecSRussell King { 1652d7c11bfSCatalin Marinas struct stackframe frame; 166f16fb1ecSRussell King 167*9fbed16cSLi Huafei if (regs) { 168*9fbed16cSLi Huafei start_stack_trace(&frame, NULL, regs->ARM_fp, regs->ARM_sp, 169*9fbed16cSLi Huafei regs->ARM_lr, regs->ARM_pc); 170*9fbed16cSLi Huafei } else if (task != current) { 171f76e9154SNicolas Pitre #ifdef CONFIG_SMP 172f76e9154SNicolas Pitre /* 173d5996b2fSRussell King * What guarantees do we have here that 'tsk' is not 174d5996b2fSRussell King * running on another CPU? For now, ignore it as we 175d5996b2fSRussell King * can't guarantee we won't explode. 176f76e9154SNicolas Pitre */ 177d5996b2fSRussell King return; 178f76e9154SNicolas Pitre #else 179*9fbed16cSLi Huafei start_stack_trace(&frame, task, thread_saved_fp(task), 180*9fbed16cSLi Huafei thread_saved_sp(task), 0, 181*9fbed16cSLi Huafei thread_saved_pc(task)); 182f76e9154SNicolas Pitre #endif 183f76e9154SNicolas Pitre } else { 184c46c2c9bSRussell King (Oracle) here: 185*9fbed16cSLi Huafei start_stack_trace(&frame, task, 186*9fbed16cSLi Huafei (unsigned long)__builtin_frame_address(0), 187*9fbed16cSLi Huafei current_stack_pointer, 188*9fbed16cSLi Huafei (unsigned long)__builtin_return_address(0), 189*9fbed16cSLi Huafei (unsigned long)&&here); 190*9fbed16cSLi Huafei /* skip this function */ 191*9fbed16cSLi Huafei if (unwind_frame(&frame)) 192*9fbed16cSLi Huafei return; 193f76e9154SNicolas Pitre } 194f76e9154SNicolas Pitre 195*9fbed16cSLi Huafei walk_stackframe(&frame, consume_entry, cookie); 1969c986661SLin Yongting } 197f16fb1ecSRussell King #endif 198