Index: llvm/trunk/include/llvm/Object/ELFObjectFile.h =================================================================== --- llvm/trunk/include/llvm/Object/ELFObjectFile.h +++ llvm/trunk/include/llvm/Object/ELFObjectFile.h @@ -41,6 +41,8 @@ namespace llvm { namespace object { +extern const llvm::EnumEntry ElfSymbolTypes[8]; + class elf_symbol_iterator; class ELFObjectFileBase : public ObjectFile { @@ -148,6 +150,17 @@ uint8_t getELFType() const { return getObject()->getSymbolELFType(getRawDataRefImpl()); } + + void getELFTypeName(StringRef &TN) const { + uint8_t et = getELFType(); + TN = ""; + for (auto &ee : ElfSymbolTypes) { + if (ee.Value == et) { + TN = ee.AltName; + break; + } + } + } }; class elf_symbol_iterator : public symbol_iterator { @@ -244,6 +257,7 @@ Expected getSymbolSection(const Elf_Sym *Symb, const Elf_Shdr *SymTab) const; Expected getSymbolSection(DataRefImpl Symb) const override; + int getSymbolSectionIndex(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, @@ -656,6 +670,13 @@ } template +int +ELFObjectFile::getSymbolSectionIndex(DataRefImpl Symb) const { + const Elf_Sym *Sym = getSymbol(Symb); + return Sym->st_shndx; +} + +template void ELFObjectFile::moveSectionNext(DataRefImpl &Sec) const { const Elf_Shdr *ESec = getSection(Sec); Sec = toDRI(++ESec); Index: llvm/trunk/include/llvm/Object/ObjectFile.h =================================================================== --- llvm/trunk/include/llvm/Object/ObjectFile.h +++ llvm/trunk/include/llvm/Object/ObjectFile.h @@ -174,6 +174,9 @@ /// end_sections() if it is undefined or is an absolute symbol. Expected getSection() const; + // Get the section index of the section of this symbol + int getSectionIndex() const; + const ObjectFile *getObject() const; }; @@ -228,6 +231,7 @@ virtual Expected getSymbolType(DataRefImpl Symb) const = 0; virtual Expected getSymbolSection(DataRefImpl Symb) const = 0; + virtual int getSymbolSectionIndex(DataRefImpl Symb) const { return -1; } // Same as above for SectionRef. friend class SectionRef; @@ -375,6 +379,10 @@ return getObject()->getCommonSymbolSize(getRawDataRefImpl()); } +inline int SymbolRef::getSectionIndex() const { + return getObject()->getSymbolSectionIndex(getRawDataRefImpl()); +} + inline Expected SymbolRef::getSection() const { return getObject()->getSymbolSection(getRawDataRefImpl()); } Index: llvm/trunk/lib/Object/ELFObjectFile.cpp =================================================================== --- llvm/trunk/lib/Object/ELFObjectFile.cpp +++ llvm/trunk/lib/Object/ELFObjectFile.cpp @@ -35,6 +35,16 @@ using namespace llvm; using namespace object; +const EnumEntry llvm::object::ElfSymbolTypes[8] = { + {"None", "NOTYPE", ELF::STT_NOTYPE}, + {"Object", "OBJECT", ELF::STT_OBJECT}, + {"Function", "FUNC", ELF::STT_FUNC}, + {"Section", "SECTION", ELF::STT_SECTION}, + {"File", "FILE", ELF::STT_FILE}, + {"Common", "COMMON", ELF::STT_COMMON}, + {"TLS", "TLS", ELF::STT_TLS}, + {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}}; + ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) : ObjectFile(Type, Source) {} Index: llvm/trunk/test/tools/llvm-nm/X86/sysv-i386.test =================================================================== --- llvm/trunk/test/tools/llvm-nm/X86/sysv-i386.test +++ llvm/trunk/test/tools/llvm-nm/X86/sysv-i386.test @@ -1,6 +1,6 @@ RUN: llvm-nm -f sysv %p/Inputs/hello.obj.elf-i386 | FileCheck %s --strict-whitespace CHECK: Name Value Class Type Size Line Section -CHECK: .L.str |00000000| r | |0000000f| | -CHECK: main |00000000| T | |00000015| | -CHECK: puts | | U | | | | +CHECK: .L.str |00000000| r | OBJECT|0000000f| |.rodata.str1.1 +CHECK: main |00000000| T | FUNC|00000015| |.text +CHECK: puts | | U | NOTYPE| | |*UND* Index: llvm/trunk/test/tools/llvm-nm/X86/sysv-x86_64.test =================================================================== --- llvm/trunk/test/tools/llvm-nm/X86/sysv-x86_64.test +++ llvm/trunk/test/tools/llvm-nm/X86/sysv-x86_64.test @@ -2,8 +2,8 @@ RUN: llvm-nm -f sysv %p/Inputs/hello.obj.macho-x86_64 2>&1 | FileCheck %s --check-prefix=MACHO --strict-whitespace ELF: Name Value Class Type Size Line Section -ELF: main |0000000000000000| T | |0000000000000015| | -ELF: puts | | U | | | | +ELF: main |0000000000000000| T | FUNC|0000000000000015| |.text +ELF: puts | | U | NOTYPE| | |*UND* MACHO: Name Value Class Type Size Line Section MACHO: EH_frame0 |0000000000000068| s | |0000000000000000| | Index: llvm/trunk/tools/llvm-nm/llvm-nm.cpp =================================================================== --- llvm/trunk/tools/llvm-nm/llvm-nm.cpp +++ llvm/trunk/tools/llvm-nm/llvm-nm.cpp @@ -262,6 +262,8 @@ uint64_t Size; char TypeChar; StringRef Name; + StringRef SectionName; + StringRef TypeName; BasicSymbolRef Sym; // The Sym field above points to the native symbol in the object file, // for Mach-O when we are creating symbols from the dyld info the above @@ -882,8 +884,13 @@ std::string PaddedName(Name); while (PaddedName.length() < 20) PaddedName += " "; + std::string TNPad = ""; + int TNL = I->TypeName.size(); + while ((TNPad.length() + TNL) < 18) + TNPad += " "; outs() << PaddedName << "|" << SymbolAddrStr << "| " << I->TypeChar - << " | |" << SymbolSizeStr << "| |\n"; + << " |" << TNPad << I->TypeName << "|" << SymbolSizeStr + << "| |" << I->SectionName << "\n"; } } @@ -1078,7 +1085,37 @@ : elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT; } -static char getNMTypeChar(SymbolicFile &Obj, basic_symbol_iterator I) { +// For ELF object files, Set TypeName to the symbol typename, to be printed +// in the 'Type' column of the SYSV format output. +static void getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I, + StringRef &TypeName) { + if (isa(&Obj)) { + elf_symbol_iterator SymI(I); + SymI->getELFTypeName(TypeName); + } +} + +// Return Posix nm class type tag (single letter), but also set SecName and +// section and name, to be used in format=sysv output. +static char getNMClassTagAndSectionName(SymbolicFile &Obj, + basic_symbol_iterator I, + StringRef &SecName) { + if (isa(&Obj)) { + elf_symbol_iterator SymI(I); + + Expected SecIOrErr = SymI->getSection(); + if (!SecIOrErr) { + consumeError(SecIOrErr.takeError()); + return '?'; + } + int SI = SymI->getSectionIndex(); + if (SI == 0) { + SecName = "*UND*"; + } else { + elf_section_iterator secT = *SecIOrErr; + secT->getName(SecName); + } + } uint32_t Symflags = I->getFlags(); if ((Symflags & object::SymbolRef::SF_Weak) && !isa(Obj)) { char Ret = isObject(Obj, I) ? 'v' : 'w'; @@ -1088,8 +1125,10 @@ if (Symflags & object::SymbolRef::SF_Undefined) return 'U'; - if (Symflags & object::SymbolRef::SF_Common) + if (Symflags & object::SymbolRef::SF_Common) { + SecName = "*COM*"; return 'C'; + } char Ret = '?'; if (Symflags & object::SymbolRef::SF_Absolute) @@ -1201,7 +1240,8 @@ } S.Address = *AddressOrErr; } - S.TypeChar = getNMTypeChar(Obj, Sym); + getNMTypeName(Obj, Sym, S.TypeName); + S.TypeChar = getNMClassTagAndSectionName(Obj, Sym, S.SectionName); std::error_code EC = Sym.printName(OS); if (EC && MachO) OS << "bad string index"; Index: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp +++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp @@ -1104,16 +1104,6 @@ {"HIDDEN", "HIDDEN", ELF::STV_HIDDEN}, {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}}; -static const EnumEntry ElfSymbolTypes[] = { - {"None", "NOTYPE", ELF::STT_NOTYPE}, - {"Object", "OBJECT", ELF::STT_OBJECT}, - {"Function", "FUNC", ELF::STT_FUNC}, - {"Section", "SECTION", ELF::STT_SECTION}, - {"File", "FILE", ELF::STT_FILE}, - {"Common", "COMMON", ELF::STT_COMMON}, - {"TLS", "TLS", ELF::STT_TLS}, - {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}}; - static const EnumEntry AMDGPUSymbolTypes[] = { { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL } };