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