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