[llvm] [llvm-profgen] Parse hex address suffixes in perf scripts (PR #219268)
Rahman Lavaee via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 12:01:53 PDT 2026
https://github.com/rlavaee updated https://github.com/llvm/llvm-project/pull/219268
>From bf4a16d7f4679c88e651de7452d6a297500ca0ee Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Thu, 27 Aug 2026 16:59:24 +0000
Subject: [PATCH] [llvm-profgen] Parse hex address suffixes in perf scripts
DSO/library names (e.g. ` [unknown]`, ` [libc.so.6]`) are sometimes appended to call stack addresses in perf scripts. This causes `parseAddress` to fail because `getAsInteger` expects the entire input string to be the integer representation.
Fix this by using `take_while` to strip trailing whitespace/non-hex suffixes from the address token inside `parseAddress`. To prevent LBR lines from being mistakenly consumed as call stack entries in `checkPerfScriptType`'s detection loop, we add an explicit check to stop when an LBR line is encountered.
Added a new test case `callstack-dso-suffix.test` verifying correct parsing with different types of suffixes.
---
.../Inputs/callstack-dso-suffix.perfscript | 12 +++++++
.../X86/callstack-dso-suffix.test | 36 +++++++++++++++++++
llvm/tools/llvm-profgen/PerfReader.cpp | 3 ++
3 files changed, 51 insertions(+)
create mode 100644 llvm/test/tools/llvm-profgen/X86/Inputs/callstack-dso-suffix.perfscript
create mode 100644 llvm/test/tools/llvm-profgen/X86/callstack-dso-suffix.test
diff --git a/llvm/test/tools/llvm-profgen/X86/Inputs/callstack-dso-suffix.perfscript b/llvm/test/tools/llvm-profgen/X86/Inputs/callstack-dso-suffix.perfscript
new file mode 100644
index 0000000000000..4d4ff8a54f730
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/X86/Inputs/callstack-dso-suffix.perfscript
@@ -0,0 +1,12 @@
+PERF_RECORD_MMAP2 2854748/2854748: [0x400000(0x1000) @ 0 00:1d 123291722 526021]: r-xp /home/noinline-cs-noprobe.perfbin
+
+ 4005dc [unknown]
+ 400634 [libc.so.6]
+ 400684
+ 7f68c5788793 [unknown]
+ 0x4005c8/0x4005dc/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005d7/0x4005e5/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005d7/0x4005e5/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005c8/0x4005dc/P/-/-/0
+
+ 4005b0 [libc.so.6]
+ 400684
+ 7f68c5788793 [unknown]
+ 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005c8/0x4005dc/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005d7/0x4005e5/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005d7/0x4005e5/P/-/-/0 0x40062f/0x4005b0/P/-/-/0
diff --git a/llvm/test/tools/llvm-profgen/X86/callstack-dso-suffix.test b/llvm/test/tools/llvm-profgen/X86/callstack-dso-suffix.test
new file mode 100644
index 0000000000000..1e073d1432d22
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/X86/callstack-dso-suffix.test
@@ -0,0 +1,36 @@
+;; The test fails on Windows. Fix it before removing the following requirement.
+; REQUIRES: x86_64-linux
+; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/callstack-dso-suffix.perfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0
+; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER
+; RUN: llvm-profgen --format=text --unsymbolized-profile=%t --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t1 --profile-summary-cold-count=0 --csspgo-preinliner=0 --gen-cs-nested-profile=0
+; RUN: FileCheck %s --input-file %t1
+
+; CHECK-UNWINDER: [main:1 @ foo]
+; CHECK-UNWINDER-NEXT: 3
+; CHECK-UNWINDER-NEXT: 5ff-62f:3
+; CHECK-UNWINDER-NEXT: 634-637:3
+; CHECK-UNWINDER-NEXT: 645-645:3
+; CHECK-UNWINDER-NEXT: 3
+; CHECK-UNWINDER-NEXT: 62f->5b0:3
+; CHECK-UNWINDER-NEXT: 637->645:3
+; CHECK-UNWINDER-NEXT: 645->5ff:3
+; CHECK-UNWINDER-NEXT: [main:1 @ foo:3 @ bar]
+; CHECK-UNWINDER-NEXT: 4
+; CHECK-UNWINDER-NEXT: 5b0-5c8:1
+; CHECK-UNWINDER-NEXT: 5b0-5d7:2
+; CHECK-UNWINDER-NEXT: 5dc-5e9:1
+; CHECK-UNWINDER-NEXT: 5e5-5e9:2
+; CHECK-UNWINDER-NEXT: 3
+; CHECK-UNWINDER-NEXT: 5c8->5dc:2
+; CHECK-UNWINDER-NEXT: 5d7->5e5:2
+; CHECK-UNWINDER-NEXT: 5e9->634:3
+
+; CHECK:[main:1 @ foo]:54:0
+; CHECK: 2: 3
+; CHECK: 3: 3 bar:3
+; CHECK:[main:1 @ foo:3 @ bar]:50:3
+; CHECK: 0: 3
+; CHECK: 1: 3
+; CHECK: 2: 2
+; CHECK: 4: 1
+; CHECK: 5: 3
diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp
index c4fc4fb25166f..daabb5183d440 100644
--- a/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
#include "PerfReader.h"
+#include <cctype>
#include "ErrorHandling.h"
#include "Options.h"
#include "ProfileGenerator.h"
@@ -708,6 +709,7 @@ void HybridPerfReader::unwindSamples() {
/// Parse a hex address from \p Str.
static bool parseAddress(StringRef Str, uint64_t &Addr, bool HasPrefix) {
+ Str = Str.take_while([](char C) { return !isspace(C); });
if (Str.consume_front("0x") != HasPrefix)
return true;
return Str.getAsInteger(16, Addr);
@@ -1264,6 +1266,7 @@ PerfContent PerfScriptReader::checkPerfScriptType(StringRef FileName) {
// Detect sample with call stack
int32_t Count = 0;
while (!TraceIt.isAtEoF() &&
+ !isLBRSample(TraceIt.getCurrentLine(), false) &&
!parseAddress(TraceIt.getCurrentLine().ltrim(), FrameAddr, false)) {
Count++;
TraceIt.advance();
More information about the llvm-commits
mailing list