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