Loading arch/arm/Kconfig +0 −1 Original line number Diff line number Diff line Loading @@ -107,7 +107,6 @@ config ARM select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI select HAVE_OPTPROBES if !THUMB2_KERNEL select HAVE_RETHOOK select HAVE_PERF_EVENTS select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP Loading arch/arm/include/asm/stacktrace.h +2 −2 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ struct stackframe { unsigned long sp; unsigned long lr; unsigned long pc; #if defined(CONFIG_KRETPROBES) || defined(CONFIG_RETHOOK) #ifdef CONFIG_KRETPROBES struct llist_node *kr_cur; struct task_struct *tsk; #endif Loading @@ -27,7 +27,7 @@ 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; #if defined(CONFIG_KRETPROBES) || defined(CONFIG_RETHOOK) #ifdef CONFIG_KRETPROBES frame->kr_cur = NULL; frame->tsk = current; #endif Loading arch/arm/kernel/stacktrace.c +0 −6 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only #include <linux/export.h> #include <linux/kprobes.h> #include <linux/rethook.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/stacktrace.h> Loading Loading @@ -67,11 +66,6 @@ int notrace unwind_frame(struct stackframe *frame) frame->sp = *(unsigned long *)(fp - 8); frame->pc = *(unsigned long *)(fp - 4); #endif #ifdef CONFIG_RETHOOK if (is_rethook_trampoline(frame->pc)) frame->pc = rethook_find_ret_addr(frame->tsk, frame->fp, &frame->kr_cur); #endif #ifdef CONFIG_KRETPROBES if (is_kretprobe_trampoline(frame->pc)) frame->pc = kretprobe_find_ret_addr(frame->tsk, Loading arch/arm/probes/Makefile +0 −1 Original line number Diff line number Diff line Loading @@ -6,4 +6,3 @@ obj-$(CONFIG_KPROBES) += decode-thumb.o else obj-$(CONFIG_KPROBES) += decode-arm.o endif obj-$(CONFIG_RETHOOK) += rethook.o arch/arm/probes/rethook.cdeleted 100644 → 0 +0 −103 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * arm implementation of rethook. Mostly copied from arch/arm/probes/kprobes/core.c */ #include <linux/kprobes.h> #include <linux/rethook.h> /* Called from arch_rethook_trampoline */ static __used unsigned long arch_rethook_trampoline_callback(struct pt_regs *regs) { return rethook_trampoline_handler(regs, regs->ARM_fp); } NOKPROBE_SYMBOL(arch_rethook_trampoline_callback); /* * When a rethook'ed function returns, it returns to arch_rethook_trampoline * which calls rethook callback. We construct a struct pt_regs to * give a view of registers r0-r11, sp, lr, and pc to the user * return-handler. This is not a complete pt_regs structure, but that * should be enough for stacktrace from the return handler with or * without pt_regs. */ asm( ".text\n" ".global arch_rethook_trampoline\n" ".type arch_rethook_trampoline, %function\n" "arch_rethook_trampoline:\n" #ifdef CONFIG_FRAME_POINTER "ldr lr, =arch_rethook_trampoline \n\t" /* this makes a framepointer on pt_regs. */ #ifdef CONFIG_CC_IS_CLANG "stmdb sp, {sp, lr, pc} \n\t" "sub sp, sp, #12 \n\t" /* In clang case, pt_regs->ip = lr. */ "stmdb sp!, {r0 - r11, lr} \n\t" /* fp points regs->r11 (fp) */ "add fp, sp, #44 \n\t" #else /* !CONFIG_CC_IS_CLANG */ /* In gcc case, pt_regs->ip = fp. */ "stmdb sp, {fp, sp, lr, pc} \n\t" "sub sp, sp, #16 \n\t" "stmdb sp!, {r0 - r11} \n\t" /* fp points regs->r15 (pc) */ "add fp, sp, #60 \n\t" #endif /* CONFIG_CC_IS_CLANG */ #else /* !CONFIG_FRAME_POINTER */ "sub sp, sp, #16 \n\t" "stmdb sp!, {r0 - r11} \n\t" #endif /* CONFIG_FRAME_POINTER */ "mov r0, sp \n\t" "bl arch_rethook_trampoline_callback \n\t" "mov lr, r0 \n\t" "ldmia sp!, {r0 - r11} \n\t" "add sp, sp, #16 \n\t" #ifdef CONFIG_THUMB2_KERNEL "bx lr \n\t" #else "mov pc, lr \n\t" #endif ".size arch_rethook_trampoline, .-arch_rethook_trampoline\n" ); NOKPROBE_SYMBOL(arch_rethook_trampoline); /* * At the entry of function with mcount. The stack and registers are prepared * for the mcount function as below. * * mov ip, sp * push {fp, ip, lr, pc} * sub fp, ip, #4 ; FP[0] = PC, FP[-4] = LR, and FP[-12] = call-site FP. * push {lr} * bl <__gnu_mcount_nc> ; call ftrace * * And when returning from the function, call-site FP, SP and PC are restored * from stack as below; * * ldm sp, {fp, sp, pc} * * Thus, if the arch_rethook_prepare() is called from real function entry, * it must change the LR and save FP in pt_regs. But if it is called via * mcount context (ftrace), it must change the LR on stack, which is next * to the PC (= FP[-4]), and save the FP value at FP[-12]. */ void arch_rethook_prepare(struct rethook_node *rh, struct pt_regs *regs, bool mcount) { unsigned long *ret_addr, *frame; if (mcount) { ret_addr = (unsigned long *)(regs->ARM_fp - 4); frame = (unsigned long *)(regs->ARM_fp - 12); } else { ret_addr = ®s->ARM_lr; frame = ®s->ARM_fp; } rh->ret_addr = *ret_addr; rh->frame = *frame; /* Replace the return addr with trampoline addr. */ *ret_addr = (unsigned long)arch_rethook_trampoline; } NOKPROBE_SYMBOL(arch_rethook_prepare); Loading
arch/arm/Kconfig +0 −1 Original line number Diff line number Diff line Loading @@ -107,7 +107,6 @@ config ARM select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI select HAVE_OPTPROBES if !THUMB2_KERNEL select HAVE_RETHOOK select HAVE_PERF_EVENTS select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP Loading
arch/arm/include/asm/stacktrace.h +2 −2 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ struct stackframe { unsigned long sp; unsigned long lr; unsigned long pc; #if defined(CONFIG_KRETPROBES) || defined(CONFIG_RETHOOK) #ifdef CONFIG_KRETPROBES struct llist_node *kr_cur; struct task_struct *tsk; #endif Loading @@ -27,7 +27,7 @@ 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; #if defined(CONFIG_KRETPROBES) || defined(CONFIG_RETHOOK) #ifdef CONFIG_KRETPROBES frame->kr_cur = NULL; frame->tsk = current; #endif Loading
arch/arm/kernel/stacktrace.c +0 −6 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only #include <linux/export.h> #include <linux/kprobes.h> #include <linux/rethook.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/stacktrace.h> Loading Loading @@ -67,11 +66,6 @@ int notrace unwind_frame(struct stackframe *frame) frame->sp = *(unsigned long *)(fp - 8); frame->pc = *(unsigned long *)(fp - 4); #endif #ifdef CONFIG_RETHOOK if (is_rethook_trampoline(frame->pc)) frame->pc = rethook_find_ret_addr(frame->tsk, frame->fp, &frame->kr_cur); #endif #ifdef CONFIG_KRETPROBES if (is_kretprobe_trampoline(frame->pc)) frame->pc = kretprobe_find_ret_addr(frame->tsk, Loading
arch/arm/probes/Makefile +0 −1 Original line number Diff line number Diff line Loading @@ -6,4 +6,3 @@ obj-$(CONFIG_KPROBES) += decode-thumb.o else obj-$(CONFIG_KPROBES) += decode-arm.o endif obj-$(CONFIG_RETHOOK) += rethook.o
arch/arm/probes/rethook.cdeleted 100644 → 0 +0 −103 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * arm implementation of rethook. Mostly copied from arch/arm/probes/kprobes/core.c */ #include <linux/kprobes.h> #include <linux/rethook.h> /* Called from arch_rethook_trampoline */ static __used unsigned long arch_rethook_trampoline_callback(struct pt_regs *regs) { return rethook_trampoline_handler(regs, regs->ARM_fp); } NOKPROBE_SYMBOL(arch_rethook_trampoline_callback); /* * When a rethook'ed function returns, it returns to arch_rethook_trampoline * which calls rethook callback. We construct a struct pt_regs to * give a view of registers r0-r11, sp, lr, and pc to the user * return-handler. This is not a complete pt_regs structure, but that * should be enough for stacktrace from the return handler with or * without pt_regs. */ asm( ".text\n" ".global arch_rethook_trampoline\n" ".type arch_rethook_trampoline, %function\n" "arch_rethook_trampoline:\n" #ifdef CONFIG_FRAME_POINTER "ldr lr, =arch_rethook_trampoline \n\t" /* this makes a framepointer on pt_regs. */ #ifdef CONFIG_CC_IS_CLANG "stmdb sp, {sp, lr, pc} \n\t" "sub sp, sp, #12 \n\t" /* In clang case, pt_regs->ip = lr. */ "stmdb sp!, {r0 - r11, lr} \n\t" /* fp points regs->r11 (fp) */ "add fp, sp, #44 \n\t" #else /* !CONFIG_CC_IS_CLANG */ /* In gcc case, pt_regs->ip = fp. */ "stmdb sp, {fp, sp, lr, pc} \n\t" "sub sp, sp, #16 \n\t" "stmdb sp!, {r0 - r11} \n\t" /* fp points regs->r15 (pc) */ "add fp, sp, #60 \n\t" #endif /* CONFIG_CC_IS_CLANG */ #else /* !CONFIG_FRAME_POINTER */ "sub sp, sp, #16 \n\t" "stmdb sp!, {r0 - r11} \n\t" #endif /* CONFIG_FRAME_POINTER */ "mov r0, sp \n\t" "bl arch_rethook_trampoline_callback \n\t" "mov lr, r0 \n\t" "ldmia sp!, {r0 - r11} \n\t" "add sp, sp, #16 \n\t" #ifdef CONFIG_THUMB2_KERNEL "bx lr \n\t" #else "mov pc, lr \n\t" #endif ".size arch_rethook_trampoline, .-arch_rethook_trampoline\n" ); NOKPROBE_SYMBOL(arch_rethook_trampoline); /* * At the entry of function with mcount. The stack and registers are prepared * for the mcount function as below. * * mov ip, sp * push {fp, ip, lr, pc} * sub fp, ip, #4 ; FP[0] = PC, FP[-4] = LR, and FP[-12] = call-site FP. * push {lr} * bl <__gnu_mcount_nc> ; call ftrace * * And when returning from the function, call-site FP, SP and PC are restored * from stack as below; * * ldm sp, {fp, sp, pc} * * Thus, if the arch_rethook_prepare() is called from real function entry, * it must change the LR and save FP in pt_regs. But if it is called via * mcount context (ftrace), it must change the LR on stack, which is next * to the PC (= FP[-4]), and save the FP value at FP[-12]. */ void arch_rethook_prepare(struct rethook_node *rh, struct pt_regs *regs, bool mcount) { unsigned long *ret_addr, *frame; if (mcount) { ret_addr = (unsigned long *)(regs->ARM_fp - 4); frame = (unsigned long *)(regs->ARM_fp - 12); } else { ret_addr = ®s->ARM_lr; frame = ®s->ARM_fp; } rh->ret_addr = *ret_addr; rh->frame = *frame; /* Replace the return addr with trampoline addr. */ *ret_addr = (unsigned long)arch_rethook_trampoline; } NOKPROBE_SYMBOL(arch_rethook_prepare);