blob: 48d118236a3af914416da70a4535c3e75cf622ea [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Greg Claytone9982672012-08-06 15:55:38 +000010
Filipe Cabecinhasdd393952012-09-11 18:11:12 +000011// FreeBSD9-STABLE requires this to know about size_t in cxxabi.h
12#include <cstddef>
Zachary Turnera45fa2c2015-01-14 18:34:43 +000013#if defined(_MSC_VER)
14#include "lldb/Host/windows/windows.h"
15#include <Dbghelp.h>
Colin Riley61979cc2013-11-20 15:19:08 +000016#elif defined (__FreeBSD__)
Greg Clayton19c8e782013-10-30 18:42:59 +000017#define LLDB_USE_BUILTIN_DEMANGLER
18#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include <cxxabi.h>
Virgile Bellod0c5c772013-09-18 08:09:31 +000020#endif
Greg Claytone9982672012-08-06 15:55:38 +000021
Greg Clayton19c8e782013-10-30 18:42:59 +000022#ifdef LLDB_USE_BUILTIN_DEMANGLER
23
Kate Stonee2b21862014-07-22 17:03:38 +000024// Provide a fast-path demangler implemented in FastDemangle.cpp until it can
25// replace the existing C++ demangler with a complete implementation
Chaoren Linb41354c2015-05-28 19:15:15 +000026#include "lldb/Core/FastDemangle.h"
27#include "lldb/Core/CxaDemangle.h"
Greg Clayton19c8e782013-10-30 18:42:59 +000028
Greg Clayton19c8e782013-10-30 18:42:59 +000029#endif
30
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031
Greg Claytone41e5892010-09-03 23:26:12 +000032#include "llvm/ADT/DenseMap.h"
33
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034#include "lldb/Core/ConstString.h"
35#include "lldb/Core/Mangled.h"
Greg Clayton83c5cd92010-11-14 22:13:40 +000036#include "lldb/Core/RegularExpression.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037#include "lldb/Core/Stream.h"
38#include "lldb/Core/Timer.h"
Jason Molendaaff1b352014-10-10 23:07:36 +000039#include "lldb/Target/CPPLanguageRuntime.h"
Eli Friedman88966972010-06-09 08:50:27 +000040#include <ctype.h>
41#include <string.h>
Daniel Maleac91e4ab2013-05-31 20:21:38 +000042#include <stdlib.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043
Jason Molendaaff1b352014-10-10 23:07:36 +000044
Chris Lattner30fdc8d2010-06-08 16:52:24 +000045using namespace lldb_private;
46
Greg Clayton5e0c5e82012-07-18 20:47:40 +000047static inline bool
48cstring_is_mangled (const char *s)
49{
50 if (s)
Zachary Turnera45fa2c2015-01-14 18:34:43 +000051#if defined(_MSC_VER)
52 return (s[0] == '?');
53#else
54 return (s[0] == '_' && s[1] == 'Z');
55#endif
Greg Clayton5e0c5e82012-07-18 20:47:40 +000056 return false;
57}
58
Jason Molendaaff1b352014-10-10 23:07:36 +000059static const ConstString &
60get_demangled_name_without_arguments (const Mangled *obj)
61{
62 // This pair is <mangled name, demangled name without function arguments>
63 static std::pair<ConstString, ConstString> g_most_recent_mangled_to_name_sans_args;
64
65 // Need to have the mangled & demangled names we're currently examining as statics
66 // so we can return a const ref to them at the end of the func if we don't have
67 // anything better.
68 static ConstString g_last_mangled;
69 static ConstString g_last_demangled;
70
71 ConstString mangled = obj->GetMangledName ();
72 ConstString demangled = obj->GetDemangledName ();
73
74 if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled)
75 {
76 return g_most_recent_mangled_to_name_sans_args.second;
77 }
78
79 g_last_demangled = demangled;
80 g_last_mangled = mangled;
81
82 const char *mangled_name_cstr = mangled.GetCString();
Jason Molendaaff1b352014-10-10 23:07:36 +000083
84 if (demangled && mangled_name_cstr && mangled_name_cstr[0])
85 {
86 if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&
87 (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo mangled_name
88 mangled_name_cstr[2] != 'G' && // avoid guard variables
89 mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
90 {
91 CPPLanguageRuntime::MethodName cxx_method (demangled);
92 if (!cxx_method.GetBasename().empty() && !cxx_method.GetContext().empty())
93 {
94 std::string shortname = cxx_method.GetContext().str();
95 shortname += "::";
96 shortname += cxx_method.GetBasename().str();
97 ConstString result(shortname.c_str());
98 g_most_recent_mangled_to_name_sans_args.first = mangled;
99 g_most_recent_mangled_to_name_sans_args.second = result;
100 return g_most_recent_mangled_to_name_sans_args.second;
101 }
102 }
103 }
104
105 if (demangled)
106 return g_last_demangled;
107 return g_last_mangled;
108}
109
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110#pragma mark Mangled
111//----------------------------------------------------------------------
112// Default constructor
113//----------------------------------------------------------------------
114Mangled::Mangled () :
115 m_mangled(),
116 m_demangled()
117{
118}
119
120//----------------------------------------------------------------------
121// Constructor with an optional string and a boolean indicating if it is
122// the mangled version.
123//----------------------------------------------------------------------
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000124Mangled::Mangled (const ConstString &s, bool mangled) :
125 m_mangled(),
126 m_demangled()
127{
128 if (s)
129 SetValue(s, mangled);
130}
131
Greg Clayton037520e2012-07-18 23:18:10 +0000132Mangled::Mangled (const ConstString &s) :
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000133 m_mangled(),
134 m_demangled()
135{
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000136 if (s)
137 SetValue(s);
138}
139
140//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141// Destructor
142//----------------------------------------------------------------------
143Mangled::~Mangled ()
144{
145}
146
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:
150//
151// Mangled mangled(...);
152// if (mangled)
153// { ...
154//----------------------------------------------------------------------
155Mangled::operator void* () const
156{
157 return (m_mangled) ? const_cast<Mangled*>(this) : NULL;
158}
159
160//----------------------------------------------------------------------
161// Logical NOT operator. This allows code to check any Mangled
162// objects to see if they are invalid using code such as:
163//
164// Mangled mangled(...);
165// if (!file_spec)
166// { ...
167//----------------------------------------------------------------------
168bool
169Mangled::operator! () const
170{
171 return !m_mangled;
172}
173
174//----------------------------------------------------------------------
175// Clear the mangled and demangled values.
176//----------------------------------------------------------------------
177void
178Mangled::Clear ()
179{
180 m_mangled.Clear();
181 m_demangled.Clear();
182}
183
184
185//----------------------------------------------------------------------
186// Compare the the string values.
187//----------------------------------------------------------------------
188int
189Mangled::Compare (const Mangled& a, const Mangled& b)
190{
Jim Ingham89bf5e92010-09-15 00:13:44 +0000191 return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000192}
193
194
195
196//----------------------------------------------------------------------
197// Set the string value in this objects. If "mangled" is true, then
198// the mangled named is set with the new value in "s", else the
199// demangled name is set.
200//----------------------------------------------------------------------
201void
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000202Mangled::SetValue (const ConstString &s, bool mangled)
203{
204 if (s)
205 {
206 if (mangled)
207 {
208 m_demangled.Clear();
209 m_mangled = s;
210 }
211 else
212 {
213 m_demangled = s;
214 m_mangled.Clear();
215 }
216 }
217 else
218 {
219 m_demangled.Clear();
220 m_mangled.Clear();
221 }
222}
223
224void
225Mangled::SetValue (const ConstString &name)
226{
227 if (name)
228 {
229 if (cstring_is_mangled(name.GetCString()))
230 {
231 m_demangled.Clear();
232 m_mangled = name;
233 }
234 else
235 {
236 m_demangled = name;
237 m_mangled.Clear();
238 }
239 }
240 else
241 {
242 m_demangled.Clear();
243 m_mangled.Clear();
244 }
245}
246
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000247//----------------------------------------------------------------------
248// Generate the demangled name on demand using this accessor. Code in
249// this class will need to use this accessor if it wishes to decode
250// the demangled name. The result is cached and will be kept until a
251// new string value is supplied to this object, or until the end of the
252// object's lifetime.
253//----------------------------------------------------------------------
254const ConstString&
255Mangled::GetDemangledName () const
256{
257 // Check to make sure we have a valid mangled name and that we
258 // haven't already decoded our mangled name.
259 if (m_mangled && !m_demangled)
260 {
261 // We need to generate and cache the demangled name.
262 Timer scoped_timer (__PRETTY_FUNCTION__,
263 "Mangled::GetDemangledName (m_mangled = %s)",
264 m_mangled.GetCString());
265
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000266 // Don't bother running anything that isn't mangled
267 const char *mangled_cstr = m_mangled.GetCString();
268 if (cstring_is_mangled(mangled_cstr))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000270 if (!m_mangled.GetMangledCounterpart(m_demangled))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271 {
Greg Claytone41e5892010-09-03 23:26:12 +0000272 // We didn't already mangle this name, demangle it and if all goes well
273 // add it to our map.
Greg Clayton19c8e782013-10-30 18:42:59 +0000274#ifdef LLDB_USE_BUILTIN_DEMANGLER
Kate Stonee2b21862014-07-22 17:03:38 +0000275 // Try to use the fast-path demangler first for the
276 // performance win, falling back to the full demangler only
277 // when necessary
278 char *demangled_name = FastDemangle (mangled_cstr,
David Majnemerfba933f2014-07-22 20:36:37 +0000279 m_mangled.GetLength());
Kate Stonee2b21862014-07-22 17:03:38 +0000280 if (!demangled_name)
281 demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL);
Colin Riley61979cc2013-11-20 15:19:08 +0000282#elif defined(_MSC_VER)
Zachary Turnera45fa2c2015-01-14 18:34:43 +0000283 char *demangled_name = (char *)::malloc(1024);
284 ::ZeroMemory(demangled_name, 1024);
285 DWORD result = ::UnDecorateSymbolName(mangled_cstr, demangled_name, 1023,
286 UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected keywords
287 UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords
288 UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications
289 UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers
290 UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords
291 );
Jim Inghamd9191632015-01-15 03:34:31 +0000292 if (result == 0)
293 {
294 free (demangled_name);
295 demangled_name = nullptr;
296 }
Virgile Bellod0c5c772013-09-18 08:09:31 +0000297#else
Greg Clayton19c8e782013-10-30 18:42:59 +0000298 char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);
Jim Inghamd9191632015-01-15 03:34:31 +0000299#endif
Greg Claytone41e5892010-09-03 23:26:12 +0000300
301 if (demangled_name)
302 {
Zachary Turnera45fa2c2015-01-14 18:34:43 +0000303 m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
Greg Claytone41e5892010-09-03 23:26:12 +0000304 free (demangled_name);
305 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000306 }
307 }
Jason Molenda3f8688b2010-12-15 04:27:04 +0000308 if (!m_demangled)
309 {
310 // Set the demangled string to the empty string to indicate we
311 // tried to parse it once and failed.
312 m_demangled.SetCString("");
313 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000314 }
315
316 return m_demangled;
317}
318
Greg Clayton83c5cd92010-11-14 22:13:40 +0000319
320bool
321Mangled::NameMatches (const RegularExpression& regex) const
322{
323 if (m_mangled && regex.Execute (m_mangled.AsCString()))
324 return true;
325
326 if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))
327 return true;
328 return false;
329}
330
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000331//----------------------------------------------------------------------
332// Get the demangled name if there is one, else return the mangled name.
333//----------------------------------------------------------------------
334const ConstString&
Jim Ingham08b87e02010-09-14 22:03:00 +0000335Mangled::GetName (Mangled::NamePreference preference) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000336{
Jason Molendaaff1b352014-10-10 23:07:36 +0000337 if (preference == ePreferDemangledWithoutArguments)
338 {
339 // Call the accessor to make sure we get a demangled name in case
340 // it hasn't been demangled yet...
341 GetDemangledName();
342
343 return get_demangled_name_without_arguments (this);
344 }
Greg Clayton87425432010-09-14 23:44:49 +0000345 if (preference == ePreferDemangled)
Jim Ingham08b87e02010-09-14 22:03:00 +0000346 {
Greg Claytond0b89f82010-09-14 23:48:44 +0000347 // Call the accessor to make sure we get a demangled name in case
348 // it hasn't been demangled yet...
349 if (GetDemangledName())
350 return m_demangled;
Greg Clayton87425432010-09-14 23:44:49 +0000351 return m_mangled;
352 }
353 else
354 {
Greg Claytond0b89f82010-09-14 23:48:44 +0000355 if (m_mangled)
356 return m_mangled;
357 return GetDemangledName();
Jim Ingham08b87e02010-09-14 22:03:00 +0000358 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000359}
360
361//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000362// Dump a Mangled object to stream "s". We don't force our
363// demangled name to be computed currently (we don't use the accessor).
364//----------------------------------------------------------------------
365void
366Mangled::Dump (Stream *s) const
367{
368 if (m_mangled)
369 {
370 *s << ", mangled = " << m_mangled;
371 }
372 if (m_demangled)
373 {
374 const char * demangled = m_demangled.AsCString();
375 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
376 }
377}
378
379//----------------------------------------------------------------------
380// Dumps a debug version of this string with extra object and state
381// information to stream "s".
382//----------------------------------------------------------------------
383void
384Mangled::DumpDebug (Stream *s) const
385{
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000386 s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void*) * 2),
387 static_cast<const void*>(this));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388 m_mangled.DumpDebug(s);
389 s->Printf(", demangled = ");
390 m_demangled.DumpDebug(s);
391}
392
393//----------------------------------------------------------------------
394// Return the size in byte that this object takes in memory. The size
395// includes the size of the objects it owns, and not the strings that
396// it references because they are shared strings.
397//----------------------------------------------------------------------
398size_t
399Mangled::MemorySize () const
400{
401 return m_mangled.MemorySize() + m_demangled.MemorySize();
402}
403
Greg Clayton94976f72015-01-23 23:18:53 +0000404lldb::LanguageType
405Mangled::GetLanguage ()
406{
407 ConstString mangled = GetMangledName();
408 if (mangled)
409 {
410 if (GetDemangledName())
411 {
412 if (cstring_is_mangled(mangled.GetCString()))
413 return lldb::eLanguageTypeC_plus_plus;
414 }
415 }
416 return lldb::eLanguageTypeUnknown;
417}
418
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000419//----------------------------------------------------------------------
420// Dump OBJ to the supplied stream S.
421//----------------------------------------------------------------------
422Stream&
423operator << (Stream& s, const Mangled& obj)
424{
425 if (obj.GetMangledName())
426 s << "mangled = '" << obj.GetMangledName() << "'";
427
428 const ConstString& demangled = obj.GetDemangledName();
429 if (demangled)
430 s << ", demangled = '" << demangled << '\'';
431 else
432 s << ", demangled = <error>";
433 return s;
434}