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