aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@kernel.org>2021-10-21 09:55:35 +0900
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2021-10-22 12:16:53 -0400
commitfed240d9c9743815fcbc0ca5c0913292ce1f25e2 (patch)
tree332b5002123a3db9bd9b6bc9a5f0144f008374eb /arch/arm/include
parentARM: kprobes: Make a frame pointer on __kretprobe_trampoline (diff)
downloadlinux-dev-fed240d9c9743815fcbc0ca5c0913292ce1f25e2.tar.xz
linux-dev-fed240d9c9743815fcbc0ca5c0913292ce1f25e2.zip
ARM: Recover kretprobe modified return address in stacktrace
Since the kretprobe replaces the function return address with the kretprobe_trampoline on the stack, arm unwinder shows it instead of the correct return address. This finds the correct return address from the per-task kretprobe_instances list and verify it is in between the caller fp and callee fp. Note that this supports both GCC and clang if CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=n. For the ARM unwinder, this is still not working correctly. Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'arch/arm/include')
-rw-r--r--arch/arm/include/asm/stacktrace.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/arm/include/asm/stacktrace.h b/arch/arm/include/asm/stacktrace.h
index 2d76a2e29f05..8f54f9ad8a9b 100644
--- a/arch/arm/include/asm/stacktrace.h
+++ b/arch/arm/include/asm/stacktrace.h
@@ -3,6 +3,7 @@
#define __ASM_STACKTRACE_H
#include <asm/ptrace.h>
+#include <linux/llist.h>
struct stackframe {
/*
@@ -13,6 +14,10 @@ struct stackframe {
unsigned long sp;
unsigned long lr;
unsigned long pc;
+#ifdef CONFIG_KRETPROBES
+ struct llist_node *kr_cur;
+ struct task_struct *tsk;
+#endif
};
static __always_inline
@@ -22,6 +27,10 @@ void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame)
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
}
extern int unwind_frame(struct stackframe *frame);