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