From a79c4fecfd2c8106176a61d5e1d297d952f53471 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 29 Jun 2017 18:29:05 +0000 Subject: [PATCH] llvm-nm: Add support for symbol demangling (-C/--demangle) Differential Revision: https://reviews.llvm.org/D34668 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306718 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CommandGuide/llvm-nm.rst | 3 --- test/tools/llvm-nm/X86/demangle.ll | 37 +++++++++++++++++++++++++++ tools/llvm-nm/CMakeLists.txt | 1 + tools/llvm-nm/llvm-nm.cpp | 41 +++++++++++++++++++++++++----- 4 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 test/tools/llvm-nm/X86/demangle.ll diff --git a/docs/CommandGuide/llvm-nm.rst b/docs/CommandGuide/llvm-nm.rst index 319e6e6aecf..da7edea4743 100644 --- a/docs/CommandGuide/llvm-nm.rst +++ b/docs/CommandGuide/llvm-nm.rst @@ -134,9 +134,6 @@ OPTIONS 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. diff --git a/test/tools/llvm-nm/X86/demangle.ll b/test/tools/llvm-nm/X86/demangle.ll new file mode 100644 index 00000000000..283e604046a --- /dev/null +++ b/test/tools/llvm-nm/X86/demangle.ll @@ -0,0 +1,37 @@ +; RUN: llc -filetype=obj -mtriple=x86_64-pc-linux -o %t.o %s +; RUN: llvm-nm %t.o | FileCheck --check-prefix="MANGLED" %s +; RUN: llvm-nm -C %t.o | FileCheck --check-prefix="DEMANGLED" %s +; RUN: llvm-nm --demangle %t.o | FileCheck --check-prefix="DEMANGLED" %s + +; RUN: llc -filetype=obj -mtriple=x86_64-apple-darwin9 -o %t.macho %s +; RUN: llvm-nm %t.macho | FileCheck --check-prefix="MACHO-MANGLED" %s +; RUN: llvm-nm -C %t.macho | FileCheck --check-prefix="DEMANGLED" %s + +; RUN: llc -filetype=obj -mtriple=x86_64-pc-win32 -o %t.coff %s +; RUN: llvm-nm %t.coff | FileCheck --check-prefix="COFF-MANGLED" %s +; RUN: llvm-nm -C %t.coff | FileCheck --check-prefix="COFF-DEMANGLED" %s + +define i32 @_Z3fooi(i32) #0 { +entry: + ret i32 1 +} + +define float @_Z3barf(float) #0 { +entry: + ret float 0.000000e+00 +} + +; MANGLED: 0000000000000010 T _Z3barf +; MANGLED: 0000000000000000 T _Z3fooi + +; MACHO-MANGLED: 0000000000000010 T __Z3barf +; MACHO-MANGLED: 0000000000000000 T __Z3fooi + +; COFF-MANGLED: 00000010 T _Z3barf +; COFF-MANGLED: 00000000 T _Z3fooi + +; DEMANGLED: 0000000000000010 T bar(float) +; DEMANGLED: 0000000000000000 T foo(int) + +; COFF-DEMANGLED: 00000010 T bar(float) +; COFF-DEMANGLED: 00000000 T foo(int) diff --git a/tools/llvm-nm/CMakeLists.txt b/tools/llvm-nm/CMakeLists.txt index 10019562565..08bcd5f3089 100644 --- a/tools/llvm-nm/CMakeLists.txt +++ b/tools/llvm-nm/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS AllTargetsDescs AllTargetsInfos Core + Demangle Object Support ) diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 513e1b87558..29836da1fcd 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/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::opt NoSort("no-sort", cl::desc("Show symbols in order encountered")); 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 @@ static void darwinPrintStab(MachOObjectFile *MachO, SymbolListT::iterator I) { outs() << Str; } +static Optional demangle(StringRef Name, bool StripUnderscore) { + if (StripUnderscore && Name.size() > 0 && Name[0] == '_') + Name = Name.substr(1); + + if (!Name.startswith("_Z")) + return None; + + int Status; + std::unique_ptr Undecorated( + itaniumDemangle(Name.str().c_str(), nullptr, nullptr, &Status)); + if (Status != 0) + return None; + + return std::string(Undecorated.get()); +} + static bool symbolIsDefined(const NMSymbol &Sym) { return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v'; } @@ -724,6 +745,12 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end(); I != E; ++I) { uint32_t SymFlags; + std::string Name = I->Name.str(); + MachOObjectFile *MachO = dyn_cast(&Obj); + if (Demangle) { + if (Optional Opt = demangle(I->Name, MachO)) + Name = *Opt; + } if (I->Sym.getRawDataRefImpl().p) SymFlags = I->Sym.getFlags(); else @@ -745,9 +772,10 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, outs() << CurrentFilename << ": "; } } - if ((JustSymbolName || (UndefinedOnly && isa(Obj) && - OutputFormat != darwin)) && OutputFormat != posix) { - outs() << I->Name << "\n"; + if ((JustSymbolName || + (UndefinedOnly && MachO && OutputFormat != darwin)) && + OutputFormat != posix) { + outs() << Name << "\n"; continue; } @@ -767,7 +795,6 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, } } - MachOObjectFile *MachO = dyn_cast(&Obj); // Otherwise, print the symbol address and size. if (symbolIsDefined(*I)) { if (Obj.isIR()) @@ -789,7 +816,7 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, 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 +831,7 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, 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 +845,7 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, } 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 -- 2.50.1