Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1607,6 +1607,19 @@ if (auto *Sec = dyn_cast(Base)) OutputSections.push_back(Sec); + // Check that no non-alloc sections were specified before any alloc sections + // in linker scripts. Otherwise we might have problems creating correct + // PT_LOAD headers. + OutputSection *NonAllocSec = nullptr; + for (OutputSection *OS : OutputSections) + if (!(OS->Flags & SHF_ALLOC) && (OS->SectionIndex != UINT32_MAX)) + NonAllocSec = OS; + else if (NonAllocSec && (OS->SectionIndex != UINT32_MAX)) { + warn("non-alloc section " + NonAllocSec->Name + " should be specified after " + "alloc sections in linker scripts"); + NonAllocSec = nullptr; + } + // Ensure data sections are not mixed with executable sections when // -execute-only is used. if (Config->ExecuteOnly) Index: test/ELF/linkerscript/non-alloc.test =================================================================== --- /dev/null +++ test/ELF/linkerscript/non-alloc.test @@ -0,0 +1,17 @@ +# REQUIRES: x86 +# RUN: echo '.data; .quad 0;.section .other; .short 0; .text; nop' \ +# RUN: | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o +# RUN: not ld.lld -o %t --script %s %t.o 2>&1 | FileCheck %s + +SECTIONS { + .data : { *(.data) } + .other : { *(.other) } + .text : { *(.text) } +} + +# .other is a non-alloc section and therefore should be placed after .text. +# Expect a warning for this section as it prevents the creation of correct +# PT_LOAD headers. + +# CHECK: warning: non-alloc section .other should be specified after alloc sections in linker scripts +# CHECK: error: section .data virtual address range overlaps with .text