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 @@ -288,7 +288,8 @@ relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; std::vector dynamic_relocation_sections() const override; - section_iterator getRelocatedSection(DataRefImpl Sec) const override; + Expected + getRelocatedSection(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; @@ -841,7 +842,7 @@ } template -section_iterator +Expected ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { if (EF.getHeader()->e_type != ELF::ET_REL) return section_end(); @@ -851,10 +852,10 @@ if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) return section_end(); - auto R = EF.getSection(EShdr->sh_info); - if (!R) - report_fatal_error(errorToErrorCode(R.takeError()).message()); - return section_iterator(SectionRef(toDRI(*R), this)); + Expected SecOrErr = EF.getSection(EShdr->sh_info); + if (!SecOrErr) + return SecOrErr.takeError(); + return section_iterator(SectionRef(toDRI(*SecOrErr), this)); } // Relocations 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 @@ -130,7 +130,7 @@ iterator_range relocations() const { return make_range(relocation_begin(), relocation_end()); } - section_iterator getRelocatedSection() const; + Expected getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; const ObjectFile *getObject() const; @@ -272,7 +272,7 @@ virtual bool isBerkeleyData(DataRefImpl Sec) const; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; - virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; + virtual Expected getRelocatedSection(DataRefImpl Sec) const; // Same as above for RelocationRef. friend class RelocationRef; @@ -501,7 +501,7 @@ return OwningObject->section_rel_end(SectionPimpl); } -inline section_iterator SectionRef::getRelocatedSection() const { +inline Expected SectionRef::getRelocatedSection() const { return OwningObject->getRelocatedSection(SectionPimpl); } 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 @@ -1527,10 +1527,19 @@ continue; StringRef Data; - section_iterator RelocatedSection = Section.getRelocatedSection(); + Expected SecOrErr = Section.getRelocatedSection(); + if (!SecOrErr) { + ErrorPolicy EP = HandleError(createError( + "failed to get relocated section: ", SecOrErr.takeError())); + if (EP == ErrorPolicy::Halt) + return; + continue; + } + // 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; if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) { Expected E = Section.getContents(); if (E) diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -348,8 +348,12 @@ for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { StubMap Stubs; - section_iterator RelocatedSection = SI->getRelocatedSection(); + Expected RelSecOrErr = SI->getRelocatedSection(); + if (!RelSecOrErr) + return RelSecOrErr.takeError(); + + section_iterator RelocatedSection = *RelSecOrErr; if (RelocatedSection == SE) continue; @@ -648,7 +652,12 @@ unsigned StubBufSize = 0; for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { - section_iterator RelSecI = SI->getRelocatedSection(); + + Expected RelSecOrErr = SI->getRelocatedSection(); + if (!RelSecOrErr) + report_fatal_error(toString(RelSecOrErr.takeError())); + + section_iterator RelSecI = *RelSecOrErr; if (!(RelSecI == Section)) continue; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -606,7 +606,12 @@ // .opd entries for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); si != se; ++si) { - section_iterator RelSecI = si->getRelocatedSection(); + + Expected RelSecOrErr = si->getRelocatedSection(); + if (!RelSecOrErr) + report_fatal_error(toString(RelSecOrErr.takeError())); + + section_iterator RelSecI = *RelSecOrErr; if (RelSecI == Obj.section_end()) continue; @@ -1871,7 +1876,12 @@ for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { if (SI->relocation_begin() != SI->relocation_end()) { - section_iterator RelocatedSection = SI->getRelocatedSection(); + Expected RelSecOrErr = SI->getRelocatedSection(); + if (!RelSecOrErr) + return make_error( + toString(RelSecOrErr.takeError())); + + section_iterator RelocatedSection = *RelSecOrErr; ObjSectionToIDMap::iterator i = SectionMap.find(*RelocatedSection); assert (i != SectionMap.end()); SectionToGOTMap[i->second] = GOTSectionID; diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -84,7 +84,8 @@ return isSectionData(Sec); } -section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { +Expected +ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); } diff --git a/llvm/test/tools/llvm-cxxdump/broken-reloc-sec.test b/llvm/test/tools/llvm-cxxdump/broken-reloc-sec.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-cxxdump/broken-reloc-sec.test @@ -0,0 +1,20 @@ +## Check we report an error when trying to dump an object +## which has a relocation section that has a broken sh_info +## field, which is larger than the number of sections. + +# RUN: yaml2obj %s -o %t +# RUN: not llvm-cxxdump %t 2>&1 | FileCheck %s +# CHECK: error: reading file: invalid section index: 255 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: +- Name: .rela.foo + Type: SHT_RELA + Link: 0 + Info: 0xFF + Relocations: [] diff --git a/llvm/test/tools/llvm-dwarfdump/elf-broken-reloc-target.yaml b/llvm/test/tools/llvm-dwarfdump/elf-broken-reloc-target.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/elf-broken-reloc-target.yaml @@ -0,0 +1,20 @@ +## Check we report an error if the relocated section identified by the +## sh_info field of a relocation section is invalid. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-dwarfdump %t 2>&1 | FileCheck %s -DFILE=%t --check-prefix=ERR + +# ERR: error: failed to get relocated section: invalid section index: 255 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: +- Name: .rela.debug_info + Type: SHT_RELA + Link: 0 + Info: 0xFF + Relocations: [] diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test --- a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test @@ -1,8 +1,8 @@ ## Show that --disassemble + --reloc prints relocations inline and does not dump ## the relocation sections. -# RUN: yaml2obj %s -o %t.o -# RUN: llvm-objdump %t.o -d -r | FileCheck %s --implicit-check-not="RELOCATION RECORDS" +# RUN: yaml2obj %s --docnum=1 -o %t1.o +# RUN: llvm-objdump %t1.o -d -r | FileCheck %s --implicit-check-not="RELOCATION RECORDS" # CHECK: 0: e8 00 00 00 00 callq 0 <.text+0x5> # CHECK-NEXT: 0000000000000001: R_X86_64_PC32 foo-4 @@ -40,3 +40,24 @@ Symbols: - Name: foo - Name: bar + +## Check we report an error if the relocated section identified by the +## sh_info field of a relocation section is invalid. + +# RUN: yaml2obj %s --docnum=2 -o %t2.o +# RUN: not llvm-objdump %t2.o --disassemble --reloc 2>&1 | FileCheck %s -DFILE=%t2.o --check-prefix=ERR + +# ERR: error: '[[FILE]]': section (1): failed to get a relocated section: invalid section index: 255 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: +- Name: .rela.debug_info + Type: SHT_RELA + Link: 0 + Info: 0xFF + Relocations: [] diff --git a/llvm/test/tools/llvm-objdump/relocations-elf.test b/llvm/test/tools/llvm-objdump/relocations-elf.test --- a/llvm/test/tools/llvm-objdump/relocations-elf.test +++ b/llvm/test/tools/llvm-objdump/relocations-elf.test @@ -74,8 +74,8 @@ ## Check we report an error if the relocated section identified by the ## sh_info field of a relocation section is invalid. # RUN: yaml2obj --docnum=2 %s > %t2 -# RUN: not llvm-objdump --reloc %t2 2>&1 | FileCheck %s --check-prefix=ERR -# ERR: LLVM ERROR: Invalid data was encountered while parsing the file +# RUN: not llvm-objdump --reloc %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=ERR +# ERR: error: '[[FILE]]': section (1): unable to get a relocation target: invalid section index: 255 --- !ELF FileHeader: @@ -86,7 +86,7 @@ Sections: - Name: .rela.foo Type: SHT_RELA - Info: 0x255 + Info: 0xFF Relocations: - Offset: 0x1 Type: R_X86_64_NONE diff --git a/llvm/test/tools/llvm-readobj/stack-sizes.test b/llvm/test/tools/llvm-readobj/stack-sizes.test --- a/llvm/test/tools/llvm-readobj/stack-sizes.test +++ b/llvm/test/tools/llvm-readobj/stack-sizes.test @@ -641,3 +641,26 @@ Relocations: - Offset: 0 Type: R_X86_64_64 + +## Check we report an error when dumping stack sizes if the relocated section +## identified by the sh_info field is invalid. Here sh_info value is larger than +## the number of sections. + +# RUN: yaml2obj --docnum=13 %s > %t18 +# RUN: not llvm-readelf --stack-sizes %t18 2>&1 | FileCheck %s -DFILE=%t18 --check-prefix=INVALID-TARGET +# RUN: not llvm-readobj --stack-sizes %t18 2>&1 | FileCheck %s -DFILE=%t18 --check-prefix=INVALID-TARGET + +# INVALID-TARGET: error: '[[FILE]]': .rela.stack_sizes: failed to get a relocated section: invalid section index: 255 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2MSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .rela.stack_sizes + Type: SHT_RELA + Link: 0 + Info: 0xFF + Relocations: [] diff --git a/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp b/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp --- a/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp +++ b/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp @@ -174,7 +174,11 @@ SectionRelocMap.clear(); for (const SectionRef &Section : Obj->sections()) { - section_iterator Sec2 = Section.getRelocatedSection(); + Expected ErrOrSec = Section.getRelocatedSection(); + if (!ErrOrSec) + error(ErrOrSec.takeError()); + + section_iterator Sec2 = *ErrOrSec; if (Sec2 != Obj->section_end()) SectionRelocMap[*Sec2].push_back(Section); } diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -993,8 +993,17 @@ static std::map> getRelocsMap(object::ObjectFile const &Obj) { std::map> Ret; + uint64_t I = (uint64_t)-1; for (SectionRef Sec : Obj.sections()) { - section_iterator Relocated = Sec.getRelocatedSection(); + ++I; + Expected RelocatedOrErr = Sec.getRelocatedSection(); + if (!RelocatedOrErr) + reportError(Obj.getFileName(), + "section (" + Twine(I) + + "): failed to get a relocated section: " + + toString(RelocatedOrErr.takeError())); + + section_iterator Relocated = *RelocatedOrErr; if (Relocated == Obj.section_end() || !checkSectionFilter(*Relocated).Keep) continue; std::vector &V = Ret[*Relocated]; @@ -1606,11 +1615,17 @@ // sections. Usually, there is an only one relocation section for // each relocated section. MapVector> SecToRelSec; - for (const SectionRef &Section : ToolSectionFilter(*Obj)) { + uint64_t Ndx; + for (const SectionRef &Section : ToolSectionFilter(*Obj, &Ndx)) { if (Section.relocation_begin() == Section.relocation_end()) continue; - const SectionRef TargetSec = *Section.getRelocatedSection(); - SecToRelSec[TargetSec].push_back(Section); + Expected SecOrErr = Section.getRelocatedSection(); + if (!SecOrErr) + reportError(Obj->getFileName(), + "section (" + Twine(Ndx) + + "): unable to get a relocation target: " + + toString(SecOrErr.takeError())); + SecToRelSec[**SecOrErr].push_back(Section); } for (std::pair> &P : SecToRelSec) { diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -4894,8 +4894,16 @@ if (SectionType != ELF::SHT_RELA && SectionType != ELF::SHT_REL) continue; - SectionRef Contents = *Sec.getRelocatedSection(); - const Elf_Shdr *ContentsSec = Obj->getSection(Contents.getRawDataRefImpl()); + Expected RelSecOrErr = Sec.getRelocatedSection(); + if (!RelSecOrErr) + reportError(createStringError(object_error::parse_failed, + "%s: failed to get a relocated section: %s", + SectionName.data(), + toString(RelSecOrErr.takeError()).c_str()), + Obj->getFileName()); + + const Elf_Shdr *ContentsSec = + Obj->getSection((*RelSecOrErr)->getRawDataRefImpl()); Expected ContentsSectionNameOrErr = EF->getSectionName(ContentsSec); if (!ContentsSectionNameOrErr) {