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