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