1 //===-- Mangled.cpp -------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Core/Mangled.h" 10 11 #include "lldb/Core/DataFileCache.h" 12 #include "lldb/Core/RichManglingContext.h" 13 #include "lldb/Target/Language.h" 14 #include "lldb/Utility/ConstString.h" 15 #include "lldb/Utility/DataEncoder.h" 16 #include "lldb/Utility/Log.h" 17 #include "lldb/Utility/Logging.h" 18 #include "lldb/Utility/RegularExpression.h" 19 #include "lldb/Utility/Stream.h" 20 #include "lldb/lldb-enumerations.h" 21 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/Demangle/Demangle.h" 24 #include "llvm/Support/Compiler.h" 25 26 #include <mutex> 27 #include <string> 28 #include <utility> 29 30 #include <cstdlib> 31 #include <cstring> 32 using namespace lldb_private; 33 34 static inline bool cstring_is_mangled(llvm::StringRef s) { 35 return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone; 36 } 37 38 #pragma mark Mangled 39 40 Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) { 41 if (name.empty()) 42 return Mangled::eManglingSchemeNone; 43 44 if (name.startswith("?")) 45 return Mangled::eManglingSchemeMSVC; 46 47 if (name.startswith("_R")) 48 return Mangled::eManglingSchemeRustV0; 49 50 if (name.startswith("_D")) 51 return Mangled::eManglingSchemeD; 52 53 if (name.startswith("_Z")) 54 return Mangled::eManglingSchemeItanium; 55 56 // ___Z is a clang extension of block invocations 57 if (name.startswith("___Z")) 58 return Mangled::eManglingSchemeItanium; 59 60 return Mangled::eManglingSchemeNone; 61 } 62 63 Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() { 64 if (s) 65 SetValue(s); 66 } 67 68 Mangled::Mangled(llvm::StringRef name) { 69 if (!name.empty()) 70 SetValue(ConstString(name)); 71 } 72 73 // Convert to pointer operator. This allows code to check any Mangled objects 74 // to see if they contain anything valid using code such as: 75 // 76 // Mangled mangled(...); 77 // if (mangled) 78 // { ... 79 Mangled::operator void *() const { 80 return (m_mangled) ? const_cast<Mangled *>(this) : nullptr; 81 } 82 83 // Logical NOT operator. This allows code to check any Mangled objects to see 84 // if they are invalid using code such as: 85 // 86 // Mangled mangled(...); 87 // if (!file_spec) 88 // { ... 89 bool Mangled::operator!() const { return !m_mangled; } 90 91 // Clear the mangled and demangled values. 92 void Mangled::Clear() { 93 m_mangled.Clear(); 94 m_demangled.Clear(); 95 } 96 97 // Compare the string values. 98 int Mangled::Compare(const Mangled &a, const Mangled &b) { 99 return ConstString::Compare(a.GetName(ePreferMangled), 100 b.GetName(ePreferMangled)); 101 } 102 103 // Set the string value in this objects. If "mangled" is true, then the mangled 104 // named is set with the new value in "s", else the demangled name is set. 105 void Mangled::SetValue(ConstString s, bool mangled) { 106 if (s) { 107 if (mangled) { 108 m_demangled.Clear(); 109 m_mangled = s; 110 } else { 111 m_demangled = s; 112 m_mangled.Clear(); 113 } 114 } else { 115 m_demangled.Clear(); 116 m_mangled.Clear(); 117 } 118 } 119 120 void Mangled::SetValue(ConstString name) { 121 if (name) { 122 if (cstring_is_mangled(name.GetStringRef())) { 123 m_demangled.Clear(); 124 m_mangled = name; 125 } else { 126 m_demangled = name; 127 m_mangled.Clear(); 128 } 129 } else { 130 m_demangled.Clear(); 131 m_mangled.Clear(); 132 } 133 } 134 135 // Local helpers for different demangling implementations. 136 static char *GetMSVCDemangledStr(const char *M) { 137 char *demangled_cstr = llvm::microsoftDemangle( 138 M, nullptr, nullptr, nullptr, nullptr, 139 llvm::MSDemangleFlags( 140 llvm::MSDF_NoAccessSpecifier | llvm::MSDF_NoCallingConvention | 141 llvm::MSDF_NoMemberType | llvm::MSDF_NoVariableType)); 142 143 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 144 if (demangled_cstr && demangled_cstr[0]) 145 LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M, demangled_cstr); 146 else 147 LLDB_LOGF(log, "demangled msvc: %s -> error", M); 148 } 149 150 return demangled_cstr; 151 } 152 153 static char *GetItaniumDemangledStr(const char *M) { 154 char *demangled_cstr = nullptr; 155 156 llvm::ItaniumPartialDemangler ipd; 157 bool err = ipd.partialDemangle(M); 158 if (!err) { 159 // Default buffer and size (will realloc in case it's too small). 160 size_t demangled_size = 80; 161 demangled_cstr = static_cast<char *>(std::malloc(demangled_size)); 162 demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size); 163 164 assert(demangled_cstr && 165 "finishDemangle must always succeed if partialDemangle did"); 166 assert(demangled_cstr[demangled_size - 1] == '\0' && 167 "Expected demangled_size to return length including trailing null"); 168 } 169 170 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 171 if (demangled_cstr) 172 LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr); 173 else 174 LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M); 175 } 176 177 return demangled_cstr; 178 } 179 180 static char *GetRustV0DemangledStr(const char *M) { 181 char *demangled_cstr = llvm::rustDemangle(M, nullptr, nullptr, nullptr); 182 183 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 184 if (demangled_cstr && demangled_cstr[0]) 185 LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr); 186 else 187 LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M); 188 } 189 190 return demangled_cstr; 191 } 192 193 static char *GetDLangDemangledStr(const char *M) { 194 char *demangled_cstr = llvm::dlangDemangle(M); 195 196 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 197 if (demangled_cstr && demangled_cstr[0]) 198 LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", M, demangled_cstr); 199 else 200 LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", M); 201 } 202 203 return demangled_cstr; 204 } 205 206 // Explicit demangling for scheduled requests during batch processing. This 207 // makes use of ItaniumPartialDemangler's rich demangle info 208 bool Mangled::DemangleWithRichManglingInfo( 209 RichManglingContext &context, SkipMangledNameFn *skip_mangled_name) { 210 // Others are not meant to arrive here. ObjC names or C's main() for example 211 // have their names stored in m_demangled, while m_mangled is empty. 212 assert(m_mangled); 213 214 // Check whether or not we are interested in this name at all. 215 ManglingScheme scheme = GetManglingScheme(m_mangled.GetStringRef()); 216 if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme)) 217 return false; 218 219 switch (scheme) { 220 case eManglingSchemeNone: 221 // The current mangled_name_filter would allow llvm_unreachable here. 222 return false; 223 224 case eManglingSchemeItanium: 225 // We want the rich mangling info here, so we don't care whether or not 226 // there is a demangled string in the pool already. 227 if (context.FromItaniumName(m_mangled)) { 228 // If we got an info, we have a name. Copy to string pool and connect the 229 // counterparts to accelerate later access in GetDemangledName(). 230 context.ParseFullName(); 231 m_demangled.SetStringWithMangledCounterpart(context.GetBufferRef(), 232 m_mangled); 233 return true; 234 } else { 235 m_demangled.SetCString(""); 236 return false; 237 } 238 239 case eManglingSchemeMSVC: { 240 // We have no rich mangling for MSVC-mangled names yet, so first try to 241 // demangle it if necessary. 242 if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) { 243 if (char *d = GetMSVCDemangledStr(m_mangled.GetCString())) { 244 // If we got an info, we have a name. Copy to string pool and connect 245 // the counterparts to accelerate later access in GetDemangledName(). 246 m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d), 247 m_mangled); 248 ::free(d); 249 } else { 250 m_demangled.SetCString(""); 251 } 252 } 253 254 if (m_demangled.IsEmpty()) { 255 // Cannot demangle it, so don't try parsing. 256 return false; 257 } else { 258 // Demangled successfully, we can try and parse it with 259 // CPlusPlusLanguage::MethodName. 260 return context.FromCxxMethodName(m_demangled); 261 } 262 } 263 264 case eManglingSchemeRustV0: 265 case eManglingSchemeD: 266 // Rich demangling scheme is not supported 267 return false; 268 } 269 llvm_unreachable("Fully covered switch above!"); 270 } 271 272 // Generate the demangled name on demand using this accessor. Code in this 273 // class will need to use this accessor if it wishes to decode the demangled 274 // name. The result is cached and will be kept until a new string value is 275 // supplied to this object, or until the end of the object's lifetime. 276 ConstString Mangled::GetDemangledName() const { 277 // Check to make sure we have a valid mangled name and that we haven't 278 // already decoded our mangled name. 279 if (m_mangled && m_demangled.IsNull()) { 280 // Don't bother running anything that isn't mangled 281 const char *mangled_name = m_mangled.GetCString(); 282 ManglingScheme mangling_scheme = 283 GetManglingScheme(m_mangled.GetStringRef()); 284 if (mangling_scheme != eManglingSchemeNone && 285 !m_mangled.GetMangledCounterpart(m_demangled)) { 286 // We didn't already mangle this name, demangle it and if all goes well 287 // add it to our map. 288 char *demangled_name = nullptr; 289 switch (mangling_scheme) { 290 case eManglingSchemeMSVC: 291 demangled_name = GetMSVCDemangledStr(mangled_name); 292 break; 293 case eManglingSchemeItanium: { 294 demangled_name = GetItaniumDemangledStr(mangled_name); 295 break; 296 } 297 case eManglingSchemeRustV0: 298 demangled_name = GetRustV0DemangledStr(mangled_name); 299 break; 300 case eManglingSchemeD: 301 demangled_name = GetDLangDemangledStr(mangled_name); 302 break; 303 case eManglingSchemeNone: 304 llvm_unreachable("eManglingSchemeNone was handled already"); 305 } 306 if (demangled_name) { 307 m_demangled.SetStringWithMangledCounterpart( 308 llvm::StringRef(demangled_name), m_mangled); 309 free(demangled_name); 310 } 311 } 312 if (m_demangled.IsNull()) { 313 // Set the demangled string to the empty string to indicate we tried to 314 // parse it once and failed. 315 m_demangled.SetCString(""); 316 } 317 } 318 319 return m_demangled; 320 } 321 322 ConstString Mangled::GetDisplayDemangledName() const { 323 return GetDemangledName(); 324 } 325 326 bool Mangled::NameMatches(const RegularExpression ®ex) const { 327 if (m_mangled && regex.Execute(m_mangled.GetStringRef())) 328 return true; 329 330 ConstString demangled = GetDemangledName(); 331 return demangled && regex.Execute(demangled.GetStringRef()); 332 } 333 334 // Get the demangled name if there is one, else return the mangled name. 335 ConstString Mangled::GetName(Mangled::NamePreference preference) const { 336 if (preference == ePreferMangled && m_mangled) 337 return m_mangled; 338 339 // Call the accessor to make sure we get a demangled name in case it hasn't 340 // been demangled yet... 341 ConstString demangled = GetDemangledName(); 342 343 if (preference == ePreferDemangledWithoutArguments) { 344 if (Language *lang = Language::FindPlugin(GuessLanguage())) { 345 return lang->GetDemangledFunctionNameWithoutArguments(*this); 346 } 347 } 348 if (preference == ePreferDemangled) { 349 if (demangled) 350 return demangled; 351 return m_mangled; 352 } 353 return demangled; 354 } 355 356 // Dump a Mangled object to stream "s". We don't force our demangled name to be 357 // computed currently (we don't use the accessor). 358 void Mangled::Dump(Stream *s) const { 359 if (m_mangled) { 360 *s << ", mangled = " << m_mangled; 361 } 362 if (m_demangled) { 363 const char *demangled = m_demangled.AsCString(); 364 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>"); 365 } 366 } 367 368 // Dumps a debug version of this string with extra object and state information 369 // to stream "s". 370 void Mangled::DumpDebug(Stream *s) const { 371 s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2), 372 static_cast<const void *>(this)); 373 m_mangled.DumpDebug(s); 374 s->Printf(", demangled = "); 375 m_demangled.DumpDebug(s); 376 } 377 378 // Return the size in byte that this object takes in memory. The size includes 379 // the size of the objects it owns, and not the strings that it references 380 // because they are shared strings. 381 size_t Mangled::MemorySize() const { 382 return m_mangled.MemorySize() + m_demangled.MemorySize(); 383 } 384 385 // We "guess" the language because we can't determine a symbol's language from 386 // it's name. For example, a Pascal symbol can be mangled using the C++ 387 // Itanium scheme, and defined in a compilation unit within the same module as 388 // other C++ units. In addition, different targets could have different ways 389 // of mangling names from a given language, likewise the compilation units 390 // within those targets. 391 lldb::LanguageType Mangled::GuessLanguage() const { 392 lldb::LanguageType result = lldb::eLanguageTypeUnknown; 393 // Ask each language plugin to check if the mangled name belongs to it. 394 Language::ForEach([this, &result](Language *l) { 395 if (l->SymbolNameFitsToLanguage(*this)) { 396 result = l->GetLanguageType(); 397 return false; 398 } 399 return true; 400 }); 401 return result; 402 } 403 404 // Dump OBJ to the supplied stream S. 405 Stream &operator<<(Stream &s, const Mangled &obj) { 406 if (obj.GetMangledName()) 407 s << "mangled = '" << obj.GetMangledName() << "'"; 408 409 ConstString demangled = obj.GetDemangledName(); 410 if (demangled) 411 s << ", demangled = '" << demangled << '\''; 412 else 413 s << ", demangled = <error>"; 414 return s; 415 } 416 417 // When encoding Mangled objects we can get away with encoding as little 418 // information as is required. The enumeration below helps us to efficiently 419 // encode Mangled objects. 420 enum MangledEncoding { 421 /// If the Mangled object has neither a mangled name or demangled name we can 422 /// encode the object with one zero byte using the Empty enumeration. 423 Empty = 0u, 424 /// If the Mangled object has only a demangled name and no mangled named, we 425 /// can encode only the demangled name. 426 DemangledOnly = 1u, 427 /// If the mangle name can calculate the demangled name (it is the 428 /// mangled/demangled counterpart), then we only need to encode the mangled 429 /// name as the demangled name can be recomputed. 430 MangledOnly = 2u, 431 /// If we have a Mangled object with two different names that are not related 432 /// then we need to save both strings. This can happen if we have a name that 433 /// isn't a true mangled name, but we want to be able to lookup a symbol by 434 /// name and type in the symbol table. We do this for Objective C symbols like 435 /// "OBJC_CLASS_$_NSValue" where the mangled named will be set to 436 /// "OBJC_CLASS_$_NSValue" and the demangled name will be manually set to 437 /// "NSValue". If we tried to demangled the name "OBJC_CLASS_$_NSValue" it 438 /// would fail, but in these cases we want these unrelated names to be 439 /// preserved. 440 MangledAndDemangled = 3u 441 }; 442 443 bool Mangled::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, 444 const StringTableReader &strtab) { 445 m_mangled.Clear(); 446 m_demangled.Clear(); 447 MangledEncoding encoding = (MangledEncoding)data.GetU8(offset_ptr); 448 switch (encoding) { 449 case Empty: 450 return true; 451 452 case DemangledOnly: 453 m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr))); 454 return true; 455 456 case MangledOnly: 457 m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr))); 458 return true; 459 460 case MangledAndDemangled: 461 m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr))); 462 m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr))); 463 return true; 464 } 465 return false; 466 } 467 /// The encoding format for the Mangled object is as follows: 468 /// 469 /// uint8_t encoding; 470 /// char str1[]; (only if DemangledOnly, MangledOnly) 471 /// char str2[]; (only if MangledAndDemangled) 472 /// 473 /// The strings are stored as NULL terminated UTF8 strings and str1 and str2 474 /// are only saved if we need them based on the encoding. 475 /// 476 /// Some mangled names have a mangled name that can be demangled by the built 477 /// in demanglers. These kinds of mangled objects know when the mangled and 478 /// demangled names are the counterparts for each other. This is done because 479 /// demangling is very expensive and avoiding demangling the same name twice 480 /// saves us a lot of compute time. For these kinds of names we only need to 481 /// save the mangled name and have the encoding set to "MangledOnly". 482 /// 483 /// If a mangled obejct has only a demangled name, then we save only that string 484 /// and have the encoding set to "DemangledOnly". 485 /// 486 /// Some mangled objects have both mangled and demangled names, but the 487 /// demangled name can not be computed from the mangled name. This is often used 488 /// for runtime named, like Objective C runtime V2 and V3 names. Both these 489 /// names must be saved and the encoding is set to "MangledAndDemangled". 490 /// 491 /// For a Mangled object with no names, we only need to set the encoding to 492 /// "Empty" and not store any string values. 493 void Mangled::Encode(DataEncoder &file, ConstStringTable &strtab) const { 494 MangledEncoding encoding = Empty; 495 if (m_mangled) { 496 encoding = MangledOnly; 497 if (m_demangled) { 498 // We have both mangled and demangled names. If the demangled name is the 499 // counterpart of the mangled name, then we only need to save the mangled 500 // named. If they are different, we need to save both. 501 ConstString s; 502 if (!(m_mangled.GetMangledCounterpart(s) && s == m_demangled)) 503 encoding = MangledAndDemangled; 504 } 505 } else if (m_demangled) { 506 encoding = DemangledOnly; 507 } 508 file.AppendU8(encoding); 509 switch (encoding) { 510 case Empty: 511 break; 512 case DemangledOnly: 513 file.AppendU32(strtab.Add(m_demangled)); 514 break; 515 case MangledOnly: 516 file.AppendU32(strtab.Add(m_mangled)); 517 break; 518 case MangledAndDemangled: 519 file.AppendU32(strtab.Add(m_mangled)); 520 file.AppendU32(strtab.Add(m_demangled)); 521 break; 522 } 523 } 524