[PATCH] D34203: [LLD][LinkerScript] Add support for segment NONE.

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 16 09:04:43 PDT 2017


Do you have commit access btw?

Cheers,
Rafael

Rafael Avila de Espindola <rafael.espindola at gmail.com> writes:

> 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