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 
11 // FreeBSD9-STABLE requires this to know about size_t in cxxabi.h
12 #include <cstddef>
13 #if defined(_MSC_VER)
14 #include "lldb/Host/windows/windows.h"
15 #include <Dbghelp.h>
16 #define LLDB_USE_BUILTIN_DEMANGLER
17 #elif defined (__FreeBSD__)
18 #define LLDB_USE_BUILTIN_DEMANGLER
19 #else
20 #include <cxxabi.h>
21 #endif
22 
23 #ifdef LLDB_USE_BUILTIN_DEMANGLER
24 
25 // Provide a fast-path demangler implemented in FastDemangle.cpp until it can
26 // replace the existing C++ demangler with a complete implementation
27 #include "lldb/Core/FastDemangle.h"
28 #include "lldb/Core/CxaDemangle.h"
29 
30 #endif
31 
32 
33 #include "llvm/ADT/DenseMap.h"
34 
35 #include "lldb/Core/ConstString.h"
36 #include "lldb/Core/Mangled.h"
37 #include "lldb/Core/RegularExpression.h"
38 #include "lldb/Core/Stream.h"
39 #include "lldb/Core/Timer.h"
40 #include "lldb/Target/CPPLanguageRuntime.h"
41 #include <ctype.h>
42 #include <string.h>
43 #include <stdlib.h>
44 
45 
46 using namespace lldb_private;
47 
48 static inline Mangled::ManglingScheme
49 cstring_mangling_scheme(const char *s)
50 {
51     if (s)
52     {
53         if (s[0] == '?')
54             return Mangled::eManglingSchemeMSVC;
55         if (s[0] == '_' && s[1] == 'Z')
56             return Mangled::eManglingSchemeItanium;
57     }
58     return Mangled::eManglingSchemeNone;
59 }
60 
61 static inline bool
62 cstring_is_mangled(const char *s)
63 {
64     return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone;
65 }
66 
67 static const ConstString &
68 get_demangled_name_without_arguments (const Mangled *obj)
69 {
70     // This pair is <mangled name, demangled name without function arguments>
71     static std::pair<ConstString, ConstString> g_most_recent_mangled_to_name_sans_args;
72 
73     // Need to have the mangled & demangled names we're currently examining as statics
74     // so we can return a const ref to them at the end of the func if we don't have
75     // anything better.
76     static ConstString g_last_mangled;
77     static ConstString g_last_demangled;
78 
79     ConstString mangled = obj->GetMangledName ();
80     ConstString demangled = obj->GetDemangledName ();
81 
82     if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled)
83     {
84         return g_most_recent_mangled_to_name_sans_args.second;
85     }
86 
87     g_last_demangled = demangled;
88     g_last_mangled = mangled;
89 
90     const char *mangled_name_cstr = mangled.GetCString();
91 
92     if (demangled && mangled_name_cstr && mangled_name_cstr[0])
93     {
94         if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&
95             (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo mangled_name
96             mangled_name_cstr[2] != 'G' && // avoid guard variables
97             mangled_name_cstr[2] != 'Z'))  // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
98         {
99             CPPLanguageRuntime::MethodName cxx_method (demangled);
100             if (!cxx_method.GetBasename().empty() && !cxx_method.GetContext().empty())
101             {
102                 std::string shortname = cxx_method.GetContext().str();
103                 shortname += "::";
104                 shortname += cxx_method.GetBasename().str();
105                 ConstString result(shortname.c_str());
106                 g_most_recent_mangled_to_name_sans_args.first = mangled;
107                 g_most_recent_mangled_to_name_sans_args.second = result;
108                 return g_most_recent_mangled_to_name_sans_args.second;
109             }
110         }
111     }
112 
113     if (demangled)
114         return g_last_demangled;
115     return g_last_mangled;
116 }
117 
118 #pragma mark Mangled
119 //----------------------------------------------------------------------
120 // Default constructor
121 //----------------------------------------------------------------------
122 Mangled::Mangled () :
123     m_mangled(),
124     m_demangled()
125 {
126 }
127 
128 //----------------------------------------------------------------------
129 // Constructor with an optional string and a boolean indicating if it is
130 // the mangled version.
131 //----------------------------------------------------------------------
132 Mangled::Mangled (const ConstString &s, bool mangled) :
133     m_mangled(),
134     m_demangled()
135 {
136     if (s)
137         SetValue(s, mangled);
138 }
139 
140 Mangled::Mangled (const ConstString &s) :
141     m_mangled(),
142     m_demangled()
143 {
144     if (s)
145         SetValue(s);
146 }
147 
148 //----------------------------------------------------------------------
149 // Destructor
150 //----------------------------------------------------------------------
151 Mangled::~Mangled ()
152 {
153 }
154 
155 //----------------------------------------------------------------------
156 // Convert to pointer operator. This allows code to check any Mangled
157 // objects to see if they contain anything valid using code such as:
158 //
159 //  Mangled mangled(...);
160 //  if (mangled)
161 //  { ...
162 //----------------------------------------------------------------------
163 Mangled::operator void* () const
164 {
165     return (m_mangled) ? const_cast<Mangled*>(this) : NULL;
166 }
167 
168 //----------------------------------------------------------------------
169 // Logical NOT operator. This allows code to check any Mangled
170 // objects to see if they are invalid using code such as:
171 //
172 //  Mangled mangled(...);
173 //  if (!file_spec)
174 //  { ...
175 //----------------------------------------------------------------------
176 bool
177 Mangled::operator! () const
178 {
179     return !m_mangled;
180 }
181 
182 //----------------------------------------------------------------------
183 // Clear the mangled and demangled values.
184 //----------------------------------------------------------------------
185 void
186 Mangled::Clear ()
187 {
188     m_mangled.Clear();
189     m_demangled.Clear();
190 }
191 
192 
193 //----------------------------------------------------------------------
194 // Compare the string values.
195 //----------------------------------------------------------------------
196 int
197 Mangled::Compare (const Mangled& a, const Mangled& b)
198 {
199     return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));
200 }
201 
202 
203 
204 //----------------------------------------------------------------------
205 // Set the string value in this objects. If "mangled" is true, then
206 // the mangled named is set with the new value in "s", else the
207 // demangled name is set.
208 //----------------------------------------------------------------------
209 void
210 Mangled::SetValue (const ConstString &s, bool mangled)
211 {
212     if (s)
213     {
214         if (mangled)
215         {
216             m_demangled.Clear();
217             m_mangled = s;
218         }
219         else
220         {
221             m_demangled = s;
222             m_mangled.Clear();
223         }
224     }
225     else
226     {
227         m_demangled.Clear();
228         m_mangled.Clear();
229     }
230 }
231 
232 void
233 Mangled::SetValue (const ConstString &name)
234 {
235     if (name)
236     {
237         if (cstring_is_mangled(name.GetCString()))
238         {
239             m_demangled.Clear();
240             m_mangled = name;
241         }
242         else
243         {
244             m_demangled = name;
245             m_mangled.Clear();
246         }
247     }
248     else
249     {
250         m_demangled.Clear();
251         m_mangled.Clear();
252     }
253 }
254 
255 //----------------------------------------------------------------------
256 // Generate the demangled name on demand using this accessor. Code in
257 // this class will need to use this accessor if it wishes to decode
258 // the demangled name. The result is cached and will be kept until a
259 // new string value is supplied to this object, or until the end of the
260 // object's lifetime.
261 //----------------------------------------------------------------------
262 const ConstString&
263 Mangled::GetDemangledName () const
264 {
265     // Check to make sure we have a valid mangled name and that we
266     // haven't already decoded our mangled name.
267     if (m_mangled && !m_demangled)
268     {
269         // We need to generate and cache the demangled name.
270         Timer scoped_timer (__PRETTY_FUNCTION__,
271                             "Mangled::GetDemangledName (m_mangled = %s)",
272                             m_mangled.GetCString());
273 
274         // Don't bother running anything that isn't mangled
275         const char *mangled_name = m_mangled.GetCString();
276         ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
277         if (mangling_scheme != eManglingSchemeNone &&
278             !m_mangled.GetMangledCounterpart(m_demangled))
279         {
280             // We didn't already mangle this name, demangle it and if all goes well
281             // add it to our map.
282             char *demangled_name = nullptr;
283             switch (mangling_scheme)
284             {
285                 case eManglingSchemeMSVC:
286                 {
287 #if defined(_MSC_VER)
288                     const size_t demangled_length = 2048;
289                     demangled_name = static_cast<char *>(::malloc(demangled_length));
290                     ::ZeroMemory(demangled_name, demangled_length);
291                     DWORD result = ::UnDecorateSymbolName(mangled_name, demangled_name, demangled_length,
292                             UNDNAME_NO_ACCESS_SPECIFIERS   | // Strip public, private, protected keywords
293                             UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords
294                             UNDNAME_NO_THROW_SIGNATURES    | // Strip throw() specifications
295                             UNDNAME_NO_MEMBER_TYPE         | // Strip virtual, static, etc specifiers
296                             UNDNAME_NO_MS_KEYWORDS           // Strip all MS extension keywords
297                         );
298                     if (result == 0)
299                     {
300                         free(demangled_name);
301                         demangled_name = nullptr;
302                     }
303 #endif
304                     break;
305                 }
306                 case eManglingSchemeItanium:
307                 {
308 #ifdef LLDB_USE_BUILTIN_DEMANGLER
309                     // Try to use the fast-path demangler first for the
310                     // performance win, falling back to the full demangler only
311                     // when necessary
312                     demangled_name = FastDemangle(mangled_name, m_mangled.GetLength());
313                     if (!demangled_name)
314                         demangled_name = __cxa_demangle(mangled_name, NULL, NULL, NULL);
315 #else
316                     demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL);
317 #endif
318                     break;
319                 }
320                 case eManglingSchemeNone:
321                     break;
322             }
323             if (demangled_name)
324             {
325                 m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
326                 free(demangled_name);
327             }
328         }
329         if (!m_demangled)
330         {
331             // Set the demangled string to the empty string to indicate we
332             // tried to parse it once and failed.
333             m_demangled.SetCString("");
334         }
335     }
336 
337     return m_demangled;
338 }
339 
340 
341 bool
342 Mangled::NameMatches (const RegularExpression& regex) const
343 {
344     if (m_mangled && regex.Execute (m_mangled.AsCString()))
345         return true;
346 
347     if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))
348         return true;
349     return false;
350 }
351 
352 //----------------------------------------------------------------------
353 // Get the demangled name if there is one, else return the mangled name.
354 //----------------------------------------------------------------------
355 const ConstString&
356 Mangled::GetName (Mangled::NamePreference preference) const
357 {
358     if (preference == ePreferDemangledWithoutArguments)
359     {
360         // Call the accessor to make sure we get a demangled name in case
361         // it hasn't been demangled yet...
362         GetDemangledName();
363 
364         return get_demangled_name_without_arguments (this);
365     }
366     if (preference == ePreferDemangled)
367     {
368         // Call the accessor to make sure we get a demangled name in case
369         // it hasn't been demangled yet...
370         if (GetDemangledName())
371             return m_demangled;
372         return m_mangled;
373     }
374     else
375     {
376         if (m_mangled)
377             return m_mangled;
378         return GetDemangledName();
379     }
380 }
381 
382 //----------------------------------------------------------------------
383 // Dump a Mangled object to stream "s". We don't force our
384 // demangled name to be computed currently (we don't use the accessor).
385 //----------------------------------------------------------------------
386 void
387 Mangled::Dump (Stream *s) const
388 {
389     if (m_mangled)
390     {
391         *s << ", mangled = " << m_mangled;
392     }
393     if (m_demangled)
394     {
395         const char * demangled = m_demangled.AsCString();
396         s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
397     }
398 }
399 
400 //----------------------------------------------------------------------
401 // Dumps a debug version of this string with extra object and state
402 // information to stream "s".
403 //----------------------------------------------------------------------
404 void
405 Mangled::DumpDebug (Stream *s) const
406 {
407     s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void*) * 2),
408               static_cast<const void*>(this));
409     m_mangled.DumpDebug(s);
410     s->Printf(", demangled = ");
411     m_demangled.DumpDebug(s);
412 }
413 
414 //----------------------------------------------------------------------
415 // Return the size in byte that this object takes in memory. The size
416 // includes the size of the objects it owns, and not the strings that
417 // it references because they are shared strings.
418 //----------------------------------------------------------------------
419 size_t
420 Mangled::MemorySize () const
421 {
422     return m_mangled.MemorySize() + m_demangled.MemorySize();
423 }
424 
425 lldb::LanguageType
426 Mangled::GuessLanguage () const
427 {
428     ConstString mangled = GetMangledName();
429     if (mangled)
430     {
431         if (GetDemangledName())
432         {
433             if (cstring_is_mangled(mangled.GetCString()))
434                 return lldb::eLanguageTypeC_plus_plus;
435         }
436     }
437     return  lldb::eLanguageTypeUnknown;
438 }
439 
440 //----------------------------------------------------------------------
441 // Dump OBJ to the supplied stream S.
442 //----------------------------------------------------------------------
443 Stream&
444 operator << (Stream& s, const Mangled& obj)
445 {
446     if (obj.GetMangledName())
447         s << "mangled = '" << obj.GetMangledName() << "'";
448 
449     const ConstString& demangled = obj.GetDemangledName();
450     if (demangled)
451         s << ", demangled = '" << demangled << '\'';
452     else
453         s << ", demangled = <error>";
454     return s;
455 }
456