diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -656,17 +656,19 @@ if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) this->sections[i] = createInputSection(sec); - if (!(sec.sh_flags & SHF_LINK_ORDER)) + // A SHF_LINK_ORDER section with sh_link=0 is handled as if it did not have + // the flag. + if (!(sec.sh_flags & SHF_LINK_ORDER) || !sec.sh_link) continue; - // .ARM.exidx sections have a reverse dependency on the InputSection they - // have a SHF_LINK_ORDER dependency, this is identified by the sh_link. InputSectionBase *linkSec = nullptr; if (sec.sh_link < this->sections.size()) linkSec = this->sections[sec.sh_link]; if (!linkSec) fatal(toString(this) + ": invalid sh_link index: " + Twine(sec.sh_link)); + // A SHF_LINK_ORDER section is discarded if its linked-to section is + // discarded. InputSection *isec = cast(this->sections[i]); linkSec->dependentSections.push_back(isec); if (!isa(linkSec)) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -275,8 +275,9 @@ } InputSection *InputSectionBase::getLinkOrderDep() const { - assert(link); assert(flags & SHF_LINK_ORDER); + if (!link) + return nullptr; return cast(file->getSections()[link]); } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1606,6 +1606,9 @@ static bool compareByFilePosition(InputSection *a, InputSection *b) { InputSection *la = a->getLinkOrderDep(); InputSection *lb = b->getLinkOrderDep(); + // SHF_LINK_ORDER sections with non-zero sh_link are ordered before others. + if (!la || !lb) + return la && !lb; OutputSection *aOut = la->getParent(); OutputSection *bOut = lb->getParent(); @@ -1646,7 +1649,7 @@ sections.push_back(isec); InputSection *link = isec->getLinkOrderDep(); - if (!link->getParent()) + if (link && !link->getParent()) error(toString(isec) + ": sh_link points to discarded section " + toString(link)); } diff --git a/lld/test/ELF/invalid/linkorder-invalid-sec2.test b/lld/test/ELF/invalid/linkorder-invalid-sec2.test deleted file mode 100644 --- a/lld/test/ELF/invalid/linkorder-invalid-sec2.test +++ /dev/null @@ -1,16 +0,0 @@ -# REQUIRES: x86 -# RUN: yaml2obj %s -o %t.o -# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s -# CHECK: invalid sh_link index: 0 - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 -Sections: - - Name: .linkorder - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_LINK_ORDER ] - Link: 0 diff --git a/lld/test/ELF/linkorder-mixed.test b/lld/test/ELF/linkorder-mixed.test new file mode 100644 --- /dev/null +++ b/lld/test/ELF/linkorder-mixed.test @@ -0,0 +1,56 @@ +## Test that we allow SHF_LINK_ORDER sections with sh_link=0. +## SHF_LINK_ORDER sections with sh_link!=0 are ordered before others. +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-readelf -S -x .linkorder %t | FileCheck %s + +# CHECK: [Nr] Name {{.*}} Size ES Flg Lk Inf +# CHECK-NEXT: [ 0] {{.*}} +# CHECK-NEXT: [ 1] .linkorder {{.*}} 000004 00 AL 3 0 +# CHECK-NEXT: [ 2] .ignore {{.*}} +# CHECK-NEXT: [ 3] .text {{.*}} + +# CHECK: Hex dump of section '.linkorder': +# CHECK-NEXT: [[#%x,ADDR:]] 01020003 + +## TODO Allow non-contiguous SHF_LINK_ORDER sections in an output section. +# RUN: yaml2obj -D EXTRA='.linkorder (4)' %s -o %t.o +# RUN: not ld.lld %t.o -o /dev/null + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text (0) + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .text (1) + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .linkorder (0) + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_LINK_ORDER ] + Link: 0 + Content: 00 + - Name: .linkorder (1) + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_LINK_ORDER ] + Link: 1 + Content: 01 + - Name: .linkorder (2) + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_LINK_ORDER ] + Link: 2 + Content: 02 + - Name: [[EXTRA=.ignore]] + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Content: 04 + - Name: .linkorder (3) + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_LINK_ORDER ] + Link: 0 + Content: 03