summaryrefslogtreecommitdiffstats
path: root/lld/test/ELF/linkerscript
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2019-09-02 10:33:58 +0000
committerFangrui Song <maskray@google.com>2019-09-02 10:33:58 +0000
commitd8bc6a48eaa9111b1fc232aa678695a57ae25ec6 (patch)
treefd8b66ad4be55416be86dbf4101b4f33817f8b48 /lld/test/ELF/linkerscript
parent252a584cbd018e21b0ab4d9ee89eab31f4c84ee2 (diff)
downloadbcm5719-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.s11
-rw-r--r--lld/test/ELF/linkerscript/icf-output-sections.s46
-rw-r--r--lld/test/ELF/linkerscript/subalign.s12
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:
OpenPOWER on IntegriCloud