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