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