summaryrefslogtreecommitdiff
path: root/arch/s390/include/asm/unwind.h
diff options
context:
space:
mode:
authorVasily Gorbik <gor@linux.ibm.com>2021-04-28 17:29:40 +0300
committerVasily Gorbik <gor@linux.ibm.com>2022-03-27 23:18:39 +0300
commitd81675b60d0959cfa3727f03d5b90558fb457011 (patch)
treeb2a3051b67ebf5ea4a58a73195c5b2193da65713 /arch/s390/include/asm/unwind.h
parent09bc20c8fb35cf1afed1612b287e9ddbe6a7d73c (diff)
downloadlinux-d81675b60d0959cfa3727f03d5b90558fb457011.tar.xz
s390/unwind: recover kretprobe modified return address in stacktrace
Based on commit cd9bc2c92588 ("arm64: Recover kretprobe modified return address in stacktrace"). """ Since the kretprobe replaces the function return address with the __kretprobe_trampoline on the stack, stack unwinder shows it instead of the correct return address. This checks whether the next return address is the __kretprobe_trampoline(), and if so, try to find the correct return address from the kretprobe instance list. """ Original patch series: https://lore.kernel.org/all/163163030719.489837.2236069935502195491.stgit@devnote2/ Reviewed-by: Tobias Huschle <huschle@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'arch/s390/include/asm/unwind.h')
-rw-r--r--arch/s390/include/asm/unwind.h13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/s390/include/asm/unwind.h b/arch/s390/include/asm/unwind.h
index 5ebf534ef753..0bf06f1682d8 100644
--- a/arch/s390/include/asm/unwind.h
+++ b/arch/s390/include/asm/unwind.h
@@ -4,6 +4,8 @@
#include <linux/sched.h>
#include <linux/ftrace.h>
+#include <linux/kprobes.h>
+#include <linux/llist.h>
#include <asm/ptrace.h>
#include <asm/stacktrace.h>
@@ -36,10 +38,21 @@ struct unwind_state {
struct pt_regs *regs;
unsigned long sp, ip;
int graph_idx;
+ struct llist_node *kr_cur;
bool reliable;
bool error;
};
+/* Recover the return address modified by kretprobe and ftrace_graph. */
+static inline unsigned long unwind_recover_ret_addr(struct unwind_state *state,
+ unsigned long ip)
+{
+ ip = ftrace_graph_ret_addr(state->task, &state->graph_idx, ip, NULL);
+ if (is_kretprobe_trampoline(ip))
+ ip = kretprobe_find_ret_addr(state->task, (void *)state->sp, &state->kr_cur);
+ return ip;
+}
+
void __unwind_start(struct unwind_state *state, struct task_struct *task,
struct pt_regs *regs, unsigned long first_frame);
bool unwind_next_frame(struct unwind_state *state);