Loading demangle/DemangleTest.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,29 @@ TEST(DemangleTest, TemplateFunction) { // Template within templates. ASSERT_EQ("one::two<three<char, int>>", demangler.Parse("_ZN3one3twoIN5threeIciEEEE")); ASSERT_EQ("one::two<three<char, four<int>>>", demangler.Parse("_ZN3one3twoIN5threeIcN4fourIiEEEEEE")); ASSERT_EQ("one<char>", demangler.Parse("_Z3oneIcE")); ASSERT_EQ("one<void>", demangler.Parse("_Z3oneIvE")); ASSERT_EQ("one<void*>", demangler.Parse("_Z3oneIPvE")); ASSERT_EQ("one<void const>", demangler.Parse("_Z3oneIKvE")); ASSERT_EQ("one<char, int, bool>", demangler.Parse("_Z3oneIcibE")); ASSERT_EQ("one(two<three>)", demangler.Parse("_Z3one3twoIN5threeEE")); ASSERT_EQ("one<char, int, two::three>", demangler.Parse("_Z3oneIciN3two5threeEE")); // Template within templates. ASSERT_EQ("one(two<three<char, int>>)", demangler.Parse("_Z3one3twoIN5threeIciEEE")); ASSERT_EQ("one(two<three<char, four<int>>>)", demangler.Parse("_Z3one3twoIN5threeIcN4fourIiEEEEE")); } TEST(DemangleTest, TemplateFunctionWithReturnType) { Demangler demangler; ASSERT_EQ("char one<int>(char)", demangler.Parse("_Z3oneIiEcc")); ASSERT_EQ("void one<int>()", demangler.Parse("_Z3oneIiEvv")); ASSERT_EQ("char one<int>()", demangler.Parse("_Z3oneIiEcv")); ASSERT_EQ("char one<int>(void, void)", demangler.Parse("_Z3oneIiEcvv")); ASSERT_EQ("char one<int>()", demangler.Parse("_ZN3oneIiEEcv")); ASSERT_EQ("char one<int>(void, void)", demangler.Parse("_ZN3oneIiEEcvv")); } TEST(DemangleTest, TemplateArguments) { Loading Loading @@ -410,6 +433,28 @@ TEST(DemangleTest, ComplexSubstitution) { demangler.Parse("_ZN3one3two5three4fourINS_4fiveEED2EPS3_")); } TEST(DemangleTest, TemplateSubstitution) { Demangler demangler; ASSERT_EQ("void one<int, double>(int)", demangler.Parse("_ZN3oneIidEEvT_")); ASSERT_EQ("void one<int, double>(double)", demangler.Parse("_ZN3oneIidEEvT0_")); ASSERT_EQ("void one<int, double, char, void>(char)", demangler.Parse("_ZN3oneIidcvEEvT1_")); ASSERT_EQ("void one<int, double>(int)", demangler.Parse("_Z3oneIidEvT_")); ASSERT_EQ("void one<int, double>(double)", demangler.Parse("_Z3oneIidEvT0_")); ASSERT_EQ("void one<int, double, char, void>(char)", demangler.Parse("_Z3oneIidcvEvT1_")); ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(l)", demangler.Parse("_ZN3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEEvT10_")); ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(m)", demangler.Parse("_ZN3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEEvT11_")); ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(l)", demangler.Parse("_Z3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEvT10_")); ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(m)", demangler.Parse("_Z3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEvT11_")); } TEST(DemangleTest, StringTooLong) { Demangler demangler; Loading @@ -434,6 +479,13 @@ TEST(DemangleTest, BooleanLiterals) { ASSERT_EQ("one<true>", demangler.Parse("_ZN3oneILb1EEE")); ASSERT_EQ("one<false>", demangler.Parse("_ZN3oneILb0EEE")); ASSERT_EQ("one<false, true>", demangler.Parse("_ZN3oneILb0ELb1EEE")); ASSERT_EQ("one<true>", demangler.Parse("_Z3oneILb1EE")); ASSERT_EQ("one<false>", demangler.Parse("_Z3oneILb0EE")); ASSERT_EQ("one<false, true>", demangler.Parse("_Z3oneILb0ELb1EE")); ASSERT_EQ("one(two<three<four>, false, true>)", demangler.Parse("_ZN3oneE3twoI5threeI4fourELb0ELb1EE")); } TEST(DemangleTest, demangle) { Loading demangle/Demangler.cpp +110 −3 Original line number Diff line number Diff line Loading @@ -347,6 +347,33 @@ const char* Demangler::ParseS(const char* name) { return name + 1; } const char* Demangler::ParseT(const char* name) { if (template_saves_.empty()) { return nullptr; } if (*name == '_') { last_save_name_ = false; AppendCurrent(template_saves_[0]); return name + 1; } // Need to get the total number. char* end; unsigned long int index = strtoul(name, &end, 10) + 1; if (name == end || *end != '_') { return nullptr; } if (index >= template_saves_.size()) { return nullptr; } last_save_name_ = false; AppendCurrent(template_saves_[index]); return end + 1; } const char* Demangler::ParseFunctionName(const char* name) { if (*name == 'E') { if (parse_funcs_.empty()) { Loading @@ -371,9 +398,28 @@ const char* Demangler::ParseFunctionName(const char* name) { return name + 1; } if (*name == 'I') { state_stack_.push(cur_state_); cur_state_.Clear(); parse_funcs_.push_back(parse_func_); parse_func_ = &Demangler::ParseFunctionNameTemplate; return name + 1; } return ParseComplexString(name); } const char* Demangler::ParseFunctionNameTemplate(const char* name) { if (*name == 'E' && name[1] == 'E') { // Only consider this a template with saves if it is right before // the end of the name. template_found_ = true; template_saves_ = cur_state_.args; } return ParseTemplateArgumentsComplex(name); } const char* Demangler::ParseComplexArgument(const char* name) { if (*name == 'E') { if (parse_funcs_.empty()) { Loading Loading @@ -690,6 +736,7 @@ const char* Demangler::ParseTemplateArgumentsComplex(const char* name) { } parse_func_ = parse_funcs_.back(); parse_funcs_.pop_back(); FinalizeTemplate(); Save(cur_state_.str, false); return name + 1; Loading @@ -699,6 +746,7 @@ const char* Demangler::ParseTemplateArgumentsComplex(const char* name) { parse_func_ = &Demangler::ParseTemplateLiteral; return name + 1; } return ParseArguments(name); } Loading @@ -713,13 +761,33 @@ const char* Demangler::ParseTemplateArguments(const char* name) { AppendArgument(cur_state_.str); cur_state_.str.clear(); return name + 1; } else if (*name == 'L') { // Literal value for a template. parse_funcs_.push_back(parse_func_); parse_func_ = &Demangler::ParseTemplateLiteral; return name + 1; } return ParseArguments(name); } const char* Demangler::ParseFunctionTemplateArguments(const char* name) { if (*name == 'E') { parse_func_ = parse_funcs_.back(); parse_funcs_.pop_back(); function_name_ += '<' + GetArgumentsString() + '>'; template_found_ = true; template_saves_ = cur_state_.args; cur_state_.Clear(); return name + 1; } return ParseTemplateArgumentsComplex(name); } const char* Demangler::FindFunctionName(const char* name) { if (*name == 'N') { parse_funcs_.push_back(&Demangler::ParseArguments); parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel); parse_func_ = &Demangler::ParseFunctionName; return name + 1; } Loading @@ -732,11 +800,35 @@ const char* Demangler::FindFunctionName(const char* name) { name = AppendOperatorString(name); function_name_ = cur_state_.str; } parse_func_ = &Demangler::ParseArguments; cur_state_.Clear(); // Check for a template argument, which will still be part of the function // name. if (name != nullptr && *name == 'I') { parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel); parse_func_ = &Demangler::ParseFunctionTemplateArguments; return name + 1; } parse_func_ = &Demangler::ParseArgumentsAtTopLevel; return name; } const char* Demangler::ParseArgumentsAtTopLevel(const char* name) { // At the top level is the only place where T is allowed. if (*name == 'T') { name++; name = ParseT(name); if (name == nullptr) { return nullptr; } AppendArgument(cur_state_.str); cur_state_.str.clear(); return name; } return Demangler::ParseArguments(name); } std::string Demangler::Parse(const char* name, size_t max_length) { if (name[0] == '\0' || name[0] != '_' || name[1] == '\0' || name[1] != 'Z') { // Name is not mangled. Loading @@ -757,6 +849,21 @@ std::string Demangler::Parse(const char* name, size_t max_length) { return name; } std::string return_type; if (template_found_) { // Only a single argument with a template is not allowed. if (cur_state_.args.size() == 1) { return name; } // If there are at least two arguments, this template has a return type. if (cur_state_.args.size() > 1) { // The first argument will be the return value. return_type = cur_state_.args[0] + ' '; cur_state_.args.erase(cur_state_.args.begin()); } } std::string arg_str; if (cur_state_.args.size() == 1 && cur_state_.args[0] == "void") { // If the only argument is void, then don't print any args. Loading @@ -767,7 +874,7 @@ std::string Demangler::Parse(const char* name, size_t max_length) { arg_str = '(' + arg_str + ')'; } } return function_name_ + arg_str + function_suffix_; return return_type + function_name_ + arg_str + function_suffix_; } std::string demangle(const char* name) { Loading demangle/Demangler.h +8 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ class Demangler { std::string GetArgumentsString(); void FinalizeTemplate(); const char* ParseS(const char* name); const char* ParseT(const char* name); const char* AppendOperatorString(const char* name); void Save(const std::string& str, bool is_name); Loading @@ -50,17 +51,21 @@ class Demangler { first_save_.clear(); cur_state_.Clear(); saves_.clear(); template_saves_.clear(); while (!state_stack_.empty()) { state_stack_.pop(); } last_save_name_ = false; template_found_ = false; } using parse_func_type = const char* (Demangler::*)(const char*); parse_func_type parse_func_; std::vector<parse_func_type> parse_funcs_; std::vector<std::string> saves_; std::vector<std::string> template_saves_; bool last_save_name_; bool template_found_; std::string function_name_; std::string function_suffix_; Loading Loading @@ -89,12 +94,15 @@ class Demangler { // Parsing functions. const char* ParseComplexString(const char* name); const char* ParseComplexArgument(const char* name); const char* ParseArgumentsAtTopLevel(const char* name); const char* ParseArguments(const char* name); const char* ParseTemplateArguments(const char* name); const char* ParseTemplateArgumentsComplex(const char* name); const char* ParseTemplateLiteral(const char* name); const char* ParseFunctionArgument(const char* name); const char* ParseFunctionName(const char* name); const char* ParseFunctionNameTemplate(const char* name); const char* ParseFunctionTemplateArguments(const char* name); const char* FindFunctionName(const char* name); const char* Fail(const char*) { return nullptr; } Loading Loading
demangle/DemangleTest.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,29 @@ TEST(DemangleTest, TemplateFunction) { // Template within templates. ASSERT_EQ("one::two<three<char, int>>", demangler.Parse("_ZN3one3twoIN5threeIciEEEE")); ASSERT_EQ("one::two<three<char, four<int>>>", demangler.Parse("_ZN3one3twoIN5threeIcN4fourIiEEEEEE")); ASSERT_EQ("one<char>", demangler.Parse("_Z3oneIcE")); ASSERT_EQ("one<void>", demangler.Parse("_Z3oneIvE")); ASSERT_EQ("one<void*>", demangler.Parse("_Z3oneIPvE")); ASSERT_EQ("one<void const>", demangler.Parse("_Z3oneIKvE")); ASSERT_EQ("one<char, int, bool>", demangler.Parse("_Z3oneIcibE")); ASSERT_EQ("one(two<three>)", demangler.Parse("_Z3one3twoIN5threeEE")); ASSERT_EQ("one<char, int, two::three>", demangler.Parse("_Z3oneIciN3two5threeEE")); // Template within templates. ASSERT_EQ("one(two<three<char, int>>)", demangler.Parse("_Z3one3twoIN5threeIciEEE")); ASSERT_EQ("one(two<three<char, four<int>>>)", demangler.Parse("_Z3one3twoIN5threeIcN4fourIiEEEEE")); } TEST(DemangleTest, TemplateFunctionWithReturnType) { Demangler demangler; ASSERT_EQ("char one<int>(char)", demangler.Parse("_Z3oneIiEcc")); ASSERT_EQ("void one<int>()", demangler.Parse("_Z3oneIiEvv")); ASSERT_EQ("char one<int>()", demangler.Parse("_Z3oneIiEcv")); ASSERT_EQ("char one<int>(void, void)", demangler.Parse("_Z3oneIiEcvv")); ASSERT_EQ("char one<int>()", demangler.Parse("_ZN3oneIiEEcv")); ASSERT_EQ("char one<int>(void, void)", demangler.Parse("_ZN3oneIiEEcvv")); } TEST(DemangleTest, TemplateArguments) { Loading Loading @@ -410,6 +433,28 @@ TEST(DemangleTest, ComplexSubstitution) { demangler.Parse("_ZN3one3two5three4fourINS_4fiveEED2EPS3_")); } TEST(DemangleTest, TemplateSubstitution) { Demangler demangler; ASSERT_EQ("void one<int, double>(int)", demangler.Parse("_ZN3oneIidEEvT_")); ASSERT_EQ("void one<int, double>(double)", demangler.Parse("_ZN3oneIidEEvT0_")); ASSERT_EQ("void one<int, double, char, void>(char)", demangler.Parse("_ZN3oneIidcvEEvT1_")); ASSERT_EQ("void one<int, double>(int)", demangler.Parse("_Z3oneIidEvT_")); ASSERT_EQ("void one<int, double>(double)", demangler.Parse("_Z3oneIidEvT0_")); ASSERT_EQ("void one<int, double, char, void>(char)", demangler.Parse("_Z3oneIidcvEvT1_")); ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(l)", demangler.Parse("_ZN3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEEvT10_")); ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(m)", demangler.Parse("_ZN3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEEvT11_")); ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(l)", demangler.Parse("_Z3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEvT10_")); ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(m)", demangler.Parse("_Z3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEvT11_")); } TEST(DemangleTest, StringTooLong) { Demangler demangler; Loading @@ -434,6 +479,13 @@ TEST(DemangleTest, BooleanLiterals) { ASSERT_EQ("one<true>", demangler.Parse("_ZN3oneILb1EEE")); ASSERT_EQ("one<false>", demangler.Parse("_ZN3oneILb0EEE")); ASSERT_EQ("one<false, true>", demangler.Parse("_ZN3oneILb0ELb1EEE")); ASSERT_EQ("one<true>", demangler.Parse("_Z3oneILb1EE")); ASSERT_EQ("one<false>", demangler.Parse("_Z3oneILb0EE")); ASSERT_EQ("one<false, true>", demangler.Parse("_Z3oneILb0ELb1EE")); ASSERT_EQ("one(two<three<four>, false, true>)", demangler.Parse("_ZN3oneE3twoI5threeI4fourELb0ELb1EE")); } TEST(DemangleTest, demangle) { Loading
demangle/Demangler.cpp +110 −3 Original line number Diff line number Diff line Loading @@ -347,6 +347,33 @@ const char* Demangler::ParseS(const char* name) { return name + 1; } const char* Demangler::ParseT(const char* name) { if (template_saves_.empty()) { return nullptr; } if (*name == '_') { last_save_name_ = false; AppendCurrent(template_saves_[0]); return name + 1; } // Need to get the total number. char* end; unsigned long int index = strtoul(name, &end, 10) + 1; if (name == end || *end != '_') { return nullptr; } if (index >= template_saves_.size()) { return nullptr; } last_save_name_ = false; AppendCurrent(template_saves_[index]); return end + 1; } const char* Demangler::ParseFunctionName(const char* name) { if (*name == 'E') { if (parse_funcs_.empty()) { Loading @@ -371,9 +398,28 @@ const char* Demangler::ParseFunctionName(const char* name) { return name + 1; } if (*name == 'I') { state_stack_.push(cur_state_); cur_state_.Clear(); parse_funcs_.push_back(parse_func_); parse_func_ = &Demangler::ParseFunctionNameTemplate; return name + 1; } return ParseComplexString(name); } const char* Demangler::ParseFunctionNameTemplate(const char* name) { if (*name == 'E' && name[1] == 'E') { // Only consider this a template with saves if it is right before // the end of the name. template_found_ = true; template_saves_ = cur_state_.args; } return ParseTemplateArgumentsComplex(name); } const char* Demangler::ParseComplexArgument(const char* name) { if (*name == 'E') { if (parse_funcs_.empty()) { Loading Loading @@ -690,6 +736,7 @@ const char* Demangler::ParseTemplateArgumentsComplex(const char* name) { } parse_func_ = parse_funcs_.back(); parse_funcs_.pop_back(); FinalizeTemplate(); Save(cur_state_.str, false); return name + 1; Loading @@ -699,6 +746,7 @@ const char* Demangler::ParseTemplateArgumentsComplex(const char* name) { parse_func_ = &Demangler::ParseTemplateLiteral; return name + 1; } return ParseArguments(name); } Loading @@ -713,13 +761,33 @@ const char* Demangler::ParseTemplateArguments(const char* name) { AppendArgument(cur_state_.str); cur_state_.str.clear(); return name + 1; } else if (*name == 'L') { // Literal value for a template. parse_funcs_.push_back(parse_func_); parse_func_ = &Demangler::ParseTemplateLiteral; return name + 1; } return ParseArguments(name); } const char* Demangler::ParseFunctionTemplateArguments(const char* name) { if (*name == 'E') { parse_func_ = parse_funcs_.back(); parse_funcs_.pop_back(); function_name_ += '<' + GetArgumentsString() + '>'; template_found_ = true; template_saves_ = cur_state_.args; cur_state_.Clear(); return name + 1; } return ParseTemplateArgumentsComplex(name); } const char* Demangler::FindFunctionName(const char* name) { if (*name == 'N') { parse_funcs_.push_back(&Demangler::ParseArguments); parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel); parse_func_ = &Demangler::ParseFunctionName; return name + 1; } Loading @@ -732,11 +800,35 @@ const char* Demangler::FindFunctionName(const char* name) { name = AppendOperatorString(name); function_name_ = cur_state_.str; } parse_func_ = &Demangler::ParseArguments; cur_state_.Clear(); // Check for a template argument, which will still be part of the function // name. if (name != nullptr && *name == 'I') { parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel); parse_func_ = &Demangler::ParseFunctionTemplateArguments; return name + 1; } parse_func_ = &Demangler::ParseArgumentsAtTopLevel; return name; } const char* Demangler::ParseArgumentsAtTopLevel(const char* name) { // At the top level is the only place where T is allowed. if (*name == 'T') { name++; name = ParseT(name); if (name == nullptr) { return nullptr; } AppendArgument(cur_state_.str); cur_state_.str.clear(); return name; } return Demangler::ParseArguments(name); } std::string Demangler::Parse(const char* name, size_t max_length) { if (name[0] == '\0' || name[0] != '_' || name[1] == '\0' || name[1] != 'Z') { // Name is not mangled. Loading @@ -757,6 +849,21 @@ std::string Demangler::Parse(const char* name, size_t max_length) { return name; } std::string return_type; if (template_found_) { // Only a single argument with a template is not allowed. if (cur_state_.args.size() == 1) { return name; } // If there are at least two arguments, this template has a return type. if (cur_state_.args.size() > 1) { // The first argument will be the return value. return_type = cur_state_.args[0] + ' '; cur_state_.args.erase(cur_state_.args.begin()); } } std::string arg_str; if (cur_state_.args.size() == 1 && cur_state_.args[0] == "void") { // If the only argument is void, then don't print any args. Loading @@ -767,7 +874,7 @@ std::string Demangler::Parse(const char* name, size_t max_length) { arg_str = '(' + arg_str + ')'; } } return function_name_ + arg_str + function_suffix_; return return_type + function_name_ + arg_str + function_suffix_; } std::string demangle(const char* name) { Loading
demangle/Demangler.h +8 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ class Demangler { std::string GetArgumentsString(); void FinalizeTemplate(); const char* ParseS(const char* name); const char* ParseT(const char* name); const char* AppendOperatorString(const char* name); void Save(const std::string& str, bool is_name); Loading @@ -50,17 +51,21 @@ class Demangler { first_save_.clear(); cur_state_.Clear(); saves_.clear(); template_saves_.clear(); while (!state_stack_.empty()) { state_stack_.pop(); } last_save_name_ = false; template_found_ = false; } using parse_func_type = const char* (Demangler::*)(const char*); parse_func_type parse_func_; std::vector<parse_func_type> parse_funcs_; std::vector<std::string> saves_; std::vector<std::string> template_saves_; bool last_save_name_; bool template_found_; std::string function_name_; std::string function_suffix_; Loading Loading @@ -89,12 +94,15 @@ class Demangler { // Parsing functions. const char* ParseComplexString(const char* name); const char* ParseComplexArgument(const char* name); const char* ParseArgumentsAtTopLevel(const char* name); const char* ParseArguments(const char* name); const char* ParseTemplateArguments(const char* name); const char* ParseTemplateArgumentsComplex(const char* name); const char* ParseTemplateLiteral(const char* name); const char* ParseFunctionArgument(const char* name); const char* ParseFunctionName(const char* name); const char* ParseFunctionNameTemplate(const char* name); const char* ParseFunctionTemplateArguments(const char* name); const char* FindFunctionName(const char* name); const char* Fail(const char*) { return nullptr; } Loading