Skip to content

Commit 71c3f57

Browse files
committed
[ELF] Allow SHF_LINK_ORDER and non-SHF_LINK_ORDER to be mixed
Currently, `error: incompatible section flags for .rodata` is reported when we mix SHF_LINK_ORDER and non-SHF_LINK_ORDER sections in an output section. This is overconstrained. This patch allows mixed flags with the requirement that SHF_LINK_ORDER sections must be contiguous. Mixing flags is used by Linux aarch64 (ClangBuiltLinux/linux#953) .init.data : { ... KEEP(*(__patchable_function_entries)) ... } When the integrated assembler is enabled, clang's -fpatchable-function-entry=N[,M] implementation sets the SHF_LINK_ORDER flag (D72215) to fix a number of garbage collection issues. Strictly speaking, the ELF specification does not require contiguous SHF_LINK_ORDER sections but for many current uses of SHF_LINK_ORDER like .ARM.exidx/__patchable_function_entries there has been a requirement for the sections to be contiguous on top of the requirements of the ELF specification. This patch also imposes one restriction: SHF_LINK_ORDER sections cannot be separated by a symbol assignment or a BYTE command. Not allowing BYTE is a natural extension that a non-SHF_LINK_ORDER cannot be a separator. Symbol assignments can delimiter the contents of SHF_LINK_ORDER sections. Allowing SHF_LINK_ORDER sections across symbol assignments (especially __start_/__stop_) can make things hard to explain. The restriction should not be a problem for practical use cases. Reviewed By: psmith Differential Revision: https://reviews.llvm.org/D77007 (cherry picked from commit 673e81e)
1 parent b2881de commit 71c3f57

File tree

4 files changed

+31
-31
lines changed

4 files changed

+31
-31
lines changed

lld/ELF/OutputSections.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,7 @@ void OutputSection::commitSection(InputSection *isec) {
114114
flags = isec->flags;
115115
} else {
116116
// Otherwise, check if new type or flags are compatible with existing ones.
117-
unsigned mask = SHF_TLS | SHF_LINK_ORDER;
118-
if ((flags & mask) != (isec->flags & mask))
117+
if ((flags ^ isec->flags) & SHF_TLS)
119118
error("incompatible section flags for " + name + "\n>>> " + toString(isec) +
120119
": 0x" + utohexstr(isec->flags) + "\n>>> output section " + name +
121120
": 0x" + utohexstr(flags));
@@ -367,8 +366,9 @@ void OutputSection::finalize() {
367366
// all InputSections in the OutputSection have the same dependency.
368367
if (auto *ex = dyn_cast<ARMExidxSyntheticSection>(first))
369368
link = ex->getLinkOrderDep()->getParent()->sectionIndex;
370-
else if (auto *d = first->getLinkOrderDep())
371-
link = d->getParent()->sectionIndex;
369+
else if (first->flags & SHF_LINK_ORDER)
370+
if (auto *d = first->getLinkOrderDep())
371+
link = d->getParent()->sectionIndex;
372372
}
373373

374374
if (type == SHT_GROUP) {

lld/ELF/Writer.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,17 +1523,30 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
15231523
// but sort must consider them all at once.
15241524
std::vector<InputSection **> scriptSections;
15251525
std::vector<InputSection *> sections;
1526+
bool started = false, stopped = false;
15261527
for (BaseCommand *base : sec->sectionCommands) {
15271528
if (auto *isd = dyn_cast<InputSectionDescription>(base)) {
15281529
for (InputSection *&isec : isd->sections) {
1529-
scriptSections.push_back(&isec);
1530-
sections.push_back(isec);
1531-
1532-
InputSection *link = isec->getLinkOrderDep();
1533-
if (!link->getParent())
1534-
error(toString(isec) + ": sh_link points to discarded section " +
1535-
toString(link));
1530+
if (!(isec->flags & SHF_LINK_ORDER)) {
1531+
if (started)
1532+
stopped = true;
1533+
} else if (stopped) {
1534+
error(toString(isec) + ": SHF_LINK_ORDER sections in " + sec->name +
1535+
" are not contiguous");
1536+
} else {
1537+
started = true;
1538+
1539+
scriptSections.push_back(&isec);
1540+
sections.push_back(isec);
1541+
1542+
InputSection *link = isec->getLinkOrderDep();
1543+
if (!link->getParent())
1544+
error(toString(isec) + ": sh_link points to discarded section " +
1545+
toString(link));
1546+
}
15361547
}
1548+
} else if (started) {
1549+
stopped = true;
15371550
}
15381551
}
15391552

lld/test/ELF/linkerscript/linkorder.s

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
# RUN: ld.lld -T %t.lds %t.o -o %t
88
# RUN: llvm-readelf -S -x .rodata -x .text %t | FileCheck %s
99

10+
# CHECK: [ 1] .rodata {{.*}} AL 3
11+
# CHECK: [ 3] .text {{.*}} AX 0
1012
# CHECK: Hex dump of section '.rodata':
1113
# CHECK-NEXT: 00020103
1214
# CHECK: Hex dump of section '.text':
@@ -17,6 +19,8 @@
1719
# RUN: ld.lld -T %t1.lds %t.o -o %t1
1820
# RUN: llvm-readelf -S -x .rodata -x .text %t1 | FileCheck --check-prefix=CHECK1 %s
1921

22+
# CHECK1: [ 1] .rodata {{.*}} AL 3
23+
# CHECK1: [ 3] .text {{.*}} AX 0
2024
# CHECK1: Hex dump of section '.rodata':
2125
# CHECK1-NEXT: 00010203
2226
# CHECK1: Hex dump of section '.text':
@@ -35,17 +39,17 @@
3539

3640
## Non-contiguous SHF_LINK_ORDER sections, separated by a BYTE.
3741
# RUN: echo 'SECTIONS { .rodata : {*(.rodata.foo) BYTE(0) *(.rodata.bar)} }' > %terr1.lds
38-
# RUN: ld.lld -T %terr1.lds %t.o -o /dev/null
42+
# RUN: not ld.lld -T %terr1.lds %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s
3943

4044
## Non-contiguous SHF_LINK_ORDER sections, separated by a non-SHF_LINK_ORDER section.
4145
# RUN: echo 'SECTIONS { .rodata : {*(.rodata.foo) *(.text) *(.rodata.bar)} }' > %terr2.lds
4246
# RUN: not ld.lld -T %terr2.lds %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s
4347

4448
## Non-contiguous SHF_LINK_ORDER sections, separated by a symbol assignment.
4549
# RUN: echo 'SECTIONS { .rodata : {*(.rodata.foo) a = .; *(.rodata.bar)} }' > %terr3.lds
46-
# RUN: ld.lld -T %terr3.lds %t.o -o /dev/null
50+
# RUN: not ld.lld -T %terr3.lds %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s
4751

48-
# ERR: error: incompatible section flags for .rodata
52+
# ERR: error: {{.*}}.o:(.rodata.bar): SHF_LINK_ORDER sections in .rodata are not contiguous
4953

5054
.global _start
5155
_start:

lld/test/ELF/linkorder-err3.s

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)