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/RichManglingContext.h" 12 #include "lldb/Target/Language.h" 13 #include "lldb/Utility/ConstString.h" 14 #include "lldb/Utility/Log.h" 15 #include "lldb/Utility/Logging.h" 16 #include "lldb/Utility/RegularExpression.h" 17 #include "lldb/Utility/Stream.h" 18 #include "lldb/lldb-enumerations.h" 19 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/Demangle/Demangle.h" 22 #include "llvm/Support/Compiler.h" 23 24 #include <mutex> 25 #include <string> 26 #include <utility> 27 28 #include <cstdlib> 29 #include <cstring> 30 using namespace lldb_private; 31 32 static inline bool cstring_is_mangled(llvm::StringRef s) { 33 return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone; 34 } 35 36 #pragma mark Mangled 37 38 Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) { 39 if (name.empty()) 40 return Mangled::eManglingSchemeNone; 41 42 if (name.startswith("?")) 43 return Mangled::eManglingSchemeMSVC; 44 45 if (name.startswith("_R")) 46 return Mangled::eManglingSchemeRustV0; 47 48 if (name.startswith("_D")) 49 return Mangled::eManglingSchemeD; 50 51 if (name.startswith("_Z")) 52 return Mangled::eManglingSchemeItanium; 53 54 // ___Z is a clang extension of block invocations 55 if (name.startswith("___Z")) 56 return Mangled::eManglingSchemeItanium; 57 58 return Mangled::eManglingSchemeNone; 59 } 60 61 Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() { 62 if (s) 63 SetValue(s); 64 } 65 66 Mangled::Mangled(llvm::StringRef name) { 67 if (!name.empty()) 68 SetValue(ConstString(name)); 69 } 70 71 // Convert to pointer operator. This allows code to check any Mangled objects 72 // to see if they contain anything valid using code such as: 73 // 74 // Mangled mangled(...); 75 // if (mangled) 76 // { ... 77 Mangled::operator void *() const { 78 return (m_mangled) ? const_cast<Mangled *>(this) : nullptr; 79 } 80 81 // Logical NOT operator. This allows code to check any Mangled objects to see 82 // if they are invalid using code such as: 83 // 84 // Mangled mangled(...); 85 // if (!file_spec) 86 // { ... 87 bool Mangled::operator!() const { return !m_mangled; } 88 89 // Clear the mangled and demangled values. 90 void Mangled::Clear() { 91 m_mangled.Clear(); 92 m_demangled.Clear(); 93 } 94 95 // Compare the string values. 96 int Mangled::Compare(const Mangled &a, const Mangled &b) { 97 return ConstString::Compare(a.GetName(ePreferMangled), 98 b.GetName(ePreferMangled)); 99 } 100 101 // Set the string value in this objects. If "mangled" is true, then the mangled 102 // named is set with the new value in "s", else the demangled name is set. 103 void Mangled::SetValue(ConstString s, bool mangled) { 104 if (s) { 105 if (mangled) { 106 m_demangled.Clear(); 107 m_mangled = s; 108 } else { 109 m_demangled = s; 110 m_mangled.Clear(); 111 } 112 } else { 113 m_demangled.Clear(); 114 m_mangled.Clear(); 115 } 116 } 117 118 void Mangled::SetValue(ConstString name) { 119 if (name) { 120 if (cstring_is_mangled(name.GetStringRef())) { 121 m_demangled.Clear(); 122 m_mangled = name; 123 } else { 124 m_demangled = name; 125 m_mangled.Clear(); 126 } 127 } else { 128 m_demangled.Clear(); 129 m_mangled.Clear(); 130 } 131 } 132 133 // Local helpers for different demangling implementations. 134 static char *GetMSVCDemangledStr(const char *M) { 135 char *demangled_cstr = llvm::microsoftDemangle( 136 M, nullptr, nullptr, nullptr, nullptr, 137 llvm::MSDemangleFlags( 138 llvm::MSDF_NoAccessSpecifier | llvm::MSDF_NoCallingConvention | 139 llvm::MSDF_NoMemberType | llvm::MSDF_NoVariableType)); 140 141 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 142 if (demangled_cstr && demangled_cstr[0]) 143 LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M, demangled_cstr); 144 else 145 LLDB_LOGF(log, "demangled msvc: %s -> error", M); 146 } 147 148 return demangled_cstr; 149 } 150 151 static char *GetItaniumDemangledStr(const char *M) { 152 char *demangled_cstr = nullptr; 153 154 llvm::ItaniumPartialDemangler ipd; 155 bool err = ipd.partialDemangle(M); 156 if (!err) { 157 // Default buffer and size (will realloc in case it's too small). 158 size_t demangled_size = 80; 159 demangled_cstr = static_cast<char *>(std::malloc(demangled_size)); 160 demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size); 161 162 assert(demangled_cstr && 163 "finishDemangle must always succeed if partialDemangle did"); 164 assert(demangled_cstr[demangled_size - 1] == '\0' && 165 "Expected demangled_size to return length including trailing null"); 166 } 167 168 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 169 if (demangled_cstr) 170 LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr); 171 else 172 LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M); 173 } 174 175 return demangled_cstr; 176 } 177 178 static char *GetRustV0DemangledStr(const char *M) { 179 char *demangled_cstr = llvm::rustDemangle(M, nullptr, nullptr, nullptr); 180 181 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 182 if (demangled_cstr && demangled_cstr[0]) 183 LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr); 184 else 185 LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M); 186 } 187 188 return demangled_cstr; 189 } 190 191 static char *GetDLangDemangledStr(const char *M) { 192 char *demangled_cstr = llvm::dlangDemangle(M); 193 194 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 195 if (demangled_cstr && demangled_cstr[0]) 196 LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", M, demangled_cstr); 197 else 198 LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", M); 199 } 200 201 return demangled_cstr; 202 } 203 204 // Explicit demangling for scheduled requests during batch processing. This 205 // makes use of ItaniumPartialDemangler's rich demangle info 206 bool Mangled::DemangleWithRichManglingInfo( 207 RichManglingContext &context, SkipMangledNameFn *skip_mangled_name) { 208 // Others are not meant to arrive here. ObjC names or C's main() for example 209 // have their names stored in m_demangled, while m_mangled is empty. 210 assert(m_mangled); 211 212 // Check whether or not we are interested in this name at all. 213 ManglingScheme scheme = GetManglingScheme(m_mangled.GetStringRef()); 214 if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme)) 215 return false; 216 217 switch (scheme) { 218 case eManglingSchemeNone: 219 // The current mangled_name_filter would allow llvm_unreachable here. 220 return false; 221 222 case eManglingSchemeItanium: 223 // We want the rich mangling info here, so we don't care whether or not 224 // there is a demangled string in the pool already. 225 if (context.FromItaniumName(m_mangled)) { 226 // If we got an info, we have a name. Copy to string pool and connect the 227 // counterparts to accelerate later access in GetDemangledName(). 228 context.ParseFullName(); 229 m_demangled.SetStringWithMangledCounterpart(context.GetBufferRef(), 230 m_mangled); 231 return true; 232 } else { 233 m_demangled.SetCString(""); 234 return false; 235 } 236 237 case eManglingSchemeMSVC: { 238 // We have no rich mangling for MSVC-mangled names yet, so first try to 239 // demangle it if necessary. 240 if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) { 241 if (char *d = GetMSVCDemangledStr(m_mangled.GetCString())) { 242 // If we got an info, we have a name. Copy to string pool and connect 243 // the counterparts to accelerate later access in GetDemangledName(). 244 m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d), 245 m_mangled); 246 ::free(d); 247 } else { 248 m_demangled.SetCString(""); 249 } 250 } 251 252 if (m_demangled.IsEmpty()) { 253 // Cannot demangle it, so don't try parsing. 254 return false; 255 } else { 256 // Demangled successfully, we can try and parse it with 257 // CPlusPlusLanguage::MethodName. 258 return context.FromCxxMethodName(m_demangled); 259 } 260 } 261 262 case eManglingSchemeRustV0: 263 case eManglingSchemeD: 264 // Rich demangling scheme is not supported 265 return false; 266 } 267 llvm_unreachable("Fully covered switch above!"); 268 } 269 270 // Generate the demangled name on demand using this accessor. Code in this 271 // class will need to use this accessor if it wishes to decode the demangled 272 // name. The result is cached and will be kept until a new string value is 273 // supplied to this object, or until the end of the object's lifetime. 274 ConstString Mangled::GetDemangledName() const { 275 // Check to make sure we have a valid mangled name and that we haven't 276 // already decoded our mangled name. 277 if (m_mangled && m_demangled.IsNull()) { 278 // Don't bother running anything that isn't mangled 279 const char *mangled_name = m_mangled.GetCString(); 280 ManglingScheme mangling_scheme = 281 GetManglingScheme(m_mangled.GetStringRef()); 282 if (mangling_scheme != eManglingSchemeNone && 283 !m_mangled.GetMangledCounterpart(m_demangled)) { 284 // We didn't already mangle this name, demangle it and if all goes well 285 // add it to our map. 286 char *demangled_name = nullptr; 287 switch (mangling_scheme) { 288 case eManglingSchemeMSVC: 289 demangled_name = GetMSVCDemangledStr(mangled_name); 290 break; 291 case eManglingSchemeItanium: { 292 demangled_name = GetItaniumDemangledStr(mangled_name); 293 break; 294 } 295 case eManglingSchemeRustV0: 296 demangled_name = GetRustV0DemangledStr(mangled_name); 297 break; 298 case eManglingSchemeD: 299 demangled_name = GetDLangDemangledStr(mangled_name); 300 break; 301 case eManglingSchemeNone: 302 llvm_unreachable("eManglingSchemeNone was handled already"); 303 } 304 if (demangled_name) { 305 m_demangled.SetStringWithMangledCounterpart( 306 llvm::StringRef(demangled_name), m_mangled); 307 free(demangled_name); 308 } 309 } 310 if (m_demangled.IsNull()) { 311 // Set the demangled string to the empty string to indicate we tried to 312 // parse it once and failed. 313 m_demangled.SetCString(""); 314 } 315 } 316 317 return m_demangled; 318 } 319 320 ConstString Mangled::GetDisplayDemangledName() const { 321 return GetDemangledName(); 322 } 323 324 bool Mangled::NameMatches(const RegularExpression ®ex) const { 325 if (m_mangled && regex.Execute(m_mangled.GetStringRef())) 326 return true; 327 328 ConstString demangled = GetDemangledName(); 329 return demangled && regex.Execute(demangled.GetStringRef()); 330 } 331 332 // Get the demangled name if there is one, else return the mangled name. 333 ConstString Mangled::GetName(Mangled::NamePreference preference) const { 334 if (preference == ePreferMangled && m_mangled) 335 return m_mangled; 336 337 // Call the accessor to make sure we get a demangled name in case it hasn't 338 // been demangled yet... 339 ConstString demangled = GetDemangledName(); 340 341 if (preference == ePreferDemangledWithoutArguments) { 342 if (Language *lang = Language::FindPlugin(GuessLanguage())) { 343 return lang->GetDemangledFunctionNameWithoutArguments(*this); 344 } 345 } 346 if (preference == ePreferDemangled) { 347 if (demangled) 348 return demangled; 349 return m_mangled; 350 } 351 return demangled; 352 } 353 354 // Dump a Mangled object to stream "s". We don't force our demangled name to be 355 // computed currently (we don't use the accessor). 356 void Mangled::Dump(Stream *s) const { 357 if (m_mangled) { 358 *s << ", mangled = " << m_mangled; 359 } 360 if (m_demangled) { 361 const char *demangled = m_demangled.AsCString(); 362 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>"); 363 } 364 } 365 366 // Dumps a debug version of this string with extra object and state information 367 // to stream "s". 368 void Mangled::DumpDebug(Stream *s) const { 369 s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2), 370 static_cast<const void *>(this)); 371 m_mangled.DumpDebug(s); 372 s->Printf(", demangled = "); 373 m_demangled.DumpDebug(s); 374 } 375 376 // Return the size in byte that this object takes in memory. The size includes 377 // the size of the objects it owns, and not the strings that it references 378 // because they are shared strings. 379 size_t Mangled::MemorySize() const { 380 return m_mangled.MemorySize() + m_demangled.MemorySize(); 381 } 382 383 // We "guess" the language because we can't determine a symbol's language from 384 // it's name. For example, a Pascal symbol can be mangled using the C++ 385 // Itanium scheme, and defined in a compilation unit within the same module as 386 // other C++ units. In addition, different targets could have different ways 387 // of mangling names from a given language, likewise the compilation units 388 // within those targets. 389 lldb::LanguageType Mangled::GuessLanguage() const { 390 lldb::LanguageType result = lldb::eLanguageTypeUnknown; 391 // Ask each language plugin to check if the mangled name belongs to it. 392 Language::ForEach([this, &result](Language *l) { 393 if (l->SymbolNameFitsToLanguage(*this)) { 394 result = l->GetLanguageType(); 395 return false; 396 } 397 return true; 398 }); 399 return result; 400 } 401 402 // Dump OBJ to the supplied stream S. 403 Stream &operator<<(Stream &s, const Mangled &obj) { 404 if (obj.GetMangledName()) 405 s << "mangled = '" << obj.GetMangledName() << "'"; 406 407 ConstString demangled = obj.GetDemangledName(); 408 if (demangled) 409 s << ", demangled = '" << demangled << '\''; 410 else 411 s << ", demangled = <error>"; 412 return s; 413 } 414