Index: test/tools/llvm-readobj/all.test =================================================================== --- test/tools/llvm-readobj/all.test +++ test/tools/llvm-readobj/all.test @@ -14,6 +14,7 @@ # ALL: Version symbols { # ALL: SHT_GNU_verdef { # ALL: SHT_GNU_verneed { +# ALL: Addrsig [ # ALL: Notes [ # ALL: StackSizes [ Index: test/tools/llvm-readobj/elf-addrsig.test =================================================================== --- /dev/null +++ test/tools/llvm-readobj/elf-addrsig.test @@ -0,0 +1,84 @@ +## Show that llvm-readobj can dump SHT_LLVM_ADDRSIG sections. + +# RUN: yaml2obj --docnum=1 %s -o %t1.o +# RUN: llvm-readobj --addrsig %t1.o | FileCheck -DFILE=%t1.o %s --check-prefix LLVM +# RUN: not llvm-readelf --addrsig %t1.o 2>&1 | FileCheck -DFILE=%t1.o %s --check-prefix GNU + +# LLVM: Addrsig [ +# LLVM-NEXT: Sym: foo (1) +# LLVM-NEXT: Sym: bar (2) +# LLVM-NEXT: ] + +# GNU: error: '[[FILE]]': --addrsig: not implemented + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .llvm_addrsig + Type: SHT_LLVM_ADDRSIG + Symbols: + - Name: foo + - Name: bar +Symbols: + - Name: foo + - Name: bar + +## Check that llvm-readobj dumps SHT_LLVM_ADDRSIG section when --all, +## is specified but llvm-readelf doesn't. +## TODO: Refine the llvm-readelf check when GNU-style dumping be implemented. + +# RUN: llvm-readobj --all %t1.o | FileCheck %s --check-prefix LLVM +# RUN: llvm-readelf --all %t1.o 2>&1 | FileCheck %s --implicit-check-not=warning --implicit-check-not=error + +## Check we report a warning when SHT_LLVM_ADDRSIG is broken (e.g. contains a malformed uleb128). + +# RUN: yaml2obj --docnum=2 %s -o %t2.o +# RUN: llvm-readobj --addrsig %t2.o 2>&1 | FileCheck %s -DFILE=%t2.o --check-prefix=MALFORMED + +# MALFORMED: warning: '[[FILE]]': malformed uleb128, extends past end + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .llvm_addrsig + Type: SHT_LLVM_ADDRSIG + Content: "FF" + +## Check we report a warning when SHT_LLVM_ADDRSIG references a symbol that can't be +## dumped (e.g. the index value is larger than the number of symbols in .symtab). + +# RUN: yaml2obj --docnum=3 %s -o %t3.o +# RUN: llvm-readobj --addrsig %t3.o 2>&1 | FileCheck %s -DFILE=%t3.o --check-prefix=INVALID-INDEX + +# INVALID-INDEX: Addrsig [ +# INVALID-INDEX-NEXT: Sym: foo (1) +# INVALID-INDEX-EMPTY: +# INVALID-INDEX-NEXT: warning: '[[FILE]]': unable to get symbol from section [index 2]: invalid symbol index (255) +# INVALID-INDEX-NEXT: Sym: (255) +# INVALID-INDEX-NEXT: Sym: bar (2) +# INVALID-INDEX-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .llvm_addrsig + Type: SHT_LLVM_ADDRSIG + Symbols: + - Index: 1 + - Index: 255 + - Index: 2 +Symbols: + - Name: foo + - Name: bar Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -302,7 +302,7 @@ void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, StringRef &SectionName, unsigned &SectionIndex) const; - std::string getStaticSymbolName(uint32_t Index) const; + Expected getStaticSymbolName(uint32_t Index) const; std::string getDynamicString(uint64_t Value) const; StringRef getSymbolVersionByIndex(StringRef StrTab, uint32_t VersionSymbolIndex, @@ -751,17 +751,22 @@ } template -std::string ELFDumper::getStaticSymbolName(uint32_t Index) const { +Expected +ELFDumper::getStaticSymbolName(uint32_t Index) const { const ELFFile *Obj = ObjF->getELFFile(); - StringRef StrTable = unwrapOrError( - ObjF->getFileName(), Obj->getStringTableForSymtab(*DotSymtabSec)); - Elf_Sym_Range Syms = - unwrapOrError(ObjF->getFileName(), Obj->symbols(DotSymtabSec)); - if (Index >= Syms.size()) - reportError(createError("Invalid symbol index"), ObjF->getFileName()); - const Elf_Sym *Sym = &Syms[Index]; - return maybeDemangle( - unwrapOrError(ObjF->getFileName(), Sym->getName(StrTable))); + Expected SymOrErr = + Obj->getSymbol(DotSymtabSec, Index); + if (!SymOrErr) + return SymOrErr.takeError(); + + Expected StrTabOrErr = Obj->getStringTableForSymtab(*DotSymtabSec); + if (!StrTabOrErr) + return StrTabOrErr.takeError(); + + Expected NameOrErr = (*SymOrErr)->getName(*StrTabOrErr); + if (!NameOrErr) + return NameOrErr.takeError(); + return maybeDemangle(*NameOrErr); } template @@ -4071,7 +4076,7 @@ template void GNUStyle::printAddrsig(const ELFFile *Obj) { - OS << "GNUStyle::printAddrsig not implemented\n"; + reportError(createError("--addrsig: not implemented"), this->FileName); } static StringRef getGenericNoteTypeName(const uint32_t NT) { @@ -5708,14 +5713,35 @@ this->dumper()->getDotCGProfileSec())); for (const Elf_CGProfile &CGPE : CGProfile) { DictScope D(W, "CGProfileEntry"); - W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from), - CGPE.cgp_from); - W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to), - CGPE.cgp_to); + W.printNumber( + "From", + unwrapOrError(this->FileName, + this->dumper()->getStaticSymbolName(CGPE.cgp_from)), + CGPE.cgp_from); + W.printNumber( + "To", + unwrapOrError(this->FileName, + this->dumper()->getStaticSymbolName(CGPE.cgp_to)), + CGPE.cgp_to); W.printNumber("Weight", CGPE.cgp_weight); } } +static Expected> toULEB128Array(ArrayRef Data) { + std::vector Ret; + const uint8_t *Cur = Data.begin(); + const uint8_t *End = Data.end(); + while (Cur != End) { + unsigned Size; + const char *Err; + Ret.push_back(decodeULEB128(Cur, &Size, End, &Err)); + if (Err) + return createError(Err); + Cur += Size; + } + return Ret; +} + template void LLVMStyle::printAddrsig(const ELFFile *Obj) { ListScope L(W, "Addrsig"); @@ -5724,18 +5750,20 @@ ArrayRef Contents = unwrapOrError( this->FileName, Obj->getSectionContents(this->dumper()->getDotAddrsigSec())); - const uint8_t *Cur = Contents.begin(); - const uint8_t *End = Contents.end(); - while (Cur != End) { - unsigned Size; - const char *Err; - uint64_t SymIndex = decodeULEB128(Cur, &Size, End, &Err); - if (Err) - reportError(createError(Err), this->FileName); + Expected> V = toULEB128Array(Contents); + if (!V) { + reportWarning(V.takeError(), this->FileName); + return; + } - W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex), - SymIndex); - Cur += Size; + for (uint64_t Sym : *V) { + Expected NameOrErr = this->dumper()->getStaticSymbolName(Sym); + if (NameOrErr) { + W.printNumber("Sym", *NameOrErr, Sym); + continue; + } + reportWarning(NameOrErr.takeError(), this->FileName); + W.printNumber("Sym", "", Sym); } } Index: tools/llvm-readobj/llvm-readobj.cpp =================================================================== --- tools/llvm-readobj/llvm-readobj.cpp +++ tools/llvm-readobj/llvm-readobj.cpp @@ -710,8 +710,10 @@ opts::UnwindInfo = true; opts::SectionGroups = true; opts::HashHistogram = true; - if (opts::Output == opts::LLVM) + if (opts::Output == opts::LLVM) { + opts::Addrsig = true; opts::PrintStackSizes = true; + } } if (opts::Headers) {