diff --git a/llvm/include/llvm/Demangle/Demangle.h b/llvm/include/llvm/Demangle/Demangle.h --- a/llvm/include/llvm/Demangle/Demangle.h +++ b/llvm/include/llvm/Demangle/Demangle.h @@ -67,6 +67,8 @@ /// demangling occurred. std::string demangle(const std::string &MangledName); +bool nonMicrosoftDemangle(const char *MangledName, std::string &Result); + /// "Partial" demangler. This supports demangling a string into an AST /// (typically an intermediate stage in itaniumDemangle) and querying certain /// properties or partially printing the demangled name. diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -652,18 +652,9 @@ std::string LLVMSymbolizer::DemangleName(const std::string &Name, const SymbolizableModule *DbiModuleDescriptor) { - // We can spoil names of symbols with C linkage, so use an heuristic - // approach to check if the name should be demangled. - if (Name.substr(0, 2) == "_Z") { - int status = 0; - char *DemangledName = - itaniumDemangle(Name.c_str(), nullptr, nullptr, &status); - if (status != 0) - return Name; - std::string Result = DemangledName; - free(DemangledName); + std::string Result; + if (nonMicrosoftDemangle(Name.c_str(), Result)) return Result; - } if (!Name.empty() && Name.front() == '?') { // Only do MSVC C++ demangling on symbols starting with '?'. @@ -674,7 +665,7 @@ MSDF_NoMemberType | MSDF_NoReturnType)); if (status != 0) return Name; - std::string Result = DemangledName; + Result = DemangledName; free(DemangledName); return Result; } diff --git a/llvm/lib/Demangle/Demangle.cpp b/llvm/lib/Demangle/Demangle.cpp --- a/llvm/lib/Demangle/Demangle.cpp +++ b/llvm/lib/Demangle/Demangle.cpp @@ -12,32 +12,46 @@ #include "llvm/Demangle/Demangle.h" #include +#include -static bool isItaniumEncoding(const std::string &MangledName) { - size_t Pos = MangledName.find_first_not_of('_'); - // A valid Itanium encoding requires 1-4 leading underscores, followed by 'Z'. - return Pos > 0 && Pos <= 4 && MangledName[Pos] == 'Z'; +static bool isItaniumEncoding(const char *S) { + // Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'. + return std::strncmp(S, "_Z", 2) == 0 || std::strncmp(S, "___Z", 4) == 0; } -static bool isRustEncoding(const std::string &MangledName) { - return MangledName.size() >= 2 && MangledName[0] == '_' && - MangledName[1] == 'R'; -} +static bool isRustEncoding(const char *S) { return S[0] == '_' && S[1] == 'R'; } std::string llvm::demangle(const std::string &MangledName) { - char *Demangled; + std::string Result; + const char *S = MangledName.c_str(); + + if (llvm::nonMicrosoftDemangle(S, Result)) + return Result; + + if (S[0] == '_' && llvm::nonMicrosoftDemangle(S + 1, Result)) + return Result; + + if (char *Demangled = + microsoftDemangle(S, nullptr, nullptr, nullptr, nullptr)) { + Result = Demangled; + std::free(Demangled); + return Result; + } + + return MangledName; +} + +bool llvm::nonMicrosoftDemangle(const char *MangledName, std::string &Result) { + char *Demangled = nullptr; if (isItaniumEncoding(MangledName)) - Demangled = itaniumDemangle(MangledName.c_str(), nullptr, nullptr, nullptr); + Demangled = itaniumDemangle(MangledName, nullptr, nullptr, nullptr); else if (isRustEncoding(MangledName)) - Demangled = rustDemangle(MangledName.c_str(), nullptr, nullptr, nullptr); - else - Demangled = microsoftDemangle(MangledName.c_str(), nullptr, nullptr, - nullptr, nullptr); + Demangled = rustDemangle(MangledName, nullptr, nullptr, nullptr); if (!Demangled) - return MangledName; + return false; - std::string Ret = Demangled; + Result = Demangled; std::free(Demangled); - return Ret; + return true; } diff --git a/llvm/test/DebugInfo/symbolize-demangling.s b/llvm/test/DebugInfo/symbolize-demangling.s --- a/llvm/test/DebugInfo/symbolize-demangling.s +++ b/llvm/test/DebugInfo/symbolize-demangling.s @@ -2,23 +2,29 @@ # RUN: llvm-mc --filetype=obj --triple=x86_64-pc-linux %s -o %t.o -g -# RUN: llvm-symbolizer --obj=%t.o 0 1 2 | FileCheck %s +# RUN: llvm-symbolizer --obj=%t.o 0 1 2 3 | FileCheck %s # CHECK: f() -# CHECK-NEXT: symbolize-demangling.s:20 +# CHECK-NEXT: symbolize-demangling.s:24 # CHECK-EMPTY: # CHECK-NEXT: {{^g$}} -# CHECK-NEXT: symbolize-demangling.s:22 +# CHECK-NEXT: symbolize-demangling.s:26 # CHECK-EMPTY: # CHECK-NEXT: {{^baz$}} -# CHECK-NEXT: symbolize-demangling.s:24 +# CHECK-NEXT: symbolize-demangling.s:28 +# CHECK-EMPTY: +# CHECK-NEXT: {{^x::y$}} +# CHECK-NEXT: symbolize-demangling.s:30 .type _Z1fv,@function .type g,@function .type baz,@function +.type _RNvC1x1y,@function _Z1fv: nop g: nop baz: nop +_RNvC1x1y: + nop diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp --- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -65,34 +65,27 @@ } static std::string demangle(const std::string &Mangled) { - int Status; - std::string Prefix; - const char *DecoratedStr = Mangled.c_str(); if (StripUnderscore) if (DecoratedStr[0] == '_') ++DecoratedStr; - size_t DecoratedLength = strlen(DecoratedStr); + std::string Result; + if (nonMicrosoftDemangle(DecoratedStr, Result)) + return Result; + + std::string Prefix; char *Undecorated = nullptr; - if (Types || - ((DecoratedLength >= 2 && strncmp(DecoratedStr, "_Z", 2) == 0) || - (DecoratedLength >= 4 && strncmp(DecoratedStr, "___Z", 4) == 0))) - Undecorated = itaniumDemangle(DecoratedStr, nullptr, nullptr, &Status); + if (Types) + Undecorated = itaniumDemangle(DecoratedStr, nullptr, nullptr, nullptr); - if (!Undecorated && - (DecoratedLength > 6 && strncmp(DecoratedStr, "__imp_", 6) == 0)) { + if (!Undecorated && strncmp(DecoratedStr, "__imp_", 6) == 0) { Prefix = "import thunk for "; - Undecorated = itaniumDemangle(DecoratedStr + 6, nullptr, nullptr, &Status); - } - - if (!Undecorated && - (DecoratedLength >= 2 && strncmp(DecoratedStr, "_R", 2) == 0)) { - Undecorated = rustDemangle(DecoratedStr, nullptr, nullptr, &Status); + Undecorated = itaniumDemangle(DecoratedStr + 6, nullptr, nullptr, nullptr); } - std::string Result(Undecorated ? Prefix + Undecorated : Mangled); + Result = Undecorated ? Prefix + Undecorated : Mangled; free(Undecorated); return Result; } diff --git a/llvm/unittests/Demangle/DemangleTest.cpp b/llvm/unittests/Demangle/DemangleTest.cpp --- a/llvm/unittests/Demangle/DemangleTest.cpp +++ b/llvm/unittests/Demangle/DemangleTest.cpp @@ -22,6 +22,7 @@ EXPECT_EQ(demangle("?foo@@YAXH@Z"), "void __cdecl foo(int)"); EXPECT_EQ(demangle("foo"), "foo"); EXPECT_EQ(demangle("_RNvC3foo3bar"), "foo::bar"); + EXPECT_EQ(demangle("__RNvC3foo3bar"), "foo::bar"); // Regression test for demangling of optional template-args for vendor // extended type qualifier (https://bugs.llvm.org/show_bug.cgi?id=48009)