Index: include/lldb/Core/Mangled.h =================================================================== --- include/lldb/Core/Mangled.h +++ include/lldb/Core/Mangled.h @@ -41,6 +41,13 @@ ePreferDemangledWithoutArguments }; + enum ManglingScheme + { + eManglingSchemeNone = 0, + eManglingSchemeMSVC, + eManglingSchemeItanium + }; + //---------------------------------------------------------------------- /// Default constructor. /// Index: source/Core/CxaDemangle.inc =================================================================== --- source/Core/CxaDemangle.inc +++ source/Core/CxaDemangle.inc @@ -1,15 +1,19 @@ //---------------------------------------------------------------------- // Inlined copy of: // http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp -// revision 199944. +// revision 235830. // // Changes include: -// - remove the "__cxxabiv1" namespace -// - stripped GCC attributes() -// - removed extern "C" from the cxa_demangle function +// - Removed the "__cxxabiv1" namespace +// - Stripped GCC attributes() +// - Removed extern "C" from the cxa_demangle function // - Changed the scope of the unnamed namespace to include cxa_demangle // function. // - Added "#undef _LIBCPP_EXTERN_TEMPLATE" to avoid warning +// - Removed constexpr member initialization for MSVC +// - Implemented missing rebind, construct, destroy in malloc_alloc +// for MSVC +// - Changed argument to alignas() to a literal for MSVC //---------------------------------------------------------------------- #undef _LIBCPP_EXTERN_TEMPLATE // Avoid warning below @@ -52,7 +56,8 @@ template const char* parse_encoding(const char* first, const char* last, C& db); template - const char* parse_name(const char* first, const char* last, C& db); + const char* parse_name(const char* first, const char* last, C& db, + bool* ends_with_template_args = 0); template const char* parse_expression(const char* first, const char* last, C& db); template @@ -68,51 +73,51 @@ void print_stack(const C& db) { - printf("---------\n"); - printf("names:\n"); + fprintf(stderr, "---------\n"); + fprintf(stderr, "names:\n"); for (auto& s : db.names) - printf("{%s#%s}\n", s.first.c_str(), s.second.c_str()); + fprintf(stderr, "{%s#%s}\n", s.first.c_str(), s.second.c_str()); int i = -1; - printf("subs:\n"); + fprintf(stderr, "subs:\n"); for (auto& v : db.subs) { if (i >= 0) - printf("S%i_ = {", i); + fprintf(stderr, "S%i_ = {", i); else - printf("S_ = {"); + fprintf(stderr, "S_ = {"); for (auto& s : v) - printf("{%s#%s}", s.first.c_str(), s.second.c_str()); - printf("}\n"); + fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); + fprintf(stderr, "}\n"); ++i; } - printf("template_param:\n"); + fprintf(stderr, "template_param:\n"); for (auto& t : db.template_param) { - printf("--\n"); + fprintf(stderr, "--\n"); i = -1; for (auto& v : t) { if (i >= 0) - printf("T%i_ = {", i); + fprintf(stderr, "T%i_ = {", i); else - printf("T_ = {"); + fprintf(stderr, "T_ = {"); for (auto& s : v) - printf("{%s#%s}", s.first.c_str(), s.second.c_str()); - printf("}\n"); + fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); + fprintf(stderr, "}\n"); ++i; } } - printf("---------\n\n"); + fprintf(stderr, "---------\n\n"); } template void print_state(const char* msg, const char* first, const char* last, const C& db) { - printf("%s: ", msg); + fprintf(stderr, "%s: ", msg); for (; first != last; ++first) - printf("%c", *first); - printf("\n"); + fprintf(stderr, "%c", *first); + fprintf(stderr, "\n"); print_stack(db); } @@ -151,30 +156,34 @@ { static const size_t mangled_size = 8; static const size_t max_demangled_size = 24; - static constexpr const char* spec = "%af"; + static const char* spec; }; -constexpr const char* float_data::spec; +const char* float_data::spec = "%af"; template <> struct float_data { static const size_t mangled_size = 16; static const size_t max_demangled_size = 32; - static constexpr const char* spec = "%a"; + static const char* spec; }; -constexpr const char* float_data::spec; +const char* float_data::spec = "%a"; template <> struct float_data { +#if defined(__arm__) + static const size_t mangled_size = 16; +#else static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms +#endif static const size_t max_demangled_size = 40; - static constexpr const char* spec = "%LaL"; + static const char* spec; }; -constexpr const char* float_data::spec; +const char* float_data::spec = "%LaL"; template const char* @@ -204,7 +213,7 @@ } if (*t == 'E') { -#if __LITTLE_ENDIAN__ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ std::reverse(buf, e); #endif char num[float_data::max_demangled_size] = {0}; @@ -366,6 +375,7 @@ // ::= Di # char32_t // ::= Ds # char16_t // ::= Da # auto (in dependent new-expressions) +// ::= Dc # decltype(auto) // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) // ::= u # vendor extended type @@ -501,6 +511,10 @@ db.names.push_back("auto"); first += 2; break; + case 'c': + db.names.push_back("decltype(auto)"); + first += 2; + break; case 'n': db.names.push_back("std::nullptr_t"); first += 2; @@ -1579,10 +1593,9 @@ const char* t = first+1; if (t != last) { - bool externC = false; if (*t == 'Y') { - externC = true; + /* extern "C" */ if (++t == last) return first; } @@ -1676,7 +1689,7 @@ auto func = std::move(db.names.back()); db.names.pop_back(); auto class_type = std::move(db.names.back()); - if (func.second.front() == '(') + if (!func.second.empty() && func.second.front() == '(') { db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*"; db.names.back().second = ")" + std::move(func.second); @@ -2023,7 +2036,8 @@ db.names[k].first += " ("; db.names[k].second.insert(0, ")"); } - else if (db.names[k].second.front() == '(') + else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') { db.names[k].first += "("; db.names[k].second.insert(0, ")"); @@ -2050,7 +2064,8 @@ db.names[k].first += " ("; db.names[k].second.insert(0, ")"); } - else if (db.names[k].second.front() == '(') + else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') { db.names[k].first += "("; db.names[k].second.insert(0, ")"); @@ -2084,7 +2099,8 @@ db.names[k].first += " ("; db.names[k].second.insert(0, ")"); } - else if (db.names[k].second.front() == '(') + else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') { db.names[k].first += "("; db.names[k].second.insert(0, ")"); @@ -3902,7 +3918,8 @@ template const char* -parse_nested_name(const char* first, const char* last, C& db) +parse_nested_name(const char* first, const char* last, C& db, + bool* ends_with_template_args) { if (first != last && *first == 'N') { @@ -3910,15 +3927,15 @@ const char* t0 = parse_cv_qualifiers(first+1, last, cv); if (t0 == last) return first; - unsigned ref = 0; + db.ref = 0; if (*t0 == 'R') { - ref = 1; + db.ref = 1; ++t0; } else if (*t0 == 'O') { - ref = 2; + db.ref = 2; ++t0; } db.names.emplace_back(); @@ -3933,8 +3950,10 @@ return first; } bool pop_subs = false; + bool component_ends_with_template_args = false; while (*t0 != 'E') { + component_ends_with_template_args = false; const char* t1; switch (*t0) { @@ -4004,6 +4023,7 @@ db.names.back().first += name; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); t0 = t1; + component_ends_with_template_args = true; } else return first; @@ -4032,10 +4052,11 @@ } } first = t0 + 1; - db.ref = ref; db.cv = cv; if (pop_subs && !db.subs.empty()) db.subs.pop_back(); + if (ends_with_template_args) + *ends_with_template_args = component_ends_with_template_args; } return first; } @@ -4083,7 +4104,8 @@ template const char* -parse_local_name(const char* first, const char* last, C& db) +parse_local_name(const char* first, const char* last, C& db, + bool* ends_with_template_args) { if (first != last && *first == 'Z') { @@ -4105,7 +4127,8 @@ if (t1 != last && *t1 == '_') { t = t1 + 1; - t1 = parse_name(t, last, db); + t1 = parse_name(t, last, db, + ends_with_template_args); if (t1 != t) { if (db.names.size() < 2) @@ -4123,7 +4146,8 @@ break; default: { - const char* t1 = parse_name(t, last, db); + const char* t1 = parse_name(t, last, db, + ends_with_template_args); if (t1 != t) { // parse but ignore discriminator @@ -4155,7 +4179,8 @@ template const char* -parse_name(const char* first, const char* last, C& db) +parse_name(const char* first, const char* last, C& db, + bool* ends_with_template_args) { if (last - first >= 2) { @@ -4167,14 +4192,16 @@ { case 'N': { - const char* t1 = parse_nested_name(t0, last, db); + const char* t1 = parse_nested_name(t0, last, db, + ends_with_template_args); if (t1 != t0) first = t1; break; } case 'Z': { - const char* t1 = parse_local_name(t0, last, db); + const char* t1 = parse_local_name(t0, last, db, + ends_with_template_args); if (t1 != t0) first = t1; break; @@ -4199,6 +4226,8 @@ db.names.pop_back(); db.names.back().first += tmp; first = t1; + if (ends_with_template_args) + *ends_with_template_args = true; } } else // @@ -4219,6 +4248,8 @@ db.names.pop_back(); db.names.back().first += tmp; first = t1; + if (ends_with_template_args) + *ends_with_template_args = true; } } } @@ -4392,7 +4423,7 @@ { if (db.names.empty()) return first; - if (first[1] == 'v') + if (first[2] == 'v') { db.names.back().first.insert(0, "virtual thunk to "); first = t; @@ -4482,7 +4513,9 @@ break; default: { - const char* t = parse_name(first, last, db); + bool ends_with_template_args = false; + const char* t = parse_name(first, last, db, + &ends_with_template_args); unsigned cv = db.cv; unsigned ref = db.ref; if (t != first) @@ -4498,8 +4531,7 @@ const typename C::String& nm = db.names.back().first; if (nm.empty()) return first; - if (!db.parsed_ctor_dtor_cv && nm.back() == '>' && nm[nm.size()-2] != '-' - && nm[nm.size()-2] != '>') + if (!db.parsed_ctor_dtor_cv && ends_with_template_args) { t2 = parse_type(t, last, db); if (t2 == t) @@ -4694,12 +4726,12 @@ class arena { static const std::size_t alignment = 16; - alignas(alignment) char buf_[N]; + alignas(16) char buf_[N]; char* ptr_; std::size_t align_up(std::size_t n) noexcept - {return n + (alignment-1) & ~(alignment-1);} + {return (n + (alignment-1)) & ~(alignment-1);} bool pointer_in_buffer(char* p) noexcept @@ -4814,6 +4846,23 @@ { std::free(p); } + template + struct rebind + { + typedef malloc_alloc other; + }; + void construct(T *p) + { + ::new (p) T(); + } + void construct(T *p, const T& t) + { + ::new (p) T(t); + } + void destroy(T *p) + { + p->~T(); + } }; template @@ -4835,32 +4884,33 @@ const size_t bs = 4 * 1024; template using Alloc = short_alloc; template using Vector = std::vector>; -using String = std::basic_string, malloc_alloc>; +template struct string_pair { - String first; - String second; + StrT first; + StrT second; string_pair() = default; - string_pair(String f) : first(std::move(f)) {} - string_pair(String f, String s) + string_pair(StrT f) : first(std::move(f)) {} + string_pair(StrT f, StrT s) : first(std::move(f)), second(std::move(s)) {} template string_pair(const char (&s)[N]) : first(s, N-1) {} size_t size() const {return first.size() + second.size();} - String full() const {return first + second;} - String move_full() {return std::move(first) + std::move(second);} + StrT full() const {return first + second;} + StrT move_full() {return std::move(first) + std::move(second);} }; struct Db { - typedef ::String String; - typedef Vector sub_type; + typedef std::basic_string, + malloc_alloc> String; + typedef Vector> sub_type; typedef Vector template_param_type; - Vector names; - Vector subs; + sub_type names; + template_param_type subs; Vector template_param; unsigned cv; unsigned ref; Index: source/Core/Mangled.cpp =================================================================== --- source/Core/Mangled.cpp +++ source/Core/Mangled.cpp @@ -13,6 +13,11 @@ #if defined(_MSC_VER) #include "lldb/Host/windows/windows.h" #include +#define LLDB_USE_BUILTIN_DEMANGLER +#define noexcept +#define constexpr +#define snprintf _snprintf +#define alignas(X) __declspec(align(X)) #elif defined (__FreeBSD__) #define LLDB_USE_BUILTIN_DEMANGLER #else @@ -49,16 +54,21 @@ using namespace lldb_private; +static inline Mangled::ManglingScheme +cstring_mangling_scheme(const char *s) +{ + if (!s) + return Mangled::eManglingSchemeNone; + if (s[0] == '?') + return Mangled::eManglingSchemeMSVC; + if (s[0] == '_' && s[1] == 'Z') + return Mangled::eManglingSchemeItanium; +} + static inline bool -cstring_is_mangled (const char *s) +cstring_is_mangled(const char *s) { - if (s) -#if defined(_MSC_VER) - return (s[0] == '?'); -#else - return (s[0] == '_' && s[1] == 'Z'); -#endif - return false; + return cstring_mangling_scheme(s); } static const ConstString & @@ -269,45 +279,57 @@ m_mangled.GetCString()); // Don't bother running anything that isn't mangled - const char *mangled_cstr = m_mangled.GetCString(); - if (cstring_is_mangled(mangled_cstr)) + const char *mangled_name = m_mangled.GetCString(); + ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)}; + if (mangling_scheme && !m_mangled.GetMangledCounterpart(m_demangled)) { - if (!m_mangled.GetMangledCounterpart(m_demangled)) + // We didn't already mangle this name, demangle it and if all goes well + // add it to our map. + char *demangled_name = nullptr; + switch (mangling_scheme) { - // We didn't already mangle this name, demangle it and if all goes well - // add it to our map. -#ifdef LLDB_USE_BUILTIN_DEMANGLER - // Try to use the fast-path demangler first for the - // performance win, falling back to the full demangler only - // when necessary - char *demangled_name = FastDemangle (mangled_cstr, - m_mangled.GetLength()); - if (!demangled_name) - demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL); -#elif defined(_MSC_VER) - char *demangled_name = (char *)::malloc(1024); - ::ZeroMemory(demangled_name, 1024); - DWORD result = ::UnDecorateSymbolName(mangled_cstr, demangled_name, 1023, - UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected keywords - UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords - UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications - UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers - UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords - ); - if (result == 0) + case eManglingSchemeMSVC: { - free (demangled_name); - demangled_name = nullptr; +#if defined(_MSC_VER) + const size_t demangled_length = 2048; + demangled_name = static_cast(::malloc(demangled_length)); + ::ZeroMemory(demangled_name, demangled_length); + DWORD result = ::UnDecorateSymbolName(mangled_name, demangled_name, demangled_length, + UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected keywords + UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords + UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications + UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers + UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords + ); + if (result == 0) + { + free(demangled_name); + demangled_name = nullptr; + } +#endif + break; } + case eManglingSchemeItanium: + { +#ifdef LLDB_USE_BUILTIN_DEMANGLER + // Try to use the fast-path demangler first for the + // performance win, falling back to the full demangler only + // when necessary + demangled_name = FastDemangle(mangled_name, m_mangled.GetLength()); + if (!demangled_name) + demangled_name = __cxa_demangle(mangled_name, NULL, NULL, NULL); #else - char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL); + demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL); #endif - - if (demangled_name) - { - m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); - free (demangled_name); + break; } + case eManglingSchemeNone: + break; + } + if (demangled_name) + { + m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); + free(demangled_name); } } if (!m_demangled)