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