The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=1db0c9fa7a32255c452c2536d657e63b55e30e03
commit 1db0c9fa7a32255c452c2536d657e63b55e30e03 Author: Nick Banks <[email protected]> AuthorDate: 2026-09-02 14:28:54 +0000 Commit: Mitchell Horne <[email protected]> CommitDate: 2026-09-02 14:29:08 +0000 hwpmc(4): stop overwalking past _start on amd64 user callchains pmc_save_user_callchain() emits the pc it just loaded before checking whether fp is the ABI's zero frame-chain terminator. At the bottom of a well-formed chain under _start, fp comes back 0 as expected, but the paired pc is stale rtld data left on the stack -- a legal userspace VA that still passes PMC_IN_USERSPACE(), so it gets emitted as a bogus extra frame. This shows up in flame graphs as a spurious hex-valued root frame below _start. Check fp == 0 alongside the existing checks before emitting, matching how arm/arm64/powerpc already load the next fp before their check. Measured via 1kHz hwpmc sampling on an OCA: stacks with any unresolved hex frame drop from 23.9% to 1.3%, and stacks with hex at the root drop from 5.5% to 0.3%. Reviewed by: mhorne, Ali Mashtizadeh <[email protected]>, gallatin MFC after: 3 days Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D59229 --- sys/dev/hwpmc/hwpmc_x86.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/hwpmc/hwpmc_x86.c b/sys/dev/hwpmc/hwpmc_x86.c index 2903c25ef5c9..c32242a2bbb9 100644 --- a/sys/dev/hwpmc/hwpmc_x86.c +++ b/sys/dev/hwpmc/hwpmc_x86.c @@ -107,7 +107,8 @@ pmc_save_user_callchain(uintptr_t *cc, int nframes, struct trapframe *tf) return (n); for (; n < nframes;) { - if (pc == 0 || !PMC_IN_USERSPACE(pc)) + /* fp == 0 is the ABI frame-chain sentinel below _start. */ + if (pc == 0 || !PMC_IN_USERSPACE(pc) || fp == 0) break; *cc++ = pc; n++;
