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