diff options
author | Jiri Olsa <jolsa@kernel.org> | 2024-04-23 22:52:34 +0200 |
---|---|---|
committer | Jiri Olsa <jolsa@kernel.org> | 2024-04-25 12:23:40 +0200 |
commit | 554d1563d6bebe03a19f9500907d0b71df555713 (patch) | |
tree | a529c4210164aceecc68cfc25b6239fa2c52edb9 | |
parent | 701e9a93fa0d2cd527e5ff28ab359e5f3c45cce8 (diff) | |
download | perf-bpf/optimized_usdt_2.tar.gz |
uprobe: Install optimized uprobebpf/optimized_usdt_2
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
-rw-r--r-- | arch/x86/kernel/uprobes.c | 28 | ||||
-rw-r--r-- | include/linux/uprobes.h | 2 | ||||
-rw-r--r-- | kernel/events/uprobes.c | 7 |
3 files changed, 36 insertions, 1 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 1380b1fa6cadff..10fc934d5b968e 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -1266,3 +1266,31 @@ void *arch_uprobe_nop_trampoline(unsigned long *tramp_size) *tramp_size = optuprobe_template_end - optuprobe_template_entry; return optuprobe_template_entry; } + +static void +__relative_insn(void *dest, void *from, void *to, u8 op) +{ + struct __arch_relative_insn { + u8 op; + s32 raddr; + } __packed *insn; + + insn = (struct __arch_relative_insn *)dest; + insn->raddr = (s32)((long)(to) - ((long)(from) + 5)); + insn->op = op; +} + +/* Insert a jump instruction at address 'from', which jumps to address 'to'.*/ +static void relcall(void *dest, void *from, void *to) +{ + __relative_insn(dest, from, to, CALL_INSN_OPCODE); +} + +int arch_optimize_uprobe(struct mm_struct *mm, unsigned long vaddr, + unsigned long tramp_vaddr) +{ + char call[5]; + + relcall(call, (void *) vaddr, (void *) tramp_vaddr); + return uprobe_write_page(mm, vaddr, call, 5, true); +} diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h index 3dca657754c154..0963786d34f712 100644 --- a/include/linux/uprobes.h +++ b/include/linux/uprobes.h @@ -147,6 +147,8 @@ extern bool arch_uprobe_can_optimize(struct arch_uprobe *auprobe, unsigned long extern void * arch_uprobe_nop_trampoline(unsigned long *psize); extern unsigned long uprobe_get_trampoline_vaddr(void); void handle_syscall_uprobe(struct pt_regs *regs, unsigned long bp_vaddr); +extern int arch_optimize_uprobe(struct mm_struct *mm, unsigned long vaddr, + unsigned long tramp_vaddr); #else /* !CONFIG_UPROBES */ struct uprobes_state { }; diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index a2860e05735068..0aa4d50d677335 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -1099,6 +1099,11 @@ static struct trampoline_area *get_trampoline_area(unsigned long vaddr) return area; } +int __weak arch_optimize_uprobe(struct mm_struct *mm, unsigned long vaddr, + unsigned long tramp_vaddr) +{ + return -EINVAL; +} static int optimize_uprobe(struct uprobe *uprobe, struct mm_struct *mm, @@ -1113,7 +1118,7 @@ optimize_uprobe(struct uprobe *uprobe, struct mm_struct *mm, if (!area) return -EINVAL; - return -EINVAL; + return arch_optimize_uprobe(mm, vaddr, area->vaddr); } static int |