1 //===-- RichManglingContext.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/RichManglingContext.h" 10 #include "lldb/Utility/LLDBLog.h" 11 12 #include "llvm/ADT/StringRef.h" 13 14 using namespace lldb; 15 using namespace lldb_private; 16 17 // RichManglingContext 18 RichManglingContext::~RichManglingContext() { 19 std::free(m_ipd_buf); 20 ResetCxxMethodParser(); 21 } 22 23 void RichManglingContext::ResetCxxMethodParser() { 24 // If we want to support parsers for other languages some day, we need a 25 // switch here to delete the correct parser type. 26 if (m_cxx_method_parser) { 27 assert(m_provider == PluginCxxLanguage); 28 m_cxx_method_parser.reset(); 29 } 30 } 31 32 void RichManglingContext::ResetProvider(InfoProvider new_provider) { 33 ResetCxxMethodParser(); 34 35 assert(new_provider != None && "Only reset to a valid provider"); 36 m_provider = new_provider; 37 } 38 39 bool RichManglingContext::FromItaniumName(ConstString mangled) { 40 bool err = m_ipd.partialDemangle(mangled.GetCString()); 41 if (!err) { 42 ResetProvider(ItaniumPartialDemangler); 43 } 44 45 if (Log *log = GetLog(LLDBLog::Demangle)) { 46 if (!err) { 47 ParseFullName(); 48 LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf); 49 } else { 50 LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle", 51 mangled); 52 } 53 } 54 55 return !err; // true == success 56 } 57 58 bool RichManglingContext::FromCxxMethodName(ConstString demangled) { 59 auto *lang = Language::FindPlugin(eLanguageTypeC_plus_plus); 60 if (!lang) 61 return false; 62 ResetProvider(PluginCxxLanguage); 63 m_cxx_method_parser = lang->GetMethodName(demangled); 64 return true; 65 } 66 67 bool RichManglingContext::IsCtorOrDtor() const { 68 assert(m_provider != None && "Initialize a provider first"); 69 switch (m_provider) { 70 case ItaniumPartialDemangler: 71 return m_ipd.isCtorOrDtor(); 72 case PluginCxxLanguage: { 73 // We can only check for destructors here. 74 auto base_name = m_cxx_method_parser->GetBasename(); 75 return base_name.starts_with("~"); 76 } 77 case None: 78 return false; 79 } 80 llvm_unreachable("Fully covered switch above!"); 81 } 82 83 llvm::StringRef RichManglingContext::processIPDStrResult(char *ipd_res, 84 size_t res_size) { 85 // Error case: Clear the buffer. 86 if (LLVM_UNLIKELY(ipd_res == nullptr)) { 87 assert(res_size == m_ipd_buf_size && 88 "Failed IPD queries keep the original size in the N parameter"); 89 90 m_ipd_buf[0] = '\0'; 91 return llvm::StringRef(m_ipd_buf, 0); 92 } 93 94 // IPD's res_size includes null terminator. 95 assert(ipd_res[res_size - 1] == '\0' && 96 "IPD returns null-terminated strings and we rely on that"); 97 98 // Update buffer/size on realloc. 99 if (LLVM_UNLIKELY(ipd_res != m_ipd_buf || res_size > m_ipd_buf_size)) { 100 m_ipd_buf = ipd_res; // std::realloc freed or reused the old buffer. 101 m_ipd_buf_size = res_size; // May actually be bigger, but we can't know. 102 103 if (Log *log = GetLog(LLDBLog::Demangle)) 104 LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}", 105 m_ipd_buf_size); 106 } 107 108 // 99% case: Just remember the string length. 109 return llvm::StringRef(m_ipd_buf, res_size - 1); 110 } 111 112 llvm::StringRef RichManglingContext::ParseFunctionBaseName() { 113 assert(m_provider != None && "Initialize a provider first"); 114 switch (m_provider) { 115 case ItaniumPartialDemangler: { 116 auto n = m_ipd_buf_size; 117 auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n); 118 return processIPDStrResult(buf, n); 119 } 120 case PluginCxxLanguage: 121 return m_cxx_method_parser->GetBasename(); 122 case None: 123 return {}; 124 } 125 llvm_unreachable("Fully covered switch above!"); 126 } 127 128 llvm::StringRef RichManglingContext::ParseFunctionDeclContextName() { 129 assert(m_provider != None && "Initialize a provider first"); 130 switch (m_provider) { 131 case ItaniumPartialDemangler: { 132 auto n = m_ipd_buf_size; 133 auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n); 134 return processIPDStrResult(buf, n); 135 } 136 case PluginCxxLanguage: 137 return m_cxx_method_parser->GetContext(); 138 case None: 139 return {}; 140 } 141 llvm_unreachable("Fully covered switch above!"); 142 } 143 144 llvm::StringRef RichManglingContext::ParseFullName() { 145 assert(m_provider != None && "Initialize a provider first"); 146 switch (m_provider) { 147 case ItaniumPartialDemangler: { 148 auto n = m_ipd_buf_size; 149 auto buf = m_ipd.finishDemangle(m_ipd_buf, &n); 150 return processIPDStrResult(buf, n); 151 } 152 case PluginCxxLanguage: 153 return m_cxx_method_parser->GetFullName().GetStringRef(); 154 case None: 155 return {}; 156 } 157 llvm_unreachable("Fully covered switch above!"); 158 } 159