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