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