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