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 #if defined(__APPLE__)
12 #define USE_BUILTIN_LIBCXXABI_DEMANGLER 1
13 #endif
14 
15 #if defined(USE_BUILTIN_LIBCXXABI_DEMANGLER)
16 #include "lldb/Core/cxa_demangle.h"
17 #else
18 #include <cxxabi.h>
19 #endif
20 
21 
22 #include "llvm/ADT/DenseMap.h"
23 
24 #include "lldb/Core/ConstString.h"
25 #include "lldb/Core/Mangled.h"
26 #include "lldb/Core/RegularExpression.h"
27 #include "lldb/Core/Stream.h"
28 #include "lldb/Core/Timer.h"
29 #include <ctype.h>
30 #include <string.h>
31 
32 using namespace lldb_private;
33 
34 static inline bool
35 cstring_is_mangled (const char *s)
36 {
37     if (s)
38         return s[0] == '_' && s[1] == 'Z';
39     return false;
40 }
41 
42 #pragma mark Mangled
43 //----------------------------------------------------------------------
44 // Default constructor
45 //----------------------------------------------------------------------
46 Mangled::Mangled () :
47     m_mangled(),
48     m_demangled()
49 {
50 }
51 
52 //----------------------------------------------------------------------
53 // Constructor with an optional string and a boolean indicating if it is
54 // the mangled version.
55 //----------------------------------------------------------------------
56 Mangled::Mangled (const ConstString &s, bool mangled) :
57     m_mangled(),
58     m_demangled()
59 {
60     if (s)
61         SetValue(s, mangled);
62 }
63 
64 Mangled::Mangled (const ConstString &s) :
65     m_mangled(),
66     m_demangled()
67 {
68     if (s)
69         SetValue(s);
70 }
71 
72 //----------------------------------------------------------------------
73 // Destructor
74 //----------------------------------------------------------------------
75 Mangled::~Mangled ()
76 {
77 }
78 
79 //----------------------------------------------------------------------
80 // Convert to pointer operator. This allows code to check any Mangled
81 // objects to see if they contain anything valid using code such as:
82 //
83 //  Mangled mangled(...);
84 //  if (mangled)
85 //  { ...
86 //----------------------------------------------------------------------
87 Mangled::operator void* () const
88 {
89     return (m_mangled) ? const_cast<Mangled*>(this) : NULL;
90 }
91 
92 //----------------------------------------------------------------------
93 // Logical NOT operator. This allows code to check any Mangled
94 // objects to see if they are invalid using code such as:
95 //
96 //  Mangled mangled(...);
97 //  if (!file_spec)
98 //  { ...
99 //----------------------------------------------------------------------
100 bool
101 Mangled::operator! () const
102 {
103     return !m_mangled;
104 }
105 
106 //----------------------------------------------------------------------
107 // Clear the mangled and demangled values.
108 //----------------------------------------------------------------------
109 void
110 Mangled::Clear ()
111 {
112     m_mangled.Clear();
113     m_demangled.Clear();
114 }
115 
116 
117 //----------------------------------------------------------------------
118 // Compare the the string values.
119 //----------------------------------------------------------------------
120 int
121 Mangled::Compare (const Mangled& a, const Mangled& b)
122 {
123     return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));
124 }
125 
126 
127 
128 //----------------------------------------------------------------------
129 // Set the string value in this objects. If "mangled" is true, then
130 // the mangled named is set with the new value in "s", else the
131 // demangled name is set.
132 //----------------------------------------------------------------------
133 void
134 Mangled::SetValue (const ConstString &s, bool mangled)
135 {
136     if (s)
137     {
138         if (mangled)
139         {
140             m_demangled.Clear();
141             m_mangled = s;
142         }
143         else
144         {
145             m_demangled = s;
146             m_mangled.Clear();
147         }
148     }
149     else
150     {
151         m_demangled.Clear();
152         m_mangled.Clear();
153     }
154 }
155 
156 void
157 Mangled::SetValue (const ConstString &name)
158 {
159     if (name)
160     {
161         if (cstring_is_mangled(name.GetCString()))
162         {
163             m_demangled.Clear();
164             m_mangled = name;
165         }
166         else
167         {
168             m_demangled = name;
169             m_mangled.Clear();
170         }
171     }
172     else
173     {
174         m_demangled.Clear();
175         m_mangled.Clear();
176     }
177 }
178 
179 
180 //----------------------------------------------------------------------
181 // Generate the demangled name on demand using this accessor. Code in
182 // this class will need to use this accessor if it wishes to decode
183 // the demangled name. The result is cached and will be kept until a
184 // new string value is supplied to this object, or until the end of the
185 // object's lifetime.
186 //----------------------------------------------------------------------
187 const ConstString&
188 Mangled::GetDemangledName () const
189 {
190     // Check to make sure we have a valid mangled name and that we
191     // haven't already decoded our mangled name.
192     if (m_mangled && !m_demangled)
193     {
194         // We need to generate and cache the demangled name.
195         Timer scoped_timer (__PRETTY_FUNCTION__,
196                             "Mangled::GetDemangledName (m_mangled = %s)",
197                             m_mangled.GetCString());
198 
199         // Don't bother running anything that isn't mangled
200         const char *mangled_cstr = m_mangled.GetCString();
201         if (cstring_is_mangled(mangled_cstr))
202         {
203             if (!m_mangled.GetMangledCounterpart(m_demangled))
204             {
205                 // We didn't already mangle this name, demangle it and if all goes well
206                 // add it to our map.
207 #if defined(USE_BUILTIN_LIBCXXABI_DEMANGLER)
208                 char *demangled_name = lldb_cxxabiv1::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);
209 #else
210                 char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);
211 #endif
212 
213                 if (demangled_name)
214                 {
215                     m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
216                     free (demangled_name);
217                 }
218             }
219         }
220         if (!m_demangled)
221         {
222             // Set the demangled string to the empty string to indicate we
223             // tried to parse it once and failed.
224             m_demangled.SetCString("");
225         }
226     }
227 
228     return m_demangled;
229 }
230 
231 
232 bool
233 Mangled::NameMatches (const RegularExpression& regex) const
234 {
235     if (m_mangled && regex.Execute (m_mangled.AsCString()))
236         return true;
237 
238     if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))
239         return true;
240     return false;
241 }
242 
243 //----------------------------------------------------------------------
244 // Get the demangled name if there is one, else return the mangled name.
245 //----------------------------------------------------------------------
246 const ConstString&
247 Mangled::GetName (Mangled::NamePreference preference) const
248 {
249     if (preference == ePreferDemangled)
250     {
251         // Call the accessor to make sure we get a demangled name in case
252         // it hasn't been demangled yet...
253         if (GetDemangledName())
254             return m_demangled;
255         return m_mangled;
256     }
257     else
258     {
259         if (m_mangled)
260             return m_mangled;
261         return GetDemangledName();
262     }
263 }
264 
265 //----------------------------------------------------------------------
266 // Dump a Mangled object to stream "s". We don't force our
267 // demangled name to be computed currently (we don't use the accessor).
268 //----------------------------------------------------------------------
269 void
270 Mangled::Dump (Stream *s) const
271 {
272     if (m_mangled)
273     {
274         *s << ", mangled = " << m_mangled;
275     }
276     if (m_demangled)
277     {
278         const char * demangled = m_demangled.AsCString();
279         s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
280     }
281 }
282 
283 //----------------------------------------------------------------------
284 // Dumps a debug version of this string with extra object and state
285 // information to stream "s".
286 //----------------------------------------------------------------------
287 void
288 Mangled::DumpDebug (Stream *s) const
289 {
290     s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this);
291     m_mangled.DumpDebug(s);
292     s->Printf(", demangled = ");
293     m_demangled.DumpDebug(s);
294 }
295 
296 //----------------------------------------------------------------------
297 // Return the size in byte that this object takes in memory. The size
298 // includes the size of the objects it owns, and not the strings that
299 // it references because they are shared strings.
300 //----------------------------------------------------------------------
301 size_t
302 Mangled::MemorySize () const
303 {
304     return m_mangled.MemorySize() + m_demangled.MemorySize();
305 }
306 
307 //----------------------------------------------------------------------
308 // Dump OBJ to the supplied stream S.
309 //----------------------------------------------------------------------
310 Stream&
311 operator << (Stream& s, const Mangled& obj)
312 {
313     if (obj.GetMangledName())
314         s << "mangled = '" << obj.GetMangledName() << "'";
315 
316     const ConstString& demangled = obj.GetDemangledName();
317     if (demangled)
318         s << ", demangled = '" << demangled << '\'';
319     else
320         s << ", demangled = <error>";
321     return s;
322 }
323