1343181Sdim//===-- RichManglingContext.cpp ---------------------------------*- C++ -*-===// 2343181Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6343181Sdim// 7343181Sdim//===----------------------------------------------------------------------===// 8343181Sdim 9343181Sdim#include "lldb/Core/RichManglingContext.h" 10343181Sdim 11343181Sdim#include "lldb/Utility/Log.h" 12343181Sdim#include "lldb/Utility/Logging.h" 13343181Sdim 14343181Sdim#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" 15343181Sdim 16343181Sdim#include "llvm/ADT/StringRef.h" 17343181Sdim 18343181Sdimusing namespace lldb; 19343181Sdimusing namespace lldb_private; 20343181Sdim 21343181Sdim// RichManglingContext 22343181Sdimvoid RichManglingContext::ResetProvider(InfoProvider new_provider) { 23343181Sdim // If we want to support parsers for other languages some day, we need a 24343181Sdim // switch here to delete the correct parser type. 25343181Sdim if (m_cxx_method_parser.hasValue()) { 26343181Sdim assert(m_provider == PluginCxxLanguage); 27343181Sdim delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser); 28343181Sdim m_cxx_method_parser.reset(); 29343181Sdim } 30343181Sdim 31343181Sdim assert(new_provider != None && "Only reset to a valid provider"); 32343181Sdim m_provider = new_provider; 33343181Sdim} 34343181Sdim 35353358Sdimbool RichManglingContext::FromItaniumName(ConstString mangled) { 36343181Sdim bool err = m_ipd.partialDemangle(mangled.GetCString()); 37343181Sdim if (!err) { 38343181Sdim ResetProvider(ItaniumPartialDemangler); 39343181Sdim } 40343181Sdim 41343181Sdim if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { 42343181Sdim if (!err) { 43343181Sdim ParseFullName(); 44343181Sdim LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf); 45343181Sdim } else { 46343181Sdim LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle", 47343181Sdim mangled); 48343181Sdim } 49343181Sdim } 50343181Sdim 51343181Sdim return !err; // true == success 52343181Sdim} 53343181Sdim 54353358Sdimbool RichManglingContext::FromCxxMethodName(ConstString demangled) { 55343181Sdim ResetProvider(PluginCxxLanguage); 56343181Sdim m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled); 57343181Sdim return true; 58343181Sdim} 59343181Sdim 60343181Sdimbool RichManglingContext::IsCtorOrDtor() const { 61343181Sdim assert(m_provider != None && "Initialize a provider first"); 62343181Sdim switch (m_provider) { 63343181Sdim case ItaniumPartialDemangler: 64343181Sdim return m_ipd.isCtorOrDtor(); 65343181Sdim case PluginCxxLanguage: { 66343181Sdim // We can only check for destructors here. 67343181Sdim auto base_name = 68343181Sdim get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename(); 69343181Sdim return base_name.startswith("~"); 70343181Sdim } 71343181Sdim case None: 72343181Sdim return false; 73343181Sdim } 74343181Sdim llvm_unreachable("Fully covered switch above!"); 75343181Sdim} 76343181Sdim 77343181Sdimbool RichManglingContext::IsFunction() const { 78343181Sdim assert(m_provider != None && "Initialize a provider first"); 79343181Sdim switch (m_provider) { 80343181Sdim case ItaniumPartialDemangler: 81343181Sdim return m_ipd.isFunction(); 82343181Sdim case PluginCxxLanguage: 83343181Sdim return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->IsValid(); 84343181Sdim case None: 85343181Sdim return false; 86343181Sdim } 87343181Sdim llvm_unreachable("Fully covered switch above!"); 88343181Sdim} 89343181Sdim 90343181Sdimvoid RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) { 91343181Sdim // Error case: Clear the buffer. 92343181Sdim if (LLVM_UNLIKELY(ipd_res == nullptr)) { 93343181Sdim assert(res_size == m_ipd_buf_size && 94343181Sdim "Failed IPD queries keep the original size in the N parameter"); 95343181Sdim 96343181Sdim m_ipd_buf[0] = '\0'; 97343181Sdim m_buffer = llvm::StringRef(m_ipd_buf, 0); 98343181Sdim return; 99343181Sdim } 100343181Sdim 101343181Sdim // IPD's res_size includes null terminator. 102343181Sdim assert(ipd_res[res_size - 1] == '\0' && 103343181Sdim "IPD returns null-terminated strings and we rely on that"); 104343181Sdim 105343181Sdim // Update buffer/size on realloc. 106343181Sdim if (LLVM_UNLIKELY(ipd_res != m_ipd_buf || res_size > m_ipd_buf_size)) { 107343181Sdim m_ipd_buf = ipd_res; // std::realloc freed or reused the old buffer. 108343181Sdim m_ipd_buf_size = res_size; // May actually be bigger, but we can't know. 109343181Sdim 110343181Sdim if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) 111343181Sdim LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}", 112343181Sdim m_ipd_buf_size); 113343181Sdim } 114343181Sdim 115343181Sdim // 99% case: Just remember the string length. 116343181Sdim m_buffer = llvm::StringRef(m_ipd_buf, res_size - 1); 117343181Sdim} 118343181Sdim 119343181Sdimvoid RichManglingContext::ParseFunctionBaseName() { 120343181Sdim assert(m_provider != None && "Initialize a provider first"); 121343181Sdim switch (m_provider) { 122343181Sdim case ItaniumPartialDemangler: { 123343181Sdim auto n = m_ipd_buf_size; 124343181Sdim auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n); 125343181Sdim processIPDStrResult(buf, n); 126343181Sdim return; 127343181Sdim } 128343181Sdim case PluginCxxLanguage: 129343181Sdim m_buffer = 130343181Sdim get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename(); 131343181Sdim return; 132343181Sdim case None: 133343181Sdim return; 134343181Sdim } 135343181Sdim} 136343181Sdim 137343181Sdimvoid RichManglingContext::ParseFunctionDeclContextName() { 138343181Sdim assert(m_provider != None && "Initialize a provider first"); 139343181Sdim switch (m_provider) { 140343181Sdim case ItaniumPartialDemangler: { 141343181Sdim auto n = m_ipd_buf_size; 142343181Sdim auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n); 143343181Sdim processIPDStrResult(buf, n); 144343181Sdim return; 145343181Sdim } 146343181Sdim case PluginCxxLanguage: 147343181Sdim m_buffer = 148343181Sdim get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext(); 149343181Sdim return; 150343181Sdim case None: 151343181Sdim return; 152343181Sdim } 153343181Sdim} 154343181Sdim 155343181Sdimvoid RichManglingContext::ParseFullName() { 156343181Sdim assert(m_provider != None && "Initialize a provider first"); 157343181Sdim switch (m_provider) { 158343181Sdim case ItaniumPartialDemangler: { 159343181Sdim auto n = m_ipd_buf_size; 160343181Sdim auto buf = m_ipd.finishDemangle(m_ipd_buf, &n); 161343181Sdim processIPDStrResult(buf, n); 162343181Sdim return; 163343181Sdim } 164343181Sdim case PluginCxxLanguage: 165343181Sdim m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser) 166343181Sdim ->GetFullName() 167343181Sdim .GetStringRef(); 168343181Sdim return; 169343181Sdim case None: 170343181Sdim return; 171343181Sdim } 172343181Sdim} 173