blob: 110fa6562811466f4e6b07f31fbc86fda5a8c7cb [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Greg Claytone41e5892010-09-03 23:26:12 +000012#include "llvm/ADT/DenseMap.h"
13
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014#include "lldb/Core/ConstString.h"
15#include "lldb/Core/Mangled.h"
Greg Clayton83c5cd92010-11-14 22:13:40 +000016#include "lldb/Core/RegularExpression.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Core/Stream.h"
18#include "lldb/Core/Timer.h"
Eli Friedman88966972010-06-09 08:50:27 +000019#include <ctype.h>
20#include <string.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021
22using namespace lldb_private;
23
24#pragma mark Mangled
25//----------------------------------------------------------------------
26// Default constructor
27//----------------------------------------------------------------------
28Mangled::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//----------------------------------------------------------------------
38Mangled::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//----------------------------------------------------------------------
51Mangled::~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//----------------------------------------------------------------------
63Mangled::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//----------------------------------------------------------------------
76bool
77Mangled::operator! () const
78{
79 return !m_mangled;
80}
81
82//----------------------------------------------------------------------
83// Clear the mangled and demangled values.
84//----------------------------------------------------------------------
85void
86Mangled::Clear ()
87{
88 m_mangled.Clear();
89 m_demangled.Clear();
90}
91
92
93//----------------------------------------------------------------------
94// Compare the the string values.
95//----------------------------------------------------------------------
96int
97Mangled::Compare (const Mangled& a, const Mangled& b)
98{
Jim Ingham89bf5e92010-09-15 00:13:44 +000099 return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100}
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//----------------------------------------------------------------------
109void
110Mangled::SetValue (const char *s, bool mangled)
111{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112 if (s)
113 {
114 if (mangled)
Greg Clayton385aa282011-04-22 03:55:06 +0000115 {
116 m_demangled.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 m_mangled.SetCString (s);
Greg Clayton385aa282011-04-22 03:55:06 +0000118 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119 else
Greg Clayton385aa282011-04-22 03:55:06 +0000120 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121 m_demangled.SetCString(s);
Greg Clayton385aa282011-04-22 03:55:06 +0000122 m_mangled.Clear();
123 }
124 }
125 else
126 {
127 m_demangled.Clear();
128 m_mangled.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129 }
130}
131
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000132//----------------------------------------------------------------------
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//----------------------------------------------------------------------
139const ConstString&
140Mangled::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();
Jason Molendab690fbb2010-12-15 04:20:25 +0000154 // Don't bother running anything that doesn't start with _Z through the demangler
155 if (mangled[0] != '\0' && mangled[0] == '_' && mangled[1] == 'Z')
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156 {
Greg Claytone41e5892010-09-03 23:26:12 +0000157 // Since demangling can be a costly, and since all names that go
158 // into a ConstString (like our m_mangled and m_demangled members)
159 // end up being unique "const char *" values, we can use a DenseMap
160 // to speed up our lookup. We do this because often our symbol table
161 // and our debug information both have the mangled names which they
162 // would each need to demangle. Also, with GCC we end up with the one
163 // definition rule where a lot of STL code produces symbols that are
164 // in multiple compile units and the mangled names end up being in
165 // the same binary multiple times. The performance win isn't huge,
166 // but we showed a 20% improvement on darwin.
167 typedef llvm::DenseMap<const char *, const char *> MangledToDemangledMap;
168 static MangledToDemangledMap g_mangled_to_demangled;
Benjamin Kramer53a61dc2010-06-22 15:28:29 +0000169
Greg Claytone41e5892010-09-03 23:26:12 +0000170 // Check our mangled string pointer to demangled string pointer map first
171 MangledToDemangledMap::const_iterator pos = g_mangled_to_demangled.find (mangled);
172 if (pos != g_mangled_to_demangled.end())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 {
Greg Claytone41e5892010-09-03 23:26:12 +0000174 // We have already demangled this string, we can just use our saved result!
175 m_demangled.SetCString(pos->second);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000176 }
177 else
178 {
Greg Claytone41e5892010-09-03 23:26:12 +0000179 // We didn't already mangle this name, demangle it and if all goes well
180 // add it to our map.
181 char *demangled_name = abi::__cxa_demangle (mangled, NULL, NULL, NULL);
182
183 if (demangled_name)
184 {
185 m_demangled.SetCString (demangled_name);
186 // Now that the name has been uniqued, add the uniqued C string
187 // pointer from m_mangled as the key to the uniqued C string
188 // pointer in m_demangled.
189 g_mangled_to_demangled.insert (std::make_pair (mangled, m_demangled.GetCString()));
190 free (demangled_name);
191 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000192 }
193 }
Jason Molenda3f8688b2010-12-15 04:27:04 +0000194 if (!m_demangled)
195 {
196 // Set the demangled string to the empty string to indicate we
197 // tried to parse it once and failed.
198 m_demangled.SetCString("");
199 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 }
201
202 return m_demangled;
203}
204
Greg Clayton83c5cd92010-11-14 22:13:40 +0000205
206bool
207Mangled::NameMatches (const RegularExpression& regex) const
208{
209 if (m_mangled && regex.Execute (m_mangled.AsCString()))
210 return true;
211
212 if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))
213 return true;
214 return false;
215}
216
217
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218//----------------------------------------------------------------------
219// Mangled name get accessor
220//----------------------------------------------------------------------
221ConstString&
222Mangled::GetMangledName ()
223{
224 return m_mangled;
225}
226
227//----------------------------------------------------------------------
228// Mangled name const get accessor
229//----------------------------------------------------------------------
230const ConstString&
231Mangled::GetMangledName () const
232{
233 return m_mangled;
234}
235
236//----------------------------------------------------------------------
237// Get the demangled name if there is one, else return the mangled name.
238//----------------------------------------------------------------------
239const ConstString&
Jim Ingham08b87e02010-09-14 22:03:00 +0000240Mangled::GetName (Mangled::NamePreference preference) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000241{
Greg Clayton87425432010-09-14 23:44:49 +0000242 if (preference == ePreferDemangled)
Jim Ingham08b87e02010-09-14 22:03:00 +0000243 {
Greg Claytond0b89f82010-09-14 23:48:44 +0000244 // Call the accessor to make sure we get a demangled name in case
245 // it hasn't been demangled yet...
246 if (GetDemangledName())
247 return m_demangled;
Greg Clayton87425432010-09-14 23:44:49 +0000248 return m_mangled;
249 }
250 else
251 {
Greg Claytond0b89f82010-09-14 23:48:44 +0000252 if (m_mangled)
253 return m_mangled;
254 return GetDemangledName();
Jim Ingham08b87e02010-09-14 22:03:00 +0000255 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256}
257
258//----------------------------------------------------------------------
259// Generate the tokens from the demangled name.
260//
261// Returns the number of tokens that were parsed.
262//----------------------------------------------------------------------
263size_t
264Mangled::GetTokens (Mangled::TokenList &tokens) const
265{
266 tokens.Clear();
267 const ConstString& demangled = GetDemangledName();
268 if (demangled && !demangled.IsEmpty())
269 tokens.Parse(demangled.AsCString());
270
271 return tokens.Size();
272}
273
274//----------------------------------------------------------------------
275// Dump a Mangled object to stream "s". We don't force our
276// demangled name to be computed currently (we don't use the accessor).
277//----------------------------------------------------------------------
278void
279Mangled::Dump (Stream *s) const
280{
281 if (m_mangled)
282 {
283 *s << ", mangled = " << m_mangled;
284 }
285 if (m_demangled)
286 {
287 const char * demangled = m_demangled.AsCString();
288 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
289 }
290}
291
292//----------------------------------------------------------------------
293// Dumps a debug version of this string with extra object and state
294// information to stream "s".
295//----------------------------------------------------------------------
296void
297Mangled::DumpDebug (Stream *s) const
298{
299 s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this);
300 m_mangled.DumpDebug(s);
301 s->Printf(", demangled = ");
302 m_demangled.DumpDebug(s);
303}
304
305//----------------------------------------------------------------------
306// Return the size in byte that this object takes in memory. The size
307// includes the size of the objects it owns, and not the strings that
308// it references because they are shared strings.
309//----------------------------------------------------------------------
310size_t
311Mangled::MemorySize () const
312{
313 return m_mangled.MemorySize() + m_demangled.MemorySize();
314}
315
316//----------------------------------------------------------------------
317// Dump OBJ to the supplied stream S.
318//----------------------------------------------------------------------
319Stream&
320operator << (Stream& s, const Mangled& obj)
321{
322 if (obj.GetMangledName())
323 s << "mangled = '" << obj.GetMangledName() << "'";
324
325 const ConstString& demangled = obj.GetDemangledName();
326 if (demangled)
327 s << ", demangled = '" << demangled << '\'';
328 else
329 s << ", demangled = <error>";
330 return s;
331}
332
333
334
335
336#pragma mark Mangled::Token
337
338//--------------------------------------------------------------
339// Default constructor
340//--------------------------------------------------------------
341Mangled::Token::Token () :
342 type(eInvalid),
343 value()
344{
345}
346
347//--------------------------------------------------------------
348// Equal to operator
349//--------------------------------------------------------------
350bool
351Mangled::Token::operator== (const Token& rhs) const
352{
353 return type == rhs.type && value == rhs.value;
354}
355
356//--------------------------------------------------------------
357// Dump the token to a stream "s"
358//--------------------------------------------------------------
359void
360Mangled::Token::Dump (Stream *s) const
361{
362 switch (type)
363 {
364 case eInvalid: s->PutCString("invalid "); break;
365 case eNameSpace: s->PutCString("namespace "); break;
366 case eMethodName: s->PutCString("method "); break;
367 case eType: s->PutCString("type "); break;
368 case eTemplate: s->PutCString("template "); break;
369 case eTemplateBeg: s->PutCString("template < "); break;
370 case eTemplateEnd: s->PutCString("template > "); break;
371 case eParamsBeg: s->PutCString("params ( "); break;
372 case eParamsEnd: s->PutCString("params ) "); break;
373 case eQualifier: s->PutCString("qualifier "); break;
374 case eError: s->PutCString("ERROR "); break;
375 default:
376 s->Printf("type = %i", type);
377 break;
378 }
379 value.DumpDebug(s);
380}
381
382//--------------------------------------------------------------
383// Returns true if this token is a wildcard
384//--------------------------------------------------------------
385bool
386Mangled::Token::IsWildcard () const
387{
388 static ConstString g_wildcard_str("*");
389 return value == g_wildcard_str;
390}
391
392
393//----------------------------------------------------------------------
394// Dump "obj" to the supplied stream "s"
395//----------------------------------------------------------------------
396Stream&
397lldb_private::operator << (Stream& s, const Mangled::Token& obj)
398{
399 obj.Dump(&s);
400 return s;
401}
402
403
404#pragma mark Mangled::TokenList
405//----------------------------------------------------------------------
406// Mangled::TokenList
407//----------------------------------------------------------------------
408
409//--------------------------------------------------------------
410// Default constructor. If demangled is non-NULL and not-empty
411// the token list will parse up the demangled string it is
412// given, else the object will initialize an empty token list.
413//--------------------------------------------------------------
414Mangled::TokenList::TokenList (const char *demangled) :
415 m_tokens()
416{
417 if (demangled && demangled[0])
418 {
419 Parse(demangled);
420 }
421}
422
423//----------------------------------------------------------------------
424// Destructor
425//----------------------------------------------------------------------
426Mangled::TokenList::~TokenList ()
427{
428}
429
430//----------------------------------------------------------------------
431// Parses "demangled" into tokens. This allows complex
432// comparisons to be done. Comparisons can include wildcards at
433// the namespace, method name, template, and template and
434// parameter type levels.
435//
436// Example queries include:
437// "std::basic_string<*>" // Find all std::basic_string variants
438// "std::basic_string<*>::erase(*)" // Find all std::basic_string::erase variants with any number of parameters
439// "*::clear()" // Find all functions with a method name of
440// // "clear" that are in any namespace that
441// // have no parameters
442// "::printf" // Find the printf function in the global namespace
443// "printf" // Ditto
444// "foo::*(int)" // Find all functions in the class or namespace "foo" that take a single integer argument
445//
446// Returns the number of tokens that were decoded, or zero when
447// we fail.
448//----------------------------------------------------------------------
449size_t
450Mangled::TokenList::Parse (const char *s)
451{
452 m_tokens.clear();
453
454 Token token;
455 token.type = eNameSpace;
456
457 TokenType max_type = eInvalid;
458 const char *p = s;
459 size_t span = 0;
460 size_t sep_size = 0;
461
462 while (*p != '\0')
463 {
464 p = p + span + sep_size;
465 while (isspace(*p))
466 ++p;
467
468 if (*p == '\0')
469 break;
470
471 span = strcspn(p, ":<>(),");
472 sep_size = 1;
473 token.type = eInvalid;
474 switch (p[span])
475 {
476 case '\0':
477 break;
478
479 case ':':
480 if (p[span+1] == ':')
481 {
482 sep_size = 2;
483 if (span > 0)
484 {
485 token.type = eNameSpace;
486 token.value.SetCStringWithLength (p, span);
487 m_tokens.push_back(token);
488 }
489 else
490 continue;
491 }
492 break;
493
494 case '(':
495 if (span > 0)
496 {
497 token.type = eMethodName;
498 token.value.SetCStringWithLength (p, span);
499 m_tokens.push_back(token);
500 }
501
502 token.type = eParamsBeg;
503 token.value.Clear();
504 m_tokens.push_back(token);
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 else
515 {
516 continue;
517 }
518 break;
519
520 case ')':
521 if (span > 0)
522 {
523 token.type = eType;
524 token.value.SetCStringWithLength (p, span);
525 m_tokens.push_back(token);
526 }
527
528 token.type = eParamsEnd;
529 token.value.Clear();
530 m_tokens.push_back(token);
531 break;
532
533 case '<':
534 if (span > 0)
535 {
536 token.type = eTemplate;
537 token.value.SetCStringWithLength (p, span);
538 m_tokens.push_back(token);
539 }
540
541 token.type = eTemplateBeg;
542 token.value.Clear();
543 m_tokens.push_back(token);
544 break;
545
546 case '>':
547 if (span > 0)
548 {
549 token.type = eType;
550 token.value.SetCStringWithLength (p, span);
551 m_tokens.push_back(token);
552 }
553
554 token.type = eTemplateEnd;
555 token.value.Clear();
556 m_tokens.push_back(token);
557 break;
558 }
559
560 if (max_type < token.type)
561 max_type = token.type;
562
563 if (token.type == eInvalid)
564 {
565 if (max_type >= eParamsEnd)
566 {
567 token.type = eQualifier;
568 token.value.SetCString(p);
569 m_tokens.push_back(token);
570 }
571 else if (max_type >= eParamsBeg)
572 {
573 token.type = eType;
574 token.value.SetCString(p);
575 m_tokens.push_back(token);
576 }
577 else
578 {
579 token.type = eMethodName;
580 token.value.SetCString(p);
581 m_tokens.push_back(token);
582 }
583 break;
584 }
585 }
586 return m_tokens.size();
587}
588
589
590//----------------------------------------------------------------------
591// Clear the token list.
592//----------------------------------------------------------------------
593void
594Mangled::TokenList::Clear ()
595{
596 m_tokens.clear();
597}
598
599//----------------------------------------------------------------------
600// Dump the token list to the stream "s"
601//----------------------------------------------------------------------
602void
603Mangled::TokenList::Dump (Stream *s) const
604{
605 collection::const_iterator pos;
606 collection::const_iterator beg = m_tokens.begin();
607 collection::const_iterator end = m_tokens.end();
608 for (pos = beg; pos != end; ++pos)
609 {
610 s->Indent("token[");
611 *s << (uint32_t)std::distance(beg, pos) << "] = " << *pos << "\n";
612 }
613}
614
615//----------------------------------------------------------------------
616// Find the first token in the list that has "token_type" as its
617// type
618//----------------------------------------------------------------------
619const Mangled::Token *
620Mangled::TokenList::Find (TokenType token_type) const
621{
622 collection::const_iterator pos;
623 collection::const_iterator beg = m_tokens.begin();
624 collection::const_iterator end = m_tokens.end();
625 for (pos = beg; pos != end; ++pos)
626 {
627 if (pos->type == token_type)
628 return &(*pos);
629 }
630 return NULL;
631}
632
633//----------------------------------------------------------------------
634// Return the token at index "idx", or NULL if the index is
635// out of range.
636//----------------------------------------------------------------------
637const Mangled::Token *
638Mangled::TokenList::GetTokenAtIndex (uint32_t idx) const
639{
640 if (idx < m_tokens.size())
641 return &m_tokens[idx];
642 return NULL;
643}
644
645
646//----------------------------------------------------------------------
647// Given a token list, see if it matches this object's tokens.
648// "token_list" can contain wild card values to enable powerful
649// matching. Matching the std::string::erase(*) example that was
650// tokenized above we could use a token list such as:
651//
652// token name
653// ----------- ----------------------------------------
654// eNameSpace "std"
655// eTemplate "basic_string"
656// eTemplateBeg
657// eInvalid "*"
658// eTemplateEnd
659// eMethodName "erase"
660// eParamsBeg
661// eInvalid "*"
662// eParamsEnd
663//
664// Returns true if it "token_list" matches this object's tokens,
665// false otherwise.
666//----------------------------------------------------------------------
667bool
668Mangled::TokenList::MatchesQuery (const Mangled::TokenList &match) const
669{
670 size_t match_count = 0;
671 collection::const_iterator pos;
672 collection::const_iterator pos_end = m_tokens.end();
673
674 collection::const_iterator match_pos;
675 collection::const_iterator match_pos_end = match.m_tokens.end();
676 collection::const_iterator match_wildcard_pos = match_pos_end;
677 collection::const_iterator match_next_pos = match_pos_end;
678
679 size_t template_scope_depth = 0;
680
681 for (pos = m_tokens.begin(), match_pos = match.m_tokens.begin();
682 pos != pos_end && match_pos != match_pos_end;
683 ++match_pos)
684 {
685 match_next_pos = match_pos + 1;
686 // Is this a wildcard?
687 if (match_pos->IsWildcard())
688 {
689 if (match_wildcard_pos != match_pos_end)
690 return false; // Can't have two wildcards in effect at once.
691
692 match_wildcard_pos = match_pos;
693 // Are we at the end of the MATCH token list?
694 if (match_next_pos == match_pos_end)
695 {
696 // There is nothing more to match, return if we have any matches so far...
697 return match_count > 0;
698 }
699 }
700
701 if (match_pos->type == eInvalid || match_pos->type == eError)
702 {
703 return false;
704 }
705 else
706 {
707 if (match_pos->type == eTemplateBeg)
708 {
709 ++template_scope_depth;
710 }
711 else if (match_pos->type == eTemplateEnd)
712 {
713 assert(template_scope_depth > 0);
714 --template_scope_depth;
715 }
716
717 // Do we have a wildcard going right now?
718 if (match_wildcard_pos == match_pos_end)
719 {
720 // No wildcard matching right now, just check and see if things match
721 if (*pos == *match_pos)
722 ++match_count;
723 else
724 return false;
725 }
726 else
727 {
728 // We have a wildcard match going
729
730 // For template types we need to make sure to match the template depths...
731 const size_t start_wildcard_template_scope_depth = template_scope_depth;
732 size_t curr_wildcard_template_scope_depth = template_scope_depth;
733 while (pos != pos_end)
734 {
735 if (match_wildcard_pos->type == eNameSpace && pos->type == eParamsBeg)
736 return false;
737
738 if (start_wildcard_template_scope_depth == curr_wildcard_template_scope_depth)
739 {
740 if (*pos == *match_next_pos)
741 {
742 ++match_count;
743 match_pos = match_next_pos;
744 match_wildcard_pos = match_pos_end;
745 break;
746 }
747 }
748 if (pos->type == eTemplateBeg)
749 ++curr_wildcard_template_scope_depth;
750 else if (pos->type == eTemplateEnd)
751 --curr_wildcard_template_scope_depth;
752
753
754 ++pos;
755 }
756 }
757 }
758
759 if (pos != pos_end)
760 ++pos;
761 }
762 if (match_pos != match_pos_end)
763 return false;
764
765 return match_count > 0;
766}
767
768
769//----------------------------------------------------------------------
770// Return the number of tokens in the token collection
771//----------------------------------------------------------------------
772size_t
773Mangled::TokenList::Size () const
774{
775 return m_tokens.size();
776}
777
778
779//----------------------------------------------------------------------
780// Stream out the tokens
781//----------------------------------------------------------------------
782Stream&
783lldb_private::operator << (Stream& s, const Mangled::TokenList& obj)
784{
785 obj.Dump(&s);
786 return s;
787}