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