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