<div dir="ltr"><div class="gmail_default" style="font-size:small">Yes, I have LLVM commit access, assuming LLD doesn't require anything extra.<br><br></div><div class="gmail_default" style="font-size:small">Cheers,<br></div><div class="gmail_default" style="font-size:small">Andrew<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 16 June 2017 at 17:04, Rafael Avila de Espindola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Do you have commit access btw?<br>
<br>
Cheers,<br>
Rafael<br>
<div class="HOEnZb"><div class="h5"><br>
Rafael Avila de Espindola <<a href="mailto:rafael.espindola@gmail.com">rafael.espindola@gmail.com</a>> writes:<br>
<br>
> LGTM.<br>
><br>
> Thanks!<br>
><br>
> Andrew Ng via Phabricator <<a href="mailto:reviews@reviews.llvm.org">reviews@reviews.llvm.org</a>> writes:<br>
><br>
>> andrewng created this revision.<br>
>> Herald added a subscriber: emaste.<br>
>><br>
>> This patch adds support for segment NONE in linker scripts which enables the<br>
>> specification that a section should not be assigned to any segment.<br>
>><br>
>> Note that GNU ld does not disallow the definition of a segment named NONE, which<br>
>> if defined, effectively overrides the behaviour described above. This feature<br>
>> has been copied.<br>
>><br>
>><br>
>> <a href="https://reviews.llvm.org/D34203" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D34203</a><br>
>><br>
>> Files:<br>
>>   ELF/LinkerScript.cpp<br>
>>   test/ELF/linkerscript/segment-<wbr>none.s<br>
>><br>
>><br>
>> Index: test/ELF/linkerscript/segment-<wbr>none.s<br>
>> ==============================<wbr>==============================<wbr>=======<br>
>> --- /dev/null<br>
>> +++ test/ELF/linkerscript/segment-<wbr>none.s<br>
>> @@ -0,0 +1,39 @@<br>
>> +# REQUIRES: x86<br>
>> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o<br>
>> +<br>
>> +## Test that section .foo is not placed in any segment when assigned to segment<br>
>> +## NONE in the linker script and segment NONE is not defined.<br>
>> +# RUN: echo "PHDRS {text PT_LOAD;} \<br>
>> +# RUN:       SECTIONS { \<br>
>> +# RUN:           .text : {*(.text .text*)} :text \<br>
>> +# RUN:           .foo : {*(.foo)} :NONE \<br>
>> +# RUN:       }" > %t.script<br>
>> +# RUN: ld.lld -o %t --script %t.script %t.o<br>
>> +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck %s<br>
>> +<br>
>> +## Test that section .foo is placed in segment NONE when assigned to segment<br>
>> +## NONE in the linker script and segment NONE is defined.<br>
>> +# RUN: echo "PHDRS {text PT_LOAD; NONE PT_LOAD;} \<br>
>> +# RUN:       SECTIONS { \<br>
>> +# RUN:           .text : {*(.text .text*)} :text \<br>
>> +# RUN:           .foo : {*(.foo)} :NONE \<br>
>> +# RUN:       }" > %t.script<br>
>> +# RUN: ld.lld -o %t --script %t.script %t.o<br>
>> +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck --check-prefix=DEFINED %s<br>
>> +<br>
>> +# CHECK: Section to Segment mapping:<br>
>> +# CHECK-NEXT: Segment Sections...<br>
>> +# CHECK-NOT: .foo<br>
>> +<br>
>> +# DEFINED: Section to Segment mapping:<br>
>> +# DEFINED-NEXT: Segment Sections...<br>
>> +# DEFINED-NEXT:  00     .text<br>
>> +# DEFINED-NEXT:  01     .foo<br>
>> +<br>
>> +.global _start<br>
>> +_start:<br>
>> + nop<br>
>> +<br>
>> +.section .foo,"a"<br>
>> +foo:<br>
>> + .long 0<br>
>> Index: ELF/LinkerScript.cpp<br>
>> ==============================<wbr>==============================<wbr>=======<br>
>> --- ELF/LinkerScript.cpp<br>
>> +++ ELF/LinkerScript.cpp<br>
>> @@ -1200,27 +1200,37 @@<br>
>><br>
>>  bool LinkerScript::isDefined(<wbr>StringRef S) { return findSymbol(S) != nullptr; }<br>
>><br>
>> +static const size_t NoPhdr = -1;<br>
>> +<br>
>>  // Returns indices of ELF headers containing specific section. Each index is a<br>
>>  // zero based number of ELF header listed within PHDRS {} script block.<br>
>>  std::vector<size_t> LinkerScript::getPhdrIndices(<wbr>OutputSection *Sec) {<br>
>>    if (OutputSectionCommand *Cmd = getCmd(Sec)) {<br>
>>      std::vector<size_t> Ret;<br>
>> -    for (StringRef PhdrName : Cmd->Phdrs)<br>
>> -      Ret.push_back(getPhdrIndex(<wbr>Cmd->Location, PhdrName));<br>
>> +    for (StringRef PhdrName : Cmd->Phdrs) {<br>
>> +      size_t Index = getPhdrIndex(Cmd->Location, PhdrName);<br>
>> +      if (Index != NoPhdr)<br>
>> +        Ret.push_back(Index);<br>
>> +    }<br>
>>      return Ret;<br>
>>    }<br>
>>    return {};<br>
>>  }<br>
>><br>
>> +// Returns the index of the segment named PhdrName if found otherwise<br>
>> +// NoPhdr. When not found, if PhdrName is not the special case value 'NONE'<br>
>> +// (which can be used to explicitly specify that a section isn't assigned to a<br>
>> +// segment) then error.<br>
>>  size_t LinkerScript::getPhdrIndex(<wbr>const Twine &Loc, StringRef PhdrName) {<br>
>>    size_t I = 0;<br>
>>    for (PhdrsCommand &Cmd : Opt.PhdrsCommands) {<br>
>>      if (Cmd.Name == PhdrName)<br>
>>        return I;<br>
>>      ++I;<br>
>>    }<br>
>> -  error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");<br>
>> -  return 0;<br>
>> +  if (PhdrName != "NONE")<br>
>> +    error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");<br>
>> +  return NoPhdr;<br>
>>  }<br>
>><br>
>>  template void OutputSectionCommand::writeTo<<wbr>ELF32LE>(uint8_t *Buf);<br>
>><br>
>><br>
>> Index: test/ELF/linkerscript/segment-<wbr>none.s<br>
>> ==============================<wbr>==============================<wbr>=======<br>
>> --- /dev/null<br>
>> +++ test/ELF/linkerscript/segment-<wbr>none.s<br>
>> @@ -0,0 +1,39 @@<br>
>> +# REQUIRES: x86<br>
>> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o<br>
>> +<br>
>> +## Test that section .foo is not placed in any segment when assigned to segment<br>
>> +## NONE in the linker script and segment NONE is not defined.<br>
>> +# RUN: echo "PHDRS {text PT_LOAD;} \<br>
>> +# RUN:       SECTIONS { \<br>
>> +# RUN:           .text : {*(.text .text*)} :text \<br>
>> +# RUN:           .foo : {*(.foo)} :NONE \<br>
>> +# RUN:       }" > %t.script<br>
>> +# RUN: ld.lld -o %t --script %t.script %t.o<br>
>> +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck %s<br>
>> +<br>
>> +## Test that section .foo is placed in segment NONE when assigned to segment<br>
>> +## NONE in the linker script and segment NONE is defined.<br>
>> +# RUN: echo "PHDRS {text PT_LOAD; NONE PT_LOAD;} \<br>
>> +# RUN:       SECTIONS { \<br>
>> +# RUN:           .text : {*(.text .text*)} :text \<br>
>> +# RUN:           .foo : {*(.foo)} :NONE \<br>
>> +# RUN:       }" > %t.script<br>
>> +# RUN: ld.lld -o %t --script %t.script %t.o<br>
>> +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck --check-prefix=DEFINED %s<br>
>> +<br>
>> +# CHECK: Section to Segment mapping:<br>
>> +# CHECK-NEXT: Segment Sections...<br>
>> +# CHECK-NOT: .foo<br>
>> +<br>
>> +# DEFINED: Section to Segment mapping:<br>
>> +# DEFINED-NEXT: Segment Sections...<br>
>> +# DEFINED-NEXT:  00     .text<br>
>> +# DEFINED-NEXT:  01     .foo<br>
>> +<br>
>> +.global _start<br>
>> +_start:<br>
>> + nop<br>
>> +<br>
>> +.section .foo,"a"<br>
>> +foo:<br>
>> + .long 0<br>
>> Index: ELF/LinkerScript.cpp<br>
>> ==============================<wbr>==============================<wbr>=======<br>
>> --- ELF/LinkerScript.cpp<br>
>> +++ ELF/LinkerScript.cpp<br>
>> @@ -1200,27 +1200,37 @@<br>
>><br>
>>  bool LinkerScript::isDefined(<wbr>StringRef S) { return findSymbol(S) != nullptr; }<br>
>><br>
>> +static const size_t NoPhdr = -1;<br>
>> +<br>
>>  // Returns indices of ELF headers containing specific section. Each index is a<br>
>>  // zero based number of ELF header listed within PHDRS {} script block.<br>
>>  std::vector<size_t> LinkerScript::getPhdrIndices(<wbr>OutputSection *Sec) {<br>
>>    if (OutputSectionCommand *Cmd = getCmd(Sec)) {<br>
>>      std::vector<size_t> Ret;<br>
>> -    for (StringRef PhdrName : Cmd->Phdrs)<br>
>> -      Ret.push_back(getPhdrIndex(<wbr>Cmd->Location, PhdrName));<br>
>> +    for (StringRef PhdrName : Cmd->Phdrs) {<br>
>> +      size_t Index = getPhdrIndex(Cmd->Location, PhdrName);<br>
>> +      if (Index != NoPhdr)<br>
>> +        Ret.push_back(Index);<br>
>> +    }<br>
>>      return Ret;<br>
>>    }<br>
>>    return {};<br>
>>  }<br>
>><br>
>> +// Returns the index of the segment named PhdrName if found otherwise<br>
>> +// NoPhdr. When not found, if PhdrName is not the special case value 'NONE'<br>
>> +// (which can be used to explicitly specify that a section isn't assigned to a<br>
>> +// segment) then error.<br>
>>  size_t LinkerScript::getPhdrIndex(<wbr>const Twine &Loc, StringRef PhdrName) {<br>
>>    size_t I = 0;<br>
>>    for (PhdrsCommand &Cmd : Opt.PhdrsCommands) {<br>
>>      if (Cmd.Name == PhdrName)<br>
>>        return I;<br>
>>      ++I;<br>
>>    }<br>
>> -  error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");<br>
>> -  return 0;<br>
>> +  if (PhdrName != "NONE")<br>
>> +    error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");<br>
>> +  return NoPhdr;<br>
>>  }<br>
>><br>
>>  template void OutputSectionCommand::writeTo<<wbr>ELF32LE>(uint8_t *Buf);<br>
</div></div></blockquote></div><br></div>