git: 1db0c9fa7a32 - main - hwpmc(4): stop overwalking past _start on amd64 user callchains
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 02 Sep 2026 14:30:30 UTC
The branch main has been updated by mhorne:
URL: https://cgit.FreeBSD.org/src/commit/?id=1db0c9fa7a32255c452c2536d657e63b55e30e03
commit 1db0c9fa7a32255c452c2536d657e63b55e30e03
Author: Nick Banks <nickbanks@netflix.com>
AuthorDate: 2026-09-02 14:28:54 +0000
Commit: Mitchell Horne <mhorne@FreeBSD.org>
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 <ali@mashtizadeh.com>, 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++;