summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Ferris2017-10-27 14:29:02 -0500
committerChristopher Ferris2017-10-31 17:00:54 -0500
commit584333e3b2da923537076944bf4eb94ddb2a4fff (patch)
treeb9e0e6348a83a9f27964de9c4c01c21fb2c779c2 /demangle
parentbb3769349de0f4becb8a4fd2ed33ffeaf8d56862 (diff)
downloadplatform-system-core-584333e3b2da923537076944bf4eb94ddb2a4fff.tar.gz
platform-system-core-584333e3b2da923537076944bf4eb94ddb2a4fff.tar.xz
platform-system-core-584333e3b2da923537076944bf4eb94ddb2a4fff.zip
Fix template support.
- Fix template applying to function name without a starting N. - Fix return types for templates handling. - Add support for the T substitution parameter. - Fix a case where the literal L handler was not being set properly. Bug: 67678053 Test: New unit tests, fuzzer. Change-Id: I4f831038047eb2cd8519426f16aa2bdcb846d92d
Diffstat (limited to 'demangle')
-rw-r--r--demangle/DemangleTest.cpp52
-rw-r--r--demangle/Demangler.cpp113
-rw-r--r--demangle/Demangler.h8
3 files changed, 170 insertions, 3 deletions
diff --git a/demangle/DemangleTest.cpp b/demangle/DemangleTest.cpp
index c93e2ab93..5825e6ce2 100644
--- a/demangle/DemangleTest.cpp
+++ b/demangle/DemangleTest.cpp
@@ -334,6 +334,29 @@ TEST(DemangleTest, TemplateFunction) {
334 // Template within templates. 334 // Template within templates.
335 ASSERT_EQ("one::two<three<char, int>>", demangler.Parse("_ZN3one3twoIN5threeIciEEEE")); 335 ASSERT_EQ("one::two<three<char, int>>", demangler.Parse("_ZN3one3twoIN5threeIciEEEE"));
336 ASSERT_EQ("one::two<three<char, four<int>>>", demangler.Parse("_ZN3one3twoIN5threeIcN4fourIiEEEEEE")); 336 ASSERT_EQ("one::two<three<char, four<int>>>", demangler.Parse("_ZN3one3twoIN5threeIcN4fourIiEEEEEE"));
337
338 ASSERT_EQ("one<char>", demangler.Parse("_Z3oneIcE"));
339 ASSERT_EQ("one<void>", demangler.Parse("_Z3oneIvE"));
340 ASSERT_EQ("one<void*>", demangler.Parse("_Z3oneIPvE"));
341 ASSERT_EQ("one<void const>", demangler.Parse("_Z3oneIKvE"));
342 ASSERT_EQ("one<char, int, bool>", demangler.Parse("_Z3oneIcibE"));
343 ASSERT_EQ("one(two<three>)", demangler.Parse("_Z3one3twoIN5threeEE"));
344 ASSERT_EQ("one<char, int, two::three>", demangler.Parse("_Z3oneIciN3two5threeEE"));
345 // Template within templates.
346 ASSERT_EQ("one(two<three<char, int>>)", demangler.Parse("_Z3one3twoIN5threeIciEEE"));
347 ASSERT_EQ("one(two<three<char, four<int>>>)",
348 demangler.Parse("_Z3one3twoIN5threeIcN4fourIiEEEEE"));
349}
350
351TEST(DemangleTest, TemplateFunctionWithReturnType) {
352 Demangler demangler;
353
354 ASSERT_EQ("char one<int>(char)", demangler.Parse("_Z3oneIiEcc"));
355 ASSERT_EQ("void one<int>()", demangler.Parse("_Z3oneIiEvv"));
356 ASSERT_EQ("char one<int>()", demangler.Parse("_Z3oneIiEcv"));
357 ASSERT_EQ("char one<int>(void, void)", demangler.Parse("_Z3oneIiEcvv"));
358 ASSERT_EQ("char one<int>()", demangler.Parse("_ZN3oneIiEEcv"));
359 ASSERT_EQ("char one<int>(void, void)", demangler.Parse("_ZN3oneIiEEcvv"));
337} 360}
338 361
339TEST(DemangleTest, TemplateArguments) { 362TEST(DemangleTest, TemplateArguments) {
@@ -410,6 +433,28 @@ TEST(DemangleTest, ComplexSubstitution) {
410 demangler.Parse("_ZN3one3two5three4fourINS_4fiveEED2EPS3_")); 433 demangler.Parse("_ZN3one3two5three4fourINS_4fiveEED2EPS3_"));
411} 434}
412 435
436TEST(DemangleTest, TemplateSubstitution) {
437 Demangler demangler;
438
439 ASSERT_EQ("void one<int, double>(int)", demangler.Parse("_ZN3oneIidEEvT_"));
440 ASSERT_EQ("void one<int, double>(double)", demangler.Parse("_ZN3oneIidEEvT0_"));
441 ASSERT_EQ("void one<int, double, char, void>(char)", demangler.Parse("_ZN3oneIidcvEEvT1_"));
442
443 ASSERT_EQ("void one<int, double>(int)", demangler.Parse("_Z3oneIidEvT_"));
444 ASSERT_EQ("void one<int, double>(double)", demangler.Parse("_Z3oneIidEvT0_"));
445 ASSERT_EQ("void one<int, double, char, void>(char)", demangler.Parse("_Z3oneIidcvEvT1_"));
446
447 ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(l)",
448 demangler.Parse("_ZN3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEEvT10_"));
449 ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(m)",
450 demangler.Parse("_ZN3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEEvT11_"));
451
452 ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(l)",
453 demangler.Parse("_Z3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEvT10_"));
454 ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(m)",
455 demangler.Parse("_Z3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEvT11_"));
456}
457
413TEST(DemangleTest, StringTooLong) { 458TEST(DemangleTest, StringTooLong) {
414 Demangler demangler; 459 Demangler demangler;
415 460
@@ -434,6 +479,13 @@ TEST(DemangleTest, BooleanLiterals) {
434 ASSERT_EQ("one<true>", demangler.Parse("_ZN3oneILb1EEE")); 479 ASSERT_EQ("one<true>", demangler.Parse("_ZN3oneILb1EEE"));
435 ASSERT_EQ("one<false>", demangler.Parse("_ZN3oneILb0EEE")); 480 ASSERT_EQ("one<false>", demangler.Parse("_ZN3oneILb0EEE"));
436 ASSERT_EQ("one<false, true>", demangler.Parse("_ZN3oneILb0ELb1EEE")); 481 ASSERT_EQ("one<false, true>", demangler.Parse("_ZN3oneILb0ELb1EEE"));
482
483 ASSERT_EQ("one<true>", demangler.Parse("_Z3oneILb1EE"));
484 ASSERT_EQ("one<false>", demangler.Parse("_Z3oneILb0EE"));
485 ASSERT_EQ("one<false, true>", demangler.Parse("_Z3oneILb0ELb1EE"));
486
487 ASSERT_EQ("one(two<three<four>, false, true>)",
488 demangler.Parse("_ZN3oneE3twoI5threeI4fourELb0ELb1EE"));
437} 489}
438 490
439TEST(DemangleTest, demangle) { 491TEST(DemangleTest, demangle) {
diff --git a/demangle/Demangler.cpp b/demangle/Demangler.cpp
index f148b21a5..18a90b4a9 100644
--- a/demangle/Demangler.cpp
+++ b/demangle/Demangler.cpp
@@ -347,6 +347,33 @@ const char* Demangler::ParseS(const char* name) {
347 return name + 1; 347 return name + 1;
348} 348}
349 349
350const char* Demangler::ParseT(const char* name) {
351 if (template_saves_.empty()) {
352 return nullptr;
353 }
354
355 if (*name == '_') {
356 last_save_name_ = false;
357 AppendCurrent(template_saves_[0]);
358 return name + 1;
359 }
360
361 // Need to get the total number.
362 char* end;
363 unsigned long int index = strtoul(name, &end, 10) + 1;
364 if (name == end || *end != '_') {
365 return nullptr;
366 }
367
368 if (index >= template_saves_.size()) {
369 return nullptr;
370 }
371
372 last_save_name_ = false;
373 AppendCurrent(template_saves_[index]);
374 return end + 1;
375}
376
350const char* Demangler::ParseFunctionName(const char* name) { 377const char* Demangler::ParseFunctionName(const char* name) {
351 if (*name == 'E') { 378 if (*name == 'E') {
352 if (parse_funcs_.empty()) { 379 if (parse_funcs_.empty()) {
@@ -371,9 +398,28 @@ const char* Demangler::ParseFunctionName(const char* name) {
371 return name + 1; 398 return name + 1;
372 } 399 }
373 400
401 if (*name == 'I') {
402 state_stack_.push(cur_state_);
403 cur_state_.Clear();
404
405 parse_funcs_.push_back(parse_func_);
406 parse_func_ = &Demangler::ParseFunctionNameTemplate;
407 return name + 1;
408 }
409
374 return ParseComplexString(name); 410 return ParseComplexString(name);
375} 411}
376 412
413const char* Demangler::ParseFunctionNameTemplate(const char* name) {
414 if (*name == 'E' && name[1] == 'E') {
415 // Only consider this a template with saves if it is right before
416 // the end of the name.
417 template_found_ = true;
418 template_saves_ = cur_state_.args;
419 }
420 return ParseTemplateArgumentsComplex(name);
421}
422
377const char* Demangler::ParseComplexArgument(const char* name) { 423const char* Demangler::ParseComplexArgument(const char* name) {
378 if (*name == 'E') { 424 if (*name == 'E') {
379 if (parse_funcs_.empty()) { 425 if (parse_funcs_.empty()) {
@@ -690,6 +736,7 @@ const char* Demangler::ParseTemplateArgumentsComplex(const char* name) {
690 } 736 }
691 parse_func_ = parse_funcs_.back(); 737 parse_func_ = parse_funcs_.back();
692 parse_funcs_.pop_back(); 738 parse_funcs_.pop_back();
739
693 FinalizeTemplate(); 740 FinalizeTemplate();
694 Save(cur_state_.str, false); 741 Save(cur_state_.str, false);
695 return name + 1; 742 return name + 1;
@@ -699,6 +746,7 @@ const char* Demangler::ParseTemplateArgumentsComplex(const char* name) {
699 parse_func_ = &Demangler::ParseTemplateLiteral; 746 parse_func_ = &Demangler::ParseTemplateLiteral;
700 return name + 1; 747 return name + 1;
701 } 748 }
749
702 return ParseArguments(name); 750 return ParseArguments(name);
703} 751}
704 752
@@ -713,13 +761,33 @@ const char* Demangler::ParseTemplateArguments(const char* name) {
713 AppendArgument(cur_state_.str); 761 AppendArgument(cur_state_.str);
714 cur_state_.str.clear(); 762 cur_state_.str.clear();
715 return name + 1; 763 return name + 1;
764 } else if (*name == 'L') {
765 // Literal value for a template.
766 parse_funcs_.push_back(parse_func_);
767 parse_func_ = &Demangler::ParseTemplateLiteral;
768 return name + 1;
716 } 769 }
770
717 return ParseArguments(name); 771 return ParseArguments(name);
718} 772}
719 773
774const char* Demangler::ParseFunctionTemplateArguments(const char* name) {
775 if (*name == 'E') {
776 parse_func_ = parse_funcs_.back();
777 parse_funcs_.pop_back();
778
779 function_name_ += '<' + GetArgumentsString() + '>';
780 template_found_ = true;
781 template_saves_ = cur_state_.args;
782 cur_state_.Clear();
783 return name + 1;
784 }
785 return ParseTemplateArgumentsComplex(name);
786}
787
720const char* Demangler::FindFunctionName(const char* name) { 788const char* Demangler::FindFunctionName(const char* name) {
721 if (*name == 'N') { 789 if (*name == 'N') {
722 parse_funcs_.push_back(&Demangler::ParseArguments); 790 parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel);
723 parse_func_ = &Demangler::ParseFunctionName; 791 parse_func_ = &Demangler::ParseFunctionName;
724 return name + 1; 792 return name + 1;
725 } 793 }
@@ -732,11 +800,35 @@ const char* Demangler::FindFunctionName(const char* name) {
732 name = AppendOperatorString(name); 800 name = AppendOperatorString(name);
733 function_name_ = cur_state_.str; 801 function_name_ = cur_state_.str;
734 } 802 }
735 parse_func_ = &Demangler::ParseArguments;
736 cur_state_.Clear(); 803 cur_state_.Clear();
804
805 // Check for a template argument, which will still be part of the function
806 // name.
807 if (name != nullptr && *name == 'I') {
808 parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel);
809 parse_func_ = &Demangler::ParseFunctionTemplateArguments;
810 return name + 1;
811 }
812 parse_func_ = &Demangler::ParseArgumentsAtTopLevel;
737 return name; 813 return name;
738} 814}
739 815
816const char* Demangler::ParseArgumentsAtTopLevel(const char* name) {
817 // At the top level is the only place where T is allowed.
818 if (*name == 'T') {
819 name++;
820 name = ParseT(name);
821 if (name == nullptr) {
822 return nullptr;
823 }
824 AppendArgument(cur_state_.str);
825 cur_state_.str.clear();
826 return name;
827 }
828
829 return Demangler::ParseArguments(name);
830}
831
740std::string Demangler::Parse(const char* name, size_t max_length) { 832std::string Demangler::Parse(const char* name, size_t max_length) {
741 if (name[0] == '\0' || name[0] != '_' || name[1] == '\0' || name[1] != 'Z') { 833 if (name[0] == '\0' || name[0] != '_' || name[1] == '\0' || name[1] != 'Z') {
742 // Name is not mangled. 834 // Name is not mangled.
@@ -757,6 +849,21 @@ std::string Demangler::Parse(const char* name, size_t max_length) {
757 return name; 849 return name;
758 } 850 }
759 851
852 std::string return_type;
853 if (template_found_) {
854 // Only a single argument with a template is not allowed.
855 if (cur_state_.args.size() == 1) {
856 return name;
857 }
858
859 // If there are at least two arguments, this template has a return type.
860 if (cur_state_.args.size() > 1) {
861 // The first argument will be the return value.
862 return_type = cur_state_.args[0] + ' ';
863 cur_state_.args.erase(cur_state_.args.begin());
864 }
865 }
866
760 std::string arg_str; 867 std::string arg_str;
761 if (cur_state_.args.size() == 1 && cur_state_.args[0] == "void") { 868 if (cur_state_.args.size() == 1 && cur_state_.args[0] == "void") {
762 // If the only argument is void, then don't print any args. 869 // If the only argument is void, then don't print any args.
@@ -767,7 +874,7 @@ std::string Demangler::Parse(const char* name, size_t max_length) {
767 arg_str = '(' + arg_str + ')'; 874 arg_str = '(' + arg_str + ')';
768 } 875 }
769 } 876 }
770 return function_name_ + arg_str + function_suffix_; 877 return return_type + function_name_ + arg_str + function_suffix_;
771} 878}
772 879
773std::string demangle(const char* name) { 880std::string demangle(const char* name) {
diff --git a/demangle/Demangler.h b/demangle/Demangler.h
index f76def64a..3b7d44ef3 100644
--- a/demangle/Demangler.h
+++ b/demangle/Demangler.h
@@ -39,6 +39,7 @@ class Demangler {
39 std::string GetArgumentsString(); 39 std::string GetArgumentsString();
40 void FinalizeTemplate(); 40 void FinalizeTemplate();
41 const char* ParseS(const char* name); 41 const char* ParseS(const char* name);
42 const char* ParseT(const char* name);
42 const char* AppendOperatorString(const char* name); 43 const char* AppendOperatorString(const char* name);
43 void Save(const std::string& str, bool is_name); 44 void Save(const std::string& str, bool is_name);
44 45
@@ -50,17 +51,21 @@ class Demangler {
50 first_save_.clear(); 51 first_save_.clear();
51 cur_state_.Clear(); 52 cur_state_.Clear();
52 saves_.clear(); 53 saves_.clear();
54 template_saves_.clear();
53 while (!state_stack_.empty()) { 55 while (!state_stack_.empty()) {
54 state_stack_.pop(); 56 state_stack_.pop();
55 } 57 }
56 last_save_name_ = false; 58 last_save_name_ = false;
59 template_found_ = false;
57 } 60 }
58 61
59 using parse_func_type = const char* (Demangler::*)(const char*); 62 using parse_func_type = const char* (Demangler::*)(const char*);
60 parse_func_type parse_func_; 63 parse_func_type parse_func_;
61 std::vector<parse_func_type> parse_funcs_; 64 std::vector<parse_func_type> parse_funcs_;
62 std::vector<std::string> saves_; 65 std::vector<std::string> saves_;
66 std::vector<std::string> template_saves_;
63 bool last_save_name_; 67 bool last_save_name_;
68 bool template_found_;
64 69
65 std::string function_name_; 70 std::string function_name_;
66 std::string function_suffix_; 71 std::string function_suffix_;
@@ -89,12 +94,15 @@ class Demangler {
89 // Parsing functions. 94 // Parsing functions.
90 const char* ParseComplexString(const char* name); 95 const char* ParseComplexString(const char* name);
91 const char* ParseComplexArgument(const char* name); 96 const char* ParseComplexArgument(const char* name);
97 const char* ParseArgumentsAtTopLevel(const char* name);
92 const char* ParseArguments(const char* name); 98 const char* ParseArguments(const char* name);
93 const char* ParseTemplateArguments(const char* name); 99 const char* ParseTemplateArguments(const char* name);
94 const char* ParseTemplateArgumentsComplex(const char* name); 100 const char* ParseTemplateArgumentsComplex(const char* name);
95 const char* ParseTemplateLiteral(const char* name); 101 const char* ParseTemplateLiteral(const char* name);
96 const char* ParseFunctionArgument(const char* name); 102 const char* ParseFunctionArgument(const char* name);
97 const char* ParseFunctionName(const char* name); 103 const char* ParseFunctionName(const char* name);
104 const char* ParseFunctionNameTemplate(const char* name);
105 const char* ParseFunctionTemplateArguments(const char* name);
98 const char* FindFunctionName(const char* name); 106 const char* FindFunctionName(const char* name);
99 const char* Fail(const char*) { return nullptr; } 107 const char* Fail(const char*) { return nullptr; }
100 108