blob: 7bae3564d0bb6264a6c73d7c92f0a80e02b4d9be [file] [log] [blame]
Christopher Ferris9323b722017-03-03 17:43:14 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <assert.h>
Florian Mayer5795d0b2019-05-17 19:47:24 +010018#include <string.h>
Christopher Ferris9323b722017-03-03 17:43:14 -080019
20#include <cctype>
21#include <stack>
22#include <string>
23#include <vector>
24
25#include "Demangler.h"
26
27constexpr const char* Demangler::kTypes[];
28constexpr const char* Demangler::kDTypes[];
29constexpr const char* Demangler::kSTypes[];
30
31void Demangler::Save(const std::string& str, bool is_name) {
32 saves_.push_back(str);
33 last_save_name_ = is_name;
34}
35
36std::string Demangler::GetArgumentsString() {
37 size_t num_args = cur_state_.args.size();
38 std::string arg_str;
39 if (num_args > 0) {
40 arg_str = cur_state_.args[0];
41 for (size_t i = 1; i < num_args; i++) {
42 arg_str += ", " + cur_state_.args[i];
43 }
44 }
45 return arg_str;
46}
47
48const char* Demangler::AppendOperatorString(const char* name) {
49 const char* oper = nullptr;
50 switch (*name) {
51 case 'a':
52 name++;
53 switch (*name) {
54 case 'a':
55 oper = "operator&&";
56 break;
57 case 'd':
58 case 'n':
59 oper = "operator&";
60 break;
61 case 'N':
62 oper = "operator&=";
63 break;
64 case 'S':
65 oper = "operator=";
66 break;
67 }
68 break;
69 case 'c':
70 name++;
71 switch (*name) {
72 case 'l':
73 oper = "operator()";
74 break;
75 case 'm':
76 oper = "operator,";
77 break;
78 case 'o':
79 oper = "operator~";
80 break;
81 }
82 break;
83 case 'd':
84 name++;
85 switch (*name) {
86 case 'a':
87 oper = "operator delete[]";
88 break;
89 case 'e':
90 oper = "operator*";
91 break;
92 case 'l':
93 oper = "operator delete";
94 break;
95 case 'v':
96 oper = "operator/";
97 break;
98 case 'V':
99 oper = "operator/=";
100 break;
101 }
102 break;
103 case 'e':
104 name++;
105 switch (*name) {
106 case 'o':
107 oper = "operator^";
108 break;
109 case 'O':
110 oper = "operator^=";
111 break;
112 case 'q':
113 oper = "operator==";
114 break;
115 }
116 break;
117 case 'g':
118 name++;
119 switch (*name) {
120 case 'e':
121 oper = "operator>=";
122 break;
123 case 't':
124 oper = "operator>";
125 break;
126 }
127 break;
128 case 'i':
129 name++;
130 switch (*name) {
131 case 'x':
132 oper = "operator[]";
133 break;
134 }
135 break;
136 case 'l':
137 name++;
138 switch (*name) {
139 case 'e':
140 oper = "operator<=";
141 break;
142 case 's':
143 oper = "operator<<";
144 break;
145 case 'S':
146 oper = "operator<<=";
147 break;
148 case 't':
149 oper = "operator<";
150 break;
151 }
152 break;
153 case 'm':
154 name++;
155 switch (*name) {
156 case 'i':
157 oper = "operator-";
158 break;
159 case 'I':
160 oper = "operator-=";
161 break;
162 case 'l':
163 oper = "operator*";
164 break;
165 case 'L':
166 oper = "operator*=";
167 break;
168 case 'm':
169 oper = "operator--";
170 break;
171 }
172 break;
173 case 'n':
174 name++;
175 switch (*name) {
176 case 'a':
177 oper = "operator new[]";
178 break;
179 case 'e':
180 oper = "operator!=";
181 break;
182 case 'g':
183 oper = "operator-";
184 break;
185 case 't':
186 oper = "operator!";
187 break;
188 case 'w':
189 oper = "operator new";
190 break;
191 }
192 break;
193 case 'o':
194 name++;
195 switch (*name) {
196 case 'o':
197 oper = "operator||";
198 break;
199 case 'r':
200 oper = "operator|";
201 break;
202 case 'R':
203 oper = "operator|=";
204 break;
205 }
206 break;
207 case 'p':
208 name++;
209 switch (*name) {
210 case 'm':
211 oper = "operator->*";
212 break;
213 case 'l':
214 oper = "operator+";
215 break;
216 case 'L':
217 oper = "operator+=";
218 break;
219 case 'p':
220 oper = "operator++";
221 break;
222 case 's':
223 oper = "operator+";
224 break;
225 case 't':
226 oper = "operator->";
227 break;
228 }
229 break;
230 case 'q':
231 name++;
232 switch (*name) {
233 case 'u':
234 oper = "operator?";
235 break;
236 }
237 break;
238 case 'r':
239 name++;
240 switch (*name) {
241 case 'm':
242 oper = "operator%";
243 break;
244 case 'M':
245 oper = "operator%=";
246 break;
247 case 's':
248 oper = "operator>>";
249 break;
250 case 'S':
251 oper = "operator>>=";
252 break;
253 }
254 break;
255 }
256 if (oper == nullptr) {
257 return nullptr;
258 }
259 AppendCurrent(oper);
260 cur_state_.last_save = oper;
261 return name + 1;
262}
263
264const char* Demangler::GetStringFromLength(const char* name, std::string* str) {
265 assert(std::isdigit(*name));
266
267 size_t length = *name - '0';
268 name++;
269 while (*name != '\0' && std::isdigit(*name)) {
270 length = length * 10 + *name - '0';
271 name++;
272 }
273
274 std::string read_str;
275 while (*name != '\0' && length != 0) {
276 read_str += *name;
277 name++;
278 length--;
279 }
280 if (length != 0) {
281 return nullptr;
282 }
283 // Special replacement of _GLOBAL__N_1 to (anonymous namespace).
284 if (read_str == "_GLOBAL__N_1") {
285 *str += "(anonymous namespace)";
286 } else {
287 *str += read_str;
288 }
289 return name;
290}
291
292void Demangler::AppendCurrent(const std::string& str) {
293 if (!cur_state_.str.empty()) {
294 cur_state_.str += "::";
295 }
296 cur_state_.str += str;
297}
298
299void Demangler::AppendCurrent(const char* str) {
300 if (!cur_state_.str.empty()) {
301 cur_state_.str += "::";
302 }
303 cur_state_.str += str;
304}
305
306const char* Demangler::ParseS(const char* name) {
307 if (std::islower(*name)) {
308 const char* type = kSTypes[*name - 'a'];
309 if (type == nullptr) {
310 return nullptr;
311 }
312 AppendCurrent(type);
313 return name + 1;
314 }
315
316 if (saves_.empty()) {
317 return nullptr;
318 }
319
320 if (*name == '_') {
321 last_save_name_ = false;
322 AppendCurrent(saves_[0]);
323 return name + 1;
324 }
325
326 bool isdigit = std::isdigit(*name);
327 if (!isdigit && !std::isupper(*name)) {
328 return nullptr;
329 }
330
331 size_t index;
332 if (isdigit) {
333 index = *name - '0' + 1;
334 } else {
335 index = *name - 'A' + 11;
336 }
337 name++;
338 if (*name != '_') {
339 return nullptr;
340 }
341
342 if (index >= saves_.size()) {
343 return nullptr;
344 }
345
346 last_save_name_ = false;
347 AppendCurrent(saves_[index]);
348 return name + 1;
349}
350
Christopher Ferris584333e2017-10-27 12:29:02 -0700351const char* Demangler::ParseT(const char* name) {
352 if (template_saves_.empty()) {
353 return nullptr;
354 }
355
356 if (*name == '_') {
357 last_save_name_ = false;
358 AppendCurrent(template_saves_[0]);
359 return name + 1;
360 }
361
362 // Need to get the total number.
363 char* end;
364 unsigned long int index = strtoul(name, &end, 10) + 1;
365 if (name == end || *end != '_') {
366 return nullptr;
367 }
368
369 if (index >= template_saves_.size()) {
370 return nullptr;
371 }
372
373 last_save_name_ = false;
374 AppendCurrent(template_saves_[index]);
375 return end + 1;
376}
377
Christopher Ferris9323b722017-03-03 17:43:14 -0800378const char* Demangler::ParseFunctionName(const char* name) {
379 if (*name == 'E') {
380 if (parse_funcs_.empty()) {
381 return nullptr;
382 }
383 parse_func_ = parse_funcs_.back();
384 parse_funcs_.pop_back();
385
386 // Remove the last saved part so that the full function name is not saved.
387 // But only if the last save was not something like a substitution.
388 if (!saves_.empty() && last_save_name_) {
389 saves_.pop_back();
390 }
391
Christopher Ferris5a72ea02017-11-01 16:22:09 -0700392 function_name_ += cur_state_.str;
Christopher Ferris9323b722017-03-03 17:43:14 -0800393 while (!cur_state_.suffixes.empty()) {
394 function_suffix_ += cur_state_.suffixes.back();
395 cur_state_.suffixes.pop_back();
396 }
397 cur_state_.Clear();
398
399 return name + 1;
400 }
401
Christopher Ferris584333e2017-10-27 12:29:02 -0700402 if (*name == 'I') {
403 state_stack_.push(cur_state_);
404 cur_state_.Clear();
405
406 parse_funcs_.push_back(parse_func_);
407 parse_func_ = &Demangler::ParseFunctionNameTemplate;
408 return name + 1;
409 }
410
Christopher Ferris9323b722017-03-03 17:43:14 -0800411 return ParseComplexString(name);
412}
413
Christopher Ferris584333e2017-10-27 12:29:02 -0700414const char* Demangler::ParseFunctionNameTemplate(const char* name) {
415 if (*name == 'E' && name[1] == 'E') {
416 // Only consider this a template with saves if it is right before
417 // the end of the name.
418 template_found_ = true;
419 template_saves_ = cur_state_.args;
420 }
421 return ParseTemplateArgumentsComplex(name);
422}
423
Christopher Ferris9323b722017-03-03 17:43:14 -0800424const char* Demangler::ParseComplexArgument(const char* name) {
425 if (*name == 'E') {
426 if (parse_funcs_.empty()) {
427 return nullptr;
428 }
429 parse_func_ = parse_funcs_.back();
430 parse_funcs_.pop_back();
431
432 AppendArgument(cur_state_.str);
433 cur_state_.str.clear();
434
435 return name + 1;
436 }
437
438 return ParseComplexString(name);
439}
440
441void Demangler::FinalizeTemplate() {
442 std::string arg_str(GetArgumentsString());
443 cur_state_ = state_stack_.top();
444 state_stack_.pop();
445 cur_state_.str += '<' + arg_str + '>';
446}
447
448const char* Demangler::ParseComplexString(const char* name) {
449 if (*name == 'S') {
450 name++;
451 if (*name == 't') {
452 AppendCurrent("std");
453 return name + 1;
454 }
455 return ParseS(name);
456 }
457 if (*name == 'L') {
458 name++;
459 if (!std::isdigit(*name)) {
460 return nullptr;
461 }
462 }
463 if (std::isdigit(*name)) {
464 std::string str;
465 name = GetStringFromLength(name, &str);
466 if (name == nullptr) {
467 return name;
468 }
469 AppendCurrent(str);
470 Save(cur_state_.str, true);
471 cur_state_.last_save = std::move(str);
472 return name;
473 }
474 if (*name == 'D') {
475 name++;
476 if (saves_.empty() || (*name != '0' && *name != '1' && *name != '2'
477 && *name != '5')) {
478 return nullptr;
479 }
480 last_save_name_ = false;
481 AppendCurrent("~" + cur_state_.last_save);
482 return name + 1;
483 }
484 if (*name == 'C') {
485 name++;
486 if (saves_.empty() || (*name != '1' && *name != '2' && *name != '3'
487 && *name != '5')) {
488 return nullptr;
489 }
490 last_save_name_ = false;
491 AppendCurrent(cur_state_.last_save);
492 return name + 1;
493 }
494 if (*name == 'K') {
495 cur_state_.suffixes.push_back(" const");
496 return name + 1;
497 }
498 if (*name == 'V') {
499 cur_state_.suffixes.push_back(" volatile");
500 return name + 1;
501 }
502 if (*name == 'I') {
503 // Save the current argument state.
504 state_stack_.push(cur_state_);
505 cur_state_.Clear();
506
507 parse_funcs_.push_back(parse_func_);
508 parse_func_ = &Demangler::ParseTemplateArgumentsComplex;
509 return name + 1;
510 }
511 name = AppendOperatorString(name);
512 if (name != nullptr) {
513 Save(cur_state_.str, true);
514 }
515 return name;
516}
517
518void Demangler::AppendArgument(const std::string& str) {
519 std::string arg(str);
520 while (!cur_state_.suffixes.empty()) {
521 arg += cur_state_.suffixes.back();
522 cur_state_.suffixes.pop_back();
523 Save(arg, false);
524 }
525 cur_state_.args.push_back(arg);
526}
527
528const char* Demangler::ParseFunctionArgument(const char* name) {
529 if (*name == 'E') {
530 // The first argument is the function modifier.
531 // The second argument is the function type.
532 // The third argument is the return type of the function.
533 // The rest of the arguments are the function arguments.
534 size_t num_args = cur_state_.args.size();
535 if (num_args < 4) {
536 return nullptr;
537 }
538 std::string function_modifier = cur_state_.args[0];
539 std::string function_type = cur_state_.args[1];
540
541 std::string str = cur_state_.args[2] + ' ';
542 if (!cur_state_.args[1].empty()) {
543 str += '(' + cur_state_.args[1] + ')';
544 }
545
546 if (num_args == 4 && cur_state_.args[3] == "void") {
547 str += "()";
548 } else {
549 str += '(' + cur_state_.args[3];
550 for (size_t i = 4; i < num_args; i++) {
551 str += ", " + cur_state_.args[i];
552 }
553 str += ')';
554 }
555 str += cur_state_.args[0];
556
557 cur_state_ = state_stack_.top();
558 state_stack_.pop();
559 cur_state_.args.emplace_back(std::move(str));
560
561 parse_func_ = parse_funcs_.back();
562 parse_funcs_.pop_back();
563 return name + 1;
564 }
565 return ParseArguments(name);
566}
567
568const char* Demangler::ParseArguments(const char* name) {
569 switch (*name) {
570 case 'P':
571 cur_state_.suffixes.push_back("*");
572 return name + 1;
573
574 case 'R':
575 // This should always be okay because the string is guaranteed to have
576 // at least two characters before this. A mangled string always starts
577 // with _Z.
578 if (name[-1] != 'R') {
579 // Multiple 'R's in a row only add a single &.
580 cur_state_.suffixes.push_back("&");
581 }
582 return name + 1;
583
Elliott Hughesd7bb8262018-02-09 17:30:14 -0800584 case 'O':
585 cur_state_.suffixes.push_back("&&");
586 return name + 1;
587
Christopher Ferris9323b722017-03-03 17:43:14 -0800588 case 'K':
589 case 'V': {
590 const char* suffix;
591 if (*name == 'K') {
592 suffix = " const";
593 } else {
594 suffix = " volatile";
595 }
Christopher Ferris15d2e422017-05-31 14:40:15 -0700596 if (!cur_state_.suffixes.empty() && (name[-1] == 'K' || name[-1] == 'V')) {
Christopher Ferris9323b722017-03-03 17:43:14 -0800597 // Special case, const/volatile apply as a single entity.
Christopher Ferris9323b722017-03-03 17:43:14 -0800598 size_t index = cur_state_.suffixes.size();
599 cur_state_.suffixes[index-1].insert(0, suffix);
600 } else {
601 cur_state_.suffixes.push_back(suffix);
602 }
603 return name + 1;
604 }
605
606 case 'F': {
607 std::string function_modifier;
608 std::string function_type;
609 if (!cur_state_.suffixes.empty()) {
610 // If the first element starts with a ' ', then this modifies the
611 // function itself.
612 if (cur_state_.suffixes.back()[0] == ' ') {
613 function_modifier = cur_state_.suffixes.back();
614 cur_state_.suffixes.pop_back();
615 }
616 while (!cur_state_.suffixes.empty()) {
617 function_type += cur_state_.suffixes.back();
618 cur_state_.suffixes.pop_back();
619 }
620 }
621
622 state_stack_.push(cur_state_);
623
624 cur_state_.Clear();
625
626 // The function parameter has this format:
627 // First argument is the function modifier.
628 // Second argument is the function type.
629 // Third argument will be the return function type but has not
630 // been parsed yet.
631 // Any other parameters are the arguments to the function. There
632 // must be at least one or this isn't valid.
633 cur_state_.args.push_back(function_modifier);
634 cur_state_.args.push_back(function_type);
635
636 parse_funcs_.push_back(parse_func_);
637 parse_func_ = &Demangler::ParseFunctionArgument;
638 return name + 1;
639 }
640
641 case 'N':
642 parse_funcs_.push_back(parse_func_);
643 parse_func_ = &Demangler::ParseComplexArgument;
644 return name + 1;
645
646 case 'S':
647 name++;
648 if (*name == 't') {
649 cur_state_.str = "std::";
650 return name + 1;
651 }
652 name = ParseS(name);
653 if (name == nullptr) {
654 return nullptr;
655 }
656 AppendArgument(cur_state_.str);
657 cur_state_.str.clear();
658 return name;
659
660 case 'D':
661 name++;
662 if (*name >= 'a' && *name <= 'z') {
663 const char* arg = Demangler::kDTypes[*name - 'a'];
664 if (arg == nullptr) {
665 return nullptr;
666 }
667 AppendArgument(arg);
668 return name + 1;
669 }
670 return nullptr;
671
672 case 'I':
673 // Save the current argument state.
674 state_stack_.push(cur_state_);
675 cur_state_.Clear();
676
677 parse_funcs_.push_back(parse_func_);
678 parse_func_ = &Demangler::ParseTemplateArguments;
679 return name + 1;
680
681 case 'v':
682 AppendArgument("void");
683 return name + 1;
684
685 default:
686 if (*name >= 'a' && *name <= 'z') {
687 const char* arg = Demangler::kTypes[*name - 'a'];
688 if (arg == nullptr) {
689 return nullptr;
690 }
691 AppendArgument(arg);
692 return name + 1;
693 } else if (std::isdigit(*name)) {
694 std::string arg = cur_state_.str;
695 name = GetStringFromLength(name, &arg);
696 if (name == nullptr) {
697 return nullptr;
698 }
699 Save(arg, true);
700 if (*name == 'I') {
701 // There is one case where this argument is not complete, and that's
702 // where this is a template argument.
703 cur_state_.str = arg;
704 } else {
705 AppendArgument(arg);
706 cur_state_.str.clear();
707 }
708 return name;
Elliott Hughesd7bb8262018-02-09 17:30:14 -0800709 } else if (strcmp(name, ".cfi") == 0) {
710 function_suffix_ += " [clone .cfi]";
711 return name + 4;
Christopher Ferris9323b722017-03-03 17:43:14 -0800712 }
713 }
714 return nullptr;
715}
716
Christopher Ferris05232752017-10-11 15:22:29 -0700717const char* Demangler::ParseTemplateLiteral(const char* name) {
718 if (*name == 'E') {
719 parse_func_ = parse_funcs_.back();
720 parse_funcs_.pop_back();
721 return name + 1;
722 }
723 // Only understand boolean values with 0 or 1.
724 if (*name == 'b') {
725 name++;
726 if (*name == '0') {
727 AppendArgument("false");
728 cur_state_.str.clear();
729 } else if (*name == '1') {
730 AppendArgument("true");
731 cur_state_.str.clear();
732 } else {
733 return nullptr;
734 }
735 return name + 1;
736 }
737 return nullptr;
738}
739
Christopher Ferris9323b722017-03-03 17:43:14 -0800740const char* Demangler::ParseTemplateArgumentsComplex(const char* name) {
741 if (*name == 'E') {
742 if (parse_funcs_.empty()) {
743 return nullptr;
744 }
745 parse_func_ = parse_funcs_.back();
746 parse_funcs_.pop_back();
Christopher Ferris584333e2017-10-27 12:29:02 -0700747
Christopher Ferris9323b722017-03-03 17:43:14 -0800748 FinalizeTemplate();
749 Save(cur_state_.str, false);
750 return name + 1;
Christopher Ferris05232752017-10-11 15:22:29 -0700751 } else if (*name == 'L') {
752 // Literal value for a template.
753 parse_funcs_.push_back(parse_func_);
754 parse_func_ = &Demangler::ParseTemplateLiteral;
755 return name + 1;
Christopher Ferris9323b722017-03-03 17:43:14 -0800756 }
Christopher Ferris584333e2017-10-27 12:29:02 -0700757
Christopher Ferris9323b722017-03-03 17:43:14 -0800758 return ParseArguments(name);
759}
760
761const char* Demangler::ParseTemplateArguments(const char* name) {
762 if (*name == 'E') {
763 if (parse_funcs_.empty()) {
764 return nullptr;
765 }
766 parse_func_ = parse_funcs_.back();
767 parse_funcs_.pop_back();
768 FinalizeTemplate();
769 AppendArgument(cur_state_.str);
770 cur_state_.str.clear();
771 return name + 1;
Christopher Ferris584333e2017-10-27 12:29:02 -0700772 } else if (*name == 'L') {
773 // Literal value for a template.
774 parse_funcs_.push_back(parse_func_);
775 parse_func_ = &Demangler::ParseTemplateLiteral;
776 return name + 1;
Christopher Ferris9323b722017-03-03 17:43:14 -0800777 }
Christopher Ferris584333e2017-10-27 12:29:02 -0700778
Christopher Ferris9323b722017-03-03 17:43:14 -0800779 return ParseArguments(name);
780}
781
Christopher Ferris584333e2017-10-27 12:29:02 -0700782const char* Demangler::ParseFunctionTemplateArguments(const char* name) {
783 if (*name == 'E') {
784 parse_func_ = parse_funcs_.back();
785 parse_funcs_.pop_back();
786
787 function_name_ += '<' + GetArgumentsString() + '>';
788 template_found_ = true;
789 template_saves_ = cur_state_.args;
790 cur_state_.Clear();
791 return name + 1;
792 }
793 return ParseTemplateArgumentsComplex(name);
794}
795
Christopher Ferris9323b722017-03-03 17:43:14 -0800796const char* Demangler::FindFunctionName(const char* name) {
Christopher Ferris5a72ea02017-11-01 16:22:09 -0700797 if (*name == 'T') {
798 // non-virtual thunk, verify that it matches one of these patterns:
799 // Thn[0-9]+_
800 // Th[0-9]+_
801 // Thn_
802 // Th_
803 name++;
804 if (*name != 'h') {
805 return nullptr;
806 }
807 name++;
808 if (*name == 'n') {
809 name++;
810 }
811 while (std::isdigit(*name)) {
812 name++;
813 }
814 if (*name != '_') {
815 return nullptr;
816 }
817 function_name_ = "non-virtual thunk to ";
818 return name + 1;
819 }
820
Christopher Ferris9323b722017-03-03 17:43:14 -0800821 if (*name == 'N') {
Christopher Ferris584333e2017-10-27 12:29:02 -0700822 parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel);
Christopher Ferris9323b722017-03-03 17:43:14 -0800823 parse_func_ = &Demangler::ParseFunctionName;
824 return name + 1;
825 }
826
Elliott Hughesd7bb8262018-02-09 17:30:14 -0800827 if (*name == 'S') {
828 name++;
829 if (*name == 't') {
830 function_name_ = "std::";
831 name++;
832 } else {
833 return nullptr;
834 }
835 }
836
Christopher Ferris9323b722017-03-03 17:43:14 -0800837 if (std::isdigit(*name)) {
838 name = GetStringFromLength(name, &function_name_);
Christopher Ferris4504bba2017-06-01 17:37:09 -0700839 } else if (*name == 'L' && std::isdigit(name[1])) {
840 name = GetStringFromLength(name + 1, &function_name_);
Christopher Ferris9323b722017-03-03 17:43:14 -0800841 } else {
842 name = AppendOperatorString(name);
843 function_name_ = cur_state_.str;
844 }
Christopher Ferris9323b722017-03-03 17:43:14 -0800845 cur_state_.Clear();
Christopher Ferris584333e2017-10-27 12:29:02 -0700846
847 // Check for a template argument, which will still be part of the function
848 // name.
849 if (name != nullptr && *name == 'I') {
850 parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel);
851 parse_func_ = &Demangler::ParseFunctionTemplateArguments;
852 return name + 1;
853 }
854 parse_func_ = &Demangler::ParseArgumentsAtTopLevel;
Christopher Ferris9323b722017-03-03 17:43:14 -0800855 return name;
856}
857
Christopher Ferris584333e2017-10-27 12:29:02 -0700858const char* Demangler::ParseArgumentsAtTopLevel(const char* name) {
859 // At the top level is the only place where T is allowed.
860 if (*name == 'T') {
861 name++;
862 name = ParseT(name);
863 if (name == nullptr) {
864 return nullptr;
865 }
866 AppendArgument(cur_state_.str);
867 cur_state_.str.clear();
868 return name;
869 }
870
871 return Demangler::ParseArguments(name);
872}
873
Christopher Ferris9323b722017-03-03 17:43:14 -0800874std::string Demangler::Parse(const char* name, size_t max_length) {
875 if (name[0] == '\0' || name[0] != '_' || name[1] == '\0' || name[1] != 'Z') {
876 // Name is not mangled.
877 return name;
878 }
879
880 Clear();
881
882 parse_func_ = &Demangler::FindFunctionName;
883 parse_funcs_.push_back(&Demangler::Fail);
884 const char* cur_name = name + 2;
885 while (cur_name != nullptr && *cur_name != '\0'
886 && static_cast<size_t>(cur_name - name) < max_length) {
887 cur_name = (this->*parse_func_)(cur_name);
888 }
Christopher Ferris15d2e422017-05-31 14:40:15 -0700889 if (cur_name == nullptr || *cur_name != '\0' || function_name_.empty() ||
890 !cur_state_.suffixes.empty()) {
Christopher Ferris9323b722017-03-03 17:43:14 -0800891 return name;
892 }
893
Christopher Ferris584333e2017-10-27 12:29:02 -0700894 std::string return_type;
895 if (template_found_) {
896 // Only a single argument with a template is not allowed.
897 if (cur_state_.args.size() == 1) {
898 return name;
899 }
900
901 // If there are at least two arguments, this template has a return type.
902 if (cur_state_.args.size() > 1) {
903 // The first argument will be the return value.
904 return_type = cur_state_.args[0] + ' ';
905 cur_state_.args.erase(cur_state_.args.begin());
906 }
907 }
908
Christopher Ferris9323b722017-03-03 17:43:14 -0800909 std::string arg_str;
910 if (cur_state_.args.size() == 1 && cur_state_.args[0] == "void") {
911 // If the only argument is void, then don't print any args.
912 arg_str = "()";
913 } else {
914 arg_str = GetArgumentsString();
915 if (!arg_str.empty()) {
916 arg_str = '(' + arg_str + ')';
917 }
918 }
Christopher Ferris584333e2017-10-27 12:29:02 -0700919 return return_type + function_name_ + arg_str + function_suffix_;
Christopher Ferris9323b722017-03-03 17:43:14 -0800920}
921
922std::string demangle(const char* name) {
923 Demangler demangler;
924 return demangler.Parse(name);
925}