diff options
| author | Fangrui Song <maskray@google.com> | 2019-09-02 10:33:58 +0000 |
|---|---|---|
| committer | Fangrui Song <maskray@google.com> | 2019-09-02 10:33:58 +0000 |
| commit | d8bc6a48eaa9111b1fc232aa678695a57ae25ec6 (patch) | |
| tree | fd8b66ad4be55416be86dbf4101b4f33817f8b48 /lld/test/ELF/linkerscript | |
| parent | 252a584cbd018e21b0ab4d9ee89eab31f4c84ee2 (diff) | |
| download | bcm5719-llvm-d8bc6a48eaa9111b1fc232aa678695a57ae25ec6.tar.gz bcm5719-llvm-d8bc6a48eaa9111b1fc232aa678695a57ae25ec6.zip | |
[ELF] Do not ICF two sections with different output sections (by SECTIONS commands)
Fixes PR39418. Complements D47241 (the non-linker-script case).
processSectionCommands() assigns input sections to output sections.
ICF is called before it, so .text.foo and .text.bar may be folded even if
their output sections are made different by SECTIONS commands.
```
markLive<ELFT>()
doIcf<ELFT>() // During ICF, we don't know the output sections
writeResult()
combineEhSections<ELFT>()
script->processSectionCommands() // InputSection -> OutputSection assignment
```
This patch splits processSectionCommands() into processSectionCommands() and
processSymbolAssignments(), and moves processSectionCommands() before ICF:
```
markLive<ELFT>()
combineEhSections<ELFT>()
script->processSectionCommands()
doIcf<ELFT>() // should remove folded input sections
writeResult()
script->processSymbolAssignments()
```
An alternative approach is to unfold a section `sec` in
processSectionCommands() when we find `sec` and `sec->repl` belong to
different output sections. I feel this patch is superior because this
can fold more sections and the decouple of
SectionCommand/SymbolAssignment gives flexibility:
* An ExprValue can't be evaluated before its section is assigned to an
output section -> we can delete getOutputSectionVA and simplify
another place where we had to check if the output section is null.
Moreover, a case in linkerscript/early-assign-symbol.s can be handled
now.
* processSectionCommands/processSymbolAssignments can be freely moved
around.
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D66717
llvm-svn: 370635
Diffstat (limited to 'lld/test/ELF/linkerscript')
| -rw-r--r-- | lld/test/ELF/linkerscript/early-assign-symbol.s | 11 | ||||
| -rw-r--r-- | lld/test/ELF/linkerscript/icf-output-sections.s | 46 | ||||
| -rw-r--r-- | lld/test/ELF/linkerscript/subalign.s | 12 |
3 files changed, 59 insertions, 10 deletions
diff --git a/lld/test/ELF/linkerscript/early-assign-symbol.s b/lld/test/ELF/linkerscript/early-assign-symbol.s index 5f611786366..7271204221a 100644 --- a/lld/test/ELF/linkerscript/early-assign-symbol.s +++ b/lld/test/ELF/linkerscript/early-assign-symbol.s @@ -1,12 +1,15 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o -# RUN: echo "SECTIONS { aaa = foo | 1; .text : { *(.text*) } }" > %t3.script -# RUN: not ld.lld -o %t --script %t3.script %t.o 2>&1 | FileCheck %s +## The definitions of symbol assignments may reference other symbols. +## Test we can handle them. -# CHECK: error: {{.*}}.script:1: unable to evaluate expression: input section .text has no output section assigned +# RUN: echo "SECTIONS { aaa = foo | 1; .text : { *(.text*) } }" > %t3.script +# RUN: ld.lld -o %t --script %t3.script %t.o +# RUN: llvm-objdump -t %t | FileCheck --check-prefix=VAL1 %s -# Simple cases that we can handle. +# VAL1: 0000000000000000 .text 00000000 foo +# VAL1: 0000000000000001 .text 00000000 aaa # RUN: echo "SECTIONS { aaa = ABSOLUTE(foo - 1) + 1; .text : { *(.text*) } }" > %t.script # RUN: ld.lld -o %t --script %t.script %t.o diff --git a/lld/test/ELF/linkerscript/icf-output-sections.s b/lld/test/ELF/linkerscript/icf-output-sections.s new file mode 100644 index 00000000000..f23d7fff06b --- /dev/null +++ b/lld/test/ELF/linkerscript/icf-output-sections.s @@ -0,0 +1,46 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: echo 'SECTIONS { .text : { *(.text*) } }' > %t1.script + +## Sections within the same output section can be freely folded. +# RUN: ld.lld %t.o --script %t1.script --icf=all --print-icf-sections -o %t | FileCheck --check-prefix=ICF1 %s +# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC1 %s --implicit-check-not=.text + +# ICF1: selected section {{.*}}.o:(.text.foo0) +# ICF1-NEXT: removing identical section {{.*}}.o:(.text.foo1) +# ICF1-NEXT: removing identical section {{.*}}.o:(.text.bar0) +# ICF1-NEXT: removing identical section {{.*}}.o:(.text.bar1) + +# SEC1: .text PROGBITS 0000000000000000 001000 000001 + +## Sections with different output sections cannot be folded. Without the +## linker script, .text.foo* and .text.bar* go to the same output section +## .text and they will be folded. +# RUN: echo 'SECTIONS { .text.foo : {*(.text.foo*)} .text.bar : {*(.text.bar*)} }' > %t2.script +# RUN: ld.lld %t.o --script %t2.script --icf=all --print-icf-sections -o %t | FileCheck --check-prefix=ICF2 %s +# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC2 %s + +# ICF2: selected section {{.*}}.o:(.text.foo0) +# ICF2-NEXT: removing identical section {{.*}}.o:(.text.foo1) +# ICF2-NEXT: selected section {{.*}}.o:(.text.bar0) +# ICF2-NEXT: removing identical section {{.*}}.o:(.text.bar1) + +# SEC2: .text.foo PROGBITS 0000000000000000 001000 000001 +# SEC2-NEXT: .text.bar PROGBITS 0000000000000001 001001 000001 + +## .text.bar* are orphans that get assigned to .text. +# RUN: echo 'SECTIONS { .text.foo : {*(.text.foo*)} }' > %t3.script +# RUN: ld.lld %t.o --script %t3.script --icf=all --print-icf-sections -o %t | FileCheck --check-prefix=ICF2 %s +# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC3 %s + +# SEC3: .text.foo PROGBITS 0000000000000000 001000 000001 +# SEC3-NEXT: .text PROGBITS 0000000000000004 001004 000001 + +.section .text.foo0,"ax" +ret +.section .text.foo1,"ax" +ret +.section .text.bar0,"ax" +ret +.section .text.bar1,"ax" +ret diff --git a/lld/test/ELF/linkerscript/subalign.s b/lld/test/ELF/linkerscript/subalign.s index 99cb3f19a99..8d8420c0f77 100644 --- a/lld/test/ELF/linkerscript/subalign.s +++ b/lld/test/ELF/linkerscript/subalign.s @@ -23,11 +23,11 @@ # SUBALIGN: 03000000 00000000 04000000 00000000 ## Test we do not assert or crash when dot(.) is used inside SUBALIGN. -## ld.bfd does not allow to use dot in such expressions, our behavior is -## different for simplicity of implementation. Value of dot is undefined. +## Value of dot is undefined. Some versions of ld.bfd do not allow to use dot +## in such expressions. # RUN: echo "SECTIONS { . = 0x32; .aaa : SUBALIGN(.) { *(.aaa*) } }" > %t3.script -# RUN: ld.lld %t1.o --script %t3.script -o %t3 -# RUN: llvm-objdump -s %t3 > /dev/null +# RUN: not ld.lld %t1.o --script %t3.script -o /dev/null 2>&1 | FileCheck --check-prefix=ERR1 %s +# ERR1: {{.*}}.script:1: unable to get location counter value ## Test we are able to link with zero alignment, this is consistent with bfd 2.26.1. # RUN: echo "SECTIONS { .aaa : SUBALIGN(0) { *(.aaa*) } }" > %t4.script @@ -36,8 +36,8 @@ ## Test we fail gracefuly when alignment value is not a power of 2. # RUN: echo "SECTIONS { .aaa : SUBALIGN(3) { *(.aaa*) } }" > %t5.script -# RUN: not ld.lld %t1.o --script %t5.script -o /dev/null 2>&1 | FileCheck -check-prefix=ERR %s -# ERR: {{.*}}.script:1: alignment must be power of 2 +# RUN: not ld.lld %t1.o --script %t5.script -o /dev/null 2>&1 | FileCheck --check-prefix=ERR2 %s +# ERR2: {{.*}}.script:1: alignment must be power of 2 .global _start _start: |

