| commit cb2d8e912512305fb5c45cf0f35f654f713dfa7c |
| Author: Peter Collingbourne <peter@pcc.me.uk> |
| Date: Thu Jul 18 16:47:29 2019 +0000 |
| |
| ELF: Allow forward references to linked sections. |
| |
| It's possible to create IR that uses !associated to refer to a global that |
| appears later in the module, which can result in these types of forward |
| references being generated. Unfortunately our assembler does not currently |
| accept the resulting .s so I needed to use yaml2obj to test this. |
| |
| Differential Revision: https://reviews.llvm.org/D64880 |
| |
| llvm-svn: 366460 |
| |
| diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp |
| index 98b88283cf0..eeb5845b85c 100644 |
| --- a/lld/ELF/InputFiles.cpp |
| +++ b/lld/ELF/InputFiles.cpp |
| @@ -573,7 +573,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) { |
| this->sectionStringTable = |
| CHECK(obj.getSectionStringTable(objSections), this); |
| |
| - for (size_t i = 0, e = objSections.size(); i < e; i++) { |
| + for (size_t i = 0, e = objSections.size(); i < e; ++i) { |
| if (this->sections[i] == &InputSection::discarded) |
| continue; |
| const Elf_Shdr &sec = objSections[i]; |
| @@ -652,25 +652,29 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) { |
| default: |
| this->sections[i] = createInputSection(sec); |
| } |
| + } |
| + |
| + for (size_t i = 0, e = objSections.size(); i < e; ++i) { |
| + if (this->sections[i] == &InputSection::discarded) |
| + continue; |
| + const Elf_Shdr &sec = objSections[i]; |
| + if (!(sec.sh_flags & SHF_LINK_ORDER)) |
| + 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. |
| - if (sec.sh_flags & SHF_LINK_ORDER) { |
| - 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)); |
| - |
| - InputSection *isec = cast<InputSection>(this->sections[i]); |
| - linkSec->dependentSections.push_back(isec); |
| - if (!isa<InputSection>(linkSec)) |
| - error("a section " + isec->name + |
| - " with SHF_LINK_ORDER should not refer a non-regular " |
| - "section: " + |
| - toString(linkSec)); |
| - } |
| + 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)); |
| + |
| + InputSection *isec = cast<InputSection>(this->sections[i]); |
| + linkSec->dependentSections.push_back(isec); |
| + if (!isa<InputSection>(linkSec)) |
| + error("a section " + isec->name + |
| + " with SHF_LINK_ORDER should not refer a non-regular section: " + |
| + toString(linkSec)); |
| } |
| } |
| |
| diff --git a/lld/test/ELF/linkorder-forward-ref.test b/lld/test/ELF/linkorder-forward-ref.test |
| new file mode 100644 |
| index 00000000000..2e00516001f |
| --- /dev/null |
| +++ b/lld/test/ELF/linkorder-forward-ref.test |
| @@ -0,0 +1,23 @@ |
| +# REQUIRES: x86 |
| +# RUN: yaml2obj %s -o %t.o |
| +# RUN: ld.lld %t.o -o %t |
| +# RUN: llvm-readelf -S %t | FileCheck %s |
| + |
| +## Test that we accept forward sh_link references. |
| + |
| +# CHECK: .linkorder |
| +# CHECK: .text |
| + |
| +--- !ELF |
| +FileHeader: |
| + Class: ELFCLASS64 |
| + Data: ELFDATA2LSB |
| + Type: ET_REL |
| + Machine: EM_X86_64 |
| +Sections: |
| + - Name: .linkorder |
| + Type: SHT_PROGBITS |
| + Flags: [ SHF_LINK_ORDER ] |
| + Link: 2 |
| + - Name: .text |
| + Type: SHT_PROGBITS |