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 34 using namespace lldb_private; 35 36 static inline bool 37 cstring_is_mangled (const char *s) 38 { 39 if (s) 40 return s[0] == '_' && s[1] == 'Z'; 41 return false; 42 } 43 44 #pragma mark Mangled 45 //---------------------------------------------------------------------- 46 // Default constructor 47 //---------------------------------------------------------------------- 48 Mangled::Mangled () : 49 m_mangled(), 50 m_demangled() 51 { 52 } 53 54 //---------------------------------------------------------------------- 55 // Constructor with an optional string and a boolean indicating if it is 56 // the mangled version. 57 //---------------------------------------------------------------------- 58 Mangled::Mangled (const ConstString &s, bool mangled) : 59 m_mangled(), 60 m_demangled() 61 { 62 if (s) 63 SetValue(s, mangled); 64 } 65 66 Mangled::Mangled (const ConstString &s) : 67 m_mangled(), 68 m_demangled() 69 { 70 if (s) 71 SetValue(s); 72 } 73 74 //---------------------------------------------------------------------- 75 // Destructor 76 //---------------------------------------------------------------------- 77 Mangled::~Mangled () 78 { 79 } 80 81 //---------------------------------------------------------------------- 82 // Convert to pointer operator. This allows code to check any Mangled 83 // objects to see if they contain anything valid using code such as: 84 // 85 // Mangled mangled(...); 86 // if (mangled) 87 // { ... 88 //---------------------------------------------------------------------- 89 Mangled::operator void* () const 90 { 91 return (m_mangled) ? const_cast<Mangled*>(this) : NULL; 92 } 93 94 //---------------------------------------------------------------------- 95 // Logical NOT operator. This allows code to check any Mangled 96 // objects to see if they are invalid using code such as: 97 // 98 // Mangled mangled(...); 99 // if (!file_spec) 100 // { ... 101 //---------------------------------------------------------------------- 102 bool 103 Mangled::operator! () const 104 { 105 return !m_mangled; 106 } 107 108 //---------------------------------------------------------------------- 109 // Clear the mangled and demangled values. 110 //---------------------------------------------------------------------- 111 void 112 Mangled::Clear () 113 { 114 m_mangled.Clear(); 115 m_demangled.Clear(); 116 } 117 118 119 //---------------------------------------------------------------------- 120 // Compare the the string values. 121 //---------------------------------------------------------------------- 122 int 123 Mangled::Compare (const Mangled& a, const Mangled& b) 124 { 125 return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled)); 126 } 127 128 129 130 //---------------------------------------------------------------------- 131 // Set the string value in this objects. If "mangled" is true, then 132 // the mangled named is set with the new value in "s", else the 133 // demangled name is set. 134 //---------------------------------------------------------------------- 135 void 136 Mangled::SetValue (const ConstString &s, bool mangled) 137 { 138 if (s) 139 { 140 if (mangled) 141 { 142 m_demangled.Clear(); 143 m_mangled = s; 144 } 145 else 146 { 147 m_demangled = s; 148 m_mangled.Clear(); 149 } 150 } 151 else 152 { 153 m_demangled.Clear(); 154 m_mangled.Clear(); 155 } 156 } 157 158 void 159 Mangled::SetValue (const ConstString &name) 160 { 161 if (name) 162 { 163 if (cstring_is_mangled(name.GetCString())) 164 { 165 m_demangled.Clear(); 166 m_mangled = name; 167 } 168 else 169 { 170 m_demangled = name; 171 m_mangled.Clear(); 172 } 173 } 174 else 175 { 176 m_demangled.Clear(); 177 m_mangled.Clear(); 178 } 179 } 180 181 182 //---------------------------------------------------------------------- 183 // Generate the demangled name on demand using this accessor. Code in 184 // this class will need to use this accessor if it wishes to decode 185 // the demangled name. The result is cached and will be kept until a 186 // new string value is supplied to this object, or until the end of the 187 // object's lifetime. 188 //---------------------------------------------------------------------- 189 const ConstString& 190 Mangled::GetDemangledName () const 191 { 192 // Check to make sure we have a valid mangled name and that we 193 // haven't already decoded our mangled name. 194 if (m_mangled && !m_demangled) 195 { 196 // We need to generate and cache the demangled name. 197 Timer scoped_timer (__PRETTY_FUNCTION__, 198 "Mangled::GetDemangledName (m_mangled = %s)", 199 m_mangled.GetCString()); 200 201 // Don't bother running anything that isn't mangled 202 const char *mangled_cstr = m_mangled.GetCString(); 203 if (cstring_is_mangled(mangled_cstr)) 204 { 205 if (!m_mangled.GetMangledCounterpart(m_demangled)) 206 { 207 // We didn't already mangle this name, demangle it and if all goes well 208 // add it to our map. 209 #if defined(USE_BUILTIN_LIBCXXABI_DEMANGLER) 210 char *demangled_name = lldb_cxxabiv1::__cxa_demangle (mangled_cstr, NULL, NULL, NULL); 211 #else 212 char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL); 213 #endif 214 215 if (demangled_name) 216 { 217 m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); 218 free (demangled_name); 219 } 220 } 221 } 222 if (!m_demangled) 223 { 224 // Set the demangled string to the empty string to indicate we 225 // tried to parse it once and failed. 226 m_demangled.SetCString(""); 227 } 228 } 229 230 return m_demangled; 231 } 232 233 234 bool 235 Mangled::NameMatches (const RegularExpression& regex) const 236 { 237 if (m_mangled && regex.Execute (m_mangled.AsCString())) 238 return true; 239 240 if (GetDemangledName() && regex.Execute (m_demangled.AsCString())) 241 return true; 242 return false; 243 } 244 245 //---------------------------------------------------------------------- 246 // Get the demangled name if there is one, else return the mangled name. 247 //---------------------------------------------------------------------- 248 const ConstString& 249 Mangled::GetName (Mangled::NamePreference preference) const 250 { 251 if (preference == ePreferDemangled) 252 { 253 // Call the accessor to make sure we get a demangled name in case 254 // it hasn't been demangled yet... 255 if (GetDemangledName()) 256 return m_demangled; 257 return m_mangled; 258 } 259 else 260 { 261 if (m_mangled) 262 return m_mangled; 263 return GetDemangledName(); 264 } 265 } 266 267 //---------------------------------------------------------------------- 268 // Dump a Mangled object to stream "s". We don't force our 269 // demangled name to be computed currently (we don't use the accessor). 270 //---------------------------------------------------------------------- 271 void 272 Mangled::Dump (Stream *s) const 273 { 274 if (m_mangled) 275 { 276 *s << ", mangled = " << m_mangled; 277 } 278 if (m_demangled) 279 { 280 const char * demangled = m_demangled.AsCString(); 281 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>"); 282 } 283 } 284 285 //---------------------------------------------------------------------- 286 // Dumps a debug version of this string with extra object and state 287 // information to stream "s". 288 //---------------------------------------------------------------------- 289 void 290 Mangled::DumpDebug (Stream *s) const 291 { 292 s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this); 293 m_mangled.DumpDebug(s); 294 s->Printf(", demangled = "); 295 m_demangled.DumpDebug(s); 296 } 297 298 //---------------------------------------------------------------------- 299 // Return the size in byte that this object takes in memory. The size 300 // includes the size of the objects it owns, and not the strings that 301 // it references because they are shared strings. 302 //---------------------------------------------------------------------- 303 size_t 304 Mangled::MemorySize () const 305 { 306 return m_mangled.MemorySize() + m_demangled.MemorySize(); 307 } 308 309 //---------------------------------------------------------------------- 310 // Dump OBJ to the supplied stream S. 311 //---------------------------------------------------------------------- 312 Stream& 313 operator << (Stream& s, const Mangled& obj) 314 { 315 if (obj.GetMangledName()) 316 s << "mangled = '" << obj.GetMangledName() << "'"; 317 318 const ConstString& demangled = obj.GetDemangledName(); 319 if (demangled) 320 s << ", demangled = '" << demangled << '\''; 321 else 322 s << ", demangled = <error>"; 323 return s; 324 } 325