Index: docs/CommandGuide/llvm-nm.rst =================================================================== --- docs/CommandGuide/llvm-nm.rst +++ docs/CommandGuide/llvm-nm.rst @@ -134,9 +134,6 @@ BUGS ---- - * :program:`llvm-nm` cannot demangle C++ mangled names, like GNU :program:`nm` - can. - * :program:`llvm-nm` does not support the full set of arguments that GNU :program:`nm` does. Index: test/tools/llvm-nm/X86/demangle.s =================================================================== --- /dev/null +++ test/tools/llvm-nm/X86/demangle.s @@ -0,0 +1,36 @@ +// RUN: llvm-mc %s -filetype=obj -triple=x86_64-pc-linux -o %t.o +// RUN: llvm-nm %t.o | FileCheck --check-prefix="MANGLED" %s +// RUN: llvm-nm -C %t.o | FileCheck --check-prefix="DEMANGLED" %s + + .text + .file "test.cc" + .globl _Z3fooi # -- Begin function _Z3fooi + .p2align 4, 0x90 + .type _Z3fooi,@function +_Z3fooi: # @_Z3fooi + .cfi_startproc +# BB#0: # %entry + movl $1, %eax + retq +.Lfunc_end0: + .size _Z3fooi, .Lfunc_end0-_Z3fooi + .cfi_endproc + # -- End function + .globl _Z3barf # -- Begin function _Z3barf + .p2align 4, 0x90 + .type _Z3barf,@function +_Z3barf: # @_Z3barf + .cfi_startproc +# BB#0: # %entry + xorps %xmm0, %xmm0 + retq +.Lfunc_end1: + .size _Z3barf, .Lfunc_end1-_Z3barf + .cfi_endproc + # -- End function + +// MANGLED: 0000000000000010 T _Z3barf +// MANGLED: 0000000000000000 T _Z3fooi + +// DEMANGLED: 0000000000000010 T bar(float) +// DEMANGLED: 0000000000000000 T foo(int) Index: tools/llvm-nm/CMakeLists.txt =================================================================== --- tools/llvm-nm/CMakeLists.txt +++ tools/llvm-nm/CMakeLists.txt @@ -3,6 +3,7 @@ AllTargetsDescs AllTargetsInfos Core + Demangle Object Support ) Index: tools/llvm-nm/llvm-nm.cpp =================================================================== --- tools/llvm-nm/llvm-nm.cpp +++ tools/llvm-nm/llvm-nm.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" @@ -124,6 +125,10 @@ cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort), cl::Grouping); +cl::opt Demangle("demangle", cl::desc("Demangle C++ symbol names")); +cl::alias DemangleC("C", cl::desc("Alias for --demangle"), cl::aliasopt(Demangle), + cl::Grouping); + cl::opt ReverseSort("reverse-sort", cl::desc("Sort in reverse order")); cl::alias ReverseSortr("r", cl::desc("Alias for --reverse-sort"), cl::aliasopt(ReverseSort), cl::Grouping); @@ -659,6 +664,22 @@ outs() << Str; } +static Optional demangle(StringRef Name) { + if ((Name.size() > 2 && Name.startswith("_Z")) || + (Name.size() > 3 && Name.startswith("___Z"))) { + int Status; + char *Undecorated = + itaniumDemangle(Name.str().c_str(), nullptr, nullptr, &Status); + if (Status == 0) { + std::string Result(Undecorated); + free(Undecorated); + return Result; + } + } + + return None; +} + static bool symbolIsDefined(const NMSymbol &Sym) { return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v'; } @@ -724,6 +745,11 @@ for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end(); I != E; ++I) { uint32_t SymFlags; + std::string Name = I->Name.str(); + if (Demangle) { + if (Optional Opt = demangle(I->Name)) + Name = *Opt; + } if (I->Sym.getRawDataRefImpl().p) SymFlags = I->Sym.getFlags(); else @@ -747,7 +773,7 @@ } if ((JustSymbolName || (UndefinedOnly && isa(Obj) && OutputFormat != darwin)) && OutputFormat != posix) { - outs() << I->Name << "\n"; + outs() << Name << "\n"; continue; } @@ -789,7 +815,7 @@ darwinPrintSymbol(Obj, I, SymbolAddrStr, printBlanks, printDashes, printFormat); } else if (OutputFormat == posix) { - outs() << I->Name << " " << I->TypeChar << " "; + outs() << Name << " " << I->TypeChar << " "; if (MachO) outs() << SymbolAddrStr << " " << "0" /* SymbolSizeStr */ << "\n"; else @@ -804,7 +830,7 @@ outs() << I->TypeChar; if (I->TypeChar == '-' && MachO) darwinPrintStab(MachO, I); - outs() << " " << I->Name; + outs() << " " << Name; if (I->TypeChar == 'I' && MachO) { outs() << " (indirect for "; if (I->Sym.getRawDataRefImpl().p) { @@ -818,7 +844,7 @@ } outs() << "\n"; } else if (OutputFormat == sysv) { - std::string PaddedName(I->Name); + std::string PaddedName(Name); while (PaddedName.length() < 20) PaddedName += " "; outs() << PaddedName << "|" << SymbolAddrStr << "| " << I->TypeChar