Home | History | Annotate | Download | only in Core
      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
     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 //----------------------------------------------------------------------
     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 //----------------------------------------------------------------------
     51 Mangled::Mangled (const ConstString &s, bool mangled) :
     52     m_mangled(),
     53     m_demangled()
     54 {
     55     if (s)
     56         SetValue(s, mangled);
     57 }
     58 
     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 //----------------------------------------------------------------------
     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 //----------------------------------------------------------------------
     82 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
     96 Mangled::operator! () const
     97 {
     98     return !m_mangled;
     99 }
    100 
    101 //----------------------------------------------------------------------
    102 // Clear the mangled and demangled values.
    103 //----------------------------------------------------------------------
    104 void
    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
    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
    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
    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&
    183 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
    224 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&
    238 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
    261 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
    279 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
    293 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&
    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