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