[PATCH] D37736: [ELF] - Do not spread specific flags when emiting output sections.

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 10 10:20:49 PDT 2017


LGTM.

Rui, what do you think?

Cheers,
Rafael

George Rimar via Phabricator <reviews at reviews.llvm.org> writes:

> grimar updated this revision to Diff 118407.
> grimar added a comment.
>
> - Updated comment.
>
>
> https://reviews.llvm.org/D37736
>
> Files:
>   ELF/LinkerScript.cpp
>   test/ELF/linkerscript/arm-exidx-order.s
>   test/ELF/linkerscript/symbol-only-flags.s
>
>
> Index: test/ELF/linkerscript/symbol-only-flags.s
> ===================================================================
> --- test/ELF/linkerscript/symbol-only-flags.s
> +++ 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", at nobits
> +.quad 0
> Index: test/ELF/linkerscript/arm-exidx-order.s
> ===================================================================
> --- test/ELF/linkerscript/arm-exidx-order.s
> +++ 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: ELF/LinkerScript.cpp
> ===================================================================
> --- ELF/LinkerScript.cpp
> +++ ELF/LinkerScript.cpp
> @@ -656,17 +656,33 @@
>  
>  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 : Opt.Commands) {
>      auto *Sec = dyn_cast<OutputSection>(Cmd);
>      if (!Sec)
>        continue;
>      if (Sec->Live) {
> -      Flags = Sec->Flags;
> +      Flags = Sec->Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR);
>        continue;
>      }
>  
>
>
> Index: test/ELF/linkerscript/symbol-only-flags.s
> ===================================================================
> --- test/ELF/linkerscript/symbol-only-flags.s
> +++ 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", at nobits
> +.quad 0
> Index: test/ELF/linkerscript/arm-exidx-order.s
> ===================================================================
> --- test/ELF/linkerscript/arm-exidx-order.s
> +++ 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: ELF/LinkerScript.cpp
> ===================================================================
> --- ELF/LinkerScript.cpp
> +++ ELF/LinkerScript.cpp
> @@ -656,17 +656,33 @@
>  
>  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 : Opt.Commands) {
>      auto *Sec = dyn_cast<OutputSection>(Cmd);
>      if (!Sec)
>        continue;
>      if (Sec->Live) {
> -      Flags = Sec->Flags;
> +      Flags = Sec->Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR);
>        continue;
>      }
>  


More information about the llvm-commits mailing list