bool
        default y
        select ARCH_32BIT_OFF_T
+       select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE if HAVE_KRETPROBES && FRAME_POINTER && !ARM_UNWIND
        select ARCH_HAS_BINFMT_FLAT
        select ARCH_HAS_DEBUG_VIRTUAL if MMU
        select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE
 
 #define __ASM_STACKTRACE_H
 
 #include <asm/ptrace.h>
+#include <linux/llist.h>
 
 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
                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);
 
        frame.sp = current_stack_pointer;
        frame.lr = (unsigned long)__builtin_return_address(0);
        frame.pc = (unsigned long)return_address;
+#ifdef CONFIG_KRETPROBES
+       frame.kr_cur = NULL;
+       frame.tsk = current;
+#endif
 
        walk_stackframe(&frame, save_return_addr, &data);
 
 
 // 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>
        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;
 }
                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);
 }
        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);
 }