diff options
Diffstat (limited to 'arch/arm/kernel/stacktrace.c')
| -rw-r--r-- | arch/arm/kernel/stacktrace.c | 17 | 
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 76ea4178a55c..75e905508f27 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -1,5 +1,6 @@  // SPDX-License-Identifier: GPL-2.0-only  #include <linux/export.h> +#include <linux/kprobes.h>  #include <linux/sched.h>  #include <linux/sched/debug.h>  #include <linux/stacktrace.h> @@ -54,8 +55,7 @@ int notrace unwind_frame(struct stackframe *frame)  	frame->sp = frame->fp;  	frame->fp = *(unsigned long *)(fp); -	frame->pc = frame->lr; -	frame->lr = *(unsigned long *)(fp + 4); +	frame->pc = *(unsigned long *)(fp + 4);  #else  	/* check current frame pointer is within bounds */  	if (fp < low + 12 || fp > high - 4) @@ -66,6 +66,11 @@ int notrace unwind_frame(struct stackframe *frame)  	frame->sp = *(unsigned long *)(fp - 8);  	frame->pc = *(unsigned long *)(fp - 4);  #endif +#ifdef CONFIG_KRETPROBES +	if (is_kretprobe_trampoline(frame->pc)) +		frame->pc = kretprobe_find_ret_addr(frame->tsk, +					(void *)frame->fp, &frame->kr_cur); +#endif  	return 0;  } @@ -157,6 +162,10 @@ static noinline void __save_stack_trace(struct task_struct *tsk,  		frame.lr = (unsigned long)__builtin_return_address(0);  		frame.pc = (unsigned long)__save_stack_trace;  	} +#ifdef CONFIG_KRETPROBES +	frame.kr_cur = NULL; +	frame.tsk = tsk; +#endif  	walk_stackframe(&frame, save_trace, &data);  } @@ -174,6 +183,10 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)  	frame.sp = regs->ARM_sp;  	frame.lr = regs->ARM_lr;  	frame.pc = regs->ARM_pc; +#ifdef CONFIG_KRETPROBES +	frame.kr_cur = NULL; +	frame.tsk = current; +#endif  	walk_stackframe(&frame, save_trace, &data);  }  | 
