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