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