52 changes: 28 additions & 24 deletions llvm/tools/llvm-readobj/ELFDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ELFTypes.h"
Expand Down Expand Up @@ -271,7 +272,7 @@ class ELFDumper : public ObjDumper {
void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
StringRef &SectionName,
unsigned &SectionIndex) const;
StringRef getStaticSymbolName(uint32_t Index) const;
std::string getStaticSymbolName(uint32_t Index) const;

void printSymbolsHelper(bool IsDynamic) const;
const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
Expand Down Expand Up @@ -795,34 +796,37 @@ StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab,
return StringRef(StrTab.data() + name_offset);
}

static std::string maybeDemangle(StringRef Name) {
return opts::Demangle ? demangle(Name) : Name.str();
}

template <typename ELFT>
StringRef ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {
std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec));
if (Index >= Syms.size())
reportError("Invalid symbol index");
const Elf_Sym *Sym = &Syms[Index];
return unwrapOrError(Sym->getName(StrTable));
return maybeDemangle(unwrapOrError(Sym->getName(StrTable)));
}

template <typename ELFT>
std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
StringRef StrTable,
bool IsDynamic) const {
StringRef SymbolName = unwrapOrError(Symbol->getName(StrTable));
std::string SymbolName =
maybeDemangle(unwrapOrError(Symbol->getName(StrTable)));
if (!IsDynamic)
return SymbolName;

std::string FullSymbolName(SymbolName);

bool IsDefault;
StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault);
if (!Version.empty()) {
FullSymbolName += (IsDefault ? "@@" : "@");
FullSymbolName += Version;
SymbolName += (IsDefault ? "@@" : "@");
SymbolName += Version;
}
return FullSymbolName;
return SymbolName;
}

template <typename ELFT>
Expand Down Expand Up @@ -2599,7 +2603,7 @@ struct GroupMember {

struct GroupSection {
StringRef Name;
StringRef Signature;
std::string Signature;
uint64_t ShName;
uint64_t Index;
uint32_t Link;
Expand Down Expand Up @@ -2630,13 +2634,13 @@ std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) {

StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
StringRef Signature = StrTable.data() + Sym->st_name;
Ret.push_back({Name,
Signature,
Sec.sh_name,
Ret.push_back({Name,
maybeDemangle(Signature),
Sec.sh_name,
I - 1,
Sec.sh_link,
Sec.sh_info,
Data[0],
Data[0],
{}});

std::vector<GroupMember> &GM = Ret.back().Members;
Expand Down Expand Up @@ -2693,7 +2697,7 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
const Elf_Rela &R, bool IsRela) {
std::string Offset, Info, Addend, Value;
SmallString<32> RelocName;
StringRef TargetName;
std::string TargetName;
const Elf_Sym *Sym = nullptr;
unsigned Width = ELFT::Is64Bits ? 16 : 8;
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
Expand All @@ -2709,7 +2713,7 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
TargetName = unwrapOrError(Obj->getSectionName(Sec));
} else if (Sym) {
StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab));
TargetName = unwrapOrError(Sym->getName(StrTable));
TargetName = maybeDemangle(unwrapOrError(Sym->getName(StrTable)));
}

if (Sym && IsRela) {
Expand Down Expand Up @@ -3375,7 +3379,7 @@ template <class ELFT>
void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela R,
bool IsRela) {
SmallString<32> RelocName;
StringRef SymbolName;
std::string SymbolName;
unsigned Width = ELFT::Is64Bits ? 16 : 8;
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
// First two fields are bit width dependent. The rest of them are after are
Expand All @@ -3385,8 +3389,8 @@ void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela R,
uint32_t SymIndex = R.getSymbol(Obj->isMips64EL());
const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex;
Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName);
SymbolName =
unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable()));
SymbolName = maybeDemangle(
unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())));
std::string Addend, Info, Offset, Value;
Offset = to_string(format_hex_no_prefix(R.r_offset, Width));
Info = to_string(format_hex_no_prefix(R.r_info, Width));
Expand Down Expand Up @@ -4249,15 +4253,15 @@ void LLVMStyle<ELFT>::printRelocation(const ELFO *Obj, Elf_Rela Rel,
const Elf_Shdr *SymTab) {
SmallString<32> RelocName;
Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
StringRef TargetName;
std::string TargetName;
const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTab));
if (Sym && Sym->getType() == ELF::STT_SECTION) {
const Elf_Shdr *Sec = unwrapOrError(
Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable()));
TargetName = unwrapOrError(Obj->getSectionName(Sec));
} else if (Sym) {
StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab));
TargetName = unwrapOrError(Sym->getName(StrTable));
TargetName = maybeDemangle(unwrapOrError(Sym->getName(StrTable)));
}

if (opts::ExpandRelocs) {
Expand Down Expand Up @@ -4459,11 +4463,11 @@ template <class ELFT>
void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) {
SmallString<32> RelocName;
Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
StringRef SymbolName;
std::string SymbolName;
uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex;
SymbolName =
unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable()));
SymbolName = maybeDemangle(
unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())));
if (opts::ExpandRelocs) {
DictScope Group(W, "Relocation");
W.printHex("Offset", Rel.r_offset);
Expand Down
6 changes: 6 additions & 0 deletions llvm/tools/llvm-readobj/llvm-readobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ namespace opts {
cl::alias HexDumpShort("x", cl::desc("Alias for --hex-dump"),
cl::aliasopt(HexDump));

// -demangle, -C
cl::opt<bool> Demangle("demangle",
cl::desc("Demangle symbol names in output"));
cl::alias DemangleShort("C", cl::desc("Alias for --demangle"),
cl::aliasopt(Demangle), cl::NotHidden);

// -hash-table
cl::opt<bool> HashTable("hash-table",
cl::desc("Display ELF hash table"));
Expand Down
1 change: 1 addition & 0 deletions llvm/tools/llvm-readobj/llvm-readobj.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace opts {
extern llvm::cl::opt<bool> ExpandRelocs;
extern llvm::cl::opt<bool> RawRelr;
extern llvm::cl::opt<bool> CodeViewSubsectionBytes;
extern llvm::cl::opt<bool> Demangle;
enum OutputStyleTy { LLVM, GNU };
extern llvm::cl::opt<OutputStyleTy> Output;
} // namespace opts
Expand Down