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