Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -657,9 +657,25 @@ void LinkerScript::adjustSectionsBeforeSorting() { // If the output section contains only symbol assignments, create a - // corresponding output section. The bfd linker seems to only create them if - // '.' is assigned to, but creating these section should not have any bad - // consequeces and gives us a section to put the symbol in. + // corresponding output section. The issue is what to do with linker script + // like ".foo : { symbol = 42; }". One option would be to convert it to + // "symbol = 42;". That is, move the symbol out of the empty section + // description. That seems to be what bfd does for this simple case. The + // problem is that this is not completely general. bfd will give up and + // create a dummy section too if there is a ". = . + 1" inside the section + // for example. + // Given that we want to create the section, we have to worry what impact + // it will have on the link. For example, if we just create a section with + // 0 for flags, it would change which PT_LOADs are created. + // We could remember that that particular section is dummy and ignore it in + // other parts of the linker, but unfortunately there are quite a few places + // that would need to change: + // * The program header creation. + // * The orphan section placement. + // * The address assignment. + // The other option is to pick flags that minimize the impact the section + // will have on the rest of the linker. That is why we copy the flags from + // the previous sections. Only a few flags are needed to keep the impact low. uint64_t Flags = SHF_ALLOC; for (BaseCommand *Cmd : SectionCommands) { @@ -667,7 +683,7 @@ if (!Sec) continue; if (Sec->Live) { - Flags = Sec->Flags; + Flags = Sec->Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR); continue; } Index: lld/trunk/test/ELF/linkerscript/arm-exidx-order.s =================================================================== --- lld/trunk/test/ELF/linkerscript/arm-exidx-order.s +++ lld/trunk/test/ELF/linkerscript/arm-exidx-order.s @@ -0,0 +1,19 @@ +# REQUIRES: arm +# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; \ +# RUN: .ARM.exidx : { *(.ARM.exidx*) } \ +# RUN: .foo : { _foo = 0; } }" > %t.script +# RUN: ld.lld -T %t.script %t.o -shared -o %t.so +# RUN: llvm-readobj -s %t.so | FileCheck %s + +# CHECK: Section { +# CHECK: Index: +# CHECK: Name: .foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: ] + +.fnstart +.cantunwind +.fnend Index: lld/trunk/test/ELF/linkerscript/symbol-only-flags.s =================================================================== --- lld/trunk/test/ELF/linkerscript/symbol-only-flags.s +++ lld/trunk/test/ELF/linkerscript/symbol-only-flags.s @@ -0,0 +1,20 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; \ +# RUN: .tbss : { *(.tbss) } \ +# RUN: .foo : { bar = .; } }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -s %t | FileCheck %s + +## Check .foo does not get SHF_TLS flag. +# CHECK: Section { +# CHECK: Index: +# CHECK: Name: .foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] + +.section .tbss,"awT",@nobits +.quad 0