diff --git a/llvm/test/tools/llvm-readobj/elf-symbol-shndx.test b/llvm/test/tools/llvm-readobj/elf-symbol-shndx.test --- a/llvm/test/tools/llvm-readobj/elf-symbol-shndx.test +++ b/llvm/test/tools/llvm-readobj/elf-symbol-shndx.test @@ -3,37 +3,41 @@ # section), reserved values and processor/os-specific index values, for both GNU # and LLVM styles. -# Use --dyn-symbols because yaml2obj does not currently support large section indexes -# and also does not allow hand-crafting of static symbol tables. # RUN: yaml2obj --docnum=1 %s > %t1 -# RUN: llvm-readobj --symbols --dyn-symbols %t1 | FileCheck %s --check-prefix=LLVM -# RUN: llvm-readelf --symbols --dyn-symbols %t1 | FileCheck %s --check-prefix=GNU1 +# RUN: llvm-readobj --symbols %t1 | FileCheck %s --check-prefix=LLVM1 +# RUN: llvm-readelf --symbols %t1 | FileCheck %s --check-prefix=GNU1 # llvm-readobj doesn't accept shndx values that are not valid section indexes # for LLVM style, so only test GNU output in this case. # RUN: yaml2obj --docnum=2 %s > %t2 # RUN: llvm-readelf --symbols %t2 | FileCheck %s --check-prefix=GNU2 -# LLVM: Name: undef -# LLVM: Section: Undefined (0x0) -# LLVM: Name: normal -# LLVM: Section: .text (0x1) -# LLVM: Name: common -# LLVM: Section: Common (0xFFF2) -# LLVM: Name: absolute -# LLVM: Section: Absolute (0xFFF1) -# LLVM: Name: proc -# LLVM: Section: Processor Specific (0xFF01) -# LLVM: Name: os -# LLVM: Section: Operating System Specific (0xFF21) -# LLVM: Name: reserved -# LLVM: Section: Reserved (0xFFFE) +# LLVM1: Name: undef +# LLVM1: Section: +# LLVM1-SAME: Undefined (0x0) +# LLVM1: Name: normal +# LLVM1: Section: +# LLVM1-SAME: .text (0x1) +# LLVM1: Name: common +# LLVM1: Section: +# LLVM1-SAME: Common (0xFFF2) +# LLVM1: Name: absolute +# LLVM1: Section: +# LLVM1-SAME: Absolute (0xFFF1) +# LLVM1: Name: proc +# LLVM1: Section: +# LLVM1-SAME: Processor Specific (0xFF01) +# LLVM1: Name: os +# LLVM1: Section: +# LLVM1-SAME: Operating System Specific (0xFF21) +# LLVM1: Name: reserved +# LLVM1: Section: +# LLVM1-SAME: Reserved (0xFFFE) +# LLVM1: Name: xindex +# LLVM1: Section: +# LLVM1: .text (0x1) -# GNU1: Symbol table '.dynsym' contains 2 entries: -# GNU1-NEXT: Num: {{.*}} Ndx Name -# GNU1-NEXT: 0: {{.*}} UND -# GNU1-NEXT: 1: {{.*}} 1 xindex -# GNU1: Symbol table '.symtab' contains 8 entries: +# GNU1: Symbol table '.symtab' contains 9 entries: # GNU1-NEXT: Num: {{.*}} Ndx Name # GNU1-NEXT: 0: {{.*}} UND # GNU1-NEXT: 1: {{.*}} UND undef @@ -43,6 +47,7 @@ # GNU1-NEXT: 5: {{.*}} PRC[0xff01] proc # GNU1-NEXT: 6: {{.*}} OS[0xff21] os # GNU1-NEXT: 7: {{.*}} RSV[0xfffe] reserved +# GNU1-NEXT: 8: {{.*}} 1 xindex # GNU2: Symbol table '.symtab' contains 2 entries: # GNU2-NEXT: Num: {{.*}} Ndx Name @@ -58,21 +63,10 @@ Sections: - Name: .text Type: SHT_PROGBITS - - Name: .dynstr - Type: SHT_STRTAB - #\0xindex\0 - Content: "0078696e64657800" - - Name: .dynsym - Type: SHT_DYNSYM - Link: .dynstr - EntSize: 16 - # Null symbol - # Symbol with st_name = 1, st_shndx = SHN_XINDEX - Content: "000000000000000000000000000000000100000000000000000000000000ffff" - Name: .symtab_shndx Type: SHT_SYMTAB_SHNDX - Link: .dynsym - Entries: [ 0, 1 ] + Link: .symtab + Entries: [ 0, 0, 0, 0, 0, 0, 0, 0, 1 ] Symbols: - Name: undef Binding: STB_GLOBAL @@ -94,6 +88,9 @@ - Name: reserved Index: 0xfffe Binding: STB_GLOBAL + - Name: xindex + Index: SHN_XINDEX + Binding: STB_GLOBAL --- !ELF FileHeader: 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 @@ -299,9 +299,10 @@ Elf_Relr_Range dyn_relrs() const; std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic) const; - void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, - StringRef &SectionName, - unsigned &SectionIndex) const; + Expected getSymbolSectionIndex(const Elf_Sym *Symbol, + const Elf_Sym *FirstSym) const; + Expected getSymbolSectionName(const Elf_Sym *Symbol, + unsigned SectionIndex) const; Expected getStaticSymbolName(uint32_t Index) const; std::string getDynamicString(uint64_t Value) const; StringRef getSymbolVersionByIndex(StringRef StrTab, @@ -821,12 +822,12 @@ unwrapOrError(ObjF->getFileName(), Symbol->getName(StrTable))); if (SymbolName.empty() && Symbol->getType() == ELF::STT_SECTION) { - unsigned SectionIndex; - StringRef SectionName; Elf_Sym_Range Syms = unwrapOrError( ObjF->getFileName(), ObjF->getELFFile()->symbols(DotSymtabSec)); - getSectionNameIndex(Symbol, Syms.begin(), SectionName, SectionIndex); - return SectionName; + unsigned SectionIndex = unwrapOrError( + ObjF->getFileName(), getSymbolSectionIndex(Symbol, Syms.begin())); + return unwrapOrError(ObjF->getFileName(), + getSymbolSectionName(Symbol, SectionIndex)); } if (!IsDynamic) @@ -842,33 +843,43 @@ } template -void ELFDumper::getSectionNameIndex(const Elf_Sym *Symbol, - const Elf_Sym *FirstSym, - StringRef &SectionName, - unsigned &SectionIndex) const { - SectionIndex = Symbol->st_shndx; +Expected +ELFDumper::getSymbolSectionIndex(const Elf_Sym *Symbol, + const Elf_Sym *FirstSym) const { + return Symbol->st_shndx == SHN_XINDEX + ? object::getExtendedSymbolTableIndex(Symbol, FirstSym, + ShndxTable) + : Symbol->st_shndx; +} + +// If the Symbol has a reserved st_shndx other than SHN_XINDEX, return a +// descriptive interpretation of the st_shndx value. Otherwise, return the name +// of the section with index SectionIndex. This function assumes that if the +// Symbol has st_shndx == SHN_XINDEX the SectionIndex will be the value derived +// from the SHT_SYMTAB_SHNDX section. +template +Expected +ELFDumper::getSymbolSectionName(const Elf_Sym *Symbol, + unsigned SectionIndex) const { if (Symbol->isUndefined()) - SectionName = "Undefined"; - else if (Symbol->isProcessorSpecific()) - SectionName = "Processor Specific"; - else if (Symbol->isOSSpecific()) - SectionName = "Operating System Specific"; - else if (Symbol->isAbsolute()) - SectionName = "Absolute"; - else if (Symbol->isCommon()) - SectionName = "Common"; - else if (Symbol->isReserved() && SectionIndex != SHN_XINDEX) - SectionName = "Reserved"; - else { - if (SectionIndex == SHN_XINDEX) - SectionIndex = unwrapOrError(ObjF->getFileName(), - object::getExtendedSymbolTableIndex( - Symbol, FirstSym, ShndxTable)); - const ELFFile *Obj = ObjF->getELFFile(); - const typename ELFT::Shdr *Sec = - unwrapOrError(ObjF->getFileName(), Obj->getSection(SectionIndex)); - SectionName = unwrapOrError(ObjF->getFileName(), Obj->getSectionName(Sec)); - } + return "Undefined"; + if (Symbol->isProcessorSpecific()) + return "Processor Specific"; + if (Symbol->isOSSpecific()) + return "Operating System Specific"; + if (Symbol->isAbsolute()) + return "Absolute"; + if (Symbol->isCommon()) + return "Common"; + if (Symbol->isReserved() && Symbol->st_shndx != SHN_XINDEX) + return "Reserved"; + + const ELFFile *Obj = ObjF->getELFFile(); + Expected SecOrErr = + Obj->getSection(SectionIndex); + if (!SecOrErr) + return SecOrErr.takeError(); + return Obj->getSectionName(*SecOrErr); } template @@ -5443,9 +5454,10 @@ template void LLVMStyle::printSymbolSection(const Elf_Sym *Symbol, const Elf_Sym *First) { - unsigned SectionIndex = 0; - StringRef SectionName; - this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex); + unsigned SectionIndex = unwrapOrError( + this->FileName, this->dumper()->getSymbolSectionIndex(Symbol, First)); + StringRef SectionName = unwrapOrError( + this->FileName, this->dumper()->getSymbolSectionName(Symbol, SectionIndex)); W.printHex("Section", SectionName, SectionIndex); }