Skip to content

Commit 7b34635

Browse files
authored
[ELF] Orphan placement: prefer the last similar section when its rank <= orphan's rank
`findOrphanPos` finds the most similar output section (that has input sections). In the event of proximity ties, we select the first section. However, when an orphan section's rank is equal to or larger than the most similar sections's, it makes sense to prioritize the last similar section. This new behavior matches GNU ld better. ``` // orphan placement for .bss (SHF_ALLOC|SHF_WRITE, SHT_NOBITS) WA SHT_PROGBITS (old behavior) <= here A WA SHT_PROGBITS AX WA (.data) (new behavior) <= here ``` When the orphan section's rank is less, the current behavior prioritizing the first section still makes sense. ``` // orphan with a smaller rank, e.g. .rodata <= here WA AX WA ``` Close llvm#92987 Pull Request: llvm#94099
1 parent 6ac5047 commit 7b34635

File tree

4 files changed

+59
-31
lines changed

4 files changed

+59
-31
lines changed

lld/ELF/Writer.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -935,27 +935,32 @@ findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
935935
return i;
936936
}
937937

938-
// Find the first element that has as close a rank as possible.
939-
if (b == e)
940-
return e;
941-
int proximity = getRankProximity(sec, *b);
942-
auto i = b;
943-
for (auto j = b; ++j != e;) {
938+
// Find the most similar output section as the anchor. Rank Proximity is a
939+
// value in the range [-1, 32] where [0, 32] indicates potential anchors (0:
940+
// least similar; 32: identical). -1 means not an anchor.
941+
//
942+
// In the event of proximity ties, we select the first or last section
943+
// depending on whether the orphan's rank is smaller.
944+
int maxP = 0;
945+
auto i = e;
946+
for (auto j = b; j != e; ++j) {
944947
int p = getRankProximity(sec, *j);
945-
if (p > proximity) {
946-
proximity = p;
948+
if (p > maxP ||
949+
(p == maxP && cast<OutputDesc>(*j)->osec.sortRank <= sec->sortRank)) {
950+
maxP = p;
947951
i = j;
948952
}
949953
}
950-
if (!isa<OutputDesc>(*i))
954+
if (i == e)
951955
return e;
952956

953957
auto isOutputSecWithInputSections = [](SectionCommand *cmd) {
954958
auto *osd = dyn_cast<OutputDesc>(cmd);
955959
return osd && osd->osec.hasInputSections;
956960
};
957961

958-
// If i's rank is larger, the orphan section can be placed before i.
962+
// Then, scan backward or forward through the script for a suitable insertion
963+
// point. If i's rank is larger, the orphan section can be placed before i.
959964
//
960965
// However, don't do this if custom program headers are defined. Otherwise,
961966
// adding the orphan to a previous segment can change its flags, for example,
@@ -967,7 +972,7 @@ findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
967972
for (auto j = ++i; j != e; ++j) {
968973
if (!isOutputSecWithInputSections(*j))
969974
continue;
970-
if (getRankProximity(sec, *j) != proximity)
975+
if (getRankProximity(sec, *j) != maxP)
971976
break;
972977
i = j + 1;
973978
}

lld/test/ELF/linkerscript/orphan.s

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@
6565
# RW-TEXT-NEXT: .text PROGBITS 0000000000001{{...}} 0
6666
# RW-TEXT-NEXT: .mytext PROGBITS 0000000000001{{...}} 0
6767

68+
# RUN: ld.lld a.o -T rw-text-rw.lds -o rw-text-rw
69+
# RUN: llvm-readelf -S rw-text-rw | FileCheck %s --check-prefix=RW-TEXT-RW
70+
# RW-TEXT-RW: .jcr PROGBITS 00000000000002{{..}} 0
71+
# RW-TEXT-RW-NEXT: .rw1 PROGBITS 00000000000002{{..}} 0
72+
# RW-TEXT-RW-NEXT: .interp PROGBITS 00000000000002{{..}} 0
73+
# RW-TEXT-RW-NEXT: .note.my NOTE 00000000000002{{..}} 0
74+
# RW-TEXT-RW-NEXT: .text PROGBITS 0000000000001{{...}} 0
75+
# RW-TEXT-RW-NEXT: .mytext PROGBITS 0000000000001{{...}} 0
76+
# RW-TEXT-RW-NEXT: .rw2 PROGBITS 0000000000002{{...}} 0
77+
# RW-TEXT-RW-NEXT: .rw3 PROGBITS 0000000000002{{...}} 0
78+
# RW-TEXT-RW-NEXT: .bss NOBITS 0000000000002{{...}} 0
79+
6880
#--- a.s
6981
.section .rw1, "aw"; .byte 0
7082
.section .rw2, "aw"; .byte 0
@@ -112,3 +124,13 @@ SECTIONS {
112124
. = ALIGN(CONSTANT(MAXPAGESIZE));
113125
.text : { *(.text) }
114126
}
127+
128+
#--- rw-text-rw.lds
129+
SECTIONS {
130+
. = SIZEOF_HEADERS;
131+
.rw1 : { *(.rw1) }
132+
. = ALIGN(CONSTANT(MAXPAGESIZE));
133+
.text : { *(.text) }
134+
. = ALIGN(CONSTANT(MAXPAGESIZE));
135+
.rw2 : { *(.rw2) }
136+
}

lld/test/ELF/linkerscript/sections-nonalloc.s

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@
1414
# CHECK-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0
1515
# CHECK-NEXT: [ 1] .bss NOBITS 0000000000000000 001000 000001 00 WA 0
1616
# CHECK-NEXT: [ 2] data1 PROGBITS 0000000000000001 001001 000001 00 WA 0
17-
# CHECK-NEXT: [ 3] data3 PROGBITS 0000000000000002 001002 000001 00 WA 0
18-
# CHECK-NEXT: [ 4] other1 PROGBITS 0000000000000000 001008 000001 00 0
19-
# CHECK-NEXT: [ 5] other2 PROGBITS 0000000000000000 001010 000001 00 0
17+
# CHECK-NEXT: [ 3] other1 PROGBITS 0000000000000000 001008 000001 00 0
18+
# CHECK-NEXT: [ 4] other2 PROGBITS 0000000000000000 001010 000001 00 0
2019
## Orphan placement places other3, .symtab, .shstrtab and .strtab after other2.
21-
# CHECK-NEXT: [ 6] other3 PROGBITS 0000000000000000 001020 000001 00 0
22-
# CHECK-NEXT: [ 7] .symtab SYMTAB 0000000000000000 001028 000030 18 9
23-
# CHECK-NEXT: [ 8] .shstrtab STRTAB 0000000000000000 001058 00004d 00 0
24-
# CHECK-NEXT: [ 9] .strtab STRTAB 0000000000000000 0010a5 000008 00 0
25-
# CHECK-NEXT: [10] data2 PROGBITS 0000000000000003 001003 000001 00 WA 0
20+
# CHECK-NEXT: [ 5] other3 PROGBITS 0000000000000000 001020 000001 00 0
21+
# CHECK-NEXT: [ 6] .symtab SYMTAB 0000000000000000 001028 000030 18 8
22+
# CHECK-NEXT: [ 7] .shstrtab STRTAB 0000000000000000 001058 00004d 00 0
23+
# CHECK-NEXT: [ 8] .strtab STRTAB 0000000000000000 0010a5 000008 00 0
24+
# CHECK-NEXT: [ 9] data2 PROGBITS 0000000000000002 001002 000001 00 WA 0
25+
## max{sortRank(data1),sortRank(data2)} <= sortRank(data3). data3 is placed after the latter.
26+
# CHECK-NEXT: [10] data3 PROGBITS 0000000000000003 001003 000001 00 WA 0
2627
# CHECK-NEXT: [11] .text PROGBITS 0000000000000004 001004 000001 00 AX 0
2728

2829
# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
@@ -38,14 +39,14 @@
3839
# CHECK1-NEXT: [ 1] .text PROGBITS 00000000000000b0 0000b0 000001 00 AX 0
3940
# CHECK1-NEXT: [ 2] .bss NOBITS 00000000000000b1 0000b1 000001 00 WA 0
4041
# CHECK1-NEXT: [ 3] data1 PROGBITS 00000000000000b2 0000b2 000001 00 WA 0
41-
# CHECK1-NEXT: [ 4] data3 PROGBITS 00000000000000b3 0000b3 000001 00 WA 0
42-
# CHECK1-NEXT: [ 5] other1 PROGBITS 0000000000000000 0000b8 000001 00 0
43-
# CHECK1-NEXT: [ 6] other2 PROGBITS 0000000000000000 0000c0 000001 00 0
44-
# CHECK1-NEXT: [ 7] other3 PROGBITS 0000000000000000 0000d0 000001 00 0
45-
# CHECK1-NEXT: [ 8] .symtab SYMTAB 0000000000000000 0000d8 000030 18 10
46-
# CHECK1-NEXT: [ 9] .shstrtab STRTAB 0000000000000000 000108 00004d 00 0
47-
# CHECK1-NEXT: [10] .strtab STRTAB 0000000000000000 000155 000008 00 0
48-
# CHECK1-NEXT: [11] data2 PROGBITS 00000000000000b4 0000b4 000001 00 WA 0
42+
# CHECK1-NEXT: [ 4] other1 PROGBITS 0000000000000000 0000b8 000001 00 0
43+
# CHECK1-NEXT: [ 5] other2 PROGBITS 0000000000000000 0000c0 000001 00 0
44+
# CHECK1-NEXT: [ 6] other3 PROGBITS 0000000000000000 0000d0 000001 00 0
45+
# CHECK1-NEXT: [ 7] .symtab SYMTAB 0000000000000000 0000d8 000030 18 9
46+
# CHECK1-NEXT: [ 8] .shstrtab STRTAB 0000000000000000 000108 00004d 00 0
47+
# CHECK1-NEXT: [ 9] .strtab STRTAB 0000000000000000 000155 000008 00 0
48+
# CHECK1-NEXT: [10] data2 PROGBITS 00000000000000b3 0000b3 000001 00 WA 0
49+
# CHECK1-NEXT: [11] data3 PROGBITS 00000000000000b4 0000b4 000001 00 WA 0
4950
# CHECK1: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
5051
# CHECK1-NEXT: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0000b5 0x0000b5 RWE 0x1000
5152
# CHECK1-NEXT: 0x60000000 0x0000b8 0x0000000000000000 0x0000000000000000 0x000009 0x000001 0x8

lld/test/ELF/linkerscript/sections.s

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@
7878
# SEP-BY-NONALLOC: [Nr] Name Type Address Off Size ES Flg
7979
# SEP-BY-NONALLOC: [ 1] .text PROGBITS 0000000000000000 001000 00000e 00 AX
8080
# SEP-BY-NONALLOC-NEXT: [ 2] .data PROGBITS 000000000000000e 00100e 000020 00 WA
81-
# SEP-BY-NONALLOC-NEXT: [ 3] .bss NOBITS 000000000000002e 00102e 000002 00 WA
82-
# SEP-BY-NONALLOC-NEXT: [ 4] .comment PROGBITS 0000000000000000 001033 000008 01 MS
83-
# SEP-BY-NONALLOC: [ 8] other PROGBITS 0000000000000030 001030 000003 00 WA
81+
# SEP-BY-NONALLOC-NEXT: [ 3] .comment PROGBITS 0000000000000000 001031 000008 01 MS
82+
# SEP-BY-NONALLOC: [ 7] other PROGBITS 000000000000002e 00102e 000003 00 WA
83+
# SEP-BY-NONALLOC-NEXT: [ 8] .bss NOBITS 0000000000000031 001031 000002 00 WA
8484

8585
# SEP-BY-NONALLOC: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
8686
# SEP-BY-NONALLOC-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x00000e 0x00000e R E 0x1000
87-
# SEP-BY-NONALLOC-NEXT: LOAD 0x00100e 0x000000000000000e 0x000000000000000e 0x000025 0x000025 RW 0x1000
87+
# SEP-BY-NONALLOC-NEXT: LOAD 0x00100e 0x000000000000000e 0x000000000000000e 0x000023 0x000025 RW 0x1000
8888
# SEP-BY-NONALLOC-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0
8989

9090
# Input section pattern contains additional semicolon.

0 commit comments

Comments
 (0)