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