On Mon, Feb 24, 2025 at 6:08 AM Jiri Olsa <jolsa@xxxxxxxxxx> wrote: > > +SYSCALL_DEFINE0(uprobe) > +{ > + struct pt_regs *regs = task_pt_regs(current); > + unsigned long bp_vaddr; > + int err; > + > + err = copy_from_user(&bp_vaddr, (void __user *)regs->sp + 3*8, sizeof(bp_vaddr)); > + if (err) { > + force_sig(SIGILL); > + return -1; > + } > + > + /* Allow execution only from uprobe trampolines. */ > + if (!in_uprobe_trampoline(regs->ip)) { > + force_sig(SIGILL); > + return -1; > + } > + > + handle_syscall_uprobe(regs, bp_vaddr - 5); > + return 0; > +} > + > +asm ( > + ".pushsection .rodata\n" > + ".balign " __stringify(PAGE_SIZE) "\n" > + "uprobe_trampoline_entry:\n" > + "endbr64\n" why endbr is there? The trampoline is called with a direct call. > + "push %rcx\n" > + "push %r11\n" > + "push %rax\n" > + "movq $" __stringify(__NR_uprobe) ", %rax\n" To avoid introducing a new syscall for a very similar operation can we disambiguate uprobe vs uretprobe via %rdi or some other way? imo not too late to change uretprobe api. Maybe it was discussed already. > + "syscall\n" > + "pop %rax\n" > + "pop %r11\n" > + "pop %rcx\n" > + "ret\n" In later patches I see nop5 is replaced with a call to uprobe_trampoline_entry, but which part saves rdi and other regs? Compiler doesn't automatically spill/fill around USDT's nop/nop5. Selftest is doing: +__naked noinline void uprobe_test(void) so just lucky ?