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