[llvm] [llvm-profgen] Preserve zero-valued first PT_LOAD address (PR #212258)
Sergey Shcherbinin via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 27 07:10:37 PDT 2026
https://github.com/SergeyShch01 created https://github.com/llvm/llvm-project/pull/212258
FirstLoadableAddress was initialized with if (!FirstLoadableAddress), so a valid first PT_LOAD at vaddr 0 was treated as unset and overwritten by a later segment. Track whether the first loadable segment has been seen instead.
Assisted by GPT-5
>From 49a2cee58f26c064241c3e6dd8d137036fa14c0c Mon Sep 17 00:00:00 2001
From: Sergey Shcherbinin <sscherbinin at nvidia.com>
Date: Mon, 27 Jul 2026 18:04:33 +0400
Subject: [PATCH] [llvm-profgen] Preserve zero-valued first PT_LOAD address
FirstLoadableAddress was initialized with if (!FirstLoadableAddress), so a
valid first PT_LOAD at vaddr 0 was treated as unset and overwritten by a later
segment. Track whether the first loadable segment has been seen instead.
Assisted by GPT-5
---
.../X86/first-loadable-address.test | 59 +++++++++++++++++++
llvm/tools/llvm-profgen/ProfiledBinary.cpp | 5 +-
2 files changed, 63 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/tools/llvm-profgen/X86/first-loadable-address.test
diff --git a/llvm/test/tools/llvm-profgen/X86/first-loadable-address.test b/llvm/test/tools/llvm-profgen/X86/first-loadable-address.test
new file mode 100644
index 0000000000000..50f9f5dcc2f63
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/X86/first-loadable-address.test
@@ -0,0 +1,59 @@
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/first-loadable-address.exe
+# RUN: llvm-profgen --binary=%t/first-loadable-address.exe \
+# RUN: --perfscript=%t/perfscript --skip-symbolization --format=text \
+# RUN: --use-offset=1 --use-first-loadable-segment-as-base=1 \
+# RUN: --output=%t/profile
+# RUN: FileCheck %s --input-file=%t/profile
+
+## The first PT_LOAD has a valid zero virtual address. Ensure it is not treated
+## as an unset value and overwritten by the following executable PT_LOAD.
+## With the default 4K page size, the text segment file offset is 0x1000, so the
+## mmap event uses that offset rather than zero.
+# CHECK: 0
+# CHECK-NEXT: 1
+# CHECK-NEXT: 11008->11000:1
+
+#--- binary.yaml
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+ Entry: 0x0000000000011000
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000011000
+ Offset: 0x0000000000001000
+ AddressAlign: 0x1
+ ## 11000: nop*8
+ ## 11008: ret
+ Content: 9090909090909090C3
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ Offset: 0x0
+ VAddr: 0x0
+ FileSize: 0x1000
+ MemSize: 0x1000
+ Align: 0x1000
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ VAddr: 0x0000000000011000
+ Align: 0x1000
+ FirstSec: .text
+ LastSec: .text
+Symbols:
+ - Name: foo
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x0000000000011000
+ Size: 0x9
+
+#--- perfscript
+PERF_RECORD_MMAP2 1/1: [0x700000001000(0x1000) @ 0x1000 00:00 0 0]: r-xp /tmp/first-loadable-address.exe
+700000001000 0x700000001008/0x700000001000/P/-/-/0
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 08fd6917c9f3a..2d147d0af7353 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -367,12 +367,15 @@ void ProfiledBinary::setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj,
// 4K page now. Note that we don't use EXEC_PAGESIZE from <linux/param.h>
// because we may build the tools on non-linux.
uint64_t PageSize = 0x1000;
+ bool SeenFirstLoadableSegment = false;
for (const typename ELFT::Phdr &Phdr : PhdrRange) {
if (Phdr.p_type == ELF::PT_INTERP)
HasInterp = true;
if (Phdr.p_type == ELF::PT_LOAD) {
- if (!FirstLoadableAddress)
+ if (!SeenFirstLoadableSegment) {
FirstLoadableAddress = Phdr.p_vaddr & ~(PageSize - 1U);
+ SeenFirstLoadableSegment = true;
+ }
if (Phdr.p_flags & ELF::PF_X) {
// Segments will always be loaded at a page boundary.
PreferredTextSegmentAddresses.push_back(Phdr.p_vaddr &
More information about the llvm-commits
mailing list