diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -108,24 +108,27 @@ } } - // This check is for -z keep-text-section-prefix. This option separates text - // sections with prefix ".text.hot", ".text.unlikely", ".text.startup" or - // ".text.exit". - // When enabled, this allows identifying the hot code region (.text.hot) in - // the final binary which can be selectively mapped to huge pages or mlocked, - // for instance. - if (config->zKeepTextSectionPrefix) - for (StringRef v : - {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) + if (!script->hasSectionsCommand) { + // When no SECTIONS is specified, emulate GNU ld's internal linker scripts + // by grouping sections with certain prefixes. + + // GNU ld places text sections with prefix ".text.hot.", ".text.unlikely.", + // ".text.startup." or ".text.exit." before others. We provide an option -z + // keep-text-section-prefix to group such sections into separate output + // sections. This is more flexible. See also sortISDBySectionOrder(). + if (config->zKeepTextSectionPrefix) + for (StringRef v : + {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) + if (isSectionPrefix(v, s->name)) + return v.drop_back(); + + for (StringRef v : {".text.", ".rodata.", ".data.rel.ro.", ".data.", + ".bss.rel.ro.", ".bss.", ".init_array.", ".fini_array.", + ".ctors.", ".dtors.", ".tbss.", ".gcc_except_table.", + ".tdata.", ".ARM.exidx.", ".ARM.extab."}) if (isSectionPrefix(v, s->name)) return v.drop_back(); - - for (StringRef v : - {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", - ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", - ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) - if (isSectionPrefix(v, s->name)) - return v.drop_back(); + } // CommonSection is identified as "COMMON" in linker scripts. // By default, it should go to .bss section. diff --git a/lld/test/ELF/linkerscript/data-commands-gc.s b/lld/test/ELF/linkerscript/data-commands-gc.s --- a/lld/test/ELF/linkerscript/data-commands-gc.s +++ b/lld/test/ELF/linkerscript/data-commands-gc.s @@ -4,7 +4,7 @@ # RUN: ld.lld --gc-sections -o %t %t.o --script %t.script # RUN: llvm-objdump -t %t | FileCheck %s -# CHECK: 0000000000000008 .rodata 00000000 bar +# CHECK: 0000000000000008 .rodata.bar 00000000 bar .section .rodata.bar .quad 0x1122334455667788 diff --git a/lld/test/ELF/linkerscript/icf-output-sections.s b/lld/test/ELF/linkerscript/icf-output-sections.s --- a/lld/test/ELF/linkerscript/icf-output-sections.s +++ b/lld/test/ELF/linkerscript/icf-output-sections.s @@ -30,11 +30,17 @@ ## .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 +# RUN: ld.lld %t.o -T %t3.script --icf=all --print-icf-sections -o %t3 | FileCheck --check-prefix=ICF3 %s +# RUN: llvm-readelf -S %t3 | FileCheck --check-prefix=SEC3 %s +# ICF3: selected section {{.*}}.o:(.text.foo0) +# ICF3-NEXT: removing identical section {{.*}}.o:(.text.foo1) + +# SEC3: Name Type Address Off Size # SEC3: .text.foo PROGBITS 0000000000000000 001000 000001 -# SEC3-NEXT: .text PROGBITS 0000000000000004 001004 000001 +# SEC3-NEXT: .text PROGBITS 0000000000000004 001004 000000 +# SEC3-NEXT: .text.bar0 PROGBITS 0000000000000004 001004 000001 +# SEC3-NEXT: .text.bar1 PROGBITS 0000000000000005 001005 000001 .section .text.foo0,"ax" ret diff --git a/lld/test/ELF/linkerscript/linkorder.s b/lld/test/ELF/linkerscript/linkorder.s --- a/lld/test/ELF/linkerscript/linkorder.s +++ b/lld/test/ELF/linkerscript/linkorder.s @@ -1,11 +1,11 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -# RUN: echo "SECTIONS { .text : { *(.text.bar) *(.text.foo) } }" > %t.script +# RUN: echo "SECTIONS { .rodata : {*(.rodata*)} .text : {*(.text.bar) *(.text.foo)} }" > %t.script # RUN: ld.lld -o %t --script %t.script %t.o # RUN: llvm-objdump -s %t | FileCheck %s -# RUN: echo "SECTIONS { .text : { *(.text.foo) *(.text.bar) } }" > %t.script +# RUN: echo "SECTIONS { .rodata : {*(.rodata*)} .text : {*(.text.foo) *(.text.bar)} }" > %t.script # RUN: ld.lld -o %t --script %t.script %t.o # RUN: llvm-objdump -s %t | FileCheck --check-prefix=INV %s diff --git a/lld/test/ELF/linkerscript/linkorder2.s b/lld/test/ELF/linkerscript/linkorder2.s --- a/lld/test/ELF/linkerscript/linkorder2.s +++ b/lld/test/ELF/linkerscript/linkorder2.s @@ -1,6 +1,6 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -# RUN: echo "SECTIONS { .text : { *(.text.*) } }" > %t.script +# RUN: echo 'SECTIONS { .rodata : {*(.rodata.*)} .text : {*(.text.*)} }' > %t.script # RUN: echo "_bar" > %t.ord # RUN: echo "_foo" >> %t.ord diff --git a/lld/test/ELF/linkerscript/memory3.s b/lld/test/ELF/linkerscript/memory3.s --- a/lld/test/ELF/linkerscript/memory3.s +++ b/lld/test/ELF/linkerscript/memory3.s @@ -18,6 +18,6 @@ # CHECK: 0 00000000 0000000000000000 # CHECK: 1 .text 00000001 0000000000001000 -.section .text.foo,"ax",%progbits +.section .text,"ax",%progbits foo: nop diff --git a/lld/test/ELF/linkerscript/orphan-report.s b/lld/test/ELF/linkerscript/orphan-report.s --- a/lld/test/ELF/linkerscript/orphan-report.s +++ b/lld/test/ELF/linkerscript/orphan-report.s @@ -24,7 +24,7 @@ # RUN: %t.o 2>&1 | FileCheck %s --check-prefixes=COMMON,DYNSYM,SYMTAB # COMMON: {{.*}}.o:(.text) is being placed in '.text' -# COMMON-NEXT: {{.*}}.o:(.text.2) is being placed in '.text' +# COMMON-NEXT: {{.*}}.o:(.text.2) is being placed in '.text.2' # COMMON-NEXT: :(.comment) is being placed in '.comment' # DYNSYM-NEXT: :(.dynsym) is being placed in '.dynsym' # DYNSYM-NEXT: :(.gnu.hash) is being placed in '.gnu.hash' diff --git a/lld/test/ELF/linkerscript/symbol-assign-many-passes2.test b/lld/test/ELF/linkerscript/symbol-assign-many-passes2.test --- a/lld/test/ELF/linkerscript/symbol-assign-many-passes2.test +++ b/lld/test/ELF/linkerscript/symbol-assign-many-passes2.test @@ -22,7 +22,7 @@ b = c + 1; c = d + 1; d = e + 1; - *(.text); + *(.text*); } e = .; } diff --git a/lld/test/ELF/mips-npic-call-pic-script.s b/lld/test/ELF/mips-npic-call-pic-script.s --- a/lld/test/ELF/mips-npic-call-pic-script.s +++ b/lld/test/ELF/mips-npic-call-pic-script.s @@ -87,13 +87,13 @@ # ORPH1: Disassembly of section .text: # ORPH1-EMPTY: # ORPH1-NEXT: __start: -# ORPH1-NEXT: 20000: jal 131156 <__LA25Thunk_foo1a> +# ORPH1-NEXT: 20000: jal 131168 <__LA25Thunk_foo1a> # ORPH1-NEXT: 20004: nop -# ORPH1-NEXT: 20008: jal 131208 <__LA25Thunk_foo2> +# ORPH1-NEXT: 20008: jal 131216 <__LA25Thunk_foo2> # ORPH1-NEXT: 2000c: nop -# ORPH1-NEXT: 20010: jal 131172 <__LA25Thunk_foo1b> +# ORPH1-NEXT: 20010: jal 131184 <__LA25Thunk_foo1b> # ORPH1-NEXT: 20014: nop -# ORPH1-NEXT: 20018: jal 131208 <__LA25Thunk_foo2> +# ORPH1-NEXT: 20018: jal 131216 <__LA25Thunk_foo2> # ORPH1-NEXT: 2001c: nop # ORPH1-NEXT: 20020: jal 131120 <__LA25Thunk_fpic> # ORPH1-NEXT: 20024: nop @@ -113,16 +113,16 @@ # ORPH1-NEXT: 20050: nop # ORPH1: __LA25Thunk_foo1a: -# ORPH1-NEXT: 20054: lui $25, 2 -# ORPH1-NEXT: 20058: j 131200 -# ORPH1-NEXT: 2005c: addiu $25, $25, 128 -# ORPH1-NEXT: 20060: nop +# ORPH1-NEXT: 20060: lui $25, 2 +# ORPH1-NEXT: j 131200 +# ORPH1-NEXT: addiu $25, $25, 128 +# ORPH1-NEXT: nop # ORPH1: __LA25Thunk_foo1b: -# ORPH1-NEXT: 20064: lui $25, 2 -# ORPH1-NEXT: 20068: j 131204 -# ORPH1-NEXT: 2006c: addiu $25, $25, 132 -# ORPH1-NEXT: 20070: nop +# ORPH1-NEXT: 20070: lui $25, 2 +# ORPH1-NEXT: j 131204 +# ORPH1-NEXT: addiu $25, $25, 132 +# ORPH1-NEXT: nop # ORPH1: foo1a: # ORPH1-NEXT: 20080: nop @@ -131,17 +131,17 @@ # ORPH1-NEXT: 20084: nop # ORPH1: __LA25Thunk_foo2: -# ORPH1-NEXT: 20088: lui $25, 2 -# ORPH1-NEXT: 2008c: j 131232 -# ORPH1-NEXT: 20090: addiu $25, $25, 160 -# ORPH1-NEXT: 20094: nop +# ORPH1-NEXT: 20090: lui $25, 2 +# ORPH1-NEXT: j 131232 +# ORPH1-NEXT: addiu $25, $25, 160 +# ORPH1-NEXT: nop # ORPH1: foo2: # ORPH1-NEXT: 200a0: nop # Test script with orphans added to new OutputSection, the .text.1 and # .text.2 sections will form a new OutputSection .text -# RUN: echo "SECTIONS { .out 0x20000 : { *(.text) } }" > %t3.script +# RUN: echo "SECTIONS { .out 0x20000 : { *(.text) } .text : {*(.text*)} }" > %t3.script # RUN: ld.lld --script %t3.script %t-npic.o %t-pic.o %t-sto-pic.o -o %t3.exe # RUN: llvm-objdump -d --no-show-raw-insn %t3.exe | FileCheck -check-prefix=ORPH2 %s diff --git a/lld/test/ELF/shuffle-sections-init-fini.s b/lld/test/ELF/shuffle-sections-init-fini.s --- a/lld/test/ELF/shuffle-sections-init-fini.s +++ b/lld/test/ELF/shuffle-sections-init-fini.s @@ -30,7 +30,9 @@ ## With a SECTIONS command, SHT_INIT_ARRAY prirotities are ignored. ## All .init_array* are shuffled together. -# RUN: echo 'SECTIONS {}' > %t.script +# RUN: echo 'SECTIONS { \ +# RUN: .init_array : { *(.init_array*) } \ +# RUN: .fini_array : { *(.fini_array*) }}' > %t.script # RUN: ld.lld -T %t.script %t.o -o %t2 # RUN: llvm-readelf -x .init -x .fini -x .init_array -x .fini_array %t2 | \ # RUN: FileCheck --check-prefixes=CHECK2,ORDERED2 %s diff --git a/lld/test/ELF/text-section-prefix.s b/lld/test/ELF/text-section-prefix.s --- a/lld/test/ELF/text-section-prefix.s +++ b/lld/test/ELF/text-section-prefix.s @@ -15,6 +15,18 @@ # CHECKNO: .text # CHECKNO-NOT: .text.hot +## With a SECTIONS command, no grouping is performed at all. +# RUN: echo 'SECTIONS {}' > %t.script +# RUN: ld.lld -T %t.script -z keep-text-section-prefix %t -o %t5 +# RUN: llvm-readelf -S %t5 | FileCheck --check-prefix=SCRIPT %s + +# SCRIPT: .text +# SCRIPT-NEXT: .text.f +# SCRIPT-NEXT: .text.hot.f_hot +# SCRIPT-NEXT: .text.startup.f_startup +# SCRIPT-NEXT: .text.exit.f_exit +# SCRIPT-NEXT: .text.unlikely.f_unlikely + _start: ret