brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · 82582a5 Raw
159 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/RichManglingContext.h"10#include "lldb/Utility/LLDBLog.h"11 12#include "llvm/ADT/StringRef.h"13 14using namespace lldb;15using namespace lldb_private;16 17// RichManglingContext18RichManglingContext::~RichManglingContext() {19  std::free(m_ipd_buf);20  ResetCxxMethodParser();21}22 23void RichManglingContext::ResetCxxMethodParser() {24  // If we want to support parsers for other languages some day, we need a25  // switch here to delete the correct parser type.26  if (m_cxx_method_parser) {27    assert(m_provider == PluginCxxLanguage);28    m_cxx_method_parser.reset();29  }30}31 32void RichManglingContext::ResetProvider(InfoProvider new_provider) {33  ResetCxxMethodParser();34 35  assert(new_provider != None && "Only reset to a valid provider");36  m_provider = new_provider;37}38 39bool RichManglingContext::FromItaniumName(ConstString mangled) {40  bool err = m_ipd.partialDemangle(mangled.GetCString());41  if (!err) {42    ResetProvider(ItaniumPartialDemangler);43  }44 45  if (Log *log = GetLog(LLDBLog::Demangle)) {46    if (!err) {47      ParseFullName();48      LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf);49    } else {50      LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle",51               mangled);52    }53  }54 55  return !err; // true == success56}57 58bool RichManglingContext::FromCxxMethodName(ConstString demangled) {59  auto *lang = Language::FindPlugin(eLanguageTypeC_plus_plus);60  if (!lang)61    return false;62  ResetProvider(PluginCxxLanguage);63  m_cxx_method_parser = lang->GetMethodName(demangled);64  return true;65}66 67bool RichManglingContext::IsCtorOrDtor() const {68  assert(m_provider != None && "Initialize a provider first");69  switch (m_provider) {70  case ItaniumPartialDemangler:71    return m_ipd.isCtorOrDtor();72  case PluginCxxLanguage: {73    // We can only check for destructors here.74    auto base_name = 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 83llvm::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 112llvm::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 m_cxx_method_parser->GetBasename();122  case None:123    return {};124  }125  llvm_unreachable("Fully covered switch above!");126}127 128llvm::StringRef RichManglingContext::ParseFunctionDeclContextName() {129  assert(m_provider != None && "Initialize a provider first");130  switch (m_provider) {131  case ItaniumPartialDemangler: {132    auto n = m_ipd_buf_size;133    auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);134    return processIPDStrResult(buf, n);135  }136  case PluginCxxLanguage:137    return m_cxx_method_parser->GetContext();138  case None:139    return {};140  }141  llvm_unreachable("Fully covered switch above!");142}143 144llvm::StringRef RichManglingContext::ParseFullName() {145  assert(m_provider != None && "Initialize a provider first");146  switch (m_provider) {147  case ItaniumPartialDemangler: {148    auto n = m_ipd_buf_size;149    auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);150    return processIPDStrResult(buf, n);151  }152  case PluginCxxLanguage:153    return m_cxx_method_parser->GetFullName().GetStringRef();154  case None:155    return {};156  }157  llvm_unreachable("Fully covered switch above!");158}159