xref: /openbsd-src/gnu/llvm/lldb/source/Core/RichManglingContext.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- RichManglingContext.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Core/RichManglingContext.h"
10061da546Spatrick #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
11*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
12061da546Spatrick 
13061da546Spatrick #include "llvm/ADT/StringRef.h"
14061da546Spatrick 
15061da546Spatrick using namespace lldb;
16061da546Spatrick using namespace lldb_private;
17061da546Spatrick 
18061da546Spatrick // RichManglingContext
~RichManglingContext()19be691f3bSpatrick RichManglingContext::~RichManglingContext() {
20be691f3bSpatrick   std::free(m_ipd_buf);
21be691f3bSpatrick   ResetCxxMethodParser();
22be691f3bSpatrick }
23be691f3bSpatrick 
ResetCxxMethodParser()24be691f3bSpatrick void RichManglingContext::ResetCxxMethodParser() {
25061da546Spatrick   // If we want to support parsers for other languages some day, we need a
26061da546Spatrick   // switch here to delete the correct parser type.
27*f6aab3d8Srobert   if (m_cxx_method_parser.has_value()) {
28061da546Spatrick     assert(m_provider == PluginCxxLanguage);
29061da546Spatrick     delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser);
30061da546Spatrick     m_cxx_method_parser.reset();
31061da546Spatrick   }
32be691f3bSpatrick }
33be691f3bSpatrick 
ResetProvider(InfoProvider new_provider)34be691f3bSpatrick void RichManglingContext::ResetProvider(InfoProvider new_provider) {
35be691f3bSpatrick   ResetCxxMethodParser();
36061da546Spatrick 
37061da546Spatrick   assert(new_provider != None && "Only reset to a valid provider");
38061da546Spatrick   m_provider = new_provider;
39061da546Spatrick }
40061da546Spatrick 
FromItaniumName(ConstString mangled)41061da546Spatrick bool RichManglingContext::FromItaniumName(ConstString mangled) {
42061da546Spatrick   bool err = m_ipd.partialDemangle(mangled.GetCString());
43061da546Spatrick   if (!err) {
44061da546Spatrick     ResetProvider(ItaniumPartialDemangler);
45061da546Spatrick   }
46061da546Spatrick 
47*f6aab3d8Srobert   if (Log *log = GetLog(LLDBLog::Demangle)) {
48061da546Spatrick     if (!err) {
49061da546Spatrick       ParseFullName();
50061da546Spatrick       LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf);
51061da546Spatrick     } else {
52061da546Spatrick       LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle",
53061da546Spatrick                mangled);
54061da546Spatrick     }
55061da546Spatrick   }
56061da546Spatrick 
57061da546Spatrick   return !err; // true == success
58061da546Spatrick }
59061da546Spatrick 
FromCxxMethodName(ConstString demangled)60061da546Spatrick bool RichManglingContext::FromCxxMethodName(ConstString demangled) {
61061da546Spatrick   ResetProvider(PluginCxxLanguage);
62061da546Spatrick   m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled);
63061da546Spatrick   return true;
64061da546Spatrick }
65061da546Spatrick 
IsCtorOrDtor() const66061da546Spatrick bool RichManglingContext::IsCtorOrDtor() const {
67061da546Spatrick   assert(m_provider != None && "Initialize a provider first");
68061da546Spatrick   switch (m_provider) {
69061da546Spatrick   case ItaniumPartialDemangler:
70061da546Spatrick     return m_ipd.isCtorOrDtor();
71061da546Spatrick   case PluginCxxLanguage: {
72061da546Spatrick     // We can only check for destructors here.
73061da546Spatrick     auto base_name =
74061da546Spatrick         get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
75061da546Spatrick     return base_name.startswith("~");
76061da546Spatrick   }
77061da546Spatrick   case None:
78061da546Spatrick     return false;
79061da546Spatrick   }
80061da546Spatrick   llvm_unreachable("Fully covered switch above!");
81061da546Spatrick }
82061da546Spatrick 
processIPDStrResult(char * ipd_res,size_t res_size)83*f6aab3d8Srobert llvm::StringRef RichManglingContext::processIPDStrResult(char *ipd_res,
84*f6aab3d8Srobert                                                          size_t res_size) {
85061da546Spatrick   // Error case: Clear the buffer.
86061da546Spatrick   if (LLVM_UNLIKELY(ipd_res == nullptr)) {
87061da546Spatrick     assert(res_size == m_ipd_buf_size &&
88061da546Spatrick            "Failed IPD queries keep the original size in the N parameter");
89061da546Spatrick 
90061da546Spatrick     m_ipd_buf[0] = '\0';
91*f6aab3d8Srobert     return llvm::StringRef(m_ipd_buf, 0);
92061da546Spatrick   }
93061da546Spatrick 
94061da546Spatrick   // IPD's res_size includes null terminator.
95061da546Spatrick   assert(ipd_res[res_size - 1] == '\0' &&
96061da546Spatrick          "IPD returns null-terminated strings and we rely on that");
97061da546Spatrick 
98061da546Spatrick   // Update buffer/size on realloc.
99061da546Spatrick   if (LLVM_UNLIKELY(ipd_res != m_ipd_buf || res_size > m_ipd_buf_size)) {
100061da546Spatrick     m_ipd_buf = ipd_res;       // std::realloc freed or reused the old buffer.
101061da546Spatrick     m_ipd_buf_size = res_size; // May actually be bigger, but we can't know.
102061da546Spatrick 
103*f6aab3d8Srobert     if (Log *log = GetLog(LLDBLog::Demangle))
104061da546Spatrick       LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}",
105061da546Spatrick                m_ipd_buf_size);
106061da546Spatrick   }
107061da546Spatrick 
108061da546Spatrick   // 99% case: Just remember the string length.
109*f6aab3d8Srobert   return llvm::StringRef(m_ipd_buf, res_size - 1);
110061da546Spatrick }
111061da546Spatrick 
ParseFunctionBaseName()112*f6aab3d8Srobert llvm::StringRef RichManglingContext::ParseFunctionBaseName() {
113061da546Spatrick   assert(m_provider != None && "Initialize a provider first");
114061da546Spatrick   switch (m_provider) {
115061da546Spatrick   case ItaniumPartialDemangler: {
116061da546Spatrick     auto n = m_ipd_buf_size;
117061da546Spatrick     auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n);
118*f6aab3d8Srobert     return processIPDStrResult(buf, n);
119061da546Spatrick   }
120061da546Spatrick   case PluginCxxLanguage:
121*f6aab3d8Srobert     return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
122*f6aab3d8Srobert         ->GetBasename();
123061da546Spatrick   case None:
124*f6aab3d8Srobert     return {};
125061da546Spatrick   }
126*f6aab3d8Srobert   llvm_unreachable("Fully covered switch above!");
127061da546Spatrick }
128061da546Spatrick 
ParseFunctionDeclContextName()129*f6aab3d8Srobert llvm::StringRef RichManglingContext::ParseFunctionDeclContextName() {
130061da546Spatrick   assert(m_provider != None && "Initialize a provider first");
131061da546Spatrick   switch (m_provider) {
132061da546Spatrick   case ItaniumPartialDemangler: {
133061da546Spatrick     auto n = m_ipd_buf_size;
134061da546Spatrick     auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);
135*f6aab3d8Srobert     return processIPDStrResult(buf, n);
136061da546Spatrick   }
137061da546Spatrick   case PluginCxxLanguage:
138*f6aab3d8Srobert     return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
139*f6aab3d8Srobert         ->GetContext();
140061da546Spatrick   case None:
141*f6aab3d8Srobert     return {};
142061da546Spatrick   }
143*f6aab3d8Srobert   llvm_unreachable("Fully covered switch above!");
144061da546Spatrick }
145061da546Spatrick 
ParseFullName()146*f6aab3d8Srobert llvm::StringRef RichManglingContext::ParseFullName() {
147061da546Spatrick   assert(m_provider != None && "Initialize a provider first");
148061da546Spatrick   switch (m_provider) {
149061da546Spatrick   case ItaniumPartialDemangler: {
150061da546Spatrick     auto n = m_ipd_buf_size;
151061da546Spatrick     auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);
152*f6aab3d8Srobert     return processIPDStrResult(buf, n);
153061da546Spatrick   }
154061da546Spatrick   case PluginCxxLanguage:
155*f6aab3d8Srobert     return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
156061da546Spatrick         ->GetFullName()
157061da546Spatrick         .GetStringRef();
158061da546Spatrick   case None:
159*f6aab3d8Srobert     return {};
160061da546Spatrick   }
161*f6aab3d8Srobert   llvm_unreachable("Fully covered switch above!");
162061da546Spatrick }
163