[PATCH] D34203: [LLD][LinkerScript] Add support for segment NONE.
Rafael Avila de Espindola via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 14 10:32:16 PDT 2017
LGTM.
Thanks!
Andrew Ng via Phabricator <reviews at reviews.llvm.org> writes:
> andrewng created this revision.
> Herald added a subscriber: emaste.
>
> This patch adds support for segment NONE in linker scripts which enables the
> specification that a section should not be assigned to any segment.
>
> Note that GNU ld does not disallow the definition of a segment named NONE, which
> if defined, effectively overrides the behaviour described above. This feature
> has been copied.
>
>
> https://reviews.llvm.org/D34203
>
> Files:
> ELF/LinkerScript.cpp
> test/ELF/linkerscript/segment-none.s
>
>
> 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
> Index: ELF/LinkerScript.cpp
> ===================================================================
> --- ELF/LinkerScript.cpp
> +++ ELF/LinkerScript.cpp
> @@ -1200,27 +1200,37 @@
>
> 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<size_t> LinkerScript::getPhdrIndices(OutputSection *Sec) {
> if (OutputSectionCommand *Cmd = getCmd(Sec)) {
> std::vector<size_t> 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) {
> if (Cmd.Name == PhdrName)
> 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<ELF32LE>(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
> Index: ELF/LinkerScript.cpp
> ===================================================================
> --- ELF/LinkerScript.cpp
> +++ ELF/LinkerScript.cpp
> @@ -1200,27 +1200,37 @@
>
> 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<size_t> LinkerScript::getPhdrIndices(OutputSection *Sec) {
> if (OutputSectionCommand *Cmd = getCmd(Sec)) {
> std::vector<size_t> 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) {
> if (Cmd.Name == PhdrName)
> 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<ELF32LE>(uint8_t *Buf);
More information about the llvm-commits
mailing list