1 //===-- Mangled.cpp ---------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Core/Mangled.h"
10 
11 #include "lldb/Core/RichManglingContext.h"
12 #include "lldb/Utility/ConstString.h"
13 #include "lldb/Utility/Log.h"
14 #include "lldb/Utility/Logging.h"
15 #include "lldb/Utility/RegularExpression.h"
16 #include "lldb/Utility/Stream.h"
17 #include "lldb/Utility/Timer.h"
18 #include "lldb/lldb-enumerations.h"
19 
20 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
21 #include "Plugins/Language/ObjC/ObjCLanguage.h"
22 
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/Demangle/Demangle.h"
25 #include "llvm/Support/Compiler.h"
26 
27 #include <mutex>
28 #include <string>
29 #include <utility>
30 
31 #include <stdlib.h>
32 #include <string.h>
33 using namespace lldb_private;
34 
35 static inline Mangled::ManglingScheme cstring_mangling_scheme(const char *s) {
36   if (s) {
37     if (s[0] == '?')
38       return Mangled::eManglingSchemeMSVC;
39     if (s[0] == '_' && s[1] == 'Z')
40       return Mangled::eManglingSchemeItanium;
41   }
42   return Mangled::eManglingSchemeNone;
43 }
44 
45 static inline bool cstring_is_mangled(const char *s) {
46   return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone;
47 }
48 
49 static ConstString
50 get_demangled_name_without_arguments(ConstString mangled,
51                                      ConstString demangled) {
52   // This pair is <mangled name, demangled name without function arguments>
53   static std::pair<ConstString, ConstString>
54       g_most_recent_mangled_to_name_sans_args;
55 
56   // Need to have the mangled & demangled names we're currently examining as
57   // statics so we can return a const ref to them at the end of the func if we
58   // don't have anything better.
59   static ConstString g_last_mangled;
60   static ConstString g_last_demangled;
61 
62   if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) {
63     return g_most_recent_mangled_to_name_sans_args.second;
64   }
65 
66   g_last_demangled = demangled;
67   g_last_mangled = mangled;
68 
69   const char *mangled_name_cstr = mangled.GetCString();
70 
71   if (demangled && mangled_name_cstr && mangled_name_cstr[0]) {
72     if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&
73         (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure,
74                                         // typeinfo structure, and typeinfo
75                                         // mangled_name
76          mangled_name_cstr[2] != 'G' && // avoid guard variables
77          mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually
78                                        // handle eSymbolTypeData, we will want
79                                        // this back)
80     {
81       CPlusPlusLanguage::MethodName cxx_method(demangled);
82       if (!cxx_method.GetBasename().empty()) {
83         std::string shortname;
84         if (!cxx_method.GetContext().empty())
85           shortname = cxx_method.GetContext().str() + "::";
86         shortname += cxx_method.GetBasename().str();
87         ConstString result(shortname.c_str());
88         g_most_recent_mangled_to_name_sans_args.first = mangled;
89         g_most_recent_mangled_to_name_sans_args.second = result;
90         return g_most_recent_mangled_to_name_sans_args.second;
91       }
92     }
93   }
94 
95   if (demangled)
96     return g_last_demangled;
97   return g_last_mangled;
98 }
99 
100 #pragma mark Mangled
101 
102 Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() {
103   if (s)
104     SetValue(s);
105 }
106 
107 Mangled::Mangled(llvm::StringRef name) {
108   if (!name.empty())
109     SetValue(ConstString(name));
110 }
111 
112 // Convert to pointer operator. This allows code to check any Mangled objects
113 // to see if they contain anything valid using code such as:
114 //
115 //  Mangled mangled(...);
116 //  if (mangled)
117 //  { ...
118 Mangled::operator void *() const {
119   return (m_mangled) ? const_cast<Mangled *>(this) : nullptr;
120 }
121 
122 // Logical NOT operator. This allows code to check any Mangled objects to see
123 // if they are invalid using code such as:
124 //
125 //  Mangled mangled(...);
126 //  if (!file_spec)
127 //  { ...
128 bool Mangled::operator!() const { return !m_mangled; }
129 
130 // Clear the mangled and demangled values.
131 void Mangled::Clear() {
132   m_mangled.Clear();
133   m_demangled.Clear();
134 }
135 
136 // Compare the string values.
137 int Mangled::Compare(const Mangled &a, const Mangled &b) {
138   return ConstString::Compare(
139       a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled),
140       b.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
141 }
142 
143 // Set the string value in this objects. If "mangled" is true, then the mangled
144 // named is set with the new value in "s", else the demangled name is set.
145 void Mangled::SetValue(ConstString s, bool mangled) {
146   if (s) {
147     if (mangled) {
148       m_demangled.Clear();
149       m_mangled = s;
150     } else {
151       m_demangled = s;
152       m_mangled.Clear();
153     }
154   } else {
155     m_demangled.Clear();
156     m_mangled.Clear();
157   }
158 }
159 
160 void Mangled::SetValue(ConstString name) {
161   if (name) {
162     if (cstring_is_mangled(name.GetCString())) {
163       m_demangled.Clear();
164       m_mangled = name;
165     } else {
166       m_demangled = name;
167       m_mangled.Clear();
168     }
169   } else {
170     m_demangled.Clear();
171     m_mangled.Clear();
172   }
173 }
174 
175 // Local helpers for different demangling implementations.
176 static char *GetMSVCDemangledStr(const char *M) {
177   char *demangled_cstr = llvm::microsoftDemangle(
178       M, nullptr, nullptr, nullptr,
179       llvm::MSDemangleFlags(llvm::MSDF_NoAccessSpecifier |
180                             llvm::MSDF_NoCallingConvention |
181                             llvm::MSDF_NoMemberType));
182 
183   if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
184     if (demangled_cstr && demangled_cstr[0])
185       LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M, demangled_cstr);
186     else
187       LLDB_LOGF(log, "demangled msvc: %s -> error", M);
188   }
189 
190   return demangled_cstr;
191 }
192 
193 static char *GetItaniumDemangledStr(const char *M) {
194   char *demangled_cstr = nullptr;
195 
196   llvm::ItaniumPartialDemangler ipd;
197   bool err = ipd.partialDemangle(M);
198   if (!err) {
199     // Default buffer and size (will realloc in case it's too small).
200     size_t demangled_size = 80;
201     demangled_cstr = static_cast<char *>(std::malloc(demangled_size));
202     demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size);
203 
204     assert(demangled_cstr &&
205            "finishDemangle must always succeed if partialDemangle did");
206     assert(demangled_cstr[demangled_size - 1] == '\0' &&
207            "Expected demangled_size to return length including trailing null");
208   }
209 
210   if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
211     if (demangled_cstr)
212       LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr);
213     else
214       LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M);
215   }
216 
217   return demangled_cstr;
218 }
219 
220 // Explicit demangling for scheduled requests during batch processing. This
221 // makes use of ItaniumPartialDemangler's rich demangle info
222 bool Mangled::DemangleWithRichManglingInfo(
223     RichManglingContext &context, SkipMangledNameFn *skip_mangled_name) {
224   // We need to generate and cache the demangled name.
225   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
226   Timer scoped_timer(func_cat,
227                      "Mangled::DemangleWithRichNameIndexInfo (m_mangled = %s)",
228                      m_mangled.GetCString());
229 
230   // Others are not meant to arrive here. ObjC names or C's main() for example
231   // have their names stored in m_demangled, while m_mangled is empty.
232   assert(m_mangled);
233 
234   // Check whether or not we are interested in this name at all.
235   ManglingScheme scheme = cstring_mangling_scheme(m_mangled.GetCString());
236   if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme))
237     return false;
238 
239   switch (scheme) {
240   case eManglingSchemeNone:
241     // The current mangled_name_filter would allow llvm_unreachable here.
242     return false;
243 
244   case eManglingSchemeItanium:
245     // We want the rich mangling info here, so we don't care whether or not
246     // there is a demangled string in the pool already.
247     if (context.FromItaniumName(m_mangled)) {
248       // If we got an info, we have a name. Copy to string pool and connect the
249       // counterparts to accelerate later access in GetDemangledName().
250       context.ParseFullName();
251       m_demangled.SetStringWithMangledCounterpart(context.GetBufferRef(),
252                                                   m_mangled);
253       return true;
254     } else {
255       m_demangled.SetCString("");
256       return false;
257     }
258 
259   case eManglingSchemeMSVC: {
260     // We have no rich mangling for MSVC-mangled names yet, so first try to
261     // demangle it if necessary.
262     if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) {
263       if (char *d = GetMSVCDemangledStr(m_mangled.GetCString())) {
264         // If we got an info, we have a name. Copy to string pool and connect
265         // the counterparts to accelerate later access in GetDemangledName().
266         m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d),
267                                                     m_mangled);
268         ::free(d);
269       } else {
270         m_demangled.SetCString("");
271       }
272     }
273 
274     if (m_demangled.IsEmpty()) {
275       // Cannot demangle it, so don't try parsing.
276       return false;
277     } else {
278       // Demangled successfully, we can try and parse it with
279       // CPlusPlusLanguage::MethodName.
280       return context.FromCxxMethodName(m_demangled);
281     }
282   }
283   }
284   llvm_unreachable("Fully covered switch above!");
285 }
286 
287 // Generate the demangled name on demand using this accessor. Code in this
288 // class will need to use this accessor if it wishes to decode the demangled
289 // name. The result is cached and will be kept until a new string value is
290 // supplied to this object, or until the end of the object's lifetime.
291 ConstString
292 Mangled::GetDemangledName(lldb::LanguageType language) const {
293   // Check to make sure we have a valid mangled name and that we haven't
294   // already decoded our mangled name.
295   if (m_mangled && m_demangled.IsNull()) {
296     // We need to generate and cache the demangled name.
297     static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
298     Timer scoped_timer(func_cat, "Mangled::GetDemangledName (m_mangled = %s)",
299                        m_mangled.GetCString());
300 
301     // Don't bother running anything that isn't mangled
302     const char *mangled_name = m_mangled.GetCString();
303     ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
304     if (mangling_scheme != eManglingSchemeNone &&
305         !m_mangled.GetMangledCounterpart(m_demangled)) {
306       // We didn't already mangle this name, demangle it and if all goes well
307       // add it to our map.
308       char *demangled_name = nullptr;
309       switch (mangling_scheme) {
310       case eManglingSchemeMSVC:
311         demangled_name = GetMSVCDemangledStr(mangled_name);
312         break;
313       case eManglingSchemeItanium: {
314         demangled_name = GetItaniumDemangledStr(mangled_name);
315         break;
316       }
317       case eManglingSchemeNone:
318         llvm_unreachable("eManglingSchemeNone was handled already");
319       }
320       if (demangled_name) {
321         m_demangled.SetStringWithMangledCounterpart(
322             llvm::StringRef(demangled_name), m_mangled);
323         free(demangled_name);
324       }
325     }
326     if (m_demangled.IsNull()) {
327       // Set the demangled string to the empty string to indicate we tried to
328       // parse it once and failed.
329       m_demangled.SetCString("");
330     }
331   }
332 
333   return m_demangled;
334 }
335 
336 ConstString
337 Mangled::GetDisplayDemangledName(lldb::LanguageType language) const {
338   return GetDemangledName(language);
339 }
340 
341 bool Mangled::NameMatches(const RegularExpression &regex,
342                           lldb::LanguageType language) const {
343   if (m_mangled && regex.Execute(m_mangled.AsCString()))
344     return true;
345 
346   ConstString demangled = GetDemangledName(language);
347   return demangled && regex.Execute(demangled.AsCString());
348 }
349 
350 // Get the demangled name if there is one, else return the mangled name.
351 ConstString Mangled::GetName(lldb::LanguageType language,
352                              Mangled::NamePreference preference) const {
353   if (preference == ePreferMangled && m_mangled)
354     return m_mangled;
355 
356   ConstString demangled = GetDemangledName(language);
357 
358   if (preference == ePreferDemangledWithoutArguments) {
359     return get_demangled_name_without_arguments(m_mangled, demangled);
360   }
361   if (preference == ePreferDemangled) {
362     // Call the accessor to make sure we get a demangled name in case it hasn't
363     // been demangled yet...
364     if (demangled)
365       return demangled;
366     return m_mangled;
367   }
368   return demangled;
369 }
370 
371 // Dump a Mangled object to stream "s". We don't force our demangled name to be
372 // computed currently (we don't use the accessor).
373 void Mangled::Dump(Stream *s) const {
374   if (m_mangled) {
375     *s << ", mangled = " << m_mangled;
376   }
377   if (m_demangled) {
378     const char *demangled = m_demangled.AsCString();
379     s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
380   }
381 }
382 
383 // Dumps a debug version of this string with extra object and state information
384 // to stream "s".
385 void Mangled::DumpDebug(Stream *s) const {
386   s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2),
387             static_cast<const void *>(this));
388   m_mangled.DumpDebug(s);
389   s->Printf(", demangled = ");
390   m_demangled.DumpDebug(s);
391 }
392 
393 // Return the size in byte that this object takes in memory. The size includes
394 // the size of the objects it owns, and not the strings that it references
395 // because they are shared strings.
396 size_t Mangled::MemorySize() const {
397   return m_mangled.MemorySize() + m_demangled.MemorySize();
398 }
399 
400 // We "guess" the language because we can't determine a symbol's language from
401 // it's name.  For example, a Pascal symbol can be mangled using the C++
402 // Itanium scheme, and defined in a compilation unit within the same module as
403 // other C++ units.  In addition, different targets could have different ways
404 // of mangling names from a given language, likewise the compilation units
405 // within those targets.
406 lldb::LanguageType Mangled::GuessLanguage() const {
407   ConstString mangled = GetMangledName();
408   if (mangled) {
409     const char *mangled_name = mangled.GetCString();
410     if (CPlusPlusLanguage::IsCPPMangledName(mangled_name))
411       return lldb::eLanguageTypeC_plus_plus;
412     else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name))
413       return lldb::eLanguageTypeObjC;
414   } else {
415     // ObjC names aren't really mangled, so they won't necessarily be in the
416     // mangled name slot.
417     ConstString demangled_name = GetDemangledName(lldb::eLanguageTypeUnknown);
418     if (demangled_name
419         && ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString()))
420       return lldb::eLanguageTypeObjC;
421 
422   }
423   return lldb::eLanguageTypeUnknown;
424 }
425 
426 // Dump OBJ to the supplied stream S.
427 Stream &operator<<(Stream &s, const Mangled &obj) {
428   if (obj.GetMangledName())
429     s << "mangled = '" << obj.GetMangledName() << "'";
430 
431   ConstString demangled =
432       obj.GetDemangledName(lldb::eLanguageTypeUnknown);
433   if (demangled)
434     s << ", demangled = '" << demangled << '\'';
435   else
436     s << ", demangled = <error>";
437   return s;
438 }
439