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