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:
parent
9a72870122
commit
d72d16f444
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {}
|
||||||
|
|
||||||
|
|
|
@ -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*
|
||||||
|
|
|
@ -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| |
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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 }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue