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