brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.9 KiB · 99e73ca Raw
306 lines · cpp
1//===-- MsvcStlVector.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 "MsvcStl.h"10 11#include "lldb/DataFormatters/FormattersHelpers.h"12#include "lldb/DataFormatters/TypeSynthetic.h"13 14using namespace lldb;15 16namespace lldb_private {17namespace formatters {18 19class MsvcStlVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {20public:21  MsvcStlVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);22 23  llvm::Expected<uint32_t> CalculateNumChildren() override;24 25  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;26 27  lldb::ChildCacheState Update() override;28 29  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;30 31private:32  ValueObject *m_start = nullptr;33  ValueObject *m_finish = nullptr;34  CompilerType m_element_type;35  uint32_t m_element_size = 0;36};37 38class MsvcStlVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd {39public:40  MsvcStlVectorBoolSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);41 42  llvm::Expected<uint32_t> CalculateNumChildren() override;43 44  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;45 46  lldb::ChildCacheState Update() override;47 48  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;49 50private:51  CompilerType m_bool_type;52  ExecutionContextRef m_exe_ctx_ref;53  uint64_t m_count = 0;54  uint64_t m_element_bit_size = 0;55  lldb::addr_t m_base_data_address = 0;56  std::map<size_t, lldb::ValueObjectSP> m_children;57};58 59} // namespace formatters60} // namespace lldb_private61 62lldb_private::formatters::MsvcStlVectorSyntheticFrontEnd::63    MsvcStlVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)64    : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {65  if (valobj_sp)66    Update();67}68 69llvm::Expected<uint32_t> lldb_private::formatters::70    MsvcStlVectorSyntheticFrontEnd::CalculateNumChildren() {71  if (!m_start || !m_finish)72    return llvm::createStringError(73        "failed to determine start/end of vector data");74 75  uint64_t start_val = m_start->GetValueAsUnsigned(0);76  uint64_t finish_val = m_finish->GetValueAsUnsigned(0);77 78  // A default-initialized empty vector.79  if (start_val == 0 && finish_val == 0)80    return 0;81 82  if (start_val == 0)83    return llvm::createStringError("invalid value for start of vector");84 85  if (finish_val == 0)86    return llvm::createStringError("invalid value for end of vector");87 88  if (start_val > finish_val)89    return llvm::createStringError(90        "start of vector data begins after end pointer");91 92  size_t num_children = (finish_val - start_val);93  if (num_children % m_element_size)94    return llvm::createStringError("size not multiple of element size");95 96  return num_children / m_element_size;97}98 99lldb::ValueObjectSP100lldb_private::formatters::MsvcStlVectorSyntheticFrontEnd::GetChildAtIndex(101    uint32_t idx) {102  if (!m_start || !m_finish)103    return lldb::ValueObjectSP();104 105  uint64_t offset = idx * m_element_size;106  offset = offset + m_start->GetValueAsUnsigned(0);107  StreamString name;108  name.Printf("[%" PRIu64 "]", (uint64_t)idx);109  return CreateValueObjectFromAddress(name.GetString(), offset,110                                      m_backend.GetExecutionContextRef(),111                                      m_element_type);112}113 114lldb::ChildCacheState115lldb_private::formatters::MsvcStlVectorSyntheticFrontEnd::Update() {116  m_start = m_finish = nullptr;117  ValueObjectSP data_sp(m_backend.GetChildAtNamePath({"_Mypair", "_Myval2"}));118 119  if (!data_sp)120    return lldb::ChildCacheState::eRefetch;121 122  m_start = data_sp->GetChildMemberWithName("_Myfirst").get();123  m_finish = data_sp->GetChildMemberWithName("_Mylast").get();124  if (!m_start || !m_finish)125    return lldb::ChildCacheState::eRefetch;126 127  m_element_type = m_start->GetCompilerType().GetPointeeType();128  llvm::Expected<uint64_t> size_or_err = m_element_type.GetByteSize(nullptr);129  if (size_or_err)130    m_element_size = *size_or_err;131  else132    LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), size_or_err.takeError(),133                    "{0}");134 135  return lldb::ChildCacheState::eRefetch;136}137 138llvm::Expected<size_t> lldb_private::formatters::139    MsvcStlVectorSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {140  if (!m_start || !m_finish)141    return llvm::createStringError("Type has no child named '%s'",142                                   name.AsCString());143  auto optional_idx = ExtractIndexFromString(name.GetCString());144  if (!optional_idx) {145    return llvm::createStringError("Type has no child named '%s'",146                                   name.AsCString());147  }148  return *optional_idx;149}150 151lldb_private::formatters::MsvcStlVectorBoolSyntheticFrontEnd::152    MsvcStlVectorBoolSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)153    : SyntheticChildrenFrontEnd(*valobj_sp), m_bool_type(), m_exe_ctx_ref(),154      m_children() {155  if (valobj_sp) {156    Update();157    m_bool_type =158        valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool);159  }160}161 162llvm::Expected<uint32_t> lldb_private::formatters::163    MsvcStlVectorBoolSyntheticFrontEnd::CalculateNumChildren() {164  return m_count;165}166 167lldb::ValueObjectSP168lldb_private::formatters::MsvcStlVectorBoolSyntheticFrontEnd::GetChildAtIndex(169    uint32_t idx) {170  auto iter = m_children.find(idx), end = m_children.end();171  if (iter != end)172    return iter->second;173  if (idx >= m_count)174    return {};175  if (m_base_data_address == 0 || m_count == 0)176    return {};177  if (!m_bool_type)178    return {};179 180  // The vector<bool> is represented as a sequence of `int`s.181  // The size of an `int` is in `m_element_bit_size` (most often 32b).182  // To access the element at index `i`:183  // (bool)((data_address[i / bit_size] >> (i % bit_size)) & 1)184 185  // int *byte_location = &data_address[i / bit_size]186  size_t byte_idx = (idx / m_element_bit_size) * (m_element_bit_size / 8);187  lldb::addr_t byte_location = m_base_data_address + byte_idx;188 189  ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());190  if (!process_sp)191    return {};192  Status err;193  Scalar scalar;194  size_t bytes_read = process_sp->ReadScalarIntegerFromMemory(195      byte_location, m_element_bit_size / 8, false, scalar, err);196  if (err.Fail() || bytes_read == 0 || !scalar.IsValid())197    return {};198 199  size_t bit_index = idx % m_element_bit_size;200  bool bit_set = scalar.GetAPSInt()[bit_index];201  std::optional<uint64_t> size =202      llvm::expectedToOptional(m_bool_type.GetByteSize(nullptr));203  if (!size)204    return {};205  WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));206  if (bit_set && buffer_sp && buffer_sp->GetBytes()) {207    // regardless of endianness, anything non-zero is true208    *(buffer_sp->GetBytes()) = 1;209  }210  StreamString name;211  name.Printf("[%" PRIu64 "]", (uint64_t)idx);212  ValueObjectSP retval_sp(CreateValueObjectFromData(213      name.GetString(),214      DataExtractor(buffer_sp, process_sp->GetByteOrder(),215                    process_sp->GetAddressByteSize()),216      m_exe_ctx_ref, m_bool_type));217  if (retval_sp)218    m_children[idx] = retval_sp;219  return retval_sp;220}221 222lldb::ChildCacheState223lldb_private::formatters::MsvcStlVectorBoolSyntheticFrontEnd::Update() {224  m_exe_ctx_ref.Clear();225  m_count = 0;226  m_element_bit_size = 0;227  m_base_data_address = 0;228  m_children.clear();229 230  ValueObjectSP valobj_sp = m_backend.GetSP();231  if (!valobj_sp)232    return lldb::ChildCacheState::eRefetch;233  auto exe_ctx_ref = valobj_sp->GetExecutionContextRef();234 235  ValueObjectSP size_sp = valobj_sp->GetChildMemberWithName("_Mysize");236  if (!size_sp)237    return lldb::ChildCacheState::eRefetch;238  uint64_t count = size_sp->GetValueAsUnsigned(0);239  if (count == 0)240    return lldb::ChildCacheState::eReuse;241 242  ValueObjectSP begin_sp(valobj_sp->GetChildAtNamePath(243      {"_Myvec", "_Mypair", "_Myval2", "_Myfirst"}));244  if (!begin_sp)245    return lldb::ChildCacheState::eRefetch;246 247  // FIXME: the STL exposes _EEN_VBITS as a constant - it should be used instead248  CompilerType begin_ty = begin_sp->GetCompilerType().GetPointeeType();249  if (!begin_ty.IsValid())250    return lldb::ChildCacheState::eRefetch;251  llvm::Expected<uint64_t> element_bit_size = begin_ty.GetBitSize(nullptr);252  if (!element_bit_size)253    return lldb::ChildCacheState::eRefetch;254 255  uint64_t base_data_address = begin_sp->GetValueAsUnsigned(0);256  if (!base_data_address)257    return lldb::ChildCacheState::eRefetch;258 259  m_exe_ctx_ref = exe_ctx_ref;260  m_count = count;261  m_element_bit_size = *element_bit_size;262  m_base_data_address = base_data_address;263  return lldb::ChildCacheState::eRefetch;264}265 266llvm::Expected<size_t>267lldb_private::formatters::MsvcStlVectorBoolSyntheticFrontEnd::268    GetIndexOfChildWithName(ConstString name) {269  if (!m_count || !m_base_data_address)270    return llvm::createStringError("Type has no child named '%s'",271                                   name.AsCString());272  auto optional_idx = ExtractIndexFromString(name.AsCString());273  if (!optional_idx) {274    return llvm::createStringError("Type has no child named '%s'",275                                   name.AsCString());276  }277  uint32_t idx = *optional_idx;278  if (idx >= CalculateNumChildrenIgnoringErrors())279    return llvm::createStringError("Type has no child named '%s'",280                                   name.AsCString());281  return idx;282}283 284lldb_private::SyntheticChildrenFrontEnd *285lldb_private::formatters::MsvcStlVectorSyntheticFrontEndCreator(286    lldb::ValueObjectSP valobj_sp) {287  if (!valobj_sp)288    return nullptr;289 290  valobj_sp = valobj_sp->GetNonSyntheticValue();291  if (!valobj_sp)292    return nullptr;293 294  // We can't check the template parameter here, because PDB doesn't include295  // this information.296 297  // vector<T>298  if (valobj_sp->GetChildMemberWithName("_Mypair") != nullptr)299    return new MsvcStlVectorSyntheticFrontEnd(valobj_sp);300  // vector<bool>301  if (valobj_sp->GetChildMemberWithName("_Myvec") != nullptr)302    return new MsvcStlVectorBoolSyntheticFrontEnd(valobj_sp);303 304  return nullptr;305}306