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

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


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

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


>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] [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;



More information about the llvm-commits mailing list