Mangled.cpp revision 5577ce043b8d766d5a12ed12a1223385eadb6da1
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
27using namespace lldb_private;
28
29static inline bool
30cstring_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//----------------------------------------------------------------------
41Mangled::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//----------------------------------------------------------------------
51Mangled::Mangled (const ConstString &s, bool mangled) :
52    m_mangled(),
53    m_demangled()
54{
55    if (s)
56        SetValue(s, mangled);
57}
58
59Mangled::Mangled (const ConstString &s) :
60    m_mangled(),
61    m_demangled()
62{
63    if (s)
64        SetValue(s);
65}
66
67//----------------------------------------------------------------------
68// Destructor
69//----------------------------------------------------------------------
70Mangled::~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//----------------------------------------------------------------------
82Mangled::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//----------------------------------------------------------------------
95bool
96Mangled::operator! () const
97{
98    return !m_mangled;
99}
100
101//----------------------------------------------------------------------
102// Clear the mangled and demangled values.
103//----------------------------------------------------------------------
104void
105Mangled::Clear ()
106{
107    m_mangled.Clear();
108    m_demangled.Clear();
109}
110
111
112//----------------------------------------------------------------------
113// Compare the the string values.
114//----------------------------------------------------------------------
115int
116Mangled::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//----------------------------------------------------------------------
128void
129Mangled::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
151void
152Mangled::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//----------------------------------------------------------------------
182const ConstString&
183Mangled::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
223bool
224Mangled::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//----------------------------------------------------------------------
237const ConstString&
238Mangled::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//----------------------------------------------------------------------
260void
261Mangled::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//----------------------------------------------------------------------
278void
279Mangled::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//----------------------------------------------------------------------
292size_t
293Mangled::MemorySize () const
294{
295    return m_mangled.MemorySize() + m_demangled.MemorySize();
296}
297
298//----------------------------------------------------------------------
299// Dump OBJ to the supplied stream S.
300//----------------------------------------------------------------------
301Stream&
302operator << (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