[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