On Mon, Jul 08, 2024 at 04:11:27PM -0700, Andrii Nakryiko wrote: > +#ifdef CONFIG_UPROBES > +/* > + * Heuristic-based check if uprobe is installed at the function entry. > + * > + * Under assumption of user code being compiled with frame pointers, > + * `push %rbp/%ebp` is a good indicator that we indeed are. > + * > + * Similarly, `endbr64` (assuming 64-bit mode) is also a common pattern. > + * If we get this wrong, captured stack trace might have one extra bogus > + * entry, but the rest of stack trace will still be meaningful. > + */ > +static bool is_uprobe_at_func_entry(struct pt_regs *regs) > +{ > + struct arch_uprobe *auprobe; > + > + if (!current->utask) > + return false; > + > + auprobe = current->utask->auprobe; > + if (!auprobe) > + return false; > + > + /* push %rbp/%ebp */ > + if (auprobe->insn[0] == 0x55) > + return true; > + > + /* endbr64 (64-bit only) */ > + if (user_64bit_mode(regs) && *(u32 *)auprobe->insn == 0xfa1e0ff3) > + return true; I meant to reply to Josh suggesting this, but... how can this be? If you scribble the ENDBR with an INT3 things will #CP and we'll never get to the #BP. Also, we tried very hard to not have a literal encode ENDBR (I really should teach objtool about this one :/). If it somehow makes sense to keep this clause, please use: gen_endbr()