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