On Tue, Apr 02, 2024 at 11:33:00AM +0200, Jiri Olsa wrote: SNIP > #include <linux/kdebug.h> > #include <asm/processor.h> > @@ -308,6 +309,88 @@ static int uprobe_init_insn(struct arch_uprobe *auprobe, struct insn *insn, bool > } > > #ifdef CONFIG_X86_64 > + > +asm ( > + ".pushsection .rodata\n" > + ".global uretprobe_syscall_entry\n" > + "uretprobe_syscall_entry:\n" > + "pushq %rax\n" > + "pushq %rcx\n" > + "pushq %r11\n" > + "movq $" __stringify(__NR_uretprobe) ", %rax\n" > + "syscall\n" > + "popq %r11\n" > + "popq %rcx\n" > + > + /* The uretprobe syscall replaces stored %rax value with final > + * return address, so we don't restore %rax in here and just > + * call ret. > + */ > + "retq\n" > + ".global uretprobe_syscall_end\n" > + "uretprobe_syscall_end:\n" > + ".popsection\n" > +); > + > +extern u8 uretprobe_syscall_entry[]; > +extern u8 uretprobe_syscall_end[]; > + > +void *arch_uprobe_trampoline(unsigned long *psize) > +{ > + *psize = uretprobe_syscall_end - uretprobe_syscall_entry; > + return uretprobe_syscall_entry; fyi I realized this screws 32-bit programs, we either need to add compat trampoline, or keep the standard breakpoint for them: + struct pt_regs *regs = task_pt_regs(current); + static uprobe_opcode_t insn = UPROBE_SWBP_INSN; + + if (user_64bit_mode(regs)) { + *psize = uretprobe_syscall_end - uretprobe_syscall_entry; + return uretprobe_syscall_entry; + } + + *psize = UPROBE_SWBP_INSN_SIZE; + return &insn; not sure it's worth the effort to add the trampoline, I'll check jirka