llvm-project

Форк
0
/
RichManglingContext.cpp 
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

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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.