diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -632,6 +632,8 @@ break; case SHT_SYMTAB: case SHT_STRTAB: + case SHT_REL: + case SHT_RELA: case SHT_NULL: break; default: @@ -639,11 +641,21 @@ } } - // This block handles SHF_LINK_ORDER. + // We have a second loop. It is used to: + // 1) handle SHF_LINK_ORDER sections. + // 2) create SHT_REL[A] sections. In some cases the section header index of a + // relocation section may be smaller than that of the relocated section. In + // such cases, the relocation section would attempt to reference a target + // section that has not yet been created. For simplicity, delay creation of + // relocation sections until now. 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_type == SHT_REL || sec.sh_type == SHT_RELA) + this->sections[i] = createInputSection(sec); + if (!(sec.sh_flags & SHF_LINK_ORDER)) continue; diff --git a/lld/test/ELF/invalid/reloc-section-reordered.test b/lld/test/ELF/invalid/reloc-section-reordered.test deleted file mode 100644 --- a/lld/test/ELF/invalid/reloc-section-reordered.test +++ /dev/null @@ -1,33 +0,0 @@ -# REQUIRES: x86 - -# RUN: yaml2obj %s -o %t.o -# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s -# CHECK: unsupported relocation reference - -## YAML below lists .rela.text before .text, we do not support it. - -!ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - OSABI: ELFOSABI_FREEBSD - Type: ET_REL - Machine: EM_X86_64 -Sections: - - Type: SHT_REL - Name: .rela.text - Link: .symtab - Info: .text - AddressAlign: 0x04 - Relocations: - - Symbol: .text - Type: R_X86_64_NONE - - Type: SHT_PROGBITS - Name: .text - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - AddressAlign: 0x04 - Content: "FFFFFFFFFFFFFFFF" -Symbols: - - Name: .text - Type: STT_SECTION - Section: .text diff --git a/lld/test/ELF/reloc-sec-before-relocated.test b/lld/test/ELF/reloc-sec-before-relocated.test new file mode 100644 --- /dev/null +++ b/lld/test/ELF/reloc-sec-before-relocated.test @@ -0,0 +1,38 @@ +## If the section header index of a SHT_REL[A] section is smaller than the +## section header index of the relocated section, we should handle it properly. +## Normally it is not what compilers would emit, but some custom tools might +## want to use this feature, which is not restricted by ELF gABI. +## GNU ld supports this as well. + +# RUN: yaml2obj %s -DTYPE=SHT_RELA -o %t1.o +# RUN: ld.lld -shared %t1.o -o %t1 +# RUN: llvm-readelf --relocs %t1 | FileCheck %s + +# RUN: yaml2obj %s -DTYPE=SHT_REL -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t2 +# RUN: llvm-readelf --relocs %t2 | FileCheck %s + +## Check we handle the relocation properly. +# CHECK: Relocation section '.rela.dyn' at offset 0x238 contains 1 entries: +# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +# CHECK-NEXT: 00000000000022f0 0000000100000001 R_X86_64_64 0000000000000000 foo + 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .relx.data + Type: [[TYPE]] + Info: .data + Relocations: + - Symbol: foo + Type: R_X86_64_64 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_WRITE ] +Symbols: + - Name: foo + Binding: STB_GLOBAL