[BOLT] Mark BOLTReserved segment executable (#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
This commit is contained in:
Amir Ayupov 2026-02-19 15:07:50 -08:00 committed by GitHub
parent 31e5f86a3c
commit 393adaac1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 1 deletions

View file

@ -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,13 @@ 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.
AddressRange Seg(Phdr.p_vaddr, Phdr.p_vaddr + Phdr.p_memsz);
if (!BC->BOLTReserved.empty() && Seg.contains(BC->BOLTReserved))
NewPhdr.p_flags |= ELF::PF_X;
break;
}
case ELF::PT_PHDR:
if (PHDRTableAddress) {
NewPhdr.p_offset = PHDRTableOffset;

View file

@ -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;