1 //===-- Mangled.cpp ---------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // FreeBSD9-STABLE requires this to know about size_t in cxxabi.h
13 #include "lldb/Host/windows/windows.h"
15 #pragma comment(lib, "dbghelp.lib")
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"
27 #include "llvm/ADT/DenseMap.h"
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"
42 using namespace lldb_private;
44 static inline Mangled::ManglingScheme cstring_mangling_scheme(const char *s) {
47 return Mangled::eManglingSchemeMSVC;
48 if (s[0] == '_' && s[1] == 'Z')
49 return Mangled::eManglingSchemeItanium;
51 return Mangled::eManglingSchemeNone;
54 static inline bool cstring_is_mangled(const char *s) {
55 return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone;
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;
65 // Need to have the mangled & demangled names we're currently examining as
67 // so we can return a const ref to them at the end of the func if we don't
70 static ConstString g_last_mangled;
71 static ConstString g_last_demangled;
73 if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) {
74 return g_most_recent_mangled_to_name_sans_args.second;
77 g_last_demangled = demangled;
78 g_last_mangled = mangled;
80 const char *mangled_name_cstr = mangled.GetCString();
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
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
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;
107 return g_last_demangled;
108 return g_last_mangled;
112 //----------------------------------------------------------------------
113 // Default constructor
114 //----------------------------------------------------------------------
115 Mangled::Mangled() : m_mangled(), m_demangled() {}
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() {
124 SetValue(s, mangled);
127 Mangled::Mangled(llvm::StringRef name, bool is_mangled) {
129 SetValue(ConstString(name), is_mangled);
132 Mangled::Mangled(const ConstString &s) : m_mangled(), m_demangled() {
137 Mangled::Mangled(llvm::StringRef name) {
139 SetValue(ConstString(name));
142 //----------------------------------------------------------------------
144 //----------------------------------------------------------------------
145 Mangled::~Mangled() {}
147 //----------------------------------------------------------------------
148 // Convert to pointer operator. This allows code to check any Mangled
149 // objects to see if they contain anything valid using code such as:
151 // Mangled mangled(...);
154 //----------------------------------------------------------------------
155 Mangled::operator void *() const {
156 return (m_mangled) ? const_cast<Mangled *>(this) : NULL;
159 //----------------------------------------------------------------------
160 // Logical NOT operator. This allows code to check any Mangled
161 // objects to see if they are invalid using code such as:
163 // Mangled mangled(...);
166 //----------------------------------------------------------------------
167 bool Mangled::operator!() const { return !m_mangled; }
169 //----------------------------------------------------------------------
170 // Clear the mangled and demangled values.
171 //----------------------------------------------------------------------
172 void Mangled::Clear() {
177 //----------------------------------------------------------------------
178 // Compare the string values.
179 //----------------------------------------------------------------------
180 int Mangled::Compare(const Mangled &a, const Mangled &b) {
181 return ConstString::Compare(
182 a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled),
183 a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
186 //----------------------------------------------------------------------
187 // Set the string value in this objects. If "mangled" is true, then
188 // the mangled named is set with the new value in "s", else the
189 // demangled name is set.
190 //----------------------------------------------------------------------
191 void Mangled::SetValue(const ConstString &s, bool mangled) {
206 void Mangled::SetValue(const ConstString &name) {
208 if (cstring_is_mangled(name.GetCString())) {
221 //----------------------------------------------------------------------
222 // Generate the demangled name on demand using this accessor. Code in
223 // this class will need to use this accessor if it wishes to decode
224 // the demangled name. The result is cached and will be kept until a
225 // new string value is supplied to this object, or until the end of the
226 // object's lifetime.
227 //----------------------------------------------------------------------
229 Mangled::GetDemangledName(lldb::LanguageType language) const {
230 // Check to make sure we have a valid mangled name and that we
231 // haven't already decoded our mangled name.
232 if (m_mangled && !m_demangled) {
233 // We need to generate and cache the demangled name.
234 Timer scoped_timer(LLVM_PRETTY_FUNCTION,
235 "Mangled::GetDemangledName (m_mangled = %s)",
236 m_mangled.GetCString());
238 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE);
240 // Don't bother running anything that isn't mangled
241 const char *mangled_name = m_mangled.GetCString();
242 ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
243 if (mangling_scheme != eManglingSchemeNone &&
244 !m_mangled.GetMangledCounterpart(m_demangled)) {
245 // We didn't already mangle this name, demangle it and if all goes well
246 // add it to our map.
247 char *demangled_name = nullptr;
248 switch (mangling_scheme) {
249 case eManglingSchemeMSVC: {
250 #if defined(_MSC_VER)
252 log->Printf("demangle msvc: %s", mangled_name);
253 const size_t demangled_length = 2048;
254 demangled_name = static_cast<char *>(::malloc(demangled_length));
255 ::ZeroMemory(demangled_name, demangled_length);
256 DWORD result = ::UnDecorateSymbolName(
257 mangled_name, demangled_name, demangled_length,
258 UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected
260 UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall,
262 UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications
263 UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc
265 UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords
268 if (demangled_name && demangled_name[0])
269 log->Printf("demangled msvc: %s -> \"%s\"", mangled_name,
272 log->Printf("demangled msvc: %s -> error: 0x%lu", mangled_name,
277 free(demangled_name);
278 demangled_name = nullptr;
283 case eManglingSchemeItanium: {
284 #ifdef LLDB_USE_BUILTIN_DEMANGLER
286 log->Printf("demangle itanium: %s", mangled_name);
287 // Try to use the fast-path demangler first for the
288 // performance win, falling back to the full demangler only
290 demangled_name = FastDemangle(mangled_name, m_mangled.GetLength());
293 llvm::itaniumDemangle(mangled_name, NULL, NULL, NULL);
295 demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL);
299 log->Printf("demangled itanium: %s -> \"%s\"", mangled_name,
302 log->Printf("demangled itanium: %s -> error: failed to demangle",
307 case eManglingSchemeNone:
310 if (demangled_name) {
311 m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
312 free(demangled_name);
316 // Set the demangled string to the empty string to indicate we
317 // tried to parse it once and failed.
318 m_demangled.SetCString("");
326 Mangled::GetDisplayDemangledName(lldb::LanguageType language) const {
327 return GetDemangledName(language);
330 bool Mangled::NameMatches(const RegularExpression ®ex,
331 lldb::LanguageType language) const {
332 if (m_mangled && regex.Execute(m_mangled.AsCString()))
335 ConstString demangled = GetDemangledName(language);
336 if (demangled && regex.Execute(demangled.AsCString()))
341 //----------------------------------------------------------------------
342 // Get the demangled name if there is one, else return the mangled name.
343 //----------------------------------------------------------------------
344 ConstString Mangled::GetName(lldb::LanguageType language,
345 Mangled::NamePreference preference) const {
346 if (preference == ePreferMangled && m_mangled)
349 ConstString demangled = GetDemangledName(language);
351 if (preference == ePreferDemangledWithoutArguments) {
352 return get_demangled_name_without_arguments(m_mangled, demangled);
354 if (preference == ePreferDemangled) {
355 // Call the accessor to make sure we get a demangled name in case
356 // it hasn't been demangled yet...
364 //----------------------------------------------------------------------
365 // Dump a Mangled object to stream "s". We don't force our
366 // demangled name to be computed currently (we don't use the accessor).
367 //----------------------------------------------------------------------
368 void Mangled::Dump(Stream *s) const {
370 *s << ", mangled = " << m_mangled;
373 const char *demangled = m_demangled.AsCString();
374 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
378 //----------------------------------------------------------------------
379 // Dumps a debug version of this string with extra object and state
380 // information to stream "s".
381 //----------------------------------------------------------------------
382 void Mangled::DumpDebug(Stream *s) const {
383 s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2),
384 static_cast<const void *>(this));
385 m_mangled.DumpDebug(s);
386 s->Printf(", demangled = ");
387 m_demangled.DumpDebug(s);
390 //----------------------------------------------------------------------
391 // Return the size in byte that this object takes in memory. The size
392 // includes the size of the objects it owns, and not the strings that
393 // it references because they are shared strings.
394 //----------------------------------------------------------------------
395 size_t Mangled::MemorySize() const {
396 return m_mangled.MemorySize() + m_demangled.MemorySize();
399 //----------------------------------------------------------------------
400 // We "guess" the language because we can't determine a symbol's language
401 // from it's name. For example, a Pascal symbol can be mangled using the
402 // C++ Itanium scheme, and defined in a compilation unit within the same
403 // module as other C++ units. In addition, different targets could have
404 // different ways of mangling names from a given language, likewise the
405 // compilation units within those targets.
406 //----------------------------------------------------------------------
407 lldb::LanguageType Mangled::GuessLanguage() const {
408 ConstString mangled = GetMangledName();
410 if (GetDemangledName(lldb::eLanguageTypeUnknown)) {
411 const char *mangled_name = mangled.GetCString();
412 if (CPlusPlusLanguage::IsCPPMangledName(mangled_name))
413 return lldb::eLanguageTypeC_plus_plus;
414 else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name))
415 return lldb::eLanguageTypeObjC;
418 return lldb::eLanguageTypeUnknown;
421 //----------------------------------------------------------------------
422 // Dump OBJ to the supplied stream S.
423 //----------------------------------------------------------------------
424 Stream &operator<<(Stream &s, const Mangled &obj) {
425 if (obj.GetMangledName())
426 s << "mangled = '" << obj.GetMangledName() << "'";
428 const ConstString &demangled =
429 obj.GetDemangledName(lldb::eLanguageTypeUnknown);
431 s << ", demangled = '" << demangled << '\'';
433 s << ", demangled = <error>";