[llvm] [BOLT] Mark BOLTReserved segment executable (PR #181606)

Amir Ayupov via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 15 23:30:21 PST 2026


https://github.com/aaupov updated https://github.com/llvm/llvm-project/pull/181606

>From aa7e7cfd088f208db7a234b525c38068eaff1bde Mon Sep 17 00:00:00 2001
From: Amir Ayupov <aaupov at fb.com>
Date: Fri, 23 Jan 2026 08:02:12 -0800
Subject: [PATCH 1/2] [BOLT] Mark BOLTReserved segment executable

Summary:
When .bolt_reserved section is defined in the linker script, there's
no way to mark the containing segment executable other than via PHDRS
command which overrides program headers entirely which is impractical.

Since .bolt_reserved contains executable code, mark segment executable
in BOLT.

Test Plan: bolt-reserved.test
---
 bolt/lib/Rewrite/RewriteInstance.cpp | 12 +++++++++-
 bolt/test/bolt-reserved.test         | 33 ++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 bolt/test/bolt-reserved.test

diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 4539b7221cb5f..90ff6e66e3051 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -4544,7 +4544,7 @@ void RewriteInstance::patchELFPHDRTable() {
 
   Phnum = Obj.getHeader().e_phnum;
 
-  if (BC->NewSegments.empty()) {
+  if (BC->NewSegments.empty() && BC->BOLTReserved.empty()) {
     BC->outs() << "BOLT-INFO: not adding new segments\n";
     return;
   }
@@ -4597,6 +4597,16 @@ void RewriteInstance::patchELFPHDRTable() {
   for (const ELF64LE::Phdr &Phdr : cantFail(Obj.program_headers())) {
     ELF64LE::Phdr NewPhdr = Phdr;
     switch (Phdr.p_type) {
+    case ELF::PT_LOAD: {
+      // Mark segment as executable if it contains BOLTReserved space.
+      const uint64_t SegStart = Phdr.p_vaddr;
+      const uint64_t SegEnd = Phdr.p_vaddr + Phdr.p_memsz;
+      if (!BC->BOLTReserved.empty() &&
+          SegStart <= BC->BOLTReserved.start() &&
+          SegEnd >= BC->BOLTReserved.end())
+        NewPhdr.p_flags |= ELF::PF_X;
+      break;
+    }
     case ELF::PT_PHDR:
       if (PHDRTableAddress) {
         NewPhdr.p_offset = PHDRTableOffset;
diff --git a/bolt/test/bolt-reserved.test b/bolt/test/bolt-reserved.test
new file mode 100644
index 0000000000000..6657728aa42f3
--- /dev/null
+++ b/bolt/test/bolt-reserved.test
@@ -0,0 +1,33 @@
+# Check that BOLT marks segment containing .bolt_reserved as executable
+
+# RUN: split-file %s %t
+# RUN: %clang %cflags %t/src.c -Wl,--script=%t/ld.script -Wl,-q -o %t.exe
+
+# Confirm the segment is not executable
+# RUN: llvm-readelf -We %t.exe | FileCheck %s --check-prefix=CHECK-SEG-BEFORE
+
+# Capture section VMA and offset
+# CHECK-SEG-BEFORE: Section Headers:
+# CHECK-SEG-BEFORE: .bolt.reserved PROGBITS [[#ADDR:]] [[#OFF:]]
+
+# Config segment flags
+# CHECK-SEG-BEFORE: Program Headers:
+# CHECK-SEG-BEFORE: LOAD 0x{{0*}}[[#OFF]] 0x{{0*}}[[#ADDR]] {{.*}} R 0x200000
+
+# RUN: llvm-bolt %t.exe -o %t.bolt
+# Confirm the segment is now marked as executable
+# RUN: llvm-readelf -We %t.bolt | FileCheck %s --check-prefix=CHECK-SEG-AFTER
+# CHECK-SEG-AFTER: .bolt.reserved PROGBITS [[#ADDR:]] [[#OFF:]]
+# CHECK-SEG-AFTER: LOAD 0x{{0*}}[[#OFF]] 0x{{0*}}[[#ADDR]] {{.*}} R E 0x200000
+
+#--- src.c
+int main() { return 0; }
+
+#--- ld.script
+SECTIONS {
+  .bolt.reserved : ALIGN(2M) {
+    __bolt_reserved_start = .;
+    . += 2M;
+    __bolt_reserved_end = .;
+  }
+} INSERT AFTER .text;

>From 415c7cdfabf6ef44f0d1d27980e4047d77d9b9bd Mon Sep 17 00:00:00 2001
From: Amir Ayupov <aaupov at fb.com>
Date: Sun, 15 Feb 2026 23:30:07 -0800
Subject: [PATCH 2/2] format

---
 bolt/lib/Rewrite/RewriteInstance.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 90ff6e66e3051..11d8151d21c72 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -4601,8 +4601,7 @@ void RewriteInstance::patchELFPHDRTable() {
       // Mark segment as executable if it contains BOLTReserved space.
       const uint64_t SegStart = Phdr.p_vaddr;
       const uint64_t SegEnd = Phdr.p_vaddr + Phdr.p_memsz;
-      if (!BC->BOLTReserved.empty() &&
-          SegStart <= BC->BOLTReserved.start() &&
+      if (!BC->BOLTReserved.empty() && SegStart <= BC->BOLTReserved.start() &&
           SegEnd >= BC->BOLTReserved.end())
         NewPhdr.p_flags |= ELF::PF_X;
       break;



More information about the llvm-commits mailing list