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