1 // C++ IA64 / g++ v3 demangler -*- C++ -*- 2 3 // Copyright (C) 2002 - 2004, by 4 // 5 // Carlo Wood, Run on IRC <carlo@alinoe.com> 6 // RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt 7 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61 8 // 9 // This file may be distributed under the terms of the Q Public License 10 // version 1.0 as appearing in the file LICENSE.QPL included in the 11 // packaging of this file. 12 13 // This file implements demangling of "C++ ABI for Itanium"-mangled symbol 14 // and type names as described in Revision 1.74 of the C++ ABI as can be found 15 // at http://www.codesourcery.com/cxx-abi/abi.html#mangling 16 17 #ifndef _DEMANGLER_H 18 #define _DEMANGLER_H 1 19 20 #include <vector> 21 #include <string> 22 23 #ifndef _GLIBCXX_DEMANGLER_DEBUG 24 #define _GLIBCXX_DEMANGLER_CWDEBUG 0 25 #define _GLIBCXX_DEMANGLER_DEBUG(x) 26 #define _GLIBCXX_DEMANGLER_DOUT(cntrl, data) 27 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING(x) 28 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING2(x) 29 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING3(x) 30 #define _GLIBCXX_DEMANGLER_RETURN return M_result 31 #define _GLIBCXX_DEMANGLER_RETURN2 return M_result 32 #define _GLIBCXX_DEMANGLER_RETURN3 33 #define _GLIBCXX_DEMANGLER_FAILURE \ 34 do { M_result = false; return false; } while(0) 35 #else 36 #define _GLIBCXX_DEMANGLER_CWDEBUG 1 37 #endif 38 39 namespace __gnu_cxx 40 { 41 namespace demangler 42 { 43 44 enum substitution_nt 45 { 46 type, 47 template_template_param, 48 nested_name_prefix, 49 nested_name_template_prefix, 50 unscoped_template_name 51 }; 52 53 struct substitution_st 54 { 55 int M_start_pos; 56 substitution_nt M_type; 57 int M_number_of_prefixes; 58 substitution_stsubstitution_st59 substitution_st(int start_pos, 60 substitution_nt type, 61 int number_of_prefixes) 62 : M_start_pos(start_pos), M_type(type), 63 M_number_of_prefixes(number_of_prefixes) 64 { } 65 }; 66 67 enum simple_qualifier_nt 68 { 69 complex_or_imaginary = 'G', 70 pointer = 'P', 71 reference = 'R' 72 }; 73 74 enum cv_qualifier_nt 75 { 76 cv_qualifier = 'K' 77 }; 78 79 enum param_qualifier_nt 80 { 81 vendor_extension = 'U', 82 array = 'A', 83 pointer_to_member = 'M' 84 }; 85 86 template<typename Allocator> 87 class qualifier; 88 89 template<typename Allocator> 90 class qualifier_list; 91 92 template<typename Allocator> 93 class session; 94 95 template<typename Allocator> 96 class qualifier 97 { 98 typedef typename Allocator::template rebind<char>::other 99 char_Allocator; 100 typedef std::basic_string<char, std::char_traits<char>, char_Allocator> 101 string_type; 102 103 private: 104 char M_qualifier1; 105 char M_qualifier2; 106 char M_qualifier3; 107 mutable unsigned char M_cnt; 108 string_type M_optional_type; 109 int M_start_pos; 110 bool M_part_of_substitution; 111 112 public: qualifier(int start_pos,simple_qualifier_nt simple_qualifier,int inside_substitution)113 qualifier(int start_pos, 114 simple_qualifier_nt simple_qualifier, 115 int inside_substitution) 116 : M_qualifier1(simple_qualifier), 117 M_start_pos(start_pos), 118 M_part_of_substitution(inside_substitution) 119 { } 120 qualifier(int start_pos,cv_qualifier_nt,char const * start,int count,int inside_substitution)121 qualifier(int start_pos, 122 cv_qualifier_nt, 123 char const* start, 124 int count, 125 int inside_substitution) 126 : M_qualifier1(start[0]), 127 M_qualifier2((count > 1) ? start[1] : '\0'), 128 M_qualifier3((count > 2) ? start[2] : '\0'), 129 M_start_pos(start_pos), 130 M_part_of_substitution(inside_substitution) 131 { } 132 qualifier(int start_pos,param_qualifier_nt param_qualifier,string_type optional_type,int inside_substitution)133 qualifier(int start_pos, 134 param_qualifier_nt param_qualifier, 135 string_type optional_type, 136 int inside_substitution) 137 : M_qualifier1(param_qualifier), 138 M_optional_type(optional_type), 139 M_start_pos(start_pos), 140 M_part_of_substitution(inside_substitution) 141 { } 142 143 int get_start_pos(void)144 get_start_pos(void) const 145 { return M_start_pos; } 146 147 char first_qualifier(void)148 first_qualifier(void) const 149 { M_cnt = 1; return M_qualifier1; } 150 151 char next_qualifier(void)152 next_qualifier(void) const 153 { 154 return (++M_cnt == 2) ? M_qualifier2 155 : ((M_cnt == 3) ? M_qualifier3 : 0); 156 } 157 158 string_type const& get_optional_type(void)159 get_optional_type(void) const 160 { return M_optional_type; } 161 162 bool part_of_substitution(void)163 part_of_substitution(void) const 164 { return M_part_of_substitution; } 165 166 #if _GLIBCXX_DEMANGLER_CWDEBUG 167 friend std::ostream& operator<<(std::ostream& os, qualifier const& qual) 168 { 169 os << (char)qual.M_qualifier1; 170 if (qual.M_qualifier1 == vendor_extension || 171 qual.M_qualifier1 == array || 172 qual.M_qualifier1 == pointer_to_member) 173 os << " [" << qual.M_optional_type << ']'; 174 else if (qual.M_qualifier1 == 'K' || 175 qual.M_qualifier1 == 'V' || 176 qual.M_qualifier1 == 'r') 177 { 178 if (qual.M_qualifier2) 179 { 180 os << (char)qual.M_qualifier2; 181 if (qual.M_qualifier3) 182 os << (char)qual.M_qualifier3; 183 } 184 } 185 return os; 186 } 187 #endif 188 }; 189 190 template<typename Allocator> 191 class qualifier_list 192 { 193 typedef typename Allocator::template rebind<char>::other 194 char_Allocator; 195 typedef std::basic_string<char, std::char_traits<char>, char_Allocator> 196 string_type; 197 198 private: 199 mutable bool M_printing_suppressed; 200 typedef qualifier<Allocator> qual; 201 typedef typename Allocator::template rebind<qual>::other qual_Allocator; 202 typedef std::vector<qual, qual_Allocator> qual_vector; 203 qual_vector M_qualifier_starts; 204 session<Allocator>& M_demangler; 205 206 void decode_KVrA(string_type& prefix, string_type& postfix, int cvq, 207 typename qual_vector:: 208 const_reverse_iterator const& iter_array) const; 209 210 public: qualifier_list(session<Allocator> & demangler_obj)211 qualifier_list(session<Allocator>& demangler_obj) 212 : M_printing_suppressed(false), M_demangler(demangler_obj) 213 { } 214 215 void add_qualifier_start(simple_qualifier_nt simple_qualifier,int start_pos,int inside_substitution)216 add_qualifier_start(simple_qualifier_nt simple_qualifier, 217 int start_pos, 218 int inside_substitution) 219 { M_qualifier_starts. 220 push_back(qualifier<Allocator>(start_pos, 221 simple_qualifier, inside_substitution)); } 222 223 void add_qualifier_start(cv_qualifier_nt cv_qualifier,int start_pos,int count,int inside_substitution)224 add_qualifier_start(cv_qualifier_nt cv_qualifier, 225 int start_pos, 226 int count, 227 int inside_substitution) 228 { M_qualifier_starts. 229 push_back(qualifier<Allocator>(start_pos, 230 cv_qualifier, &M_demangler.M_str[start_pos], 231 count, inside_substitution)); } 232 233 void add_qualifier_start(param_qualifier_nt param_qualifier,int start_pos,string_type optional_type,int inside_substitution)234 add_qualifier_start(param_qualifier_nt param_qualifier, 235 int start_pos, 236 string_type optional_type, 237 int inside_substitution) 238 { M_qualifier_starts. 239 push_back(qualifier<Allocator>(start_pos, 240 param_qualifier, optional_type, inside_substitution)); } 241 242 void 243 decode_qualifiers(string_type& prefix, 244 string_type& postfix, 245 bool member_function_pointer_qualifiers = false) const; 246 247 bool suppressed(void)248 suppressed(void) const 249 { return M_printing_suppressed; } 250 251 void printing_suppressed(void)252 printing_suppressed(void) 253 { M_printing_suppressed = true; } 254 255 size_t size(void)256 size(void) const 257 { return M_qualifier_starts.size(); } 258 259 #if _GLIBCXX_DEMANGLER_CWDEBUG 260 friend std::ostream& operator<<(std::ostream& os, qualifier_list const& list) 261 { 262 typename qual_vector::const_iterator 263 iter = list.M_qualifier_starts.begin(); 264 if (iter != list.M_qualifier_starts.end()) 265 { 266 os << "{ " << *iter; 267 while (++iter != list.M_qualifier_starts.end()) 268 os << ", " << *iter; 269 os << " }"; 270 } 271 else 272 os << "{ }"; 273 return os; 274 } 275 #endif 276 }; 277 278 struct implementation_details 279 { 280 private: 281 unsigned int M_style; 282 283 public: 284 // The following flags change the behaviour of the demangler. The 285 // default behaviour is that none of these flags is set. 286 287 static unsigned int const style_void = 1; 288 // Default behaviour: int f() 289 // Use (void) instead of (): int f(void) 290 291 static unsigned int const style_literal = 2; 292 // Default behaviour: (long)13, 293 // (unsigned long long)19 294 // Use extensions 'u', 'l' and 'll' for integral 295 // literals (as in template arguments): 13l, 19ull 296 297 static unsigned int const style_literal_int = 4; 298 // Default behaviour: 4 299 // Use also an explicit 300 // cast for int in literals: (int)4 301 302 static unsigned int const style_compact_expr_ops = 8; 303 // Default behaviour: (i) < (3), sizeof (int) 304 // Don't output spaces around 305 // operators in expressions: (i)<(3), sizeof(int) 306 307 static unsigned int const style_sizeof_typename = 16; 308 // Default behaviour: sizeof (X::t) 309 // Put 'typename' infront of <nested-name> 310 // types inside a 'sizeof': sizeof (typename X::t) 311 312 public: 313 implementation_details(unsigned int style_flags = 0) : M_styleimplementation_details314 M_style(style_flags) { } ~implementation_detailsimplementation_details315 virtual ~implementation_details() { } get_style_voidimplementation_details316 bool get_style_void(void) const 317 { return (M_style & style_void); } get_style_literalimplementation_details318 bool get_style_literal(void) const 319 { return (M_style & style_literal); } get_style_literal_intimplementation_details320 bool get_style_literal_int(void) const 321 { return (M_style & style_literal_int); } get_style_compact_expr_opsimplementation_details322 bool get_style_compact_expr_ops(void) const 323 { return (M_style & style_compact_expr_ops); } get_style_sizeof_typenameimplementation_details324 bool get_style_sizeof_typename(void) const 325 { return (M_style & style_sizeof_typename); } 326 // This can be overridden by user implementations. decode_realimplementation_details327 virtual bool decode_real(char* /* output */, unsigned long* /* input */, 328 size_t /* size_of_real */) const 329 { return false; } 330 }; 331 332 template<typename Allocator> 333 class session 334 { 335 friend class qualifier_list<Allocator>; 336 typedef typename Allocator::template rebind<char>::other 337 char_Allocator; 338 typedef std::basic_string<char, std::char_traits<char>, char_Allocator> 339 string_type; 340 341 private: 342 char const* M_str; 343 int M_pos; 344 int M_maxpos; 345 bool M_result; 346 int M_inside_template_args; 347 int M_inside_type; 348 int M_inside_substitution; 349 bool M_saw_destructor; 350 bool M_name_is_cdtor; 351 bool M_name_is_template; 352 bool M_name_is_conversion_operator; 353 bool M_template_args_need_space; 354 string_type M_function_name; 355 typedef typename Allocator::template rebind<int>::other 356 int_Allocator; 357 typedef typename Allocator::template rebind<substitution_st>::other 358 subst_Allocator; 359 std::vector<int, int_Allocator> M_template_arg_pos; 360 int M_template_arg_pos_offset; 361 std::vector<substitution_st, subst_Allocator> M_substitutions_pos; 362 implementation_details const& M_implementation_details; 363 #if _GLIBCXX_DEMANGLER_CWDEBUG 364 bool M_inside_add_substitution; 365 #endif 366 367 public: 368 explicit session(char const* in, int len, 369 implementation_details const& id = implementation_details()) M_str(in)370 : M_str(in), M_pos(0), M_maxpos(len - 1), M_result(true), 371 M_inside_template_args(0), M_inside_type(0), 372 M_inside_substitution(0), M_saw_destructor(false), 373 M_name_is_cdtor(false), M_name_is_template(false), 374 M_name_is_conversion_operator(false), 375 M_template_args_need_space(false), M_template_arg_pos_offset(0), 376 M_implementation_details(id) 377 #if _GLIBCXX_DEMANGLER_CWDEBUG 378 , M_inside_add_substitution(false) 379 #endif 380 { } 381 382 static int 383 decode_encoding(string_type& output, char const* input, int len, 384 implementation_details const& id = implementation_details()); 385 386 bool 387 decode_type(string_type& output, 388 qualifier_list<Allocator>* qualifiers = NULL) 389 { 390 string_type postfix; 391 bool res = decode_type_with_postfix(output, postfix, qualifiers); 392 output += postfix; 393 return res; 394 } 395 396 bool remaining_input_characters(void)397 remaining_input_characters(void) const 398 { return current() != 0; } 399 400 private: 401 char current(void)402 current(void) const 403 { return (M_pos > M_maxpos) ? 0 : M_str[M_pos]; } 404 405 char next_peek(void)406 next_peek(void) const 407 { return (M_pos >= M_maxpos) ? 0 : M_str[M_pos + 1]; } 408 409 char next(void)410 next(void) 411 { return (M_pos >= M_maxpos) ? 0 : M_str[++M_pos]; } 412 413 char eat_current(void)414 eat_current(void) 415 { return (M_pos > M_maxpos) ? 0 : M_str[M_pos++]; } 416 417 void store(int & saved_pos)418 store(int& saved_pos) 419 { saved_pos = M_pos; } 420 421 void restore(int saved_pos)422 restore(int saved_pos) 423 { M_pos = saved_pos; M_result = true; } 424 425 void 426 add_substitution(int start_pos, 427 substitution_nt sub_type, 428 int number_of_prefixes = 0); 429 430 bool decode_type_with_postfix(string_type& prefix, 431 string_type& postfix, qualifier_list<Allocator>* qualifiers = NULL); 432 bool decode_bare_function_type(string_type& output); 433 bool decode_builtin_type(string_type& output); 434 bool decode_call_offset(string_type& output); 435 bool decode_class_enum_type(string_type& output); 436 bool decode_expression(string_type& output); 437 bool decode_literal(string_type& output); 438 bool decode_local_name(string_type& output); 439 bool decode_name(string_type& output, 440 string_type& nested_name_qualifiers); 441 bool decode_nested_name(string_type& output, 442 string_type& qualifiers); 443 bool decode_number(string_type& output); 444 bool decode_operator_name(string_type& output); 445 bool decode_source_name(string_type& output); 446 bool decode_substitution(string_type& output, 447 qualifier_list<Allocator>* qualifiers = NULL); 448 bool decode_template_args(string_type& output); 449 bool decode_template_param(string_type& output, 450 qualifier_list<Allocator>* qualifiers = NULL); 451 bool decode_unqualified_name(string_type& output); 452 bool decode_unscoped_name(string_type& output); 453 bool decode_non_negative_decimal_integer(string_type& output); 454 bool decode_special_name(string_type& output); 455 bool decode_real(string_type& output, size_t size_of_real); 456 }; 457 458 template<typename Allocator> 459 #if !_GLIBCXX_DEMANGLER_CWDEBUG 460 inline 461 #endif 462 void add_substitution(int start_pos,substitution_nt sub_type,int number_of_prefixes)463 session<Allocator>::add_substitution(int start_pos, 464 substitution_nt sub_type, 465 int number_of_prefixes) 466 { 467 if (!M_inside_substitution) 468 { 469 #if _GLIBCXX_DEMANGLER_CWDEBUG 470 if (M_inside_add_substitution) 471 return; 472 #endif 473 M_substitutions_pos. 474 push_back(substitution_st(start_pos, 475 sub_type, number_of_prefixes)); 476 #if _GLIBCXX_DEMANGLER_CWDEBUG 477 if (!libcwd::channels::dc::demangler.is_on()) 478 return; 479 string_type substitution_name("S"); 480 int n = M_substitutions_pos.size() - 1; 481 if (n > 0) 482 substitution_name += (n <= 10) ? (char)(n + '0' - 1) 483 : (char)(n + 'A' - 11); 484 substitution_name += '_'; 485 string_type subst; 486 int saved_pos = M_pos; 487 M_pos = start_pos; 488 M_inside_add_substitution = true; 489 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.off() ); 490 switch(sub_type) 491 { 492 case type: 493 decode_type(subst); 494 break; 495 case template_template_param: 496 decode_template_param(subst); 497 break; 498 case nested_name_prefix: 499 case nested_name_template_prefix: 500 for (int cnt = number_of_prefixes; cnt > 0; --cnt) 501 { 502 if (current() == 'I') 503 { 504 subst += ' '; 505 decode_template_args(subst); 506 } 507 else 508 { 509 if (cnt < number_of_prefixes) 510 subst += "::"; 511 if (current() == 'S') 512 decode_substitution(subst); 513 else if (current() == 'T') 514 decode_template_param(subst); 515 else 516 decode_unqualified_name(subst); 517 } 518 } 519 break; 520 case unscoped_template_name: 521 decode_unscoped_name(subst); 522 break; 523 } 524 M_pos = saved_pos; 525 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.on() ); 526 _GLIBCXX_DEMANGLER_DOUT(dc::demangler, 527 "Adding substitution " << substitution_name 528 << " : " << subst 529 << " (from " << location_ct((char*)__builtin_return_address(0) 530 + builtin_return_address_offset) 531 << " <- " << location_ct((char*)__builtin_return_address(1) 532 + builtin_return_address_offset) 533 << " <- " << location_ct((char*)__builtin_return_address(2) 534 + builtin_return_address_offset) 535 << ")."); 536 M_inside_add_substitution = false; 537 #endif 538 } 539 } 540 541 // We don't want to depend on locale (or include <cctype> for that matter). 542 // We also don't want to use "safe-ctype.h" because that headerfile is not 543 // available to the users. isdigit(char c)544 inline bool isdigit(char c) { return c >= '0' && c <= '9'; } islower(char c)545 inline bool islower(char c) { return c >= 'a' && c <= 'z'; } isupper(char c)546 inline bool isupper(char c) { return c >= 'A' && c <= 'Z'; } tolower(char c)547 inline char tolower(char c) { return isupper(c) ? c - 'A' + 'a' : c; } 548 549 // 550 // <non-negative decimal integer> ::= 0 551 // ::= 1|2|3|4|5|6|7|8|9 [<digit>+] 552 // <digit> ::= 0|1|2|3|4|5|6|7|8|9 553 // 554 template<typename Allocator> 555 bool 556 session<Allocator>:: decode_non_negative_decimal_integer(string_type & output)557 decode_non_negative_decimal_integer(string_type& output) 558 { 559 char c = current(); 560 if (c == '0') 561 { 562 output += '0'; 563 eat_current(); 564 } 565 else if (!isdigit(c)) 566 M_result = false; 567 else 568 { 569 do 570 { 571 output += c; 572 } 573 while (isdigit((c = next()))); 574 } 575 return M_result; 576 } 577 578 // <number> ::= [n] <non-negative decimal integer> 579 // 580 template<typename Allocator> 581 bool decode_number(string_type & output)582 session<Allocator>::decode_number(string_type& output) 583 { 584 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_number"); 585 if (current() != 'n') 586 decode_non_negative_decimal_integer(output); 587 else 588 { 589 output += '-'; 590 eat_current(); 591 decode_non_negative_decimal_integer(output); 592 } 593 _GLIBCXX_DEMANGLER_RETURN; 594 } 595 596 // <builtin-type> ::= v # void 597 // ::= w # wchar_t 598 // ::= b # bool 599 // ::= c # char 600 // ::= a # signed char 601 // ::= h # unsigned char 602 // ::= s # short 603 // ::= t # unsigned short 604 // ::= i # int 605 // ::= j # unsigned int 606 // ::= l # long 607 // ::= m # unsigned long 608 // ::= x # long long, __int64 609 // ::= y # unsigned long long, __int64 610 // ::= n # __int128 611 // ::= o # unsigned __int128 612 // ::= f # float 613 // ::= d # double 614 // ::= e # long double, __float80 615 // ::= g # __float128 616 // ::= z # ellipsis 617 // ::= u <source-name> # vendor extended type 618 // 619 char const* const builtin_type_c[26] = 620 { 621 "signed char", // a 622 "bool", // b 623 "char", // c 624 "double", // d 625 "long double", // e 626 "float", // f 627 "__float128", // g 628 "unsigned char", // h 629 "int", // i 630 "unsigned int", // j 631 NULL, // k 632 "long", // l 633 "unsigned long", // m 634 "__int128", // n 635 "unsigned __int128", // o 636 NULL, // p 637 NULL, // q 638 NULL, // r 639 "short", // s 640 "unsigned short", // t 641 NULL, // u 642 "void", // v 643 "wchar_t", // w 644 "long long", // x 645 "unsigned long long", // y 646 "..." // z 647 }; 648 649 // 650 template<typename Allocator> 651 bool decode_builtin_type(string_type & output)652 session<Allocator>::decode_builtin_type(string_type& output) 653 { 654 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_builtin_type"); 655 if (!islower(current())) 656 _GLIBCXX_DEMANGLER_FAILURE; 657 char const* bt = builtin_type_c[current() - 'a']; 658 if (!bt) 659 _GLIBCXX_DEMANGLER_FAILURE; 660 output += bt; 661 eat_current(); 662 _GLIBCXX_DEMANGLER_RETURN; 663 } 664 665 // <class-enum-type> ::= <name> 666 // 667 template<typename Allocator> 668 bool decode_class_enum_type(string_type & output)669 session<Allocator>::decode_class_enum_type(string_type& output) 670 { 671 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_class_enum_type"); 672 string_type nested_name_qualifiers; 673 if (!decode_name(output, nested_name_qualifiers)) 674 _GLIBCXX_DEMANGLER_FAILURE; 675 output += nested_name_qualifiers; 676 _GLIBCXX_DEMANGLER_RETURN; 677 } 678 679 // <substitution> ::= 680 // S <seq-id> _ 681 // S_ 682 // St # ::std:: 683 // Sa # ::std::allocator 684 // Sb # ::std::basic_string 685 // Ss # ::std::basic_string<char, std::char_traits<char>, 686 // std::allocator<char> > 687 // Si # ::std::basic_istream<char, std::char_traits<char> > 688 // So # ::std::basic_ostream<char, std::char_traits<char> > 689 // Sd # ::std::basic_iostream<char, std::char_traits<char> > 690 // 691 // <seq-id> ::= 692 // 0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z 693 // [<seq-id>] # Base 36 number 694 // 695 template<typename Allocator> 696 bool decode_substitution(string_type & output,qualifier_list<Allocator> * qualifiers)697 session<Allocator>::decode_substitution(string_type& output, 698 qualifier_list<Allocator>* qualifiers) 699 { 700 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_substitution"); 701 unsigned int value = 0; 702 char c = next(); 703 if (c != '_') 704 { 705 switch(c) 706 { 707 case 'a': 708 { 709 output += "std::allocator"; 710 if (!M_inside_template_args) 711 { 712 M_function_name = "allocator"; 713 M_name_is_template = true; 714 M_name_is_cdtor = false; 715 M_name_is_conversion_operator = false; 716 } 717 eat_current(); 718 if (qualifiers) 719 qualifiers->printing_suppressed(); 720 _GLIBCXX_DEMANGLER_RETURN; 721 } 722 case 'b': 723 { 724 output += "std::basic_string"; 725 if (!M_inside_template_args) 726 { 727 M_function_name = "basic_string"; 728 M_name_is_template = true; 729 M_name_is_cdtor = false; 730 M_name_is_conversion_operator = false; 731 } 732 eat_current(); 733 if (qualifiers) 734 qualifiers->printing_suppressed(); 735 _GLIBCXX_DEMANGLER_RETURN; 736 } 737 case 'd': 738 output += "std::iostream"; 739 if (!M_inside_template_args) 740 { 741 M_function_name = "iostream"; 742 M_name_is_template = true; 743 M_name_is_cdtor = false; 744 M_name_is_conversion_operator = false; 745 } 746 eat_current(); 747 if (qualifiers) 748 qualifiers->printing_suppressed(); 749 _GLIBCXX_DEMANGLER_RETURN; 750 case 'i': 751 output += "std::istream"; 752 if (!M_inside_template_args) 753 { 754 M_function_name = "istream"; 755 M_name_is_template = true; 756 M_name_is_cdtor = false; 757 M_name_is_conversion_operator = false; 758 } 759 eat_current(); 760 if (qualifiers) 761 qualifiers->printing_suppressed(); 762 _GLIBCXX_DEMANGLER_RETURN; 763 case 'o': 764 output += "std::ostream"; 765 if (!M_inside_template_args) 766 { 767 M_function_name = "ostream"; 768 M_name_is_template = true; 769 M_name_is_cdtor = false; 770 M_name_is_conversion_operator = false; 771 } 772 eat_current(); 773 if (qualifiers) 774 qualifiers->printing_suppressed(); 775 _GLIBCXX_DEMANGLER_RETURN; 776 case 's': 777 output += "std::string"; 778 if (!M_inside_template_args) 779 { 780 M_function_name = "string"; 781 M_name_is_template = true; 782 M_name_is_cdtor = false; 783 M_name_is_conversion_operator = false; 784 } 785 eat_current(); 786 if (qualifiers) 787 qualifiers->printing_suppressed(); 788 _GLIBCXX_DEMANGLER_RETURN; 789 case 't': 790 output += "std"; 791 eat_current(); 792 if (qualifiers) 793 qualifiers->printing_suppressed(); 794 _GLIBCXX_DEMANGLER_RETURN; 795 default: 796 for(;; c = next()) 797 { 798 if (isdigit(c)) 799 value = value * 36 + c - '0'; 800 else if (isupper(c)) 801 value = value * 36 + c - 'A' + 10; 802 else if (c == '_') 803 break; 804 else 805 _GLIBCXX_DEMANGLER_FAILURE; 806 } 807 ++value; 808 break; 809 } 810 } 811 eat_current(); 812 if (value >= M_substitutions_pos.size() || 813 M_inside_type > 20) // Rather than core dump. 814 _GLIBCXX_DEMANGLER_FAILURE; 815 ++M_inside_substitution; 816 int saved_pos = M_pos; 817 substitution_st& substitution(M_substitutions_pos[value]); 818 M_pos = substitution.M_start_pos; 819 switch(substitution.M_type) 820 { 821 case type: 822 decode_type(output, qualifiers); 823 break; 824 case template_template_param: 825 decode_template_param(output, qualifiers); 826 break; 827 case nested_name_prefix: 828 case nested_name_template_prefix: 829 for (int cnt = substitution.M_number_of_prefixes; cnt > 0; --cnt) 830 { 831 if (current() == 'I') 832 { 833 if (M_template_args_need_space) 834 output += ' '; 835 M_template_args_need_space = false; 836 if (!decode_template_args(output)) 837 _GLIBCXX_DEMANGLER_FAILURE; 838 } 839 else 840 { 841 if (cnt < substitution.M_number_of_prefixes) 842 output += "::"; 843 if (current() == 'S') 844 { 845 if (!decode_substitution(output)) 846 _GLIBCXX_DEMANGLER_FAILURE; 847 } 848 else if (!decode_unqualified_name(output)) 849 _GLIBCXX_DEMANGLER_FAILURE; 850 } 851 } 852 if (qualifiers) 853 qualifiers->printing_suppressed(); 854 break; 855 case unscoped_template_name: 856 decode_unscoped_name(output); 857 if (qualifiers) 858 qualifiers->printing_suppressed(); 859 break; 860 } 861 M_pos = saved_pos; 862 --M_inside_substitution; 863 _GLIBCXX_DEMANGLER_RETURN; 864 } 865 866 // <template-param> ::= T_ # first template parameter 867 // ::= T <parameter-2 non-negative number> _ 868 // 869 template<typename Allocator> 870 bool decode_template_param(string_type & output,qualifier_list<Allocator> * qualifiers)871 session<Allocator>::decode_template_param(string_type& output, 872 qualifier_list<Allocator>* qualifiers) 873 { 874 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_parameter"); 875 if (current() != 'T') 876 _GLIBCXX_DEMANGLER_FAILURE; 877 unsigned int value = 0; 878 char c; 879 if ((c = next()) != '_') 880 { 881 while(isdigit(c)) 882 { 883 value = value * 10 + c - '0'; 884 c = next(); 885 } 886 ++value; 887 } 888 if (eat_current() != '_') 889 _GLIBCXX_DEMANGLER_FAILURE; 890 value += M_template_arg_pos_offset; 891 if (value >= M_template_arg_pos.size()) 892 _GLIBCXX_DEMANGLER_FAILURE; 893 int saved_pos = M_pos; 894 M_pos = M_template_arg_pos[value]; 895 if (M_inside_type > 20) // Rather than core dump. 896 _GLIBCXX_DEMANGLER_FAILURE; 897 ++M_inside_substitution; 898 if (current() == 'X') 899 { 900 eat_current(); 901 decode_expression(output); 902 } 903 else if (current() == 'L') 904 decode_literal(output); 905 else 906 decode_type(output, qualifiers); 907 --M_inside_substitution; 908 M_pos = saved_pos; 909 _GLIBCXX_DEMANGLER_RETURN; 910 } 911 912 template<typename Allocator> 913 bool decode_real(string_type & output,size_t size_of_real)914 session<Allocator>::decode_real(string_type& output, size_t size_of_real) 915 { 916 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_real"); 917 918 unsigned long words[4]; // 32 bit per long, maximum of 128 bits. 919 unsigned long* word = &words[0]; 920 921 int saved_pos; 922 store(saved_pos); 923 924 // The following assumes that leading zeroes are also included in the 925 // mangled name, I am not sure that is conforming to the C++-ABI, but 926 // it is what g++ does. 927 unsigned char nibble, c = current(); 928 for(size_t word_cnt = size_of_real / 4; word_cnt > 0; --word_cnt) 929 { 930 for (int nibble_cnt = 0; nibble_cnt < 8; ++nibble_cnt) 931 { 932 // Translate character into nibble. 933 if (c < '0' || c > 'f') 934 _GLIBCXX_DEMANGLER_FAILURE; 935 if (c <= '9') 936 nibble = c - '0'; 937 else if (c >= 'a') 938 nibble = c - 'a' + 10; 939 else 940 _GLIBCXX_DEMANGLER_FAILURE; 941 // Write nibble into word array. 942 if (nibble_cnt == 0) 943 *word = nibble << 28; 944 else 945 *word |= (nibble << (28 - 4 * nibble_cnt)); 946 c = next(); 947 } 948 ++word; 949 } 950 char buf[24]; 951 if (M_implementation_details.decode_real(buf, words, size_of_real)) 952 { 953 output += buf; 954 _GLIBCXX_DEMANGLER_RETURN; 955 } 956 restore(saved_pos); 957 958 output += '['; 959 c = current(); 960 for(size_t nibble_cnt = 0; nibble_cnt < 2 * size_of_real; ++nibble_cnt) 961 { 962 if (c < '0' || c > 'f' || (c > '9' && c < 'a')) 963 _GLIBCXX_DEMANGLER_FAILURE; 964 output += c; 965 c = next(); 966 } 967 output += ']'; 968 969 _GLIBCXX_DEMANGLER_RETURN; 970 } 971 972 template<typename Allocator> 973 bool decode_literal(string_type & output)974 session<Allocator>::decode_literal(string_type& output) 975 { 976 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_literal"); 977 eat_current(); // Eat the 'L'. 978 if (current() == '_') 979 { 980 if (next() != 'Z') 981 _GLIBCXX_DEMANGLER_FAILURE; 982 eat_current(); 983 if ((M_pos += decode_encoding(output, M_str + M_pos, 984 M_maxpos - M_pos + 1, M_implementation_details)) < 0) 985 _GLIBCXX_DEMANGLER_FAILURE; 986 } 987 else 988 { 989 // Special cases 990 if (current() == 'b') 991 { 992 if (next() == '0') 993 output += "false"; 994 else 995 output += "true"; 996 eat_current(); 997 _GLIBCXX_DEMANGLER_RETURN; 998 } 999 char c = current(); 1000 if ((c == 'i' || c == 'j' || c == 'l' || 1001 c == 'm' || c == 'x' || c == 'y') && 1002 M_implementation_details.get_style_literal()) 1003 eat_current(); 1004 else if (c == 'i' && 1005 !M_implementation_details.get_style_literal_int()) 1006 eat_current(); 1007 else 1008 { 1009 output += '('; 1010 if (!decode_type(output)) 1011 _GLIBCXX_DEMANGLER_FAILURE; 1012 output += ')'; 1013 } 1014 if (c >= 'd' && c <= 'g') 1015 { 1016 size_t size_of_real = (c == 'd') ? sizeof(double) : 1017 ((c == 'f') ? sizeof(float) : 1018 (c == 'e') ? sizeof(long double) : 16); 1019 if (!decode_real(output, size_of_real)) 1020 _GLIBCXX_DEMANGLER_FAILURE; 1021 } 1022 else if (!decode_number(output)) 1023 _GLIBCXX_DEMANGLER_FAILURE; 1024 if (M_implementation_details.get_style_literal()) 1025 { 1026 if (c == 'j' || c == 'm' || c == 'y') 1027 output += 'u'; 1028 if (c == 'l' || c == 'm') 1029 output += 'l'; 1030 if (c == 'x' || c == 'y') 1031 output += "ll"; 1032 } 1033 } 1034 _GLIBCXX_DEMANGLER_RETURN; 1035 } 1036 1037 // <operator-name> ::= 1038 // nw # new 1039 // na # new[] 1040 // dl # delete 1041 // da # delete[] 1042 // ps # + (unary) 1043 // ng # - (unary) 1044 // ad # & (unary) 1045 // de # * (unary) 1046 // co # ~ 1047 // pl # + 1048 // mi # - 1049 // ml # * 1050 // dv # / 1051 // rm # % 1052 // an # & 1053 // or # | 1054 // eo # ^ 1055 // aS # = 1056 // pL # += 1057 // mI # -= 1058 // mL # *= 1059 // dV # /= 1060 // rM # %= 1061 // aN # &= 1062 // oR # |= 1063 // eO # ^= 1064 // ls # << 1065 // rs # >> 1066 // lS # <<= 1067 // rS # >>= 1068 // eq # == 1069 // ne # != 1070 // lt # < 1071 // gt # > 1072 // le # <= 1073 // ge # >= 1074 // nt # ! 1075 // aa # && 1076 // oo # || 1077 // pp # ++ 1078 // mm # -- 1079 // cm # , 1080 // pm # ->* 1081 // pt # -> 1082 // cl # () 1083 // ix # [] 1084 // qu # ? 1085 // st # sizeof (a type) 1086 // sz # sizeof (an expression) 1087 // cv <type> # (cast) 1088 // v <digit> <source-name> # vendor extended operator 1089 // 1090 // Symbol operator codes exist of two characters, we need to find a 1091 // quick hash so that their names can be looked up in a table. 1092 // 1093 // The puzzle :) 1094 // Shift the rows so that there is at most one character per column. 1095 // 1096 // A perfect solution (Oh no, it's THE MATRIX!): 1097 // horizontal 1098 // ....................................... offset + 'a' 1099 // a, a||d|||||||||n||||s|||||||||||||||||||| 0 1100 // c, || |||||||lm o||| |||||||||||||||||||| 0 1101 // d, || a|||e|| l|| ||||||v||||||||||||| 4 1102 // e, || ||| || || |||o|q ||||||||||||| 8 1103 // g, || ||| || || e|| | ||||||||t|||| 15 1104 // i, || ||| || || || | |||||||| |||x 15 1105 // l, |e ||| || st || | |||||||| ||| -2 1106 // m, | |i| lm || | |||||||| ||| -2 1107 // n, a e g t| w |||||||| ||| 1 1108 // o, | ||||o||r ||| 16 1109 // p, | ||lm |p st| 17 1110 // q, | u| | | 6 1111 // r, m s | | 9 1112 // s, t z 12 1113 // ....................................... 1114 // ^ ^__ second character 1115 // |___ first character 1116 // 1117 1118 // Putting that solution in tables: 1119 1120 char const offset_table_c [1 + CHAR_MAX - CHAR_MIN ] = 1121 { 1122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1128 #if (CHAR_MIN < 0) 1129 // Add -CHAR_MIN extra zeroes (128): 1130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1138 // a b c d e f g h i j k 1139 0, -97, 0, -97, -93, -89, 0, -82, 0, -82, 0, 0, 1140 // l m n o p q r s t u v 1141 -99, -99, -96, -81, -80, -91, -88, -85, 0, 0, 0, 1142 #else 1143 // a b c d e f g h i j k 1144 0, 159, 0, 159, 163, 167, 0, 174, 0, 174, 0, 0, 1145 // l m n o p q r s t u v 1146 157, 157, 160, 175, 176, 165, 168, 171, 0, 0, 0, 1147 #endif 1148 // ... more zeros 1149 }; 1150 1151 enum xary_nt { 1152 unary, 1153 binary, 1154 trinary 1155 }; 1156 1157 struct entry_st 1158 { 1159 char const* opcode; 1160 char const* symbol_name; 1161 xary_nt type; 1162 }; 1163 1164 entry_st const symbol_name_table_c[39] = { 1165 { "aa", "operator&&", binary }, 1166 { "na", "operator new[]", unary }, 1167 { "le", "operator<=", binary }, 1168 { "ad", "operator&", unary }, 1169 { "da", "operator delete[]", unary }, 1170 { "ne", "operator!=", binary }, 1171 { "mi=", "operator-", binary }, 1172 { "ng", "operator-", unary }, 1173 { "de", "operator*", unary }, 1174 { "ml=", "operator*", binary }, 1175 { "mm", "operator--", unary }, 1176 { "cl", "operator()", unary }, 1177 { "cm", "operator,", binary }, 1178 { "an=", "operator&", binary }, 1179 { "co", "operator~", binary }, 1180 { "dl", "operator delete", unary }, 1181 { "ls=", "operator<<", binary }, 1182 { "lt", "operator<", binary }, 1183 { "as=", "operator", binary }, 1184 { "ge", "operator>=", binary }, 1185 { "nt", "operator!", unary }, 1186 { "rm=", "operator%", binary }, 1187 { "eo=", "operator^", binary }, 1188 { "nw", "operator new", unary }, 1189 { "eq", "operator==", binary }, 1190 { "dv=", "operator/", binary }, 1191 { "qu", "operator?", trinary }, 1192 { "rs=", "operator>>", binary }, 1193 { "pl=", "operator+", binary }, 1194 { "pm", "operator->*", binary }, 1195 { "oo", "operator||", binary }, 1196 { "st", "sizeof", unary }, 1197 { "pp", "operator++", unary }, 1198 { "or=", "operator|", binary }, 1199 { "gt", "operator>", binary }, 1200 { "ps", "operator+", unary }, 1201 { "pt", "operator->", binary }, 1202 { "sz", "sizeof", unary }, 1203 { "ix", "operator[]", unary } 1204 }; 1205 1206 template<typename Allocator> 1207 bool decode_operator_name(string_type & output)1208 session<Allocator>::decode_operator_name(string_type& output) 1209 { 1210 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_operator_name"); 1211 1212 char opcode0 = current(); 1213 char opcode1 = tolower(next()); 1214 1215 register char hash = offset_table_c[opcode0 - CHAR_MIN]; 1216 if (hash) 1217 { 1218 hash += opcode1; 1219 if ( 1220 #if (CHAR_MIN < 0) 1221 hash >= 0 && 1222 #endif 1223 hash < 39) 1224 { 1225 int index = static_cast<int>(static_cast<unsigned char>(hash)); 1226 entry_st entry = symbol_name_table_c[index]; 1227 if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1 1228 && (opcode1 == current() || entry.opcode[2] == '=')) 1229 { 1230 output += entry.symbol_name; 1231 if (opcode1 != current()) 1232 output += '='; 1233 eat_current(); 1234 if (hash == 16 || hash == 17) 1235 M_template_args_need_space = true; 1236 _GLIBCXX_DEMANGLER_RETURN; 1237 } 1238 else if (opcode0 == 'c' && opcode1 == 'v') // casting operator 1239 { 1240 eat_current(); 1241 output += "operator "; 1242 if (current() == 'T') 1243 { 1244 // This is a templated cast operator. 1245 // It must be of the form "cvT_I...E". 1246 // Let M_template_arg_pos already point 1247 // to the template argument. 1248 M_template_arg_pos_offset = M_template_arg_pos.size(); 1249 M_template_arg_pos.push_back(M_pos + 3); 1250 } 1251 if (!decode_type(output)) 1252 _GLIBCXX_DEMANGLER_FAILURE; 1253 if (!M_inside_template_args) 1254 M_name_is_conversion_operator = true; 1255 _GLIBCXX_DEMANGLER_RETURN; 1256 } 1257 } 1258 } 1259 _GLIBCXX_DEMANGLER_FAILURE; 1260 } 1261 1262 // 1263 // <expression> ::= <unary operator-name> <expression> 1264 // ::= <binary operator-name> <expression> <expression> 1265 // ::= <trinary operator-name> <expression> <expression> <expression> 1266 // ::= st <type> 1267 // ::= <template-param> 1268 // ::= sr <type> <unqualified-name> # dependent name 1269 // ::= sr <type> <unqualified-name> <template-args> # dependent template-id 1270 // ::= <expr-primary> 1271 // 1272 // <expr-primary> ::= L <type> <value number> E # integer literal 1273 // ::= L <type> <value float> E # floating literal 1274 // ::= L <mangled-name> E # external name 1275 // 1276 template<typename Allocator> 1277 bool decode_expression(string_type & output)1278 session<Allocator>::decode_expression(string_type& output) 1279 { 1280 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_expression"); 1281 if (current() == 'T') 1282 { 1283 if (!decode_template_param(output)) 1284 _GLIBCXX_DEMANGLER_FAILURE; 1285 _GLIBCXX_DEMANGLER_RETURN; 1286 } 1287 else if (current() == 'L') 1288 { 1289 if (!decode_literal(output)) 1290 _GLIBCXX_DEMANGLER_FAILURE; 1291 if (current() != 'E') 1292 _GLIBCXX_DEMANGLER_FAILURE; 1293 eat_current(); 1294 _GLIBCXX_DEMANGLER_RETURN; 1295 } 1296 else if (current() == 's') 1297 { 1298 char opcode1 = next(); 1299 if (opcode1 == 't' || opcode1 == 'z') 1300 { 1301 eat_current(); 1302 if (M_implementation_details.get_style_compact_expr_ops()) 1303 output += "sizeof("; 1304 else 1305 output += "sizeof ("; 1306 if (opcode1 == 't') 1307 { 1308 // I cannot think of a mangled name that is valid for both cases 1309 // when just replacing the 't' by a 'z' or vica versa, which 1310 // indicates that there is no ambiguity that dictates the need 1311 // for a seperate "st" case, except to be able catch invalid 1312 // mangled names. However there CAN be ambiguity in the demangled 1313 // name when there are both a type and a symbol of the same name, 1314 // which then leads to different encoding (of course) with 1315 // sizeof (type) or sizeof (expression) respectively, but that 1316 // ambiguity is not per se related to "sizeof" except that that 1317 // is the only place where both a type AND an expression are valid 1318 // in as part of a (template function) type. 1319 // 1320 // Example: 1321 // 1322 // struct B { typedef int t; }; 1323 // struct A : public B { static int t[2]; }; 1324 // template<int i, int j> struct C { typedef int q; }; 1325 // template<int i, typename T> 1326 // void f(typename C<sizeof (typename T::t), 1327 // sizeof (T::t)>::q) { } 1328 // void instantiate() { f<5, A>(0); } 1329 // 1330 // Leads to _Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE which 1331 // demangles as 1332 // void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q) 1333 // 1334 // This is ambiguity is very unlikely to happen and it is kind 1335 // of fuzzy to detect when adding a 'typename' makes sense. 1336 // 1337 if (M_implementation_details.get_style_sizeof_typename()) 1338 { 1339 // We can only get here inside a template parameter, 1340 // so this is syntactically correct if the given type is 1341 // a typedef. The only disadvantage is that it is inconsistent 1342 // with all other places where the 'typename' keyword should be 1343 // used and we don't. 1344 // With this, the above example will demangle as 1345 // void f<5, A>(C<sizeof (typename T::t), sizeof (T::t)>::q) 1346 if (current() == 'N' || // <nested-name> 1347 // This should be a safe bet. 1348 (current() == 'S' && 1349 next_peek() == 't')) // std::something, guess that 1350 // this involves a typedef. 1351 output += "typename "; 1352 } 1353 if (!decode_type(output)) 1354 _GLIBCXX_DEMANGLER_FAILURE; 1355 } 1356 else 1357 { 1358 if (!decode_expression(output)) 1359 _GLIBCXX_DEMANGLER_FAILURE; 1360 } 1361 output += ')'; 1362 _GLIBCXX_DEMANGLER_RETURN; 1363 } 1364 else if (current() == 'r') 1365 { 1366 eat_current(); 1367 if (!decode_type(output)) 1368 _GLIBCXX_DEMANGLER_FAILURE; 1369 output += "::"; 1370 if (!decode_unqualified_name(output)) 1371 _GLIBCXX_DEMANGLER_FAILURE; 1372 if (current() != 'I' || decode_template_args(output)) 1373 _GLIBCXX_DEMANGLER_RETURN; 1374 } 1375 } 1376 else 1377 { 1378 char opcode0 = current(); 1379 char opcode1 = tolower(next()); 1380 1381 register char hash = offset_table_c[opcode0 - CHAR_MIN]; 1382 if (hash) 1383 { 1384 hash += opcode1; 1385 if ( 1386 #if (CHAR_MIN < 0) 1387 hash >= 0 && 1388 #endif 1389 hash < 39) 1390 { 1391 int index = static_cast<int>(static_cast<unsigned char>(hash)); 1392 entry_st entry = symbol_name_table_c[index]; 1393 if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1 1394 && (opcode1 == current() || entry.opcode[2] == '=')) 1395 { 1396 char const* op = entry.symbol_name + 8; // Skip "operator". 1397 if (*op == ' ') // operator new and delete. 1398 ++op; 1399 if (entry.type == unary) 1400 output += op; 1401 bool is_eq = (opcode1 != current()); 1402 eat_current(); 1403 if (index == 34 && M_inside_template_args) // operator> 1404 output += '('; 1405 output += '('; 1406 if (!decode_expression(output)) 1407 _GLIBCXX_DEMANGLER_FAILURE; 1408 output += ')'; 1409 if (entry.type != unary) 1410 { 1411 if (!M_implementation_details.get_style_compact_expr_ops()) 1412 output += ' '; 1413 output += op; 1414 if (is_eq) 1415 output += '='; 1416 if (!M_implementation_details.get_style_compact_expr_ops()) 1417 output += ' '; 1418 output += '('; 1419 if (!decode_expression(output)) 1420 _GLIBCXX_DEMANGLER_FAILURE; 1421 output += ')'; 1422 if (index == 34 && M_inside_template_args) 1423 output += ')'; 1424 if (entry.type == trinary) 1425 { 1426 if (M_implementation_details.get_style_compact_expr_ops()) 1427 output += ":("; 1428 else 1429 output += " : ("; 1430 if (!decode_expression(output)) 1431 _GLIBCXX_DEMANGLER_FAILURE; 1432 output += ')'; 1433 } 1434 } 1435 _GLIBCXX_DEMANGLER_RETURN; 1436 } 1437 else if (opcode0 == 'c' && 1438 opcode1 == 'v') // casting operator. 1439 { 1440 eat_current(); 1441 output += '('; 1442 if (!decode_type(output)) 1443 _GLIBCXX_DEMANGLER_FAILURE; 1444 output += ")("; 1445 if (!decode_expression(output)) 1446 _GLIBCXX_DEMANGLER_FAILURE; 1447 output += ')'; 1448 _GLIBCXX_DEMANGLER_RETURN; 1449 } 1450 } 1451 } 1452 } 1453 _GLIBCXX_DEMANGLER_FAILURE; 1454 } 1455 1456 // 1457 // <template-args> ::= I <template-arg>+ E 1458 // <template-arg> ::= <type> # type or template 1459 // ::= L <type> <value number> E # integer literal 1460 // ::= L <type> <value float> E # floating literal 1461 // ::= L <mangled-name> E # external name 1462 // ::= X <expression> E # expression 1463 template<typename Allocator> 1464 bool decode_template_args(string_type & output)1465 session<Allocator>::decode_template_args(string_type& output) 1466 { 1467 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_args"); 1468 if (eat_current() != 'I') 1469 _GLIBCXX_DEMANGLER_FAILURE; 1470 int prev_size = M_template_arg_pos.size(); 1471 ++M_inside_template_args; 1472 if (M_template_args_need_space) 1473 { 1474 output += ' '; 1475 M_template_args_need_space = false; 1476 } 1477 output += '<'; 1478 for(;;) 1479 { 1480 if (M_inside_template_args == 1 && !M_inside_type) 1481 M_template_arg_pos.push_back(M_pos); 1482 if (current() == 'X') 1483 { 1484 eat_current(); 1485 if (!decode_expression(output)) 1486 _GLIBCXX_DEMANGLER_FAILURE; 1487 if (current() != 'E') 1488 _GLIBCXX_DEMANGLER_FAILURE; 1489 eat_current(); 1490 } 1491 else if (current() == 'L') 1492 { 1493 if (!decode_literal(output)) 1494 _GLIBCXX_DEMANGLER_FAILURE; 1495 if (current() != 'E') 1496 _GLIBCXX_DEMANGLER_FAILURE; 1497 eat_current(); 1498 } 1499 else if (!decode_type(output)) 1500 _GLIBCXX_DEMANGLER_FAILURE; 1501 if (current() == 'E') 1502 break; 1503 output += ", "; 1504 } 1505 eat_current(); 1506 if (*(output.rbegin()) == '>') 1507 output += ' '; 1508 output += '>'; 1509 --M_inside_template_args; 1510 if (!M_inside_template_args && !M_inside_type) 1511 { 1512 M_name_is_template = true; 1513 M_template_arg_pos_offset = prev_size; 1514 } 1515 _GLIBCXX_DEMANGLER_RETURN; 1516 } 1517 1518 // <bare-function-type> ::= 1519 // <signature type>+ # Types are parameter types. 1520 // 1521 // Note that the possible return type of the <bare-function-type> 1522 // has already been eaten before we call this function. This makes 1523 // our <bare-function-type> slightly different from the one in 1524 // the C++-ABI description. 1525 // 1526 template<typename Allocator> 1527 bool decode_bare_function_type(string_type & output)1528 session<Allocator>::decode_bare_function_type(string_type& output) 1529 { 1530 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_bare_function_type"); 1531 if (M_saw_destructor) 1532 { 1533 if (eat_current() != 'v' || (current() != 'E' && current() != 0)) 1534 _GLIBCXX_DEMANGLER_FAILURE; 1535 output += "()"; 1536 M_saw_destructor = false; 1537 _GLIBCXX_DEMANGLER_RETURN; 1538 } 1539 if (current() == 'v' && !M_implementation_details.get_style_void()) 1540 { 1541 eat_current(); 1542 if (current() != 'E' && current() != 0) 1543 _GLIBCXX_DEMANGLER_FAILURE; 1544 output += "()"; 1545 M_saw_destructor = false; 1546 _GLIBCXX_DEMANGLER_RETURN; 1547 } 1548 output += '('; 1549 M_template_args_need_space = false; 1550 if (!decode_type(output)) // Must have at least one parameter. 1551 _GLIBCXX_DEMANGLER_FAILURE; 1552 while (current() != 'E' && current() != 0) 1553 { 1554 output += ", "; 1555 if (!decode_type(output)) 1556 _GLIBCXX_DEMANGLER_FAILURE; 1557 } 1558 output += ')'; 1559 _GLIBCXX_DEMANGLER_RETURN; 1560 } 1561 1562 // <type> ::= 1563 // <builtin-type> # Starts with a lower case character != r. 1564 // <function-type> # Starts with F 1565 // <class-enum-type> # Starts with N, S, C, D, Z, a digit or a lower 1566 // # case character. Since a lower case character 1567 // # would be an operator name, that would be an 1568 // # error. The S is a substitution or St 1569 // # (::std::). A 'C' would be a constructor and 1570 // # thus also an error. 1571 // <template-param> # Starts with T 1572 // <substitution> # Starts with S 1573 // <template-template-param> <template-args> # Starts with T or S, 1574 // # equivalent with the above. 1575 // 1576 // <array-type> # Starts with A 1577 // <pointer-to-member-type> # Starts with M 1578 // <CV-qualifiers> <type> # Starts with r, V or K 1579 // P <type> # pointer-to # Starts with P 1580 // R <type> # reference-to # Starts with R 1581 // C <type> # complex (C 2000) # Starts with C 1582 // G <type> # imaginary (C 2000)# Starts with G 1583 // U <source-name> <type> # vendor extended type qualifier, 1584 // # starts with U 1585 // 1586 // <template-template-param> ::= <template-param> 1587 // ::= <substitution> 1588 1589 // My own analysis of how to decode qualifiers: 1590 // 1591 // F is a <function-type>, <T> is a <builtin-type>, <class-enum-type>, 1592 // <template-param> or <template-template-param> <template-args>. 1593 // <Q> represents a series of qualifiers (not G or C). 1594 // <C> is an unqualified type. 1595 // <R> is a qualified type. 1596 // <B> is the bare-function-type without return type. 1597 // <I> is the array index. 1598 // Substitutions: 1599 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2 "<C>", "F<R><B>E" 1600 // (<R> and <B> recursive), 1601 // "M<C><Q2>F<R><B>E". 1602 // <Q>F<R><B>E ==> R (Q)B "<R>", "<B>" (<B> recursive) 1603 // and "F<R><B>E". 1604 // 1605 // Note that if <R> has postfix qualifiers (an array or function), then 1606 // those are added AFTER the (member) function type. For example: 1607 // <Q>FPA<R><B>E ==> R (*(Q)B) [], where the PA added the prefix 1608 // "(*" and the postfix ") []". 1609 // 1610 // <Q>G<T> ==> imaginary T Q "<T>", "G<T>" (<T> recursive). 1611 // <Q>C<T> ==> complex T Q "<T>", "C<T>" (<T> recursive). 1612 // <Q><T> ==> T Q "<T>" (<T> recursive). 1613 // 1614 // where <Q> is any of: 1615 // 1616 // <Q>P ==> *Q "P..." 1617 // <Q>R ==> &Q "R..." 1618 // <Q>[K|V|r]+ ==> [ const| volatile| restrict]+Q "KVr..." 1619 // <Q>U<S> ==> SQ "U<S>..." 1620 // <Q>M<C> ==> C::*Q "M<C>..." (<C> recurs.) 1621 // A<I> ==> [I] "A<I>..." (<I> recurs.) 1622 // <Q>A<I> ==> (Q) [I] "A<I>..." (<I> recurs.) 1623 // Note that when <Q> ends on an A<I2> then the brackets are omitted 1624 // and no space is written between the two: 1625 // A<I2>A<I> ==> [I2][I] 1626 // If <Q> ends on [KVr]+, which can happen in combination with 1627 // substitutions only, then special handling is required, see below. 1628 // 1629 // A <substitution> is handled with an input position switch during which 1630 // new substitutions are turned off. Because recursive handling of types 1631 // (and therefore the order in which substitutions must be generated) must 1632 // be done left to right, but the generation of Q needs processing right to 1633 // left, substitutions per <type> are generated by reading the input left 1634 // to right and marking the starts of all substitutions only - implicitly 1635 // finishing them at the end of the type. Then the output and real 1636 // substitutions are generated. 1637 // 1638 // The following comment was for the demangling of g++ version 3.0.x. The 1639 // mangling (and I believe even the ABI description) have been fixed now 1640 // (as of g++ version 3.1). 1641 // 1642 // g++ 3.0.x only: 1643 // The ABI specifies for pointer-to-member function types the format 1644 // <Q>M<T>F<R><B>E. In other words, the qualifier <Q2> (see above) is 1645 // implicitely contained in <T> instead of explicitly part of the M format. 1646 // I am convinced that this is a bug in the ABI. Unfortunately, this is 1647 // how we have to demangle things as it has a direct impact on the order 1648 // in which substitutions are stored. This ill-formed design results in 1649 // rather ill-formed demangler code too however :/ 1650 // 1651 // <Q2> is now explicitely part of the M format. 1652 // For some weird reason, g++ (3.2.1) does not add substitutions for 1653 // qualified member function pointers. I think that is another bug. 1654 // 1655 1656 // In the case of 1657 // <Q>A<I> 1658 // where <Q> ends on [K|V|r]+ then that part should be processed as 1659 // if it was behind the A<I> instead of in front of it. This is 1660 // because a constant array of ints is normally always mangled as 1661 // an array of constant ints. KVr qualifiers can end up in front 1662 // of an array when the array is part of a substitution or template 1663 // parameter, but the demangling should still result in the same 1664 // syntax; thus KA2_i (const array of ints) must result in the same 1665 // demangling as A2_Ki (array of const ints). As a result we must 1666 // demangle ...[...[[KVr]+A<I0>][KVr]+A<I1>]...[KVr]+A<In>[KVr]+ 1667 // as A<I0>A<I1>...A<In>[KVr]+ where each K, V and r in the series 1668 // collapses to a single character at the right of the string. 1669 // For example: 1670 // VA9_KrA6_KVi --> A9_A6_KVri --> int volatile const restrict [9][6] 1671 // Note that substitutions are still added as usual (the translation 1672 // to A9_A6_KVri does not really happen). 1673 // 1674 // This decoding is achieved by delaying the decoding of any sequence 1675 // of [KVrA]'s and processing them together in the order: first the 1676 // short-circuited KVr part and then the arrays. 1677 static int const cvq_K = 1; // Saw at least one K 1678 static int const cvq_V = 2; // Saw at least one V 1679 static int const cvq_r = 4; // Saw at least one r 1680 static int const cvq_A = 8; // Saw at least one A 1681 static int const cvq_last = 16; // No remaining qualifiers. 1682 static int const cvq_A_cnt = 32; // Bit 5 and higher represent the 1683 // number of A's in the series. 1684 // In the function below, iter_array points to the first (right most) 1685 // A in the series, if any. 1686 template<typename Allocator> 1687 void decode_KVrA(string_type & prefix,string_type & postfix,int cvq,typename qual_vector::const_reverse_iterator const & iter_array)1688 qualifier_list<Allocator>::decode_KVrA( 1689 string_type& prefix, string_type& postfix, int cvq, 1690 typename qual_vector::const_reverse_iterator const& iter_array) const 1691 { 1692 _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_KVrA"); 1693 if ((cvq & cvq_K)) 1694 prefix += " const"; 1695 if ((cvq & cvq_V)) 1696 prefix += " volatile"; 1697 if ((cvq & cvq_r)) 1698 prefix += " restrict"; 1699 if ((cvq & cvq_A)) 1700 { 1701 int n = cvq >> 5; 1702 for (typename qual_vector:: 1703 const_reverse_iterator iter = iter_array; 1704 iter != M_qualifier_starts.rend(); ++iter) 1705 { 1706 switch((*iter).first_qualifier()) 1707 { 1708 case 'K': 1709 case 'V': 1710 case 'r': 1711 break; 1712 case 'A': 1713 { 1714 string_type index = (*iter).get_optional_type(); 1715 if (--n == 0 && (cvq & cvq_last)) 1716 postfix = " [" + index + "]" + postfix; 1717 else if (n > 0) 1718 postfix = "[" + index + "]" + postfix; 1719 else 1720 { 1721 prefix += " ("; 1722 postfix = ") [" + index + "]" + postfix; 1723 } 1724 break; 1725 } 1726 default: 1727 _GLIBCXX_DEMANGLER_RETURN3; 1728 } 1729 } 1730 } 1731 _GLIBCXX_DEMANGLER_RETURN3; 1732 } 1733 1734 template<typename Allocator> 1735 void decode_qualifiers(string_type & prefix,string_type & postfix,bool member_function_pointer_qualifiers)1736 qualifier_list<Allocator>::decode_qualifiers( 1737 string_type& prefix, 1738 string_type& postfix, 1739 bool member_function_pointer_qualifiers) const 1740 { 1741 _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_qualifiers"); 1742 int cvq = 0; 1743 typename qual_vector::const_reverse_iterator iter_array; 1744 for(typename qual_vector:: 1745 const_reverse_iterator iter = M_qualifier_starts.rbegin(); 1746 iter != M_qualifier_starts.rend(); ++iter) 1747 { 1748 if (!member_function_pointer_qualifiers 1749 && !(*iter).part_of_substitution()) 1750 { 1751 int saved_inside_substitution = M_demangler.M_inside_substitution; 1752 M_demangler.M_inside_substitution = 0; 1753 M_demangler.add_substitution((*iter).get_start_pos(), type); 1754 M_demangler.M_inside_substitution = saved_inside_substitution; 1755 } 1756 char qualifier_char = (*iter).first_qualifier(); 1757 for(; qualifier_char; qualifier_char = (*iter).next_qualifier()) 1758 { 1759 switch(qualifier_char) 1760 { 1761 case 'P': 1762 if (cvq) 1763 { 1764 decode_KVrA(prefix, postfix, cvq, iter_array); 1765 cvq = 0; 1766 } 1767 prefix += "*"; 1768 break; 1769 case 'R': 1770 if (cvq) 1771 { 1772 decode_KVrA(prefix, postfix, cvq, iter_array); 1773 cvq = 0; 1774 } 1775 prefix += "&"; 1776 break; 1777 case 'K': 1778 cvq |= cvq_K; 1779 continue; 1780 case 'V': 1781 cvq |= cvq_V; 1782 continue; 1783 case 'r': 1784 cvq |= cvq_r; 1785 continue; 1786 case 'A': 1787 if (!(cvq & cvq_A)) 1788 { 1789 cvq |= cvq_A; 1790 iter_array = iter; 1791 } 1792 cvq += cvq_A_cnt; 1793 break; 1794 case 'M': 1795 if (cvq) 1796 { 1797 decode_KVrA(prefix, postfix, cvq, iter_array); 1798 cvq = 0; 1799 } 1800 prefix += " "; 1801 prefix += (*iter).get_optional_type(); 1802 prefix += "::*"; 1803 break; 1804 case 'U': 1805 if (cvq) 1806 { 1807 decode_KVrA(prefix, postfix, cvq, iter_array); 1808 cvq = 0; 1809 } 1810 prefix += " "; 1811 prefix += (*iter).get_optional_type(); 1812 break; 1813 case 'G': // Only here so we added a substitution. 1814 break; 1815 } 1816 break; 1817 } 1818 } 1819 if (cvq) 1820 decode_KVrA(prefix, postfix, cvq|cvq_last, iter_array); 1821 M_printing_suppressed = false; 1822 _GLIBCXX_DEMANGLER_RETURN3; 1823 } 1824 1825 // 1826 template<typename Allocator> 1827 bool decode_type_with_postfix(string_type & prefix,string_type & postfix,qualifier_list<Allocator> * qualifiers)1828 session<Allocator>::decode_type_with_postfix( 1829 string_type& prefix, string_type& postfix, 1830 qualifier_list<Allocator>* qualifiers) 1831 { 1832 _GLIBCXX_DEMANGLER_DOUT_ENTERING2("decode_type"); 1833 ++M_inside_type; 1834 bool recursive_template_param_or_substitution_call; 1835 if (!(recursive_template_param_or_substitution_call = qualifiers)) 1836 qualifiers = new qualifier_list<Allocator>(*this); 1837 // First eat all qualifiers. 1838 bool failure = false; 1839 for(;;) // So we can use 'continue' to eat the next qualifier. 1840 { 1841 int start_pos = M_pos; 1842 switch(current()) 1843 { 1844 case 'P': 1845 qualifiers->add_qualifier_start(pointer, start_pos, 1846 M_inside_substitution); 1847 eat_current(); 1848 continue; 1849 case 'R': 1850 qualifiers->add_qualifier_start(reference, start_pos, 1851 M_inside_substitution); 1852 eat_current(); 1853 continue; 1854 case 'K': 1855 case 'V': 1856 case 'r': 1857 { 1858 char c; 1859 int count = 0; 1860 do 1861 { 1862 ++count; 1863 c = next(); 1864 } 1865 while(c == 'K' || c == 'V' || c == 'r'); 1866 qualifiers->add_qualifier_start(cv_qualifier, start_pos, count, 1867 M_inside_substitution); 1868 continue; 1869 } 1870 case 'U': 1871 { 1872 eat_current(); 1873 string_type source_name; 1874 if (!decode_source_name(source_name)) 1875 { 1876 failure = true; 1877 break; 1878 } 1879 qualifiers->add_qualifier_start(vendor_extension, start_pos, 1880 source_name, M_inside_substitution); 1881 continue; 1882 } 1883 case 'A': 1884 { 1885 // <array-type> ::= A <positive dimension number> _ <element type> 1886 // ::= A [<dimension expression>] _ <element type> 1887 // 1888 string_type index; 1889 int saved_pos; 1890 store(saved_pos); 1891 if (next() == 'n' || !decode_number(index)) 1892 { 1893 restore(saved_pos); 1894 if (next() != '_' && !decode_expression(index)) 1895 { 1896 failure = true; 1897 break; 1898 } 1899 } 1900 if (eat_current() != '_') 1901 { 1902 failure = true; 1903 break; 1904 } 1905 qualifiers->add_qualifier_start(array, start_pos, index, 1906 M_inside_substitution); 1907 continue; 1908 } 1909 case 'M': 1910 { 1911 // <pointer-to-member-type> ::= M <class type> <member type> 1912 // <Q>M<C> or <Q>M<C><Q2>F<R><B>E 1913 eat_current(); 1914 string_type class_type; 1915 if (!decode_type(class_type)) // Substitution: "<C>". 1916 { 1917 failure = true; 1918 break; 1919 } 1920 char c = current(); 1921 if (c == 'F' || c == 'K' || c == 'V' || c == 'r') 1922 // Must be CV-qualifiers and a member function pointer. 1923 { 1924 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2 1925 // substitutions: "<C>", "F<R><B>E" (<R> and <B> 1926 // recursive), "M<C><Q2>F<R><B>E". 1927 int count = 0; 1928 int Q2_start_pos = M_pos; 1929 while(c == 'K' || c == 'V' || c == 'r') // Decode <Q2>. 1930 { 1931 ++count; 1932 c = next(); 1933 } 1934 qualifier_list<Allocator> class_type_qualifiers(*this); 1935 if (count) 1936 class_type_qualifiers. 1937 add_qualifier_start(cv_qualifier, Q2_start_pos, 1938 count, M_inside_substitution); 1939 string_type member_function_qualifiers; 1940 // It is unclear why g++ doesn't add a substitution for 1941 // "<Q2>F<R><B>E" as it should I think. 1942 string_type member_function_qualifiers_postfix; 1943 class_type_qualifiers. 1944 decode_qualifiers(member_function_qualifiers, 1945 member_function_qualifiers_postfix, true); 1946 member_function_qualifiers += 1947 member_function_qualifiers_postfix; 1948 // I don't think this substitution is actually ever used. 1949 int function_pos = M_pos; 1950 if (eat_current() != 'F') 1951 { 1952 failure = true; 1953 break; 1954 } 1955 // Return type. 1956 // Constructors, destructors and conversion operators don't 1957 // have a return type, but seem to never get here. 1958 string_type return_type_postfix; 1959 if (!decode_type_with_postfix(prefix, return_type_postfix)) 1960 // substitution: <R> recursive 1961 { 1962 failure = true; 1963 break; 1964 } 1965 prefix += " ("; 1966 prefix += class_type; 1967 prefix += "::*"; 1968 string_type bare_function_type; 1969 if (!decode_bare_function_type(bare_function_type) 1970 || eat_current() != 'E') // Substitution: <B> recursive. 1971 { 1972 failure = true; 1973 break; 1974 } 1975 // substitution: "F<R><B>E". 1976 add_substitution(function_pos, type); 1977 // substitution: "M<C><Q2>F<R><B>E". 1978 add_substitution(start_pos, type); 1979 // substitution: all qualified types if any. 1980 qualifiers->decode_qualifiers(prefix, postfix); 1981 postfix += ")"; 1982 postfix += bare_function_type; 1983 postfix += member_function_qualifiers; 1984 postfix += return_type_postfix; 1985 goto decode_type_exit; 1986 } 1987 qualifiers->add_qualifier_start(pointer_to_member, start_pos, 1988 class_type, M_inside_substitution); 1989 continue; 1990 } 1991 default: 1992 break; 1993 } 1994 break; 1995 } 1996 if (!failure) 1997 { 1998 // <Q>G<T> ==> imaginary T Q 1999 // substitutions: "<T>", "G<T>" (<T> recursive). 2000 // <Q>C<T> ==> complex T Q 2001 // substitutions: "<T>", "C<T>" (<T> recursive). 2002 if (current() == 'C' || current() == 'G') 2003 { 2004 prefix += current() == 'C' ? "complex " : "imaginary "; 2005 qualifiers->add_qualifier_start(complex_or_imaginary, M_pos, 2006 M_inside_substitution); 2007 eat_current(); 2008 } 2009 int start_pos = M_pos; 2010 switch(current()) 2011 { 2012 case 'F': 2013 { 2014 // <function-type> ::= F [Y] <bare-function-type> E 2015 // 2016 // Note that g++ never generates the 'Y', but we try to 2017 // demangle it anyway. 2018 bool extern_C = (next() == 'Y'); 2019 if (extern_C) 2020 eat_current(); 2021 2022 // <Q>F<R><B>E ==> R (Q)B 2023 // substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E". 2024 2025 // Return type. 2026 string_type return_type_postfix; 2027 if (!decode_type_with_postfix(prefix, return_type_postfix)) 2028 // Substitution: "<R>". 2029 { 2030 failure = true; 2031 break; 2032 } 2033 // Only array and function (pointer) types have a postfix. 2034 // In that case we don't want the space but expect something 2035 // like prefix is "int (*" and postfix is ") [1]". 2036 // We do want the space if this pointer is qualified. 2037 if (return_type_postfix.size() == 0 || 2038 (prefix.size() > 0 && *prefix.rbegin() != '*')) 2039 prefix += ' '; 2040 prefix += '('; 2041 string_type bare_function_type; 2042 if (!decode_bare_function_type(bare_function_type) 2043 // substitution: "<B>" (<B> recursive). 2044 || eat_current() != 'E') 2045 { 2046 failure = true; 2047 break; 2048 } 2049 add_substitution(start_pos, type); // Substitution: "F<R><B>E". 2050 qualifiers->decode_qualifiers(prefix, postfix); 2051 // substitution: all qualified types, if any. 2052 postfix += ")"; 2053 if (extern_C) 2054 postfix += " [extern \"C\"] "; 2055 postfix += bare_function_type; 2056 postfix += return_type_postfix; 2057 break; 2058 } 2059 case 'T': 2060 if (!decode_template_param(prefix, qualifiers)) 2061 { 2062 failure = true; 2063 break; 2064 } 2065 if (current() == 'I') 2066 { 2067 add_substitution(start_pos, template_template_param); 2068 // substitution: "<template-template-param>". 2069 if (!decode_template_args(prefix)) 2070 { 2071 failure = true; 2072 break; 2073 } 2074 } 2075 if (!recursive_template_param_or_substitution_call 2076 && qualifiers->suppressed()) 2077 { 2078 add_substitution(start_pos, type); 2079 // substitution: "<template-param>" or 2080 // "<template-template-param> <template-args>". 2081 qualifiers->decode_qualifiers(prefix, postfix); 2082 // substitution: all qualified types, if any. 2083 } 2084 break; 2085 case 'S': 2086 if (M_pos >= M_maxpos) 2087 { 2088 failure = true; 2089 break; 2090 } 2091 if (M_str[M_pos + 1] != 't') 2092 { 2093 if (!decode_substitution(prefix, qualifiers)) 2094 { 2095 failure = true; 2096 break; 2097 } 2098 if (current() == 'I') 2099 { 2100 if (!decode_template_args(prefix)) 2101 { 2102 failure = true; 2103 break; 2104 } 2105 if (!recursive_template_param_or_substitution_call 2106 && qualifiers->suppressed()) 2107 add_substitution(start_pos, type); 2108 // Substitution: 2109 // "<template-template-param> <template-args>". 2110 } 2111 if (!recursive_template_param_or_substitution_call 2112 && qualifiers->suppressed()) 2113 qualifiers->decode_qualifiers(prefix, postfix); 2114 // Substitution: all qualified types, if any. 2115 break; 2116 } 2117 /* Fall-through for St */ 2118 case 'N': 2119 case 'Z': 2120 case '0': 2121 case '1': 2122 case '2': 2123 case '3': 2124 case '4': 2125 case '5': 2126 case '6': 2127 case '7': 2128 case '8': 2129 case '9': 2130 // <Q><T> ==> T Q 2131 // substitutions: "<T>" (<T> recursive). 2132 if (!decode_class_enum_type(prefix)) 2133 { 2134 failure = true; 2135 break; 2136 } 2137 if (!recursive_template_param_or_substitution_call) 2138 { 2139 add_substitution(start_pos, type); 2140 // substitution: "<class-enum-type>". 2141 qualifiers->decode_qualifiers(prefix, postfix); 2142 // substitution: all qualified types, if any. 2143 } 2144 else 2145 qualifiers->printing_suppressed(); 2146 break; 2147 default: 2148 // <Q><T> ==> T Q 2149 // substitutions: "<T>" (<T> recursive). 2150 if (!decode_builtin_type(prefix)) 2151 { 2152 failure = true; 2153 break; 2154 } 2155 // If decode_type was called from decode_template_param then we 2156 // need to suppress calling qualifiers here in order to get a 2157 // substitution added anyway (for the <template-param>). 2158 if (!recursive_template_param_or_substitution_call) 2159 qualifiers->decode_qualifiers(prefix, postfix); 2160 else 2161 qualifiers->printing_suppressed(); 2162 break; 2163 } 2164 } 2165 decode_type_exit: 2166 --M_inside_type; 2167 if (!recursive_template_param_or_substitution_call) 2168 delete qualifiers; 2169 if (failure) 2170 _GLIBCXX_DEMANGLER_FAILURE; 2171 _GLIBCXX_DEMANGLER_RETURN2; 2172 } 2173 2174 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E 2175 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E 2176 // 2177 // <prefix> ::= <prefix> <unqualified-name> 2178 // ::= <template-prefix> <template-args> 2179 // ::= <template-param> 2180 // ::= # empty 2181 // ::= <substitution> 2182 // 2183 // <template-prefix> ::= <prefix> <template unqualified-name> 2184 // ::= <template-param> 2185 // ::= <substitution> 2186 // 2187 template<typename Allocator> 2188 bool decode_nested_name(string_type & output,string_type & qualifiers)2189 session<Allocator>::decode_nested_name(string_type& output, 2190 string_type& qualifiers) 2191 { 2192 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_nested_name"); 2193 2194 if (current() != 'N' || M_pos >= M_maxpos) 2195 _GLIBCXX_DEMANGLER_FAILURE; 2196 2197 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const 2198 char const* qualifiers_start = &M_str[M_pos + 1]; 2199 for (char c = next(); c == 'K' || c == 'V' || c == 'r'; c = next()) ; 2200 for (char const* qualifier_ptr = &M_str[M_pos - 1]; 2201 qualifier_ptr >= qualifiers_start; --qualifier_ptr) 2202 switch(*qualifier_ptr) 2203 { 2204 case 'K': 2205 qualifiers += " const"; 2206 break; 2207 case 'V': 2208 qualifiers += " volatile"; 2209 break; 2210 case 'r': 2211 qualifiers += " restrict"; 2212 break; 2213 } 2214 2215 int number_of_prefixes = 0; 2216 int substitution_start = M_pos; 2217 for(;;) 2218 { 2219 ++number_of_prefixes; 2220 if (current() == 'S') 2221 { 2222 if (!decode_substitution(output)) 2223 _GLIBCXX_DEMANGLER_FAILURE; 2224 } 2225 else if (current() == 'I') 2226 { 2227 if (!decode_template_args(output)) 2228 _GLIBCXX_DEMANGLER_FAILURE; 2229 if (current() != 'E') 2230 { 2231 // substitution: "<template-prefix> <template-args>". 2232 add_substitution(substitution_start, nested_name_prefix, 2233 number_of_prefixes); 2234 } 2235 } 2236 else 2237 { 2238 if (current() == 'T') 2239 { 2240 if (!decode_template_param(output)) 2241 _GLIBCXX_DEMANGLER_FAILURE; 2242 } 2243 else if (!decode_unqualified_name(output)) 2244 _GLIBCXX_DEMANGLER_FAILURE; 2245 if (current() != 'E') 2246 { 2247 // substitution: "<prefix> <unqualified-name>" or 2248 // "<prefix> <template unqualified-name>". 2249 add_substitution(substitution_start, 2250 (current() == 'I') ? nested_name_template_prefix 2251 : nested_name_prefix, 2252 number_of_prefixes); 2253 } 2254 } 2255 if (current() == 'E') 2256 { 2257 eat_current(); 2258 _GLIBCXX_DEMANGLER_RETURN; 2259 } 2260 if (current() != 'I') 2261 output += "::"; 2262 else if (M_template_args_need_space) 2263 output += ' '; 2264 M_template_args_need_space = false; 2265 } 2266 _GLIBCXX_DEMANGLER_FAILURE; 2267 } 2268 2269 // <local-name> := Z <function encoding> E <entity name> [<discriminator>] 2270 // := Z <function encoding> E s [<discriminator>] 2271 // <discriminator> := _ <non-negative number> 2272 // 2273 template<typename Allocator> 2274 bool decode_local_name(string_type & output)2275 session<Allocator>::decode_local_name(string_type& output) 2276 { 2277 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_local_name"); 2278 if (current() != 'Z' || M_pos >= M_maxpos) 2279 _GLIBCXX_DEMANGLER_FAILURE; 2280 if ((M_pos += decode_encoding(output, M_str + M_pos + 1, 2281 M_maxpos - M_pos, M_implementation_details) + 1) < 0 || 2282 eat_current() != 'E') 2283 _GLIBCXX_DEMANGLER_FAILURE; 2284 output += "::"; 2285 if (current() == 's') 2286 { 2287 eat_current(); 2288 output += "string literal"; 2289 } 2290 else 2291 { 2292 string_type nested_name_qualifiers; 2293 if (!decode_name(output, nested_name_qualifiers)) 2294 _GLIBCXX_DEMANGLER_FAILURE; 2295 output += nested_name_qualifiers; 2296 } 2297 string_type discriminator; 2298 if (current() == '_' && next() != 'n' && !decode_number(discriminator)) 2299 _GLIBCXX_DEMANGLER_FAILURE; 2300 _GLIBCXX_DEMANGLER_RETURN; 2301 } 2302 2303 // <source-name> ::= <positive length number> <identifier> 2304 // 2305 template<typename Allocator> 2306 bool decode_source_name(string_type & output)2307 session<Allocator>::decode_source_name(string_type& output) 2308 { 2309 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_source_name"); 2310 int length = current() - '0'; 2311 if (length < 1 || length > 9) 2312 _GLIBCXX_DEMANGLER_FAILURE; 2313 while(isdigit(next())) 2314 length = 10 * length + current() - '0'; 2315 char const* ptr = &M_str[M_pos]; 2316 if (length > 11 && !strncmp(ptr, "_GLOBAL_", 8) && ptr[9] == 'N' 2317 && ptr[8] == ptr[10]) 2318 { 2319 output += "(anonymous namespace)"; 2320 if ((M_pos += length) > M_maxpos + 1) 2321 _GLIBCXX_DEMANGLER_FAILURE; 2322 } 2323 else 2324 while(length--) 2325 { 2326 if (current() == 0) 2327 _GLIBCXX_DEMANGLER_FAILURE; 2328 output += eat_current(); 2329 } 2330 _GLIBCXX_DEMANGLER_RETURN; 2331 } 2332 2333 // <unqualified-name> ::= <operator-name> # Starts with lower case. 2334 // ::= <ctor-dtor-name> # Starts with 'C' or 'D'. 2335 // ::= <source-name> # Starts with a digit. 2336 // 2337 template<typename Allocator> 2338 bool decode_unqualified_name(string_type & output)2339 session<Allocator>::decode_unqualified_name(string_type& output) 2340 { 2341 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unqualified_name"); 2342 if (M_inside_template_args) 2343 { 2344 if (!decode_source_name(output)) 2345 _GLIBCXX_DEMANGLER_FAILURE; 2346 } 2347 else if (isdigit(current())) 2348 { 2349 bool recursive_unqualified_name = (&M_function_name == &output); 2350 // This can be a recursive call when we are decoding 2351 // an <operator-name> that is a cast operator for a some 2352 // <unqualified-name>; for example "operator Foo()". 2353 // In that case this is thus not a ctor or dtor and we 2354 // are not interested in updating M_function_name. 2355 if (!recursive_unqualified_name) 2356 M_function_name.clear(); 2357 M_name_is_template = false; 2358 M_name_is_cdtor = false; 2359 M_name_is_conversion_operator = false; 2360 if (!decode_source_name(M_function_name)) 2361 _GLIBCXX_DEMANGLER_FAILURE; 2362 if (!recursive_unqualified_name) 2363 output += M_function_name; 2364 } 2365 else if (islower(current())) 2366 { 2367 M_function_name.clear(); 2368 M_name_is_template = false; 2369 M_name_is_cdtor = false; 2370 M_name_is_conversion_operator = false; 2371 if (!decode_operator_name(M_function_name)) 2372 _GLIBCXX_DEMANGLER_FAILURE; 2373 output += M_function_name; 2374 } 2375 else if (current() == 'C' || current() == 'D') 2376 { 2377 // <ctor-dtor-name> ::= 2378 // C1 # complete object (in-charge) constructor 2379 // C2 # base object (not-in-charge) constructor 2380 // C3 # complete object (in-charge) allocating constructor 2381 // D0 # deleting (in-charge) destructor 2382 // D1 # complete object (in-charge) destructor 2383 // D2 # base object (not-in-charge) destructor 2384 // 2385 if (current() == 'C') 2386 { 2387 char c = next(); 2388 if (c < '1' || c > '3') 2389 _GLIBCXX_DEMANGLER_FAILURE; 2390 } 2391 else 2392 { 2393 char c = next(); 2394 if (c < '0' || c > '2') 2395 _GLIBCXX_DEMANGLER_FAILURE; 2396 output += '~'; 2397 M_saw_destructor = true; 2398 } 2399 M_name_is_cdtor = true; 2400 eat_current(); 2401 output += M_function_name; 2402 } 2403 else 2404 _GLIBCXX_DEMANGLER_FAILURE; 2405 _GLIBCXX_DEMANGLER_RETURN; 2406 } 2407 2408 // <unscoped-name> ::= 2409 // <unqualified-name> # Starts not with an 'S' 2410 // St <unqualified-name> # ::std:: 2411 // 2412 template<typename Allocator> 2413 bool decode_unscoped_name(string_type & output)2414 session<Allocator>::decode_unscoped_name(string_type& output) 2415 { 2416 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unscoped_name"); 2417 if (current() == 'S') 2418 { 2419 if (next() != 't') 2420 _GLIBCXX_DEMANGLER_FAILURE; 2421 eat_current(); 2422 output += "std::"; 2423 } 2424 decode_unqualified_name(output); 2425 _GLIBCXX_DEMANGLER_RETURN; 2426 } 2427 2428 // <name> ::= 2429 // <nested-name> # Starts with 'N' 2430 // <unscoped-template-name> <template-args> # idem 2431 // <local-name> # Starts with 'Z' 2432 // <unscoped-name> # Starts with 'S', 'C', 'D', 2433 // # a digit or a lower case 2434 // # character. 2435 // 2436 // <unscoped-template-name> ::= <unscoped-name> 2437 // ::= <substitution> 2438 template<typename Allocator> 2439 bool decode_name(string_type & output,string_type & nested_name_qualifiers)2440 session<Allocator>::decode_name(string_type& output, 2441 string_type& nested_name_qualifiers) 2442 { 2443 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_name"); 2444 int substitution_start = M_pos; 2445 if (current() == 'S' && (M_pos >= M_maxpos || M_str[M_pos + 1] != 't')) 2446 { 2447 if (!decode_substitution(output)) 2448 _GLIBCXX_DEMANGLER_FAILURE; 2449 } 2450 else if (current() == 'N') 2451 { 2452 decode_nested_name(output, nested_name_qualifiers); 2453 _GLIBCXX_DEMANGLER_RETURN; 2454 } 2455 else if (current() == 'Z') 2456 { 2457 decode_local_name(output); 2458 _GLIBCXX_DEMANGLER_RETURN; 2459 } 2460 else if (!decode_unscoped_name(output)) 2461 _GLIBCXX_DEMANGLER_FAILURE; 2462 if (current() == 'I') 2463 { 2464 // Must have been an <unscoped-template-name>. 2465 add_substitution(substitution_start, unscoped_template_name); 2466 if (!decode_template_args(output)) 2467 _GLIBCXX_DEMANGLER_FAILURE; 2468 } 2469 M_template_args_need_space = false; 2470 _GLIBCXX_DEMANGLER_RETURN; 2471 } 2472 2473 // <call-offset> ::= h <nv-offset> _ 2474 // ::= v <v-offset> _ 2475 // <nv-offset> ::= <offset number> 2476 // non-virtual base override 2477 // 2478 // <v-offset> ::= <offset number> _ <virtual offset number> 2479 // virtual base override, with vcall offset 2480 template<typename Allocator> 2481 bool decode_call_offset(string_type & output)2482 session<Allocator>::decode_call_offset(string_type& 2483 #if _GLIBCXX_DEMANGLER_CWDEBUG 2484 output 2485 #endif 2486 ) 2487 { 2488 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_call_offset"); 2489 if (current() == 'h') 2490 { 2491 string_type dummy; 2492 eat_current(); 2493 if (decode_number(dummy) && current() == '_') 2494 { 2495 eat_current(); 2496 _GLIBCXX_DEMANGLER_RETURN; 2497 } 2498 } 2499 else if (current() == 'v') 2500 { 2501 string_type dummy; 2502 eat_current(); 2503 if (decode_number(dummy) && current() == '_') 2504 { 2505 eat_current(); 2506 if (decode_number(dummy) && current() == '_') 2507 { 2508 eat_current(); 2509 _GLIBCXX_DEMANGLER_RETURN; 2510 } 2511 } 2512 } 2513 _GLIBCXX_DEMANGLER_FAILURE; 2514 } 2515 2516 // 2517 // <special-name> ::= 2518 // TV <type> # virtual table 2519 // TT <type> # VTT structure (construction 2520 // vtable index). 2521 // TI <type> # typeinfo structure 2522 // TS <type> # typeinfo name (null-terminated 2523 // byte string). 2524 // GV <object name> # Guard variable for one-time 2525 // initialization of static objects in 2526 // a local scope. 2527 // T <call-offset> <base encoding># base is the nominal target function 2528 // of thunk. 2529 // Tc <call-offset> <call-offset> <base encoding> # base is the nominal 2530 // target function of thunk; first 2531 // call-offset is 'this' adjustment; 2532 // second call-offset is result 2533 // adjustment 2534 // 2535 template<typename Allocator> 2536 bool decode_special_name(string_type & output)2537 session<Allocator>::decode_special_name(string_type& output) 2538 { 2539 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_special_name"); 2540 if (current() == 'G') 2541 { 2542 if (next() != 'V') 2543 _GLIBCXX_DEMANGLER_FAILURE; 2544 output += "guard variable for "; 2545 string_type nested_name_qualifiers; 2546 eat_current(); 2547 if (!decode_name(output, nested_name_qualifiers)) 2548 _GLIBCXX_DEMANGLER_FAILURE; 2549 output += nested_name_qualifiers; 2550 _GLIBCXX_DEMANGLER_RETURN; 2551 } 2552 else if (current() != 'T') 2553 _GLIBCXX_DEMANGLER_FAILURE; 2554 switch(next()) 2555 { 2556 case 'V': 2557 output += "vtable for "; 2558 eat_current(); 2559 decode_type(output); 2560 _GLIBCXX_DEMANGLER_RETURN; 2561 case 'T': 2562 output += "VTT for "; 2563 eat_current(); 2564 decode_type(output); 2565 _GLIBCXX_DEMANGLER_RETURN; 2566 case 'I': 2567 output += "typeinfo for "; 2568 eat_current(); 2569 decode_type(output); 2570 _GLIBCXX_DEMANGLER_RETURN; 2571 case 'S': 2572 output += "typeinfo name for "; 2573 eat_current(); 2574 decode_type(output); 2575 _GLIBCXX_DEMANGLER_RETURN; 2576 case 'c': 2577 output += "covariant return thunk to "; 2578 if (!decode_call_offset(output) 2579 || !decode_call_offset(output) 2580 || (M_pos += decode_encoding(output, M_str + M_pos, 2581 M_maxpos - M_pos + 1, M_implementation_details)) < 0) 2582 _GLIBCXX_DEMANGLER_FAILURE; 2583 _GLIBCXX_DEMANGLER_RETURN; 2584 case 'C': // GNU extension? 2585 { 2586 string_type first; 2587 output += "construction vtable for "; 2588 eat_current(); 2589 if (!decode_type(first)) 2590 _GLIBCXX_DEMANGLER_FAILURE; 2591 while(isdigit(current())) 2592 eat_current(); 2593 if (eat_current() != '_') 2594 _GLIBCXX_DEMANGLER_FAILURE; 2595 if (!decode_type(output)) 2596 _GLIBCXX_DEMANGLER_FAILURE; 2597 output += "-in-"; 2598 output += first; 2599 _GLIBCXX_DEMANGLER_RETURN; 2600 } 2601 default: 2602 if (current() == 'v') 2603 output += "virtual thunk to "; 2604 else 2605 output += "non-virtual thunk to "; 2606 if (!decode_call_offset(output) 2607 || (M_pos += decode_encoding(output, M_str + M_pos, 2608 M_maxpos - M_pos + 1, M_implementation_details)) < 0) 2609 _GLIBCXX_DEMANGLER_FAILURE; 2610 _GLIBCXX_DEMANGLER_RETURN; 2611 } 2612 } 2613 2614 // <encoding> ::= 2615 // <function name> <bare-function-type> # Starts with 'C', 'D', 'N', 2616 // 'S', a digit or a lower case 2617 // character. 2618 // <data name> # Idem. 2619 // <special-name> # Starts with 'T' or 'G'. 2620 template<typename Allocator> 2621 int decode_encoding(string_type & output,char const * in,int len,implementation_details const & id)2622 session<Allocator>::decode_encoding(string_type& output, 2623 char const* in, int len, implementation_details const& id) 2624 { 2625 #if _GLIBCXX_DEMANGLER_CWDEBUG 2626 _GLIBCXX_DEMANGLER_DOUT(dc::demangler, 2627 "Output thus far: \"" << output << '"'); 2628 string_type input(in, len > 0x40000000 ? strlen(in) : len); 2629 _GLIBCXX_DEMANGLER_DOUT( 2630 dc::demangler, "Entering decode_encoding(\"" << input << "\")"); 2631 #endif 2632 if (len <= 0) 2633 return INT_MIN; 2634 session<Allocator> demangler_session(in, len, id); 2635 string_type nested_name_qualifiers; 2636 int saved_pos; 2637 demangler_session.store(saved_pos); 2638 if (demangler_session.decode_special_name(output)) 2639 return demangler_session.M_pos; 2640 demangler_session.restore(saved_pos); 2641 string_type name; 2642 if (!demangler_session.decode_name(name, nested_name_qualifiers)) 2643 return INT_MIN; 2644 if (demangler_session.current() == 0 2645 || demangler_session.current() == 'E') 2646 { 2647 output += name; 2648 output += nested_name_qualifiers; 2649 return demangler_session.M_pos; 2650 } 2651 // Must have been a <function name>. 2652 string_type return_type_postfix; 2653 if (demangler_session.M_name_is_template 2654 && !(demangler_session.M_name_is_cdtor 2655 || demangler_session.M_name_is_conversion_operator)) 2656 { 2657 // Return type of function 2658 if (!demangler_session.decode_type_with_postfix(output, 2659 return_type_postfix)) 2660 return INT_MIN; 2661 output += ' '; 2662 } 2663 output += name; 2664 if (!demangler_session.decode_bare_function_type(output)) 2665 return INT_MIN; 2666 output += nested_name_qualifiers; 2667 output += return_type_postfix; 2668 return demangler_session.M_pos; 2669 } 2670 2671 } // namespace demangler 2672 2673 // Public interface 2674 template<typename Allocator> 2675 struct demangle 2676 { 2677 typedef typename Allocator::template rebind<char>::other char_Allocator; 2678 typedef std::basic_string<char, std::char_traits<char>, char_Allocator> 2679 string_type; 2680 static string_type symbol(char const* in, 2681 demangler::implementation_details const& id); 2682 static string_type type(char const* in, 2683 demangler::implementation_details const& id); 2684 }; 2685 2686 // demangle::symbol() 2687 // 2688 // Demangle `input' which should be a mangled function name as for 2689 // instance returned by nm(1). 2690 template<typename Allocator> 2691 typename demangle<Allocator>::string_type symbol(char const * input,demangler::implementation_details const & id)2692 demangle<Allocator>::symbol(char const* input, 2693 demangler::implementation_details const& id) 2694 { 2695 // <mangled-name> ::= _Z <encoding> 2696 // <mangled-name> ::= _GLOBAL_ _<type>_ <disambiguation part> 2697 // <type> can be I or D (GNU extension) 2698 typedef demangler::session<Allocator> demangler_type; 2699 string_type result; 2700 bool failure = (input[0] != '_'); 2701 2702 if (!failure) 2703 { 2704 if (input[1] == 'G') 2705 { 2706 if (!strncmp(input, "_GLOBAL__", 9) 2707 && (input[9] == 'D' || input[9] == 'I') 2708 && input[10] == '_') 2709 { 2710 if (input[9] == 'D') 2711 result.assign("global destructors keyed to ", 28); 2712 else 2713 result.assign("global constructors keyed to ", 29); 2714 // Output the disambiguation part as-is. 2715 result += input + 11; 2716 } 2717 else 2718 failure = true; 2719 } 2720 else if (input[1] == 'Z') 2721 { 2722 int cnt = 2723 demangler_type::decode_encoding(result, input + 2, INT_MAX, id); 2724 if (cnt < 0 || input[cnt + 2] != 0) 2725 failure = true; 2726 } 2727 else 2728 failure = true; 2729 } 2730 2731 // Failure to demangle, return the mangled name. 2732 if (failure) 2733 result.assign(input, strlen(input)); 2734 2735 return result; 2736 } 2737 2738 // demangle::type() 2739 // Demangle `input' which must be a zero terminated mangled type 2740 // name as for instance returned by std::type_info::name(). 2741 template<typename Allocator> 2742 typename demangle<Allocator>::string_type type(char const * input,demangler::implementation_details const & id)2743 demangle<Allocator>::type(char const* input, 2744 demangler::implementation_details const& id) 2745 { 2746 std::basic_string<char, std::char_traits<char>, Allocator> result; 2747 if (input == NULL) 2748 result = "(null)"; 2749 else 2750 { 2751 demangler::session<Allocator> demangler_session(input, INT_MAX, id); 2752 if (!demangler_session.decode_type(result) 2753 || demangler_session.remaining_input_characters()) 2754 { 2755 // Failure to demangle, return the mangled name. 2756 result = input; 2757 } 2758 } 2759 return result; 2760 } 2761 2762 } // namespace __gnu_cxx 2763 2764 #endif // __DEMANGLE_H 2765