Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -1200,18 +1200,27 @@ bool LinkerScript::isDefined(StringRef S) { return findSymbol(S) != nullptr; } +static const size_t NoPhdr = -1; + // Returns indices of ELF headers containing specific section. Each index is a // zero based number of ELF header listed within PHDRS {} script block. std::vector LinkerScript::getPhdrIndices(OutputSection *Sec) { if (OutputSectionCommand *Cmd = getCmd(Sec)) { std::vector Ret; - for (StringRef PhdrName : Cmd->Phdrs) - Ret.push_back(getPhdrIndex(Cmd->Location, PhdrName)); + for (StringRef PhdrName : Cmd->Phdrs) { + size_t Index = getPhdrIndex(Cmd->Location, PhdrName); + if (Index != NoPhdr) + Ret.push_back(Index); + } return Ret; } return {}; } +// Returns the index of the segment named PhdrName if found otherwise +// NoPhdr. When not found, if PhdrName is not the special case value 'NONE' +// (which can be used to explicitly specify that a section isn't assigned to a +// segment) then error. size_t LinkerScript::getPhdrIndex(const Twine &Loc, StringRef PhdrName) { size_t I = 0; for (PhdrsCommand &Cmd : Opt.PhdrsCommands) { @@ -1219,8 +1228,9 @@ return I; ++I; } - error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS"); - return 0; + if (PhdrName != "NONE") + error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS"); + return NoPhdr; } template void OutputSectionCommand::writeTo(uint8_t *Buf); Index: test/ELF/linkerscript/segment-none.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/segment-none.s @@ -0,0 +1,39 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +## Test that section .foo is not placed in any segment when assigned to segment +## NONE in the linker script and segment NONE is not defined. +# RUN: echo "PHDRS {text PT_LOAD;} \ +# RUN: SECTIONS { \ +# RUN: .text : {*(.text .text*)} :text \ +# RUN: .foo : {*(.foo)} :NONE \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck %s + +## Test that section .foo is placed in segment NONE when assigned to segment +## NONE in the linker script and segment NONE is defined. +# RUN: echo "PHDRS {text PT_LOAD; NONE PT_LOAD;} \ +# RUN: SECTIONS { \ +# RUN: .text : {*(.text .text*)} :text \ +# RUN: .foo : {*(.foo)} :NONE \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck --check-prefix=DEFINED %s + +# CHECK: Section to Segment mapping: +# CHECK-NEXT: Segment Sections... +# CHECK-NOT: .foo + +# DEFINED: Section to Segment mapping: +# DEFINED-NEXT: Segment Sections... +# DEFINED-NEXT: 00 .text +# DEFINED-NEXT: 01 .foo + +.global _start +_start: + nop + +.section .foo,"a" +foo: + .long 0