Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1503,9 +1503,18 @@ // PT_GNU_RELRO includes all sections that should be marked as // read-only by dynamic linker after proccessing relocations. PhdrEntry *RelRo = make(PT_GNU_RELRO, PF_R); - for (OutputSection *Sec : OutputSections) - if (needsPtLoad(Sec) && isRelroSection(Sec)) + bool SeenRelro = false; + for (OutputSection *Sec : OutputSections) { + if (!needsPtLoad(Sec)) + continue; + if (isRelroSection(Sec)) { + SeenRelro = true; RelRo->add(Sec); + } else if (SeenRelro) + // The Relro sections added must be contiguous in memory. Any later + // Relro sections will be read-write. + break; + } if (RelRo->FirstSec) Ret.push_back(RelRo); Index: test/ELF/linkerscript/non-contiguous-relro.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/non-contiguous-relro.s @@ -0,0 +1,53 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t2.so + +# The following linker script will match the isRelroSection() .bss.rel.ro in +# .bss. This will mean that the isRelroSections are non contiguous in the +# memory map. The PT_GNU_RELRO can only match a contiguous range of bytes so +# we exclude the .bss.rel.ro section. + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .plt : { *(.plt) } \ +# RUN: .text : { *(.text) } \ +# RUN: . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); \ +# RUN: .dynamic : { *(.dynamic) } \ +# RUN: .got : { *(.got) } \ +# RUN: . = DATA_SEGMENT_RELRO_END (1 ? 24 : 0, .); \ +# RUN: .got.plt : { *(.got.plt) } \ +# RUN: .data : { *(.data) } \ +# RUN: .bss : { *(.bss .bss.*) } \ +# RUN: . = DATA_SEGMENT_END (.); \ +# RUN: }" > %t.script + +# RUN: ld.lld --hash-style=sysv -z relro %t1.o %t2.so --script %t.script -o %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s + +# CHECK: Type: PT_GNU_RELRO +# CHECK-NEXT: Offset: 0x1000 +# CHECK-NEXT: VirtualAddress: 0x1000 +# CHECK-NEXT: PhysicalAddress: 0x1000 +# CHECK-NEXT: FileSize: +# CHECK-NEXT: MemSize: 4096 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 1 +# CHECK-NEXT: } + + +.global _start +_start: + .long bar + jmp *bar2@GOTPCREL(%rip) + +.section .data,"aw" +# At least one page in size, if it were incorrectly included in PT_GNU_RELRO +# it would affect MemSize of PT_GNU_RELRO. +.space 4 * 1024 + +.zero 4 +.section .foo,"aw" +.section .bss.rel.ro,"",@nobits