Index: llvm/trunk/include/llvm/Object/ELFTypes.h =================================================================== --- llvm/trunk/include/llvm/Object/ELFTypes.h +++ llvm/trunk/include/llvm/Object/ELFTypes.h @@ -248,7 +248,11 @@ Expected Elf_Sym_Impl::getName(StringRef StrTab) const { uint32_t Offset = this->st_name; if (Offset >= StrTab.size()) - return errorCodeToError(object_error::parse_failed); + return createStringError(object_error::parse_failed, + "st_name (0x%" PRIx32 + ") is past the end of the string table" + " of size 0x%zx", + Offset, StrTab.size()); return StringRef(StrTab.data() + Offset); } Index: llvm/trunk/test/Object/invalid.test =================================================================== --- llvm/trunk/test/Object/invalid.test +++ llvm/trunk/test/Object/invalid.test @@ -390,7 +390,7 @@ # RUN: yaml2obj %s --docnum=19 -o %t19 # RUN: not llvm-readobj --symbols %t19 2>&1 | FileCheck -DFILE=%t19 --check-prefix=INVALID-SYM-NAME %s -# INVALID-SYM-NAME: error: '[[FILE]]': Invalid data was encountered while parsing the file +# INVALID-SYM-NAME: error: '[[FILE]]': st_name (0x1) is past the end of the string table of size 0x1 --- !ELF FileHeader: Index: llvm/trunk/test/tools/llvm-readobj/elf-broken-dynamic-reloc-name.test =================================================================== --- llvm/trunk/test/tools/llvm-readobj/elf-broken-dynamic-reloc-name.test +++ llvm/trunk/test/tools/llvm-readobj/elf-broken-dynamic-reloc-name.test @@ -0,0 +1,51 @@ +## Check that llvm-readobj/llvm-readelf reports an error when dumping relocations if a dynamic +## symbol name offset is broken (goes past the end of the dynamic symbol string table). + +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj --dyn-relocations %t 2>&1 | FileCheck %s -DFILE=%t --check-prefix=LLVM +# RUN: llvm-readelf --dyn-relocations %t 2>&1 | FileCheck %s -DFILE=%t --check-prefix=GNU + +# LLVM: Dynamic Relocations { +# LLVM-EMPTY: +# LLVM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: st_name (0x1234) is past the end of the string table of size 0x1 +# LLVM-NEXT: 0x0 R_X86_64_NONE 0x0 +# LLVM-NEXT: } + +# GNU: 'RELA' relocation section at offset {{.+}} contains 24 bytes: +# GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +# GNU-EMPTY: +# GNU-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: st_name (0x1234) is past the end of the string table of size 0x1 +# GNU-NEXT: 0000000000000000 0000000100000000 R_X86_64_NONE 0000000000000000 + 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela.dyn + Type: SHT_RELA + Link: .dynsym + Relocations: + - Offset: 0x0 + Symbol: 1 ## Index of a dynamic symbol with a broken st_name. + Type: R_X86_64_NONE + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_RELA + Value: 0x0000000000000000 + - Tag: DT_RELASZ + Value: 0x0000000000000018 + - Tag: DT_RELAENT + Value: 0x0000000000000018 + - Tag: DT_NULL + Value: 0x0000000000000000 +DynamicSymbols: + - NameIndex: 0x1234 +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .rela.dyn + - Section: .dynamic Index: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp +++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp @@ -3525,14 +3525,40 @@ } } +namespace { +template struct RelSymbol { + const typename ELFT::Sym *Sym; + std::string Name; +}; + +template +RelSymbol getSymbolForReloc(const ELFFile *Obj, StringRef FileName, + const ELFDumper *Dumper, + const typename ELFT::Rela &Reloc) { + uint32_t SymIndex = Reloc.getSymbol(Obj->isMips64EL()); + const typename ELFT::Sym *Sym = Dumper->dynamic_symbols().begin() + SymIndex; + Expected ErrOrName = Sym->getName(Dumper->getDynamicStringTable()); + + std::string Name; + if (ErrOrName) { + Name = maybeDemangle(*ErrOrName); + } else { + reportWarning( + createError("unable to get name of the dynamic symbol with index " + + Twine(SymIndex) + ": " + toString(ErrOrName.takeError())), + FileName); + Name = ""; + } + + return {Sym, std::move(Name)}; +} +} // namespace + template void GNUStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela) { - uint32_t SymIndex = R.getSymbol(Obj->isMips64EL()); - const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; - std::string SymbolName = maybeDemangle(unwrapOrError( - this->FileName, Sym->getName(this->dumper()->getDynamicStringTable()))); - printRelocation(Obj, Sym, SymbolName, R, IsRela); + RelSymbol S = getSymbolForReloc(Obj, this->FileName, this->dumper(), R); + printRelocation(Obj, S.Sym, S.Name, R, IsRela); } template void GNUStyle::printDynamic(const ELFO *Obj) { @@ -5404,11 +5430,9 @@ void LLVMStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { SmallString<32> RelocName; Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); - std::string SymbolName; - uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); - const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; - SymbolName = maybeDemangle(unwrapOrError( - this->FileName, Sym->getName(this->dumper()->getDynamicStringTable()))); + std::string SymbolName = + getSymbolForReloc(Obj, this->FileName, this->dumper(), Rel).Name; + if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset);