Messages in this thread |  | | Subject | Re: [PATCH 2/4] LoongArch: Add kretprobe support | | From | Jinyang He <> | | Date | Wed, 21 Sep 2022 16:22:39 +0800 |
| |
On 09/20/2022 11:37 AM, Tiezhu Yang wrote:
> Use the generic kretprobe trampoline handler to add kretprobe > support for LoongArch. > > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> > --- > arch/loongarch/Kconfig | 1 + > arch/loongarch/kernel/kprobes.c | 49 ++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 49 insertions(+), 1 deletion(-) > > diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig > index 6b01073..5f8503a 100644 > --- a/arch/loongarch/Kconfig > +++ b/arch/loongarch/Kconfig > @@ -95,6 +95,7 @@ config LOONGARCH > select HAVE_IRQ_EXIT_ON_IRQ_STACK > select HAVE_IRQ_TIME_ACCOUNTING > select HAVE_KPROBES > + select HAVE_KRETPROBES > select HAVE_MOD_ARCH_SPECIFIC > select HAVE_NMI > select HAVE_PCI > diff --git a/arch/loongarch/kernel/kprobes.c b/arch/loongarch/kernel/kprobes.c > index b2c73a5..8c3efe5 100644 > --- a/arch/loongarch/kernel/kprobes.c > +++ b/arch/loongarch/kernel/kprobes.c > @@ -303,7 +303,54 @@ int kprobe_exceptions_notify(struct notifier_block *self, > } > NOKPROBE_SYMBOL(kprobe_exceptions_notify); > > +/* > + * For function-return probes, init_kprobes() establishes a probepoint > + * here. When a retprobed function returns, this probe is hit and > + * trampoline_probe_handler() runs, calling the kretprobe's handler. > + */ > +static void __used kretprobe_trampoline_holder(void) > +{ > + asm volatile(".global __kretprobe_trampoline\n" > + "__kretprobe_trampoline:\n" > + "nop\n"); > +} > + > +/* Called when the probe at kretprobe trampoline is hit */ > +static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) > +{ > + instruction_pointer(regs) = __kretprobe_trampoline_handler(regs, NULL); > + /* > + * By returning a non-zero value, we are telling > + * kprobe_handler() that we don't want the post_handler > + * to run (and have re-enabled preemption) > + */ > + return 1; > +} > +NOKPROBE_SYMBOL(trampoline_probe_handler); > + > +static struct kprobe trampoline_p = { > + .addr = (kprobe_opcode_t *)__kretprobe_trampoline, > + .pre_handler = trampoline_probe_handler > +}; > + > +void arch_prepare_kretprobe(struct kretprobe_instance *ri, > + struct pt_regs *regs) > +{ > + ri->ret_addr = (kprobe_opcode_t *)regs->regs[1]; > + ri->fp = NULL; > + > + /* Replace the return addr with trampoline addr */ > + regs->regs[1] = (unsigned long)__kretprobe_trampoline; > +} > +NOKPROBE_SYMBOL(arch_prepare_kretprobe); > + > +int arch_trampoline_kprobe(struct kprobe *p) > +{ > + return p->addr == trampoline_p.addr; > +} > +NOKPROBE_SYMBOL(arch_trampoline_kprobe); > + > int __init arch_init_kprobes(void) > { > - return 0; > + return register_kprobe(&trampoline_p); Hi, Tiezhu,
For kretprobe, we can do things like arm64/riscv... did. It avoid the break exception when function return.
Thanks, Jinyang > }
|  |