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