Skip to content

Commit

Permalink
[ELF] Keep orphan section names (.rodata.foo .text.foo) unchanged if …
Browse files Browse the repository at this point in the history
…!hasSectionsCommand

This behavior matches GNU ld and seems reasonable.

```
// If a SECTIONS command is not specified
.text.* -> .text
.rodata.* -> .rodata
.init_array.* -> .init_array
```

A proposed Linux feature CONFIG_FG_KASLR may depend on the GNU ld behavior.

Reword a comment about -z keep-text-section-prefix and a comment about
CommonSection (deleted by rL286234).

Reviewed By: grimar

Differential Revision: https://reviews.llvm.org/D75225
  • Loading branch information
MaskRay committed Mar 23, 2020
1 parent 9607a11 commit 9e33c09
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 41 deletions.
26 changes: 15 additions & 11 deletions lld/ELF/Writer.cpp
Expand Up @@ -108,12 +108,21 @@ StringRef getOutputSectionName(const InputSectionBase *s) {
}
}

// 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.
// A BssSection created for a common symbol is identified as "COMMON" in
// linker scripts. It should go to .bss section.
if (s->name == "COMMON")
return ".bss";

if (script->hasSectionsCommand)
return s->name;

// 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."})
Expand All @@ -127,11 +136,6 @@ StringRef getOutputSectionName(const InputSectionBase *s) {
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.
if (s->name == "COMMON")
return ".bss";

return s->name;
}

Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/data-commands-gc.s
Expand Up @@ -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 g .rodata 0000000000000000 bar
# CHECK: 0000000000000008 g .rodata.bar 0000000000000000 bar

.section .rodata.bar
.quad 0x1122334455667788
Expand Down
14 changes: 10 additions & 4 deletions lld/test/ELF/linkerscript/icf-output-sections.s
Expand Up @@ -28,13 +28,19 @@
# SEC2: .text.foo PROGBITS 0000000000000000 001000 000001
# SEC2-NEXT: .text.bar PROGBITS 0000000000000001 001001 000001

## .text.bar* are orphans that get assigned to .text.
## .text.bar* are orphan sections.
# 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
Expand Down
4 changes: 2 additions & 2 deletions 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

Expand Down
2 changes: 1 addition & 1 deletion 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
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/memory3.s
Expand Up @@ -18,6 +18,6 @@
# CHECK: 0 00000000 0000000000000000
# CHECK: 1 .text 00000001 0000000000001000

.section .text.foo,"ax",%progbits
.section .text,"ax",%progbits
foo:
nop
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/orphan-report.s
Expand Up @@ -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: <internal>:(.comment) is being placed in '.comment'
# DYNSYM-NEXT: <internal>:(.dynsym) is being placed in '.dynsym'
# DYNSYM-NEXT: <internal>:(.gnu.hash) is being placed in '.gnu.hash'
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/symbol-assign-many-passes2.test
Expand Up @@ -22,7 +22,7 @@ SECTIONS {
b = c + 1;
c = d + 1;
d = e + 1;
*(.text);
*(.text*);
}
e = .;
}
34 changes: 17 additions & 17 deletions lld/test/ELF/mips-npic-call-pic-script.s
Expand Up @@ -87,13 +87,13 @@ __start:
# 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
Expand All @@ -113,16 +113,16 @@ __start:
# ORPH1-NEXT: 20050: nop

# ORPH1: <__LA25Thunk_foo1a>:
# ORPH1-NEXT: 20054: lui $25, 2
# ORPH1-NEXT: 20058: j 131200 <foo1a>
# ORPH1-NEXT: 2005c: addiu $25, $25, 128
# ORPH1-NEXT: 20060: nop
# ORPH1-NEXT: 20060: lui $25, 2
# ORPH1-NEXT: j 131200 <foo1a>
# ORPH1-NEXT: addiu $25, $25, 128
# ORPH1-NEXT: nop

# ORPH1: <__LA25Thunk_foo1b>:
# ORPH1-NEXT: 20064: lui $25, 2
# ORPH1-NEXT: 20068: j 131204 <foo1b>
# ORPH1-NEXT: 2006c: addiu $25, $25, 132
# ORPH1-NEXT: 20070: nop
# ORPH1-NEXT: 20070: lui $25, 2
# ORPH1-NEXT: j 131204 <foo1b>
# ORPH1-NEXT: addiu $25, $25, 132
# ORPH1-NEXT: nop

# ORPH1: <foo1a>:
# ORPH1-NEXT: 20080: nop
Expand All @@ -131,17 +131,17 @@ __start:
# ORPH1-NEXT: 20084: nop

# ORPH1: <__LA25Thunk_foo2>:
# ORPH1-NEXT: 20088: lui $25, 2
# ORPH1-NEXT: 2008c: j 131232 <foo2>
# ORPH1-NEXT: 20090: addiu $25, $25, 160
# ORPH1-NEXT: 20094: nop
# ORPH1-NEXT: 20090: lui $25, 2
# ORPH1-NEXT: j 131232 <foo2>
# 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

Expand Down
4 changes: 3 additions & 1 deletion lld/test/ELF/shuffle-sections-init-fini.s
Expand Up @@ -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
Expand Down
14 changes: 13 additions & 1 deletion lld/test/ELF/text-section-prefix.s
@@ -1,4 +1,7 @@
# REQUIRES: x86
## -z keep-text-section-prefix separates text sections with prefix .text.hot,
## .text.unlikely, .text.startup, or .text.exit, in the absence of a SECTIONS command.

# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: ld.lld %t.o -o %t1
# RUN: llvm-readelf -S %t1 | FileCheck --check-prefix=NOKEEP %s
Expand All @@ -17,9 +20,18 @@
# NOKEEP: [ 1] .text
# NOKEEP-NOT: .text

## With a SECTIONS command, orphan sections are created verbatim.
## No grouping is performed for them.
# RUN: echo 'SECTIONS {}' > %t.lds
# RUN: ld.lld -T %t.lds -z keep-text-section-prefix %t.o -o %t.script
# RUN: llvm-readelf -S %t.script | FileCheck --check-prefix=KEEP %s
# RUN: llvm-readelf -S %t.script | 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

.globl _start
_start:
Expand Down

0 comments on commit 9e33c09

Please sign in to comment.