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 } 78 79 bool RichManglingContext::IsFunction() const { 80 assert(m_provider != None && "Initialize a provider first"); 81 switch (m_provider) { 82 case ItaniumPartialDemangler: 83 return m_ipd.isFunction(); 84 case PluginCxxLanguage: 85 return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->IsValid(); 86 case None: 87 return false; 88 } 89 } 90 91 void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) { 92 // Error case: Clear the buffer. 93 if (LLVM_UNLIKELY(ipd_res == nullptr)) { 94 assert(res_size == m_ipd_buf_size && 95 "Failed IPD queries keep the original size in the N parameter"); 96 97 m_ipd_buf[0] = '\0'; 98 m_buffer = llvm::StringRef(m_ipd_buf, 0); 99 return; 100 } 101 102 // IPD's res_size includes null terminator. 103 assert(ipd_res[res_size - 1] == '\0' && 104 "IPD returns null-terminated strings and we rely on that"); 105 106 // Update buffer/size on realloc. 107 if (LLVM_UNLIKELY(ipd_res != m_ipd_buf || res_size > m_ipd_buf_size)) { 108 m_ipd_buf = ipd_res; // std::realloc freed or reused the old buffer. 109 m_ipd_buf_size = res_size; // May actually be bigger, but we can't know. 110 111 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) 112 LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}", 113 m_ipd_buf_size); 114 } 115 116 // 99% case: Just remember the string length. 117 m_buffer = llvm::StringRef(m_ipd_buf, res_size - 1); 118 } 119 120 void RichManglingContext::ParseFunctionBaseName() { 121 assert(m_provider != None && "Initialize a provider first"); 122 switch (m_provider) { 123 case ItaniumPartialDemangler: { 124 auto n = m_ipd_buf_size; 125 auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n); 126 processIPDStrResult(buf, n); 127 return; 128 } 129 case PluginCxxLanguage: 130 m_buffer = 131 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename(); 132 return; 133 case None: 134 return; 135 } 136 } 137 138 void RichManglingContext::ParseFunctionDeclContextName() { 139 assert(m_provider != None && "Initialize a provider first"); 140 switch (m_provider) { 141 case ItaniumPartialDemangler: { 142 auto n = m_ipd_buf_size; 143 auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n); 144 processIPDStrResult(buf, n); 145 return; 146 } 147 case PluginCxxLanguage: 148 m_buffer = 149 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext(); 150 return; 151 case None: 152 return; 153 } 154 } 155 156 void RichManglingContext::ParseFullName() { 157 assert(m_provider != None && "Initialize a provider first"); 158 switch (m_provider) { 159 case ItaniumPartialDemangler: { 160 auto n = m_ipd_buf_size; 161 auto buf = m_ipd.finishDemangle(m_ipd_buf, &n); 162 processIPDStrResult(buf, n); 163 return; 164 } 165 case PluginCxxLanguage: 166 m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser) 167 ->GetFullName() 168 .GetStringRef(); 169 return; 170 case None: 171 return; 172 } 173 } 174