1 //===-- Mangled.cpp ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include <cxxabi.h> 11 12 #include "llvm/ADT/DenseMap.h" 13 14 #include "lldb/Core/ConstString.h" 15 #include "lldb/Core/Mangled.h" 16 #include "lldb/Core/RegularExpression.h" 17 #include "lldb/Core/Stream.h" 18 #include "lldb/Core/Timer.h" 19 #include <ctype.h> 20 #include <string.h> 21 22 using namespace lldb_private; 23 24 #pragma mark Mangled 25 //---------------------------------------------------------------------- 26 // Default constructor 27 //---------------------------------------------------------------------- 28 Mangled::Mangled () : 29 m_mangled(), 30 m_demangled() 31 { 32 } 33 34 //---------------------------------------------------------------------- 35 // Constructor with an optional string and a boolean indicating if it is 36 // the mangled version. 37 //---------------------------------------------------------------------- 38 Mangled::Mangled (const char *s, bool mangled) : 39 m_mangled(), 40 m_demangled() 41 { 42 if (s && s[0]) 43 { 44 SetValue(s, mangled); 45 } 46 } 47 48 //---------------------------------------------------------------------- 49 // Destructor 50 //---------------------------------------------------------------------- 51 Mangled::~Mangled () 52 { 53 } 54 55 //---------------------------------------------------------------------- 56 // Convert to pointer operator. This allows code to check any Mangled 57 // objects to see if they contain anything valid using code such as: 58 // 59 // Mangled mangled(...); 60 // if (mangled) 61 // { ... 62 //---------------------------------------------------------------------- 63 Mangled::operator void* () const 64 { 65 return (m_mangled) ? const_cast<Mangled*>(this) : NULL; 66 } 67 68 //---------------------------------------------------------------------- 69 // Logical NOT operator. This allows code to check any Mangled 70 // objects to see if they are invalid using code such as: 71 // 72 // Mangled mangled(...); 73 // if (!file_spec) 74 // { ... 75 //---------------------------------------------------------------------- 76 bool 77 Mangled::operator! () const 78 { 79 return !m_mangled; 80 } 81 82 //---------------------------------------------------------------------- 83 // Clear the mangled and demangled values. 84 //---------------------------------------------------------------------- 85 void 86 Mangled::Clear () 87 { 88 m_mangled.Clear(); 89 m_demangled.Clear(); 90 } 91 92 93 //---------------------------------------------------------------------- 94 // Compare the the string values. 95 //---------------------------------------------------------------------- 96 int 97 Mangled::Compare (const Mangled& a, const Mangled& b) 98 { 99 return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled)); 100 } 101 102 103 104 //---------------------------------------------------------------------- 105 // Set the string value in this objects. If "mangled" is true, then 106 // the mangled named is set with the new value in "s", else the 107 // demangled name is set. 108 //---------------------------------------------------------------------- 109 void 110 Mangled::SetValue (const char *s, bool mangled) 111 { 112 if (s) 113 { 114 if (mangled) 115 { 116 m_demangled.Clear(); 117 m_mangled.SetCString (s); 118 } 119 else 120 { 121 m_demangled.SetCString(s); 122 m_mangled.Clear(); 123 } 124 } 125 else 126 { 127 m_demangled.Clear(); 128 m_mangled.Clear(); 129 } 130 } 131 132 //---------------------------------------------------------------------- 133 // Generate the demangled name on demand using this accessor. Code in 134 // this class will need to use this accessor if it wishes to decode 135 // the demangled name. The result is cached and will be kept until a 136 // new string value is supplied to this object, or until the end of the 137 // object's lifetime. 138 //---------------------------------------------------------------------- 139 const ConstString& 140 Mangled::GetDemangledName () const 141 { 142 // Check to make sure we have a valid mangled name and that we 143 // haven't already decoded our mangled name. 144 if (m_mangled && !m_demangled) 145 { 146 // We need to generate and cache the demangled name. 147 Timer scoped_timer (__PRETTY_FUNCTION__, 148 "Mangled::GetDemangledName (m_mangled = %s)", 149 m_mangled.GetCString()); 150 151 // We already know mangled is valid from the above check, 152 // lets just make sure it isn't empty... 153 const char * mangled = m_mangled.AsCString(); 154 // Don't bother running anything that doesn't start with _Z through the demangler 155 if (mangled[0] == '_' && mangled[1] == 'Z') 156 { 157 if (!m_mangled.GetMangledCounterpart(m_demangled)) 158 { 159 // We didn't already mangle this name, demangle it and if all goes well 160 // add it to our map. 161 char *demangled_name = abi::__cxa_demangle (mangled, NULL, NULL, NULL); 162 163 if (demangled_name) 164 { 165 m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); 166 free (demangled_name); 167 } 168 } 169 } 170 if (!m_demangled) 171 { 172 // Set the demangled string to the empty string to indicate we 173 // tried to parse it once and failed. 174 m_demangled.SetCString(""); 175 } 176 } 177 178 return m_demangled; 179 } 180 181 182 bool 183 Mangled::NameMatches (const RegularExpression& regex) const 184 { 185 if (m_mangled && regex.Execute (m_mangled.AsCString())) 186 return true; 187 188 if (GetDemangledName() && regex.Execute (m_demangled.AsCString())) 189 return true; 190 return false; 191 } 192 193 194 //---------------------------------------------------------------------- 195 // Mangled name get accessor 196 //---------------------------------------------------------------------- 197 ConstString& 198 Mangled::GetMangledName () 199 { 200 return m_mangled; 201 } 202 203 //---------------------------------------------------------------------- 204 // Mangled name const get accessor 205 //---------------------------------------------------------------------- 206 const ConstString& 207 Mangled::GetMangledName () const 208 { 209 return m_mangled; 210 } 211 212 //---------------------------------------------------------------------- 213 // Get the demangled name if there is one, else return the mangled name. 214 //---------------------------------------------------------------------- 215 const ConstString& 216 Mangled::GetName (Mangled::NamePreference preference) const 217 { 218 if (preference == ePreferDemangled) 219 { 220 // Call the accessor to make sure we get a demangled name in case 221 // it hasn't been demangled yet... 222 if (GetDemangledName()) 223 return m_demangled; 224 return m_mangled; 225 } 226 else 227 { 228 if (m_mangled) 229 return m_mangled; 230 return GetDemangledName(); 231 } 232 } 233 234 //---------------------------------------------------------------------- 235 // Generate the tokens from the demangled name. 236 // 237 // Returns the number of tokens that were parsed. 238 //---------------------------------------------------------------------- 239 size_t 240 Mangled::GetTokens (Mangled::TokenList &tokens) const 241 { 242 tokens.Clear(); 243 const ConstString& demangled = GetDemangledName(); 244 if (demangled && !demangled.IsEmpty()) 245 tokens.Parse(demangled.AsCString()); 246 247 return tokens.Size(); 248 } 249 250 //---------------------------------------------------------------------- 251 // Dump a Mangled object to stream "s". We don't force our 252 // demangled name to be computed currently (we don't use the accessor). 253 //---------------------------------------------------------------------- 254 void 255 Mangled::Dump (Stream *s) const 256 { 257 if (m_mangled) 258 { 259 *s << ", mangled = " << m_mangled; 260 } 261 if (m_demangled) 262 { 263 const char * demangled = m_demangled.AsCString(); 264 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>"); 265 } 266 } 267 268 //---------------------------------------------------------------------- 269 // Dumps a debug version of this string with extra object and state 270 // information to stream "s". 271 //---------------------------------------------------------------------- 272 void 273 Mangled::DumpDebug (Stream *s) const 274 { 275 s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this); 276 m_mangled.DumpDebug(s); 277 s->Printf(", demangled = "); 278 m_demangled.DumpDebug(s); 279 } 280 281 //---------------------------------------------------------------------- 282 // Return the size in byte that this object takes in memory. The size 283 // includes the size of the objects it owns, and not the strings that 284 // it references because they are shared strings. 285 //---------------------------------------------------------------------- 286 size_t 287 Mangled::MemorySize () const 288 { 289 return m_mangled.MemorySize() + m_demangled.MemorySize(); 290 } 291 292 //---------------------------------------------------------------------- 293 // Dump OBJ to the supplied stream S. 294 //---------------------------------------------------------------------- 295 Stream& 296 operator << (Stream& s, const Mangled& obj) 297 { 298 if (obj.GetMangledName()) 299 s << "mangled = '" << obj.GetMangledName() << "'"; 300 301 const ConstString& demangled = obj.GetDemangledName(); 302 if (demangled) 303 s << ", demangled = '" << demangled << '\''; 304 else 305 s << ", demangled = <error>"; 306 return s; 307 } 308 309 310 311 312 #pragma mark Mangled::Token 313 314 //-------------------------------------------------------------- 315 // Default constructor 316 //-------------------------------------------------------------- 317 Mangled::Token::Token () : 318 type(eInvalid), 319 value() 320 { 321 } 322 323 //-------------------------------------------------------------- 324 // Equal to operator 325 //-------------------------------------------------------------- 326 bool 327 Mangled::Token::operator== (const Token& rhs) const 328 { 329 return type == rhs.type && value == rhs.value; 330 } 331 332 //-------------------------------------------------------------- 333 // Dump the token to a stream "s" 334 //-------------------------------------------------------------- 335 void 336 Mangled::Token::Dump (Stream *s) const 337 { 338 switch (type) 339 { 340 case eInvalid: s->PutCString("invalid "); break; 341 case eNameSpace: s->PutCString("namespace "); break; 342 case eMethodName: s->PutCString("method "); break; 343 case eType: s->PutCString("type "); break; 344 case eTemplate: s->PutCString("template "); break; 345 case eTemplateBeg: s->PutCString("template < "); break; 346 case eTemplateEnd: s->PutCString("template > "); break; 347 case eParamsBeg: s->PutCString("params ( "); break; 348 case eParamsEnd: s->PutCString("params ) "); break; 349 case eQualifier: s->PutCString("qualifier "); break; 350 case eError: s->PutCString("ERROR "); break; 351 default: 352 s->Printf("type = %i", type); 353 break; 354 } 355 value.DumpDebug(s); 356 } 357 358 //-------------------------------------------------------------- 359 // Returns true if this token is a wildcard 360 //-------------------------------------------------------------- 361 bool 362 Mangled::Token::IsWildcard () const 363 { 364 static ConstString g_wildcard_str("*"); 365 return value == g_wildcard_str; 366 } 367 368 369 //---------------------------------------------------------------------- 370 // Dump "obj" to the supplied stream "s" 371 //---------------------------------------------------------------------- 372 Stream& 373 lldb_private::operator << (Stream& s, const Mangled::Token& obj) 374 { 375 obj.Dump(&s); 376 return s; 377 } 378 379 380 #pragma mark Mangled::TokenList 381 //---------------------------------------------------------------------- 382 // Mangled::TokenList 383 //---------------------------------------------------------------------- 384 385 //-------------------------------------------------------------- 386 // Default constructor. If demangled is non-NULL and not-empty 387 // the token list will parse up the demangled string it is 388 // given, else the object will initialize an empty token list. 389 //-------------------------------------------------------------- 390 Mangled::TokenList::TokenList (const char *demangled) : 391 m_tokens() 392 { 393 if (demangled && demangled[0]) 394 { 395 Parse(demangled); 396 } 397 } 398 399 //---------------------------------------------------------------------- 400 // Destructor 401 //---------------------------------------------------------------------- 402 Mangled::TokenList::~TokenList () 403 { 404 } 405 406 //---------------------------------------------------------------------- 407 // Parses "demangled" into tokens. This allows complex 408 // comparisons to be done. Comparisons can include wildcards at 409 // the namespace, method name, template, and template and 410 // parameter type levels. 411 // 412 // Example queries include: 413 // "std::basic_string<*>" // Find all std::basic_string variants 414 // "std::basic_string<*>::erase(*)" // Find all std::basic_string::erase variants with any number of parameters 415 // "*::clear()" // Find all functions with a method name of 416 // // "clear" that are in any namespace that 417 // // have no parameters 418 // "::printf" // Find the printf function in the global namespace 419 // "printf" // Ditto 420 // "foo::*(int)" // Find all functions in the class or namespace "foo" that take a single integer argument 421 // 422 // Returns the number of tokens that were decoded, or zero when 423 // we fail. 424 //---------------------------------------------------------------------- 425 size_t 426 Mangled::TokenList::Parse (const char *s) 427 { 428 m_tokens.clear(); 429 430 Token token; 431 token.type = eNameSpace; 432 433 TokenType max_type = eInvalid; 434 const char *p = s; 435 size_t span = 0; 436 size_t sep_size = 0; 437 438 while (*p != '\0') 439 { 440 p = p + span + sep_size; 441 while (isspace(*p)) 442 ++p; 443 444 if (*p == '\0') 445 break; 446 447 span = strcspn(p, ":<>(),"); 448 sep_size = 1; 449 token.type = eInvalid; 450 switch (p[span]) 451 { 452 case '\0': 453 break; 454 455 case ':': 456 if (p[span+1] == ':') 457 { 458 sep_size = 2; 459 if (span > 0) 460 { 461 token.type = eNameSpace; 462 token.value.SetCStringWithLength (p, span); 463 m_tokens.push_back(token); 464 } 465 else 466 continue; 467 } 468 break; 469 470 case '(': 471 if (span > 0) 472 { 473 token.type = eMethodName; 474 token.value.SetCStringWithLength (p, span); 475 m_tokens.push_back(token); 476 } 477 478 token.type = eParamsBeg; 479 token.value.Clear(); 480 m_tokens.push_back(token); 481 break; 482 483 case ',': 484 if (span > 0) 485 { 486 token.type = eType; 487 token.value.SetCStringWithLength (p, span); 488 m_tokens.push_back(token); 489 } 490 else 491 { 492 continue; 493 } 494 break; 495 496 case ')': 497 if (span > 0) 498 { 499 token.type = eType; 500 token.value.SetCStringWithLength (p, span); 501 m_tokens.push_back(token); 502 } 503 504 token.type = eParamsEnd; 505 token.value.Clear(); 506 m_tokens.push_back(token); 507 break; 508 509 case '<': 510 if (span > 0) 511 { 512 token.type = eTemplate; 513 token.value.SetCStringWithLength (p, span); 514 m_tokens.push_back(token); 515 } 516 517 token.type = eTemplateBeg; 518 token.value.Clear(); 519 m_tokens.push_back(token); 520 break; 521 522 case '>': 523 if (span > 0) 524 { 525 token.type = eType; 526 token.value.SetCStringWithLength (p, span); 527 m_tokens.push_back(token); 528 } 529 530 token.type = eTemplateEnd; 531 token.value.Clear(); 532 m_tokens.push_back(token); 533 break; 534 } 535 536 if (max_type < token.type) 537 max_type = token.type; 538 539 if (token.type == eInvalid) 540 { 541 if (max_type >= eParamsEnd) 542 { 543 token.type = eQualifier; 544 token.value.SetCString(p); 545 m_tokens.push_back(token); 546 } 547 else if (max_type >= eParamsBeg) 548 { 549 token.type = eType; 550 token.value.SetCString(p); 551 m_tokens.push_back(token); 552 } 553 else 554 { 555 token.type = eMethodName; 556 token.value.SetCString(p); 557 m_tokens.push_back(token); 558 } 559 break; 560 } 561 } 562 return m_tokens.size(); 563 } 564 565 566 //---------------------------------------------------------------------- 567 // Clear the token list. 568 //---------------------------------------------------------------------- 569 void 570 Mangled::TokenList::Clear () 571 { 572 m_tokens.clear(); 573 } 574 575 //---------------------------------------------------------------------- 576 // Dump the token list to the stream "s" 577 //---------------------------------------------------------------------- 578 void 579 Mangled::TokenList::Dump (Stream *s) const 580 { 581 collection::const_iterator pos; 582 collection::const_iterator beg = m_tokens.begin(); 583 collection::const_iterator end = m_tokens.end(); 584 for (pos = beg; pos != end; ++pos) 585 { 586 s->Indent("token["); 587 *s << (uint32_t)std::distance(beg, pos) << "] = " << *pos << "\n"; 588 } 589 } 590 591 //---------------------------------------------------------------------- 592 // Find the first token in the list that has "token_type" as its 593 // type 594 //---------------------------------------------------------------------- 595 const Mangled::Token * 596 Mangled::TokenList::Find (TokenType token_type) const 597 { 598 collection::const_iterator pos; 599 collection::const_iterator beg = m_tokens.begin(); 600 collection::const_iterator end = m_tokens.end(); 601 for (pos = beg; pos != end; ++pos) 602 { 603 if (pos->type == token_type) 604 return &(*pos); 605 } 606 return NULL; 607 } 608 609 //---------------------------------------------------------------------- 610 // Return the token at index "idx", or NULL if the index is 611 // out of range. 612 //---------------------------------------------------------------------- 613 const Mangled::Token * 614 Mangled::TokenList::GetTokenAtIndex (uint32_t idx) const 615 { 616 if (idx < m_tokens.size()) 617 return &m_tokens[idx]; 618 return NULL; 619 } 620 621 622 //---------------------------------------------------------------------- 623 // Given a token list, see if it matches this object's tokens. 624 // "token_list" can contain wild card values to enable powerful 625 // matching. Matching the std::string::erase(*) example that was 626 // tokenized above we could use a token list such as: 627 // 628 // token name 629 // ----------- ---------------------------------------- 630 // eNameSpace "std" 631 // eTemplate "basic_string" 632 // eTemplateBeg 633 // eInvalid "*" 634 // eTemplateEnd 635 // eMethodName "erase" 636 // eParamsBeg 637 // eInvalid "*" 638 // eParamsEnd 639 // 640 // Returns true if it "token_list" matches this object's tokens, 641 // false otherwise. 642 //---------------------------------------------------------------------- 643 bool 644 Mangled::TokenList::MatchesQuery (const Mangled::TokenList &match) const 645 { 646 size_t match_count = 0; 647 collection::const_iterator pos; 648 collection::const_iterator pos_end = m_tokens.end(); 649 650 collection::const_iterator match_pos; 651 collection::const_iterator match_pos_end = match.m_tokens.end(); 652 collection::const_iterator match_wildcard_pos = match_pos_end; 653 collection::const_iterator match_next_pos = match_pos_end; 654 655 size_t template_scope_depth = 0; 656 657 for (pos = m_tokens.begin(), match_pos = match.m_tokens.begin(); 658 pos != pos_end && match_pos != match_pos_end; 659 ++match_pos) 660 { 661 match_next_pos = match_pos + 1; 662 // Is this a wildcard? 663 if (match_pos->IsWildcard()) 664 { 665 if (match_wildcard_pos != match_pos_end) 666 return false; // Can't have two wildcards in effect at once. 667 668 match_wildcard_pos = match_pos; 669 // Are we at the end of the MATCH token list? 670 if (match_next_pos == match_pos_end) 671 { 672 // There is nothing more to match, return if we have any matches so far... 673 return match_count > 0; 674 } 675 } 676 677 if (match_pos->type == eInvalid || match_pos->type == eError) 678 { 679 return false; 680 } 681 else 682 { 683 if (match_pos->type == eTemplateBeg) 684 { 685 ++template_scope_depth; 686 } 687 else if (match_pos->type == eTemplateEnd) 688 { 689 assert(template_scope_depth > 0); 690 --template_scope_depth; 691 } 692 693 // Do we have a wildcard going right now? 694 if (match_wildcard_pos == match_pos_end) 695 { 696 // No wildcard matching right now, just check and see if things match 697 if (*pos == *match_pos) 698 ++match_count; 699 else 700 return false; 701 } 702 else 703 { 704 // We have a wildcard match going 705 706 // For template types we need to make sure to match the template depths... 707 const size_t start_wildcard_template_scope_depth = template_scope_depth; 708 size_t curr_wildcard_template_scope_depth = template_scope_depth; 709 while (pos != pos_end) 710 { 711 if (match_wildcard_pos->type == eNameSpace && pos->type == eParamsBeg) 712 return false; 713 714 if (start_wildcard_template_scope_depth == curr_wildcard_template_scope_depth) 715 { 716 if (*pos == *match_next_pos) 717 { 718 ++match_count; 719 match_pos = match_next_pos; 720 match_wildcard_pos = match_pos_end; 721 break; 722 } 723 } 724 if (pos->type == eTemplateBeg) 725 ++curr_wildcard_template_scope_depth; 726 else if (pos->type == eTemplateEnd) 727 --curr_wildcard_template_scope_depth; 728 729 730 ++pos; 731 } 732 } 733 } 734 735 if (pos != pos_end) 736 ++pos; 737 } 738 if (match_pos != match_pos_end) 739 return false; 740 741 return match_count > 0; 742 } 743 744 745 //---------------------------------------------------------------------- 746 // Return the number of tokens in the token collection 747 //---------------------------------------------------------------------- 748 size_t 749 Mangled::TokenList::Size () const 750 { 751 return m_tokens.size(); 752 } 753 754 755 //---------------------------------------------------------------------- 756 // Stream out the tokens 757 //---------------------------------------------------------------------- 758 Stream& 759 lldb_private::operator << (Stream& s, const Mangled::TokenList& obj) 760 { 761 obj.Dump(&s); 762 return s; 763 } 764