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 #include "lldb/Core/Mangled.h" 11 12 #if defined(_WIN32) 13 #include "lldb/Host/windows/windows.h" 14 15 #include <dbghelp.h> 16 #pragma comment(lib, "dbghelp.lib") 17 #endif 18 19 #ifdef LLDB_USE_BUILTIN_DEMANGLER 20 // Provide a fast-path demangler implemented in FastDemangle.cpp until it can 21 // replace the existing C++ demangler with a complete implementation 22 #include "lldb/Utility/FastDemangle.h" 23 #include "llvm/Demangle/Demangle.h" 24 #else 25 // FreeBSD9-STABLE requires this to know about size_t in cxxabi. 26 #include <cstddef> 27 #include <cxxabi.h> 28 #endif 29 30 #include "lldb/Utility/ConstString.h" 31 #include "lldb/Utility/Log.h" 32 #include "lldb/Utility/Logging.h" 33 #include "lldb/Utility/RegularExpression.h" 34 #include "lldb/Utility/Stream.h" 35 #include "lldb/Utility/Timer.h" 36 #include "lldb/lldb-enumerations.h" // for LanguageType 37 38 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" 39 #include "Plugins/Language/ObjC/ObjCLanguage.h" 40 41 #include "llvm/ADT/StringRef.h" // for StringRef 42 #include "llvm/Support/Compiler.h" // for LLVM_PRETT... 43 44 #include <mutex> // for mutex, loc... 45 #include <string> // for string 46 #include <utility> // for pair 47 48 #include <stdlib.h> 49 #include <string.h> 50 using namespace lldb_private; 51 52 #if defined(_MSC_VER) 53 static DWORD safeUndecorateName(const char *Mangled, char *Demangled, 54 DWORD DemangledLength) { 55 static std::mutex M; 56 std::lock_guard<std::mutex> Lock(M); 57 return ::UnDecorateSymbolName( 58 Mangled, Demangled, DemangledLength, 59 UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected 60 // keywords 61 UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, 62 // etc keywords 63 UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications 64 UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc 65 // specifiers 66 UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords 67 ); 68 } 69 #endif 70 71 static inline Mangled::ManglingScheme cstring_mangling_scheme(const char *s) { 72 if (s) { 73 if (s[0] == '?') 74 return Mangled::eManglingSchemeMSVC; 75 if (s[0] == '_' && s[1] == 'Z') 76 return Mangled::eManglingSchemeItanium; 77 } 78 return Mangled::eManglingSchemeNone; 79 } 80 81 static inline bool cstring_is_mangled(const char *s) { 82 return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone; 83 } 84 85 static const ConstString & 86 get_demangled_name_without_arguments(ConstString mangled, 87 ConstString demangled) { 88 // This pair is <mangled name, demangled name without function arguments> 89 static std::pair<ConstString, ConstString> 90 g_most_recent_mangled_to_name_sans_args; 91 92 // Need to have the mangled & demangled names we're currently examining as 93 // statics so we can return a const ref to them at the end of the func if we 94 // don't have anything better. 95 static ConstString g_last_mangled; 96 static ConstString g_last_demangled; 97 98 if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) { 99 return g_most_recent_mangled_to_name_sans_args.second; 100 } 101 102 g_last_demangled = demangled; 103 g_last_mangled = mangled; 104 105 const char *mangled_name_cstr = mangled.GetCString(); 106 107 if (demangled && mangled_name_cstr && mangled_name_cstr[0]) { 108 if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' && 109 (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, 110 // typeinfo structure, and typeinfo 111 // mangled_name 112 mangled_name_cstr[2] != 'G' && // avoid guard variables 113 mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually 114 // handle eSymbolTypeData, we will want 115 // this back) 116 { 117 CPlusPlusLanguage::MethodName cxx_method(demangled); 118 if (!cxx_method.GetBasename().empty()) { 119 std::string shortname; 120 if (!cxx_method.GetContext().empty()) 121 shortname = cxx_method.GetContext().str() + "::"; 122 shortname += cxx_method.GetBasename().str(); 123 ConstString result(shortname.c_str()); 124 g_most_recent_mangled_to_name_sans_args.first = mangled; 125 g_most_recent_mangled_to_name_sans_args.second = result; 126 return g_most_recent_mangled_to_name_sans_args.second; 127 } 128 } 129 } 130 131 if (demangled) 132 return g_last_demangled; 133 return g_last_mangled; 134 } 135 136 #pragma mark Mangled 137 //---------------------------------------------------------------------- 138 // Default constructor 139 //---------------------------------------------------------------------- 140 Mangled::Mangled() : m_mangled(), m_demangled() {} 141 142 //---------------------------------------------------------------------- 143 // Constructor with an optional string and a boolean indicating if it is the 144 // mangled version. 145 //---------------------------------------------------------------------- 146 Mangled::Mangled(const ConstString &s, bool mangled) 147 : m_mangled(), m_demangled() { 148 if (s) 149 SetValue(s, mangled); 150 } 151 152 Mangled::Mangled(llvm::StringRef name, bool is_mangled) { 153 if (!name.empty()) 154 SetValue(ConstString(name), is_mangled); 155 } 156 157 Mangled::Mangled(const ConstString &s) : m_mangled(), m_demangled() { 158 if (s) 159 SetValue(s); 160 } 161 162 Mangled::Mangled(llvm::StringRef name) { 163 if (!name.empty()) 164 SetValue(ConstString(name)); 165 } 166 167 //---------------------------------------------------------------------- 168 // Destructor 169 //---------------------------------------------------------------------- 170 Mangled::~Mangled() {} 171 172 //---------------------------------------------------------------------- 173 // Convert to pointer operator. This allows code to check any Mangled objects 174 // to see if they contain anything valid using code such as: 175 // 176 // Mangled mangled(...); 177 // if (mangled) 178 // { ... 179 //---------------------------------------------------------------------- 180 Mangled::operator void *() const { 181 return (m_mangled) ? const_cast<Mangled *>(this) : NULL; 182 } 183 184 //---------------------------------------------------------------------- 185 // Logical NOT operator. This allows code to check any Mangled objects to see 186 // if they are invalid using code such as: 187 // 188 // Mangled mangled(...); 189 // if (!file_spec) 190 // { ... 191 //---------------------------------------------------------------------- 192 bool Mangled::operator!() const { return !m_mangled; } 193 194 //---------------------------------------------------------------------- 195 // Clear the mangled and demangled values. 196 //---------------------------------------------------------------------- 197 void Mangled::Clear() { 198 m_mangled.Clear(); 199 m_demangled.Clear(); 200 } 201 202 //---------------------------------------------------------------------- 203 // Compare the string values. 204 //---------------------------------------------------------------------- 205 int Mangled::Compare(const Mangled &a, const Mangled &b) { 206 return ConstString::Compare( 207 a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled), 208 a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled)); 209 } 210 211 //---------------------------------------------------------------------- 212 // Set the string value in this objects. If "mangled" is true, then the mangled 213 // named is set with the new value in "s", else the demangled name is set. 214 //---------------------------------------------------------------------- 215 void Mangled::SetValue(const ConstString &s, bool mangled) { 216 if (s) { 217 if (mangled) { 218 m_demangled.Clear(); 219 m_mangled = s; 220 } else { 221 m_demangled = s; 222 m_mangled.Clear(); 223 } 224 } else { 225 m_demangled.Clear(); 226 m_mangled.Clear(); 227 } 228 } 229 230 void Mangled::SetValue(const ConstString &name) { 231 if (name) { 232 if (cstring_is_mangled(name.GetCString())) { 233 m_demangled.Clear(); 234 m_mangled = name; 235 } else { 236 m_demangled = name; 237 m_mangled.Clear(); 238 } 239 } else { 240 m_demangled.Clear(); 241 m_mangled.Clear(); 242 } 243 } 244 245 //---------------------------------------------------------------------- 246 // Generate the demangled name on demand using this accessor. Code in this 247 // class will need to use this accessor if it wishes to decode the demangled 248 // name. The result is cached and will be kept until a new string value is 249 // supplied to this object, or until the end of the object's lifetime. 250 //---------------------------------------------------------------------- 251 const ConstString & 252 Mangled::GetDemangledName(lldb::LanguageType language) const { 253 // Check to make sure we have a valid mangled name and that we haven't 254 // already decoded our mangled name. 255 if (m_mangled && !m_demangled) { 256 // We need to generate and cache the demangled name. 257 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 258 Timer scoped_timer(func_cat, "Mangled::GetDemangledName (m_mangled = %s)", 259 m_mangled.GetCString()); 260 261 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE); 262 263 // Don't bother running anything that isn't mangled 264 const char *mangled_name = m_mangled.GetCString(); 265 ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)}; 266 if (mangling_scheme != eManglingSchemeNone && 267 !m_mangled.GetMangledCounterpart(m_demangled)) { 268 // We didn't already mangle this name, demangle it and if all goes well 269 // add it to our map. 270 char *demangled_name = nullptr; 271 switch (mangling_scheme) { 272 case eManglingSchemeMSVC: { 273 #if defined(_MSC_VER) 274 if (log) 275 log->Printf("demangle msvc: %s", mangled_name); 276 const size_t demangled_length = 2048; 277 demangled_name = static_cast<char *>(::malloc(demangled_length)); 278 ::ZeroMemory(demangled_name, demangled_length); 279 DWORD result = 280 safeUndecorateName(mangled_name, demangled_name, demangled_length); 281 if (log) { 282 if (demangled_name && demangled_name[0]) 283 log->Printf("demangled msvc: %s -> \"%s\"", mangled_name, 284 demangled_name); 285 else 286 log->Printf("demangled msvc: %s -> error: 0x%lu", mangled_name, 287 result); 288 } 289 290 if (result == 0) { 291 free(demangled_name); 292 demangled_name = nullptr; 293 } 294 #endif 295 break; 296 } 297 case eManglingSchemeItanium: { 298 #ifdef LLDB_USE_BUILTIN_DEMANGLER 299 if (log) 300 log->Printf("demangle itanium: %s", mangled_name); 301 // Try to use the fast-path demangler first for the performance win, 302 // falling back to the full demangler only when necessary 303 demangled_name = FastDemangle(mangled_name, m_mangled.GetLength()); 304 if (!demangled_name) 305 demangled_name = 306 llvm::itaniumDemangle(mangled_name, NULL, NULL, NULL); 307 #else 308 demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL); 309 #endif 310 if (log) { 311 if (demangled_name) 312 log->Printf("demangled itanium: %s -> \"%s\"", mangled_name, 313 demangled_name); 314 else 315 log->Printf("demangled itanium: %s -> error: failed to demangle", 316 mangled_name); 317 } 318 break; 319 } 320 case eManglingSchemeNone: 321 break; 322 } 323 if (demangled_name) { 324 m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); 325 free(demangled_name); 326 } 327 } 328 if (!m_demangled) { 329 // Set the demangled string to the empty string to indicate we tried to 330 // parse it once and failed. 331 m_demangled.SetCString(""); 332 } 333 } 334 335 return m_demangled; 336 } 337 338 ConstString 339 Mangled::GetDisplayDemangledName(lldb::LanguageType language) const { 340 return GetDemangledName(language); 341 } 342 343 bool Mangled::NameMatches(const RegularExpression ®ex, 344 lldb::LanguageType language) const { 345 if (m_mangled && regex.Execute(m_mangled.AsCString())) 346 return true; 347 348 ConstString demangled = GetDemangledName(language); 349 if (demangled && regex.Execute(demangled.AsCString())) 350 return true; 351 return false; 352 } 353 354 //---------------------------------------------------------------------- 355 // Get the demangled name if there is one, else return the mangled name. 356 //---------------------------------------------------------------------- 357 ConstString Mangled::GetName(lldb::LanguageType language, 358 Mangled::NamePreference preference) const { 359 if (preference == ePreferMangled && m_mangled) 360 return m_mangled; 361 362 ConstString demangled = GetDemangledName(language); 363 364 if (preference == ePreferDemangledWithoutArguments) { 365 return get_demangled_name_without_arguments(m_mangled, demangled); 366 } 367 if (preference == ePreferDemangled) { 368 // Call the accessor to make sure we get a demangled name in case it hasn't 369 // been demangled yet... 370 if (demangled) 371 return demangled; 372 return m_mangled; 373 } 374 return demangled; 375 } 376 377 //---------------------------------------------------------------------- 378 // Dump a Mangled object to stream "s". We don't force our demangled name to be 379 // computed currently (we don't use the accessor). 380 //---------------------------------------------------------------------- 381 void Mangled::Dump(Stream *s) const { 382 if (m_mangled) { 383 *s << ", mangled = " << m_mangled; 384 } 385 if (m_demangled) { 386 const char *demangled = m_demangled.AsCString(); 387 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>"); 388 } 389 } 390 391 //---------------------------------------------------------------------- 392 // Dumps a debug version of this string with extra object and state information 393 // to stream "s". 394 //---------------------------------------------------------------------- 395 void Mangled::DumpDebug(Stream *s) const { 396 s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2), 397 static_cast<const void *>(this)); 398 m_mangled.DumpDebug(s); 399 s->Printf(", demangled = "); 400 m_demangled.DumpDebug(s); 401 } 402 403 //---------------------------------------------------------------------- 404 // Return the size in byte that this object takes in memory. The size includes 405 // the size of the objects it owns, and not the strings that it references 406 // because they are shared strings. 407 //---------------------------------------------------------------------- 408 size_t Mangled::MemorySize() const { 409 return m_mangled.MemorySize() + m_demangled.MemorySize(); 410 } 411 412 //---------------------------------------------------------------------- 413 // We "guess" the language because we can't determine a symbol's language from 414 // it's name. For example, a Pascal symbol can be mangled using the C++ 415 // Itanium scheme, and defined in a compilation unit within the same module as 416 // other C++ units. In addition, different targets could have different ways 417 // of mangling names from a given language, likewise the compilation units 418 // within those targets. 419 //---------------------------------------------------------------------- 420 lldb::LanguageType Mangled::GuessLanguage() const { 421 ConstString mangled = GetMangledName(); 422 if (mangled) { 423 if (GetDemangledName(lldb::eLanguageTypeUnknown)) { 424 const char *mangled_name = mangled.GetCString(); 425 if (CPlusPlusLanguage::IsCPPMangledName(mangled_name)) 426 return lldb::eLanguageTypeC_plus_plus; 427 else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name)) 428 return lldb::eLanguageTypeObjC; 429 } 430 } else { 431 // ObjC names aren't really mangled, so they won't necessarily be in the 432 // mangled name slot. 433 ConstString demangled_name = GetDemangledName(lldb::eLanguageTypeUnknown); 434 if (demangled_name 435 && ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString())) 436 return lldb::eLanguageTypeObjC; 437 438 } 439 return lldb::eLanguageTypeUnknown; 440 } 441 442 //---------------------------------------------------------------------- 443 // Dump OBJ to the supplied stream S. 444 //---------------------------------------------------------------------- 445 Stream &operator<<(Stream &s, const Mangled &obj) { 446 if (obj.GetMangledName()) 447 s << "mangled = '" << obj.GetMangledName() << "'"; 448 449 const ConstString &demangled = 450 obj.GetDemangledName(lldb::eLanguageTypeUnknown); 451 if (demangled) 452 s << ", demangled = '" << demangled << '\''; 453 else 454 s << ", demangled = <error>"; 455 return s; 456 } 457