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