//===-- Mangled.cpp ---------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // FreeBSD9-STABLE requires this to know about size_t in cxxabi.h #include #include #include "llvm/ADT/DenseMap.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Mangled.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Timer.h" #include #include #include using namespace lldb_private; static inline bool cstring_is_mangled (const char *s) { if (s) return s[0] == '_' && s[1] == 'Z'; return false; } #pragma mark Mangled //---------------------------------------------------------------------- // Default constructor //---------------------------------------------------------------------- Mangled::Mangled () : m_mangled(), m_demangled() { } //---------------------------------------------------------------------- // Constructor with an optional string and a boolean indicating if it is // the mangled version. //---------------------------------------------------------------------- Mangled::Mangled (const ConstString &s, bool mangled) : m_mangled(), m_demangled() { if (s) SetValue(s, mangled); } Mangled::Mangled (const ConstString &s) : m_mangled(), m_demangled() { if (s) SetValue(s); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- Mangled::~Mangled () { } //---------------------------------------------------------------------- // Convert to pointer operator. This allows code to check any Mangled // objects to see if they contain anything valid using code such as: // // Mangled mangled(...); // if (mangled) // { ... //---------------------------------------------------------------------- Mangled::operator void* () const { return (m_mangled) ? const_cast(this) : NULL; } //---------------------------------------------------------------------- // Logical NOT operator. This allows code to check any Mangled // objects to see if they are invalid using code such as: // // Mangled mangled(...); // if (!file_spec) // { ... //---------------------------------------------------------------------- bool Mangled::operator! () const { return !m_mangled; } //---------------------------------------------------------------------- // Clear the mangled and demangled values. //---------------------------------------------------------------------- void Mangled::Clear () { m_mangled.Clear(); m_demangled.Clear(); } //---------------------------------------------------------------------- // Compare the the string values. //---------------------------------------------------------------------- int Mangled::Compare (const Mangled& a, const Mangled& b) { return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled)); } //---------------------------------------------------------------------- // Set the string value in this objects. If "mangled" is true, then // the mangled named is set with the new value in "s", else the // demangled name is set. //---------------------------------------------------------------------- void Mangled::SetValue (const ConstString &s, bool mangled) { if (s) { if (mangled) { m_demangled.Clear(); m_mangled = s; } else { m_demangled = s; m_mangled.Clear(); } } else { m_demangled.Clear(); m_mangled.Clear(); } } void Mangled::SetValue (const ConstString &name) { if (name) { if (cstring_is_mangled(name.GetCString())) { m_demangled.Clear(); m_mangled = name; } else { m_demangled = name; m_mangled.Clear(); } } else { m_demangled.Clear(); m_mangled.Clear(); } } //---------------------------------------------------------------------- // Generate the demangled name on demand using this accessor. Code in // this class will need to use this accessor if it wishes to decode // the demangled name. The result is cached and will be kept until a // new string value is supplied to this object, or until the end of the // object's lifetime. //---------------------------------------------------------------------- const ConstString& Mangled::GetDemangledName () const { // Check to make sure we have a valid mangled name and that we // haven't already decoded our mangled name. if (m_mangled && !m_demangled) { // We need to generate and cache the demangled name. Timer scoped_timer (__PRETTY_FUNCTION__, "Mangled::GetDemangledName (m_mangled = %s)", m_mangled.GetCString()); // Don't bother running anything that isn't mangled const char *mangled_cstr = m_mangled.GetCString(); if (cstring_is_mangled(mangled_cstr)) { if (!m_mangled.GetMangledCounterpart(m_demangled)) { // We didn't already mangle this name, demangle it and if all goes well // add it to our map. char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL); if (demangled_name) { m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); free (demangled_name); } } } if (!m_demangled) { // Set the demangled string to the empty string to indicate we // tried to parse it once and failed. m_demangled.SetCString(""); } } return m_demangled; } bool Mangled::NameMatches (const RegularExpression& regex) const { if (m_mangled && regex.Execute (m_mangled.AsCString())) return true; if (GetDemangledName() && regex.Execute (m_demangled.AsCString())) return true; return false; } //---------------------------------------------------------------------- // Get the demangled name if there is one, else return the mangled name. //---------------------------------------------------------------------- const ConstString& Mangled::GetName (Mangled::NamePreference preference) const { if (preference == ePreferDemangled) { // Call the accessor to make sure we get a demangled name in case // it hasn't been demangled yet... if (GetDemangledName()) return m_demangled; return m_mangled; } else { if (m_mangled) return m_mangled; return GetDemangledName(); } } //---------------------------------------------------------------------- // Dump a Mangled object to stream "s". We don't force our // demangled name to be computed currently (we don't use the accessor). //---------------------------------------------------------------------- void Mangled::Dump (Stream *s) const { if (m_mangled) { *s << ", mangled = " << m_mangled; } if (m_demangled) { const char * demangled = m_demangled.AsCString(); s->Printf(", demangled = %s", demangled[0] ? demangled : ""); } } //---------------------------------------------------------------------- // Dumps a debug version of this string with extra object and state // information to stream "s". //---------------------------------------------------------------------- void Mangled::DumpDebug (Stream *s) const { s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this); m_mangled.DumpDebug(s); s->Printf(", demangled = "); m_demangled.DumpDebug(s); } //---------------------------------------------------------------------- // Return the size in byte that this object takes in memory. The size // includes the size of the objects it owns, and not the strings that // it references because they are shared strings. //---------------------------------------------------------------------- size_t Mangled::MemorySize () const { return m_mangled.MemorySize() + m_demangled.MemorySize(); } //---------------------------------------------------------------------- // Dump OBJ to the supplied stream S. //---------------------------------------------------------------------- Stream& operator << (Stream& s, const Mangled& obj) { if (obj.GetMangledName()) s << "mangled = '" << obj.GetMangledName() << "'"; const ConstString& demangled = obj.GetDemangledName(); if (demangled) s << ", demangled = '" << demangled << '\''; else s << ", demangled = "; return s; }