Improve "llvm-nm -f sysv" output for Elf files

Specifically, compute and Print Type and Section columns.

Differential Revision: https://reviews.llvm.org/D58263

llvm-svn: 354833
This commit is contained in:
Sunil Srivastava 2019-02-26 00:19:39 +00:00
parent 9a72870122
commit d72d16f444
7 changed files with 88 additions and 19 deletions

View File

@ -41,6 +41,8 @@
namespace llvm { namespace llvm {
namespace object { namespace object {
extern const llvm::EnumEntry<unsigned> ElfSymbolTypes[8];
class elf_symbol_iterator; class elf_symbol_iterator;
class ELFObjectFileBase : public ObjectFile { class ELFObjectFileBase : public ObjectFile {
@ -148,6 +150,17 @@ public:
uint8_t getELFType() const { uint8_t getELFType() const {
return getObject()->getSymbolELFType(getRawDataRefImpl()); 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 { class elf_symbol_iterator : public symbol_iterator {
@ -244,6 +257,7 @@ protected:
Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb, Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb,
const Elf_Shdr *SymTab) const; const Elf_Shdr *SymTab) const;
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
int getSymbolSectionIndex(DataRefImpl Symb) const override;
void moveSectionNext(DataRefImpl &Sec) const override; void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec, std::error_code getSectionName(DataRefImpl Sec,
@ -655,6 +669,13 @@ ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const {
return getSymbolSection(Sym, SymTab); return getSymbolSection(Sym, SymTab);
} }
template <class ELFT>
int
ELFObjectFile<ELFT>::getSymbolSectionIndex(DataRefImpl Symb) const {
const Elf_Sym *Sym = getSymbol(Symb);
return Sym->st_shndx;
}
template <class ELFT> template <class ELFT>
void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const {
const Elf_Shdr *ESec = getSection(Sec); const Elf_Shdr *ESec = getSection(Sec);

View File

@ -174,6 +174,9 @@ public:
/// end_sections() if it is undefined or is an absolute symbol. /// end_sections() if it is undefined or is an absolute symbol.
Expected<section_iterator> getSection() const; Expected<section_iterator> getSection() const;
// Get the section index of the section of this symbol
int getSectionIndex() const;
const ObjectFile *getObject() const; const ObjectFile *getObject() const;
}; };
@ -228,6 +231,7 @@ protected:
virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0; virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0;
virtual Expected<section_iterator> virtual Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const = 0; getSymbolSection(DataRefImpl Symb) const = 0;
virtual int getSymbolSectionIndex(DataRefImpl Symb) const { return -1; }
// Same as above for SectionRef. // Same as above for SectionRef.
friend class SectionRef; friend class SectionRef;
@ -375,6 +379,10 @@ inline uint64_t SymbolRef::getCommonSize() const {
return getObject()->getCommonSymbolSize(getRawDataRefImpl()); return getObject()->getCommonSymbolSize(getRawDataRefImpl());
} }
inline int SymbolRef::getSectionIndex() const {
return getObject()->getSymbolSectionIndex(getRawDataRefImpl());
}
inline Expected<section_iterator> SymbolRef::getSection() const { inline Expected<section_iterator> SymbolRef::getSection() const {
return getObject()->getSymbolSection(getRawDataRefImpl()); return getObject()->getSymbolSection(getRawDataRefImpl());
} }

View File

@ -35,6 +35,16 @@
using namespace llvm; using namespace llvm;
using namespace object; using namespace object;
const EnumEntry<unsigned> 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) ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
: ObjectFile(Type, Source) {} : ObjectFile(Type, Source) {}

View File

@ -1,6 +1,6 @@
RUN: llvm-nm -f sysv %p/Inputs/hello.obj.elf-i386 | FileCheck %s --strict-whitespace RUN: llvm-nm -f sysv %p/Inputs/hello.obj.elf-i386 | FileCheck %s --strict-whitespace
CHECK: Name Value Class Type Size Line Section CHECK: Name Value Class Type Size Line Section
CHECK: .L.str |00000000| r | |0000000f| | CHECK: .L.str |00000000| r | OBJECT|0000000f| |.rodata.str1.1
CHECK: main |00000000| T | |00000015| | CHECK: main |00000000| T | FUNC|00000015| |.text
CHECK: puts | | U | | | | CHECK: puts | | U | NOTYPE| | |*UND*

View File

@ -2,8 +2,8 @@ RUN: llvm-nm -f sysv %p/Inputs/hello.obj.elf-x86_64 | FileCheck %s --check-prefi
RUN: llvm-nm -f sysv %p/Inputs/hello.obj.macho-x86_64 2>&1 | FileCheck %s --check-prefix=MACHO --strict-whitespace 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: Name Value Class Type Size Line Section
ELF: main |0000000000000000| T | |0000000000000015| | ELF: main |0000000000000000| T | FUNC|0000000000000015| |.text
ELF: puts | | U | | | | ELF: puts | | U | NOTYPE| | |*UND*
MACHO: Name Value Class Type Size Line Section MACHO: Name Value Class Type Size Line Section
MACHO: EH_frame0 |0000000000000068| s | |0000000000000000| | MACHO: EH_frame0 |0000000000000068| s | |0000000000000000| |

View File

@ -262,6 +262,8 @@ struct NMSymbol {
uint64_t Size; uint64_t Size;
char TypeChar; char TypeChar;
StringRef Name; StringRef Name;
StringRef SectionName;
StringRef TypeName;
BasicSymbolRef Sym; BasicSymbolRef Sym;
// The Sym field above points to the native symbol in the object file, // 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 // for Mach-O when we are creating symbols from the dyld info the above
@ -882,8 +884,13 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
std::string PaddedName(Name); std::string PaddedName(Name);
while (PaddedName.length() < 20) while (PaddedName.length() < 20)
PaddedName += " "; PaddedName += " ";
std::string TNPad = "";
int TNL = I->TypeName.size();
while ((TNPad.length() + TNL) < 18)
TNPad += " ";
outs() << PaddedName << "|" << SymbolAddrStr << "| " << I->TypeChar outs() << PaddedName << "|" << SymbolAddrStr << "| " << I->TypeChar
<< " | |" << SymbolSizeStr << "| |\n"; << " |" << TNPad << I->TypeName << "|" << SymbolSizeStr
<< "| |" << I->SectionName << "\n";
} }
} }
@ -1078,7 +1085,37 @@ static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) {
: elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT; : 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<ELFObjectFileBase>(&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<ELFObjectFileBase>(&Obj)) {
elf_symbol_iterator SymI(I);
Expected<elf_section_iterator> 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(); uint32_t Symflags = I->getFlags();
if ((Symflags & object::SymbolRef::SF_Weak) && !isa<MachOObjectFile>(Obj)) { if ((Symflags & object::SymbolRef::SF_Weak) && !isa<MachOObjectFile>(Obj)) {
char Ret = isObject(Obj, I) ? 'v' : 'w'; char Ret = isObject(Obj, I) ? 'v' : 'w';
@ -1088,8 +1125,10 @@ static char getNMTypeChar(SymbolicFile &Obj, basic_symbol_iterator I) {
if (Symflags & object::SymbolRef::SF_Undefined) if (Symflags & object::SymbolRef::SF_Undefined)
return 'U'; return 'U';
if (Symflags & object::SymbolRef::SF_Common) if (Symflags & object::SymbolRef::SF_Common) {
SecName = "*COM*";
return 'C'; return 'C';
}
char Ret = '?'; char Ret = '?';
if (Symflags & object::SymbolRef::SF_Absolute) if (Symflags & object::SymbolRef::SF_Absolute)
@ -1201,7 +1240,8 @@ dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
} }
S.Address = *AddressOrErr; 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); std::error_code EC = Sym.printName(OS);
if (EC && MachO) if (EC && MachO)
OS << "bad string index"; OS << "bad string index";

View File

@ -1104,16 +1104,6 @@ static const EnumEntry<unsigned> ElfSymbolVisibilities[] = {
{"HIDDEN", "HIDDEN", ELF::STV_HIDDEN}, {"HIDDEN", "HIDDEN", ELF::STV_HIDDEN},
{"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}}; {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}};
static const EnumEntry<unsigned> 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<unsigned> AMDGPUSymbolTypes[] = { static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = {
{ "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL } { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL }
}; };