diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2385,9 +2385,13 @@ } } + bool nonContiguousVMA = false; for (OutputSection *sec : outputSections) { - if (!needsPtLoad(sec)) + if (!needsPtLoad(sec)) { + if (sec->memRegion && sec->memRegion == load->firstSec->memRegion) + nonContiguousVMA = true; continue; + } // Normally, sections in partitions other than the current partition are // ignored. But partition number 255 is a special case: it contains the @@ -2411,11 +2415,12 @@ uint64_t newFlags = computeFlags(sec->getPhdrFlags()); bool sameLMARegion = load && !sec->lmaExpr && sec->lmaRegion == load->firstSec->lmaRegion; - if (!(load && newFlags == flags && sec != relroEnd && + if (nonContiguousVMA || !(load && newFlags == flags && sec != relroEnd && sec->memRegion == load->firstSec->memRegion && (sameLMARegion || load->lastSec == Out::programHeaders))) { load = addHdr(PT_LOAD, newFlags); flags = newFlags; + nonContiguousVMA = false; } load->add(sec); diff --git a/lld/test/ELF/linkerscript/phdrs-noload.test b/lld/test/ELF/linkerscript/phdrs-noload.test new file mode 100644 --- /dev/null +++ b/lld/test/ELF/linkerscript/phdrs-noload.test @@ -0,0 +1,71 @@ +# REQUIRES: x86 +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/main.s -o %t.o + +## NOLOAD sections do not require a PT_LOAD segment, but they can still occupy +## memory in the executable image. +## If two output sections with the same VMA and LMA regions are interleaved by +## a NOLOAD output section, two separate PT_LOAD segments are required. +# RUN: ld.lld -T %t/link.ld %t.o -o %ta +# RUN: llvm-readelf -S -l %ta | FileCheck %s + +# CHECK: [Nr] Name Type Address Off Size ES Flg Lk +# CHECK-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 +# CHECK-NEXT: [ 1] .text PROGBITS 0000000008000000 001000 000001 00 AX 0 +# CHECK-NEXT: [ 2] .data PROGBITS 0000000020000400 001400 000004 00 WA 0 +# CHECK-NEXT: [ 3] .data2 NOBITS 0000000020000404 001404 000004 00 WA 0 +# CHECK-NEXT: [ 4] .data3 PROGBITS 0000000020000408 001408 000004 00 WA 0 +# CHECK-NEXT: [ 5] .data4 PROGBITS 0000000008000009 002009 00000c 00 WA 0 + + +# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# CHECK-NEXT: LOAD 0x001000 0x0000000008000000 0x0000000008000000 0x000001 0x000001 R E 0x1000 +# CHECK-NEXT: LOAD 0x001400 0x0000000020000400 0x0000000008000001 0x000004 0x000004 RW 0x1000 +# CHECK-NEXT: LOAD 0x001408 0x0000000020000408 0x0000000008000005 0x000004 0x000004 RW 0x1000 +# CHECK-NEXT: LOAD 0x002009 0x0000000008000009 0x0000000008000009 0x00000c 0x00000c RW 0x1000 +# CHECK-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x0 + + +#--- link.ld +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 512K + DATA (rw) : ORIGIN = 0x20000400, LENGTH = 512K +} +SECTIONS +{ + .text : + { + *(.text) + } > CODE + + .data : + { + *(.a.data) + } > DATA AT> CODE + + .data2 (NOLOAD) : + { + . += 4; + } > DATA + + .data3 : + { + *(.b.data) + } > DATA AT> CODE + + .data4 : + { + LONG(-1); LONG(-1); LONG(-1); + } > CODE +} + +#--- main.s +.globl _start +_start: nop + +.section .a.data, "aw" +.long 0xabcdef01 + +.section .b.data, "aw" +.long 0xbcdefa12 \ No newline at end of file