Skip to content

Commit 0329c1b

Browse files
authored
[ELF] --no-rosegment: don't mark read-only PT_LOAD segments executable (#81223)
Once we move `.lrodata` after .bss (#78521), or if we use `SECTIONS` commands, certain read-only sections may be in their own PT_LOAD, not in the traditional "text segment". Current --no-rosegment code may unnecessarily mark read-only PT_LOAD executable. Fix it.
1 parent 407f9c0 commit 0329c1b

File tree

2 files changed

+17
-13
lines changed

2 files changed

+17
-13
lines changed

lld/ELF/Writer.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2353,17 +2353,12 @@ static bool needsPtLoad(OutputSection *sec) {
23532353
return true;
23542354
}
23552355

2356-
// Linker scripts are responsible for aligning addresses. Unfortunately, most
2357-
// linker scripts are designed for creating two PT_LOADs only, one RX and one
2358-
// RW. This means that there is no alignment in the RO to RX transition and we
2359-
// cannot create a PT_LOAD there.
2356+
// Adjust phdr flags according to certain options.
23602357
static uint64_t computeFlags(uint64_t flags) {
23612358
if (config->omagic)
23622359
return PF_R | PF_W | PF_X;
23632360
if (config->executeOnly && (flags & PF_X))
23642361
return flags & ~PF_R;
2365-
if (config->singleRoRx && !(flags & PF_W))
2366-
return flags | PF_X;
23672362
return flags;
23682363
}
23692364

@@ -2451,7 +2446,7 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
24512446
// Segments are contiguous memory regions that has the same attributes
24522447
// (e.g. executable or writable). There is one phdr for each segment.
24532448
// Therefore, we need to create a new phdr when the next section has
2454-
// different flags or is loaded at a discontiguous address or memory region
2449+
// compatible flags or is loaded at a discontiguous address or memory region
24552450
// using AT or AT> linker script command, respectively.
24562451
//
24572452
// As an exception, we don't create a separate load segment for the ELF
@@ -2465,13 +2460,22 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
24652460
// so when hasSectionsCommand, since we cannot introduce the extra alignment
24662461
// needed to create a new LOAD)
24672462
uint64_t newFlags = computeFlags(sec->getPhdrFlags());
2463+
// When --no-rosegment is specified, RO and RX sections are compatible.
2464+
uint32_t diff = flags ^ newFlags;
2465+
if (config->singleRoRx && !(newFlags & PF_W))
2466+
diff &= ~PF_X;
2467+
if (diff)
2468+
load = nullptr;
2469+
24682470
bool sameLMARegion =
24692471
load && !sec->lmaExpr && sec->lmaRegion == load->firstSec->lmaRegion;
2470-
if (!(load && newFlags == flags && sec != relroEnd &&
2471-
sec->memRegion == load->firstSec->memRegion &&
2472-
(sameLMARegion || load->lastSec == Out::programHeaders) &&
2473-
(script->hasSectionsCommand || sec->type == SHT_NOBITS ||
2474-
load->lastSec->type != SHT_NOBITS))) {
2472+
if (load && sec != relroEnd &&
2473+
sec->memRegion == load->firstSec->memRegion &&
2474+
(sameLMARegion || load->lastSec == Out::programHeaders) &&
2475+
(script->hasSectionsCommand || sec->type == SHT_NOBITS ||
2476+
load->lastSec->type != SHT_NOBITS)) {
2477+
load->p_flags |= newFlags;
2478+
} else {
24752479
load = addHdr(PT_LOAD, newFlags);
24762480
flags = newFlags;
24772481
}

lld/test/ELF/segments.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
# NOROSEGMENT1-NEXT: LOAD 0x001006 0x0000000000000006 0x0000000000000006 0x000001 0x000001 RW 0x1000
4545
# NOROSEGMENT1-NEXT: LOAD 0x001007 0x0000000000000007 0x0000000000000007 0x000002 0x000002 R E 0x1000
4646
# NOROSEGMENT1-NEXT: LOAD 0x001009 0x0000000000000009 0x0000000000000009 0x000001 0x000001 RW 0x1000
47-
# NOROSEGMENT1-NEXT: LOAD 0x00100a 0x000000000000000a 0x000000000000000a 0x000001 0x000001 R E 0x1000
47+
# NOROSEGMENT1-NEXT: LOAD 0x00100a 0x000000000000000a 0x000000000000000a 0x000001 0x000001 R 0x1000
4848
# NOROSEGMENT1-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0
4949

5050
# RUN: ld.lld -N a.o -o omagic

0 commit comments

Comments
 (0)