diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -975,9 +975,6 @@ template Expected ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { - if (EF.getHeader().e_type != ELF::ET_REL) - return section_end(); - const Elf_Shdr *EShdr = getSection(Sec); uintX_t Type = EShdr->sh_type; if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -132,6 +132,9 @@ iterator_range relocations() const { return make_range(relocation_begin(), relocation_end()); } + + /// Returns the related section if this section contains relocations. The + /// returned section may or may not have applied its relocations. Expected getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1687,7 +1687,8 @@ // Try to obtain an already relocated version of this section. // Else use the unrelocated section from the object file. We'll have to // apply relocations ourselves later. - section_iterator RelocatedSection = *SecOrErr; + section_iterator RelocatedSection = + Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end(); if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) { Expected E = Section.getContents(); if (E) diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -440,7 +440,7 @@ bool XCOFFObjectFile::isRelocatableObject() const { if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); + return !(fileHeader64()->Flags & NoRelMask); return !(fileHeader32()->Flags & NoRelMask); } diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -590,3 +590,68 @@ DoCheck(OverLimitNumBlocks, "ULEB128 value at offset 0x8 exceeds UINT32_MAX (0x100000000)"); } + +// Test for ObjectFile::getRelocatedSection: check that it returns a relocated +// section for executable and relocatable files. +TEST(ELFObjectFileTest, ExecutableWithRelocs) { + StringRef HeaderString(R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB +)"); + StringRef ContentsString(R"( +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Info: .text +)"); + + auto DoCheck = [&](StringRef YamlString) { + SmallString<0> Storage; + Expected> ElfOrErr = + toBinary(Storage, YamlString); + ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); + const ELFObjectFile &Obj = *ElfOrErr; + + bool FoundRela; + + for (SectionRef Sec : Obj.sections()) { + Expected SecNameOrErr = Sec.getName(); + ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded()); + StringRef SecName = *SecNameOrErr; + if (SecName != ".rela.text") + continue; + FoundRela = true; + Expected RelSecOrErr = Sec.getRelocatedSection(); + ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded()); + section_iterator RelSec = *RelSecOrErr; + ASSERT_NE(RelSec, Obj.section_end()); + Expected TextSecNameOrErr = RelSec->getName(); + ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded()); + StringRef TextSecName = *TextSecNameOrErr; + EXPECT_EQ(TextSecName, ".text"); + } + ASSERT_TRUE(FoundRela); + }; + + // Check ET_EXEC file (`ld --emit-relocs` use-case). + SmallString<128> ExecFileYamlString(HeaderString); + ExecFileYamlString += R"( + Type: ET_EXEC +)"; + ExecFileYamlString += ContentsString; + DoCheck(ExecFileYamlString); + + // Check ET_REL file. + SmallString<128> RelocatableFileYamlString(HeaderString); + RelocatableFileYamlString += R"( + Type: ET_REL +)"; + RelocatableFileYamlString += ContentsString; + DoCheck(RelocatableFileYamlString); +}